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.

`````` public static float4x4 TRS(float3 translation, quaternion rotation, float3 scale)
{
float3x3 r = float3x3(rotation);
return float4x4(  float4(r.c0 * scale.x, 0.0f),
float4(r.c1 * scale.y, 0.0f),
float4(r.c2 * scale.z, 0.0f),
float4(translation, 1.0f));
}
``````

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.

``````    // Current unexpected behavior.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float4x4 TSR (float3 translation, quaternion rotation, float3 scale) {
float3x3 r = float3x3(rotation);
return float4x4(float4(r.c0 * scale.x, 0.0f),
float4(r.c1 * scale.y, 0.0f),
float4(r.c2 * scale.z, 0.0f),
float4(translation, 1.0f));
}

// Correct expected behavior.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float4x4 TRS (float3 translation, quaternion rotation, float3 scale) {
float3x3 m = mul(Unity.Mathematics.float3x3.Scale(scale), float3x3(rotation));
return float4x4(float4(m.c0, 0.0f),
float4(m.c1, 0.0f),
float4(m.c2, 0.0f),
float4(translation, 1.0f));
}

// Optimized for uniform scale.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float4x4 TRS (float3 translation, quaternion rotation, float scale) {
float3x3 r = float3x3(rotation);
return float4x4(float4(r.c0 * scale, 0.0f),
float4(r.c1 * scale, 0.0f),
float4(r.c2 * scale, 0.0f),
float4(translation, 1.0f));
}
``````
8 Likes

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.