Using unity 4.7.
When I try and bake a skinned mesh using BakeMesh. The resultant mesh is in local coordinates except that it is scaled by the world scale. Why is this exactly? I have to go through and scale all the coordinates.
Also the localBounds for the skinned renderer seems to be scaled and rotated in some arbitrary direction I can’t discern.
It’s all world space. The mesh (scale and position) will be relative to the game object that has the mesh renderer. You can scale the object it gets placed on. Or you can scale the vert positions when you make the mesh.
Did you recalculate the bounds?
I believe you are mistaken. I have done extensive tests. All the points in the mesh are baked in local coordinates. But I have to scale all the vertices by lossyScale.x to get them similar to as if it was a MeshFilter instead of a SkinnedMeshRender. You wouldn’t notice this unless your skinned mesh is in a heirachy like this with A,B,C being game object with different scales:
A
B
C
SkinnedMesh
GameObject with transform set to identity to accept MeshRender for testing
Try it for yourself. (Not sure if its fixed in Unity 5. But this definitely happens in Unity 4.7.0) I am using the legacy animation system.
Here is my exact code I used for testing:
Mesh mesh=new Mesh();
skin.BakeMesh (mesh);
GameObject GO=skin.gameObject;
Vector3[] verts=mesh.vertices;
float scale = 1.0f/GO.transform.lossyScale.y;
for(int i=0;i<verts.Length;i++){
verts[i] = verts[i]*scale ;
}
mesh.vertices=verts;
mesh.RecalculateBounds();
//for testing to see comparison
meshfilter.mesh = mesh;
It’s not a problem for me to do this. I just wondered why? And if this is deliberate?

The only explanation I can think of is that the skinned mesh render is applied in world coordinates except when it is overridden by the animations which are applied in local coordinates. But animations only use position and rotation and not scale so the scales stay in world coordinates. Hence when you bake a mesh the scales are all wrong.
2 Likes
Alternatively one can use this script for baking the skinned mesh which I modified from one on a different thread:
using UnityEngine;
using System.Collections.Generic;
public class SkinnedMeshHelper {
public static Mesh GetPosedMesh(SkinnedMeshRenderer skin)
{
float MIN_VALUE = 0.00001f;
Mesh mesh = new Mesh ();
Mesh sharedMesh = skin.sharedMesh;
GameObject root = skin.gameObject;
Vector3[] vertices = sharedMesh.vertices;
Matrix4x4[] bindposes = sharedMesh.bindposes;
BoneWeight[] boneWeights = sharedMesh.boneWeights;
Transform[] bones = skin.bones;
Vector3[] newVert = new Vector3[vertices.Length];
Vector3 localPt;
for (int i = 0; i < vertices.Length; i++)
{
BoneWeight bw = boneWeights[i];
if (Mathf.Abs(bw.weight0) > MIN_VALUE)
{
localPt = bindposes[bw.boneIndex0].MultiplyPoint3x4(vertices[i]);
newVert[i] +=
root.transform.InverseTransformPoint
(
bones[bw.boneIndex0].transform.localToWorldMatrix.MultiplyPoint3x4(localPt)) * bw.weight0;
}
if (Mathf.Abs(bw.weight1) > MIN_VALUE)
{
localPt = bindposes[bw.boneIndex1].MultiplyPoint3x4(vertices[i]);
newVert[i] +=
root.transform.InverseTransformPoint
(
bones[bw.boneIndex1].transform.localToWorldMatrix.MultiplyPoint3x4(localPt)) * bw.weight1;
}
if (Mathf.Abs(bw.weight2) > MIN_VALUE)
{
localPt = bindposes[bw.boneIndex2].MultiplyPoint3x4(vertices[i]);
newVert[i] += root.transform.InverseTransformPoint
(
bones[bw.boneIndex2].transform.localToWorldMatrix.MultiplyPoint3x4(localPt)) * bw.weight2;
}
if (Mathf.Abs(bw.weight3) > MIN_VALUE)
{
localPt = bindposes[bw.boneIndex3].MultiplyPoint3x4(vertices[i]);
newVert[i] +=
root.transform.InverseTransformPoint
(
bones[bw.boneIndex3].transform.localToWorldMatrix.MultiplyPoint3x4(localPt)) * bw.weight3;
}
}
mesh.vertices = newVert;
mesh.triangles = skin.sharedMesh.triangles;
mesh.RecalculateBounds ();
return mesh;
}
}
It just gives a simple mesh, no UVs or anything else. There are a lot of transforms. But at least it doesn’t have the scaling problem.
Also, this is quite useful if you just wanted to know where a single vertex will be instead of having to bake an entire mesh you can use these formulas.
1 Like
Sorry, I meant mesh() data in general.
Are in any of those parents *gameobject,gameobject,gameobject). scaled? And where are you attaching the the generated mesh to? If you read if from one object that isn’t scaled and attach it to one that is (and vice versa), you will get what appear to be different scales.
I’m just going to work around the issue.