1
\$\begingroup\$

As the title says I need to decompose 4x4 TRS transformation matrices and extract the proper scale vectors and the proper rotation vectors (or rotation quaternions).

I know how to extract those information when the upper 3x3 matrix determinant is not negative. The problem is that those matrices can have that negative determinant and as far as I could understand, this negative determinant indicates a flip or mirrored transformation.

What do I have to do to extract the proper values for scale and rotation in those cases?

\$\endgroup\$
6
  • \$\begingroup\$ This situation is ambiguous, unfortunately. You can detect that the object has flipped (swapped chirality) but you can't detect on which axis it was flipped. Every combination of "Flip on axis A, then rotate by quaternion Q" can be expressed equivalently as "Flip on axis B, then rotate by quaternion R". So we can't extract "the one true rotation and scale triplet" - just some equivalent rotation and scale triplet. Is that sufficient for your needs, or do you have any conventions in your situation we could use to choose between these equivalent options? \$\endgroup\$ – DMGregory Nov 18 '20 at 16:01
  • \$\begingroup\$ @DMGregory that would be perfectly fine to have an equivalent rotation and scale. I don't need to exact original values, just ones that gives me the same transformation. Is that possible? \$\endgroup\$ – andresantacruz Nov 18 '20 at 16:44
  • 1
    \$\begingroup\$ Yes. Please see existing answers here, which cover this case. \$\endgroup\$ – DMGregory Nov 18 '20 at 16:52
  • \$\begingroup\$ @DMGregory I just read your other answer. Very nicely explained! Although I'm wondering why I can't find suitable library functions that can do that matrix decomposition. Maybe I didn't use the right terms googling it. May you suggest terms I could search to find libraries that can decompose a TRS matrix with possible negative scalar? \$\endgroup\$ – andresantacruz Nov 18 '20 at 20:33
  • 1
    \$\begingroup\$ I don't know of any particular library or keywords to recommend. But it seems like you could implement this yourself if so needed, no? Did you run into any snags in this that we can help you overcome? \$\endgroup\$ – DMGregory Nov 18 '20 at 20:37
1
\$\begingroup\$

Reopened this to give you a Unity implementation of the method described in the Q&A I linked above:

public static class MatrixHelpers
{
    public static Vector3 GetTranslation(this Matrix4x4 matrix) { 
        return matrix.GetColumn(3); 
    }

    public static bool TryGetRotation(this Matrix4x4 matrix, out Quaternion rotation) {
        Vector3 forward = matrix.GetColumn(2);
        if (forward.sqrMagnitude == 0f) {
            rotation = Quaternion.identity;
            return false;
        }

        Vector3 up = matrix.GetColumn(1);
        if (up.sqrMagnitude == 0f) {
            rotation = Quaternion.LookRotation(forward);
            return false;
        }

        rotation = Quaternion.LookRotation(forward, up);
        return true;
    }

    public static bool TryDecomposeTRS(this Matrix4x4 matrix, 
           out Vector3 translation, out Quaternion rotation, out Vector3 scale) {
        translation = matrix.GetTranslation();
        scale = matrix.lossyScale;

        return (matrix.TryGetRotation(out rotation) && matrix.ValidTRS());
    }
}

With this you can write:

if (!someMatrix.TryDecomposeTRS(out Vector3 t, out Quaternion r, out Vector3 s)) {
    Debug.LogWarning("Input matrix was not in TRS form."
                     + " It may include shear or projection."
                     + " Results will be approximate.");
}
// TODO: Do something useful with the decomposed translation, rotation, and scale.

You can probably see why there's not much in the way of external libraries for this - you can do everything you need in just a few lines with the built-in Unity types.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.