Search Unity

float4x4 position, rotation, and scale

Discussion in 'Entity Component System' started by TheGabelle, May 3, 2021.

  1. TheGabelle

    TheGabelle

    Joined:
    Aug 23, 2013
    Posts:
    242
    I'm exploring float4x4 and created some helper methods to access data from it. Everything works well until the scale is no longer float3(1, 1, 1). To visualize the error I have attached this component to a teapot, and in the scene view I draw it again using a different color. As soon as the scale is changed the two meshes are rendered differently. What's going on here?

    Code (CSharp):
    1.  
    2. public class Float4x4Testing : MonoBehaviour
    3. {
    4.  
    5.     float3 GetPosition(float4x4 m)
    6.     {
    7.         return new float3(m.c3.x, m.c3.y, m.c3.z);
    8.     }
    9.  
    10.     quaternion GetRotation(float4x4 m)
    11.     {
    12.         return new quaternion(m);
    13.     }
    14.  
    15.     float3 GetScale(float4x4 m)
    16.     {
    17.         return new float3(
    18.             math.length(new float3(m.c0.x, m.c1.x, m.c2.x)),
    19.             math.length(new float3(m.c0.y, m.c1.y, m.c2.y)),
    20.             math.length(new float3(m.c0.z, m.c1.z, m.c2.z))
    21.         );
    22.     }
    23.  
    24.  
    25.     void OnDrawGizmos()
    26.     {
    27.         var pos = transform.position;
    28.         var rot = transform.rotation.normalized;
    29.         var scale = transform.lossyScale;
    30.  
    31.         float4x4 m = float4x4.TRS(pos, rot, scale);
    32.  
    33.         var p = GetPosition(m);
    34.         var q = GetRotation(m);
    35.         var s = GetScale(m);
    36.  
    37.         Gizmos.color = Color.grey;
    38.         var mesh = gameObject.GetComponent<MeshFilter>().sharedMesh;
    39.         Gizmos.DrawMesh(mesh, 0, p, q, s);
    40.     }
    41. }
    42.  
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Code (CSharp):
    1.     float3 GetPosition(float4x4 m)
    2.     {
    3.         return new float3(m.c3.x, m.c3.y, m.c3.z);
    4.     }
    5.     quaternion GetRotation(float4x4 m)
    6.     {
    7.         return new quaternion(m);
    8.     }
    Because this is only valid when the transformation matrix has no scale.

    If you have scale on your matrix you have to remove it first (it's been a while but I think it's just a division) before calculating position/rotation. This is basically why it's a good idea to avoid scale!
     
    Last edited: May 3, 2021