- Home /
Bake transforms into Mesh
I need to take all the transforms applied to a GameObject and apply them to the actual mesh object it contains. I thought I could just use TransformPoint, but it doesn't seem to do what it's suppose to do. It returns the same vector as it's given, not the transformed world coord vector. Am I misunderstanding TransformPoint's purpose?
for (int i = 0; i < MainObject.sharedMesh.vertices.Length;i++)
MainObject.sharedMesh.vertices[i] = MainObject.transform.TransformPoint(MainObject.sharedMesh.vertices[i]);
How would I "bake" the transforms into the GameObject's Mesh?
Edit: (complete source code)
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
void Awake () {
//Create Test object with transforms
Mesh m = new Mesh();
m.vertices = new Vector3[] {new Vector3(1,1,1),new Vector3(2,2,2),new Vector3(3,1,1)};
m.uv = new Vector2[] { new Vector2(0, 0), new Vector2(1, 1), new Vector2(0, 1) };
m.triangles = new int[] {0,1,2};
m.RecalculateNormals();
GameObject go = new GameObject("TEST OBJECT");
MeshFilter mf = go.AddComponent<MeshFilter>();
mf.sharedMesh = m;
MeshRenderer mr = go.AddComponent<MeshRenderer>();
mr.sharedMaterials = new Material[] { new Material(Shader.Find("Diffuse")) };
go.transform.Rotate(90, 0, 0);
go.transform.localScale = new Vector3(2, 2, 2);
//Create baked object from test object
GameObject goBaked = new GameObject("Baked OBJECT");
MeshFilter mfBaked = goBaked.AddComponent<MeshFilter>();
MeshRenderer mrBaked = goBaked.AddComponent<MeshRenderer>();
Mesh mBaked = (Mesh)Instantiate(m);
mrBaked.sharedMaterials = mr.sharedMaterials;
mfBaked.sharedMesh = mBaked;
for (int i = 0; i < m.vertexCount; i++)
{
Debug.Log("Before:" + m.vertices[i]);
mBaked.vertices[i] = go.transform.TransformPoint(m.vertices[i]);
Debug.Log("After:" + m.vertices[i]);
}
}
}
Answer by ShinyMark.du · Aug 15, 2011 at 07:48 PM
TransformPoint takes a point in local space and converts it to world space based on the used transform's position, rotation, and scale. I'd only expect it to return the same point as was passed in if the transform was the identity, meaning the position is at (0,0,0) and there is no rotation or scale.
Given that, if MainObject.transform is not the identity and MainObject.sharedMesh.vertices is returning vertices in local space I'd expect your code to mostly work. Note that to "bake" a transform you'd need to also reset it to the identity after transforming the vertices or you'd essentially be transforming them twice.
$$anonymous$$ainObject.transform has local scale, local rotation, and local position that is applied, Debug printing before and after "TransformPoint" gives the exact same Vector3. I'm not sure why TransformPoint isn't working.
Have you looked at each component of this individually to make sure it is what you expect?
For example, first looking at the value of $$anonymous$$ainObject.shared$$anonymous$$esh.vertices[i] to make sure it's what you expect.
Then use TransformPoint and store the result in a separate variable so you can take a look at the output of that before assigning it back into the vertex array.
Then look at what happens after you assign the Transformed vertex back into the mesh's vertices array. It's possible Unity engine code gets executed during that assignment, though I kind of doubt it. I'd have to test this myself know for sure but by looking at each step in this process you might be able to find where it isn't doing what you expect.
Yes. I've edited the original post to include a self-contained example source code. It creates the mesh item, sets it's transforms, then tries to retrieve the world coordinates of the vertices using "TransformPoint", with no luck.
It looks like it's the assignment that isn't working. Put this in your sample code inside of the loop:
Debug.Log("Before:" + m.vertices[i]); Vector3 transformedVert = go.transform.TransformPoint(m.vertices[i]); Debug.Log("TransformedPoint:" + transformedVert); mBaked.vertices[i] = transformedVert; Debug.Log("After:" + mBaked.vertices[i]);
Take a look at the "TransformedPoint" debug log, that output looks correct at a glance.
That helped quite a bit, I should have tried that before. Apparently vertices cannot be changed individually, I had to create a new vertices (Vector3) array, put all the new vert positions in it, then assign it back to the mesh all at once.
Answer by Eric5h5 · Aug 15, 2011 at 10:34 PM
I use a Matrix4x4. Here's a copy&paste from one of my utilities, where I'm baking the transform into the mesh:
var thisMatrix = transform.localToWorldMatrix;
for (int i = 0; i < thisPoints.Length; i++) {
thisPoints[i] = thisMatrix.MultiplyPoint3x4(line.points3[i]);
}
Let me know if that's not clear enough.