Search code examples
c#unity-game-enginemeshverticeslerp

How would you lerp the positions of two matrices?


In my code, I create 2 matrices that store information about two different meshes, using the following code:

Mesh mesh;
MeshFilter filter;

public SphereMesh SphereMesh;
public CubeMesh CubeMesh;

public Material pointMaterial;
public Mesh pointMesh;

public List<Matrix4x4> matrices1 = new List<Matrix4x4>();
public List<Matrix4x4> matrices2 = new List<Matrix4x4>();

[Space]
public float normalOffset = 0f;
public float globalScale = 0.1f;
public Vector3 scale = Vector3.one;

public int matricesNumber = 1; //determines which matrices to store info in

public void StorePoints()
{
    Vector3[] vertices = mesh.vertices;
    Vector3[] normals = mesh.normals;
    Vector3 scaleVector = scale * globalScale;

    // Initialize chunk indexes.
    int startIndex = 0;
    int endIndex = Mathf.Min(1023, mesh.vertexCount);
    int pointCount = 0;

    while (pointCount < mesh.vertexCount)
    {
        // Create points for the current chunk.
        for (int i = startIndex; i < endIndex; i++)
        {
            var position = transform.position + transform.rotation * vertices[i] + transform.rotation * (normals[i].normalized * normalOffset);
            var rotation = Quaternion.identity;
            pointCount++;

            if (matricesNumber == 1)
            {
                matrices1.Add(Matrix4x4.TRS(position, rotation, scaleVector));
            }

            if (matricesNumber == 2)
            {
                matrices2.Add(Matrix4x4.TRS(position, rotation, scaleVector));
            }
            rotation = transform.rotation * Quaternion.LookRotation(normals[i]);
        }

        // Modify start and end index to the range of the next chunk.
        startIndex = endIndex;
        endIndex = Mathf.Min(startIndex + 1023, mesh.vertexCount);
    }
}

The GameObject starts as a Cube mesh, and this code stores the info about the mesh in matrices1. Elsewhere in code not shown, I have it so that the Mesh changes to a Sphere and then changes matricesnumber to 2, then triggers the code above to store the info of the new Sphere mesh in matrices2.

This seems to be working, as I'm able to use code like Graphics.DrawMesh(pointMesh, matrices1[i], pointMaterial, 0); to draw 1 mesh per vertex of the Cube mesh. And I can use that same line (but with matrices2[i]) to draw 1 mesh per vertex of the Sphere mesh.

The Question: How would I draw a mesh for each vertex of the Cube mesh (info stored in matrices1) on the screen and then make those vertex meshes Lerp into the positions of the Sphere mesh's (info stored in matrices2) vertices?

I'm trying to hack at it with things like

float t = Mathf.Clamp((Time.time % 2f) / 2f, 0f, 1f);
matrices1.position.Lerp(matrices1.position, matrices2.position, t);

but obviously this is invalid code. What might be the solution? Thanks.


Solution

  • Matrix4x4 is usually only used in special cases for directly calculating transformation matrices.

    You rarely use matrices in scripts; most often using Vector3s, Quaternions and functionality of Transform class is more straightforward. Plain matrices are used in special cases like setting up nonstandard camera projection.

    In your case it seems to me you actually only need to somehow store and access position, rotation and scale.

    I would suggest to not use Matrix4x4 at all but rather something simple like e.g.

    // The Serializable makes them actually appear in the Inspector
    // which might be very helpful in you case
    [Serializable]
    public class TransformData 
    { 
        public Vector3 position;
        public Quaternion rotation; 
        public Vector3 scale; 
    }
    

    Then with

    public List<TransformData> matrices1 = new List<TransformData>();
    public List<TransformData> matrices2 = new List<TransformData>();
    

    you could simply lerp over

    var lerpedPosition = Vector3.Lerp(matrices1[index].position, matrices2[index].position, lerpFactor);
    

    And if you then need it as a Matrix4x4 you can still create it ad-hoc like e.g.

    var lerpedMatrix = Matrix4x4.Translation(lerpedPosition);
    

    or however you want to use the values.