I have a transformation matrix that rotates and scales. Is there any easy way to disassemble it into the original rotation and scaling matrices?
For instance:
M = R * S;
// I need f and h such that
R = f(M); S = h(M);
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It only takes a minute to sign up.
Sign up to join this communityI have a transformation matrix that rotates and scales. Is there any easy way to disassemble it into the original rotation and scaling matrices?
For instance:
M = R * S;
// I need f and h such that
R = f(M); S = h(M);
As long as you're doing only uniform scaling, this is easy; you can simply extract each row (or column; it doesn't matter), of the 3x3 matrix. The scale factor will be the length of the row vector. If you normalize each row vector and construct a new matrix from the normalized rows, that will be the rotation part. (If you have a 4x4 matrix, you just do this to the upper-left 3x3 part.)
This can be done because uniform scaling commutes with rotation, and therefore the two can be cleanly separated. In fact, a matrix constructed from any sequence of rotations and uniform scales can be broken down into a single rotation and a single scale.
If you have nonuniform scaling, but it's done along the axes before any rotations are applied in the transformation chain, you can also extract that with the same technique as above; you just get the three axial scale factors from the lengths of each of the three rows or columns (depending which convention you use; here, it does matter).
The general case of an arbitrary combination of nonuniform scales and rotations can't be decomposed into a single rotation and a single scale, since nonuniform scaling doesn't commute with rotation in general. However, using singular value decomposition, a general linear transformation can be decomposed as a rotation, a nonuniform scale, and another rotation.
You can apply the transformation matrix to a point and calculate the orientation and the scale from it. This of course only works if there are no other transformations than that.
Vec2 scale;
Angle rotation;
Vec2 point(0, 1);
point = matrix.apply(point);
scale.Y = point.length();
rotation = AngleBetween(point, Vec2(0, 1));
Vec2 pointX(1, 0);
pointX = matrix.apply(pointX);
scale.X = pointX.length();
Though, it would be better if you just store the parameters alongside with the transformation and just read out that information when needed.
This is what I did. Please comment and vote if it's correct?
I had a 3d transform matrix that both scales and rotates a vector:
I took the vectors : \$(1, 0, 0); (0, 1, 0); (0, 0, 1)\$ (let's call them x1, y1, z1) and I multiplied the matrix by those vectors. I then intuitively checked their lengths much like API-Beast suggested.
So I figured the scaling Matrix is:
$$ \begin{pmatrix} Tx1.length & 0 & 0 \\ 0 & Ty1.length & 0 \\ 0 & 0 & Tz1.length \\ \end{pmatrix} $$
I then inverted this matrix (easily)
$$ \begin{pmatrix} \dfrac 1 {Tx1.length} & 0 & 0 \\ 0 & \dfrac 1 {Ty1.length} & 0 \\ 0 & 0 & \dfrac 1 {Tz1.length} \\ \end{pmatrix} $$
And if \$T = RS\$ then \$T(S^-1) = RS(S^-1) = R\$.