Search Unity

Bug float4x4.TRS does TSR instead

Discussion in 'Entity Component System' started by Jasper-Flick, Aug 25, 2022.

  1. Jasper-Flick

    Jasper-Flick

    Joined:
    Jan 17, 2011
    Posts:
    959
    The float4x4.TRS method applies scale on top of rotation instead of the other way around. This makes no difference for uniform scaling but makes a big difference for non-uniform scaling.

    Code (CSharp):
    1.  public static float4x4 TRS(float3 translation, quaternion rotation, float3 scale)
    2.         {
    3.             float3x3 r = float3x3(rotation);
    4.             return float4x4(  float4(r.c0 * scale.x, 0.0f),
    5.                               float4(r.c1 * scale.y, 0.0f),
    6.                               float4(r.c2 * scale.z, 0.0f),
    7.                               float4(translation, 1.0f));
    8.         }
    The indicated TRS transformation matches Unity's GO transformation matrix behavior. The actual TSR transformation does not.

    My suggestion is to make TRS perform the indicated transformation and add a high-performance variant with a float scale parameter for uniform scaling.

    Code (CSharp):
    1.     // Current unexpected behavior.
    2.     [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3.     public static float4x4 TSR (float3 translation, quaternion rotation, float3 scale) {
    4.         float3x3 r = float3x3(rotation);
    5.         return float4x4(float4(r.c0 * scale.x, 0.0f),
    6.         float4(r.c1 * scale.y, 0.0f),
    7.         float4(r.c2 * scale.z, 0.0f),
    8.         float4(translation, 1.0f));
    9.     }
    10.  
    11.     // Correct expected behavior.
    12.     [MethodImpl(MethodImplOptions.AggressiveInlining)]
    13.     public static float4x4 TRS (float3 translation, quaternion rotation, float3 scale) {
    14.         float3x3 m = mul(Unity.Mathematics.float3x3.Scale(scale), float3x3(rotation));
    15.         return float4x4(float4(m.c0, 0.0f),
    16.         float4(m.c1, 0.0f),
    17.         float4(m.c2, 0.0f),
    18.         float4(translation, 1.0f));
    19.     }
    20.  
    21.     // Optimized for uniform scale.
    22.     [MethodImpl(MethodImplOptions.AggressiveInlining)]
    23.     public static float4x4 TRS (float3 translation, quaternion rotation, float scale) {
    24.         float3x3 r = float3x3(rotation);
    25.         return float4x4(float4(r.c0 * scale, 0.0f),
    26.         float4(r.c1 * scale, 0.0f),
    27.         float4(r.c2 * scale, 0.0f),
    28.         float4(translation, 1.0f));
    29.     }
     
    Krajca, Occuros, tonytopper and 5 others like this.
  2. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    226
    Thanks for taking the time to post about this! And for providing a function to fix it.

    I've been scratching my head wondering what the heck was going on with these AABBs I was trying to TRS inside a job. "Why is the Y size so small!?", I was saying.

    I imagine this is the culprit.