Transform coordinates to local space with quaternion

Hi,

I am trying to retrieve triangle vertex coordinates from a MeshFilter’s mesh and and transform them so that the triangle is centered around (0,0,0) and the axis (0,1,0) - meaning it is lying on the x,z plane. The goal is to compare one triangle with another independently of their position/rotation, so that I can morph one into the other.

Well, I’m failing miserably, and would much appreciate any input on what I’m doing wrong! the following is the method that is supposed to return localized coordinates (if the localize parameter is true). The sourceTransform parameter is used to convert the positions to world coords.

Thanks for any help!

public GameObject MeshObject;

public TriangleMeshData GetTriangleMesh (int triangle, bool localize = false, Transform sourceTransform = null)
{
    var filter = this.MeshObject.GetComponent<MeshFilter> ();

    var data = new TriangleMeshData ();
    Vector3[] verts = new Vector3[3];
    verts [0] = (filter.sharedMesh.vertices [filter.sharedMesh.triangles [triangle]]);
    verts [1] = (filter.sharedMesh.vertices [filter.sharedMesh.triangles [triangle + 1]]);
    verts [2] = (filter.sharedMesh.vertices [filter.sharedMesh.triangles [triangle + 2]]);

    if (sourceTransform != null)
        for (int v = 0; v < 3; v++)
            verts [v] = sourceTransform.TransformPoint (verts [v]);

     data.Position = (verts [0] + verts [1] + verts [2]) / 3;
     data.Normal = filter.sharedMesh.normals [filter.sharedMesh.triangles [triangle]];
     if (sourceTransform != null)
         data.Normal = sourceTransform.TransformDirection (data.Normal);

     if (localize) {
         Quaternion translation = Quaternion.FromToRotation (data.Normal, Vector3.up);
         for (int v = 0; v < 3; v++) {
             verts [v] -= data.Position;
             verts [v] = translation * verts [v];
         }
    }

    data.Vertices = verts;
    return data;
}

public struct TriangleMeshData
{
    public Vector3 Position;
    public Vector3 Normal;
    public Vector3[] Vertices;
}

Well, it could be your vertex normal. Are you sure that your vertex normals equals your face normal? Usually they doesn’t match the face normal unless the triangle is part of a flat surface like a cube. If you want to make sure the triangle is really flat, calculate the face normal. Just do this after you transformed your 3 verts into worldspace, the calculated normal will be automatically in worldspace ;):

// No guarantee that the normal is facing the right way :D
// Unity's left-handed-system is always confusing me.
data.Normal = Vector3.Cross(verts[1] - verts[0], verts[2] - verts[0]).normalized;

I guess the rest should be ok.

Don’t forget if you use the worldspace coordinates the normal will be in world space. If you use the local space coordinated it will be in local space.