0
\$\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
    Commented Nov 18, 2020 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\$ Commented Nov 18, 2020 at 16:44
  • 1
    \$\begingroup\$ Yes. Please see existing answers here, which cover this case. \$\endgroup\$
    – DMGregory
    Commented Nov 18, 2020 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\$ Commented Nov 18, 2020 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
    Commented Nov 18, 2020 at 20:37

1 Answer 1

2
\$\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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .