How to decompose a matrix44 to scale, rotation and translation?

Started by
7 comments, last by John Schultz 18 years, 1 month ago
Hi, I want to know how to decompose a matrix44 to scale, rotation and translation? Though I know how to compose these to a matrix. But it seems much more difficult to decompose a matrix.
Advertisement
Quote:Original post by zhouzhengchun
I want to know how to decompose a matrix44 to scale, rotation and translation? Though I know how to compose these to a matrix. But it seems much more difficult to decompose a matrix.
If you're using the DirectX library, I think there's a function available for this. Otherwise, if the order of transformation was scale->rotate->translate, it's fairly easy to do manually. The scale factors are the lengths of the basis vectors of the matrix. Once you have the lengths, you can normalize the vectors to get an orthonormal basis (the rotation matrix). The translation is unaffected by the concatenation and can simply be extracted directly from the matrix.

Anyway, I'm pretty sure that's right. You might try it and see if you get the expected results.
See the decomp_affine() links in this thread.

Decompose.c
Decompose.h

It might be helpful to add Matrix Decomposition (and links to Ken Shoemake's code) to the FAQ.
Quote:Original post by jyk
Otherwise, if the order of transformation was scale->rotate->translate, it's fairly easy to do manually. The scale factors are the lengths of the basis vectors of the matrix. Once you have the lengths, you can normalize the vectors to get an orthonormal basis (the rotation matrix).


If you know you have Y=S*R*X+T, where S is a diagonal matrix of scales, R is a rotation, and T is a translation, then you can figure out S, R, and T as you indicated. The problem is when you have a composition of such transformations. The translation is not a problem to figure out when you have Y=M*X+T. The decomposition of M = S*R, where S is a diagonal matrix and R is an orthogonal matrix, is not always possible. The best you can do is "polar decomposition", where S is a symmetric matrix that represents the scaling, but in a different coordinate system, or "singular value decomposition" M = L*D*R, where L and R are orthogonal and D is a diagonal matrix of nonnegative values (the diagonal terms are positive when M is invertible). The function decomp_affine() mentioned in another follow-up post essentially does this type of decomposition.

Quote:Original post by Wasting Time
Quote:Original post by jyk
Otherwise, if the order of transformation was scale->rotate->translate, it's fairly easy to do manually. The scale factors are the lengths of the basis vectors of the matrix. Once you have the lengths, you can normalize the vectors to get an orthonormal basis (the rotation matrix).


If you know you have Y=S*R*X+T, where S is a diagonal matrix of scales, R is a rotation, and T is a translation, then you can figure out S, R, and T as you indicated. The problem is when you have a composition of such transformations. The translation is not a problem to figure out when you have Y=M*X+T. The decomposition of M = S*R, where S is a diagonal matrix and R is an orthogonal matrix, is not always possible. The best you can do is "polar decomposition", where S is a symmetric matrix that represents the scaling, but in a different coordinate system, or "singular value decomposition" M = L*D*R, where L and R are orthogonal and D is a diagonal matrix of nonnegative values (the diagonal terms are positive when M is invertible). The function decomp_affine() mentioned in another follow-up post essentially does this type of decomposition.
Yes, my suggestion was just for the simple case of a single scale->rotate->translate sequence - I didn't mean to imply that it was a general solution (I think my post was fairly clear in that regard). In any case, the OP now has some options to choose from :)
Why should the order of individual -hardcoded- transformations, matter at all? (in finding the S/R/T components, that is)
And besides, I don't see the need for any sort of matrix decomposition here...

Let this be the world matrix:
[ m11  m12  m13  m14 ][ m21  m22  m23  m24 ][ m31  m32  m32  m34 ][  0    0    0     1 ]

then the origin (0, 0, 0, 1)T obviously maps to (m14, m24, m34, 1)T
The global X axis gX = (1, 0, 0, 0)T, maps to the scaled global X sgX=(m11, m21, m31, 0)T,

The global Y axis gY = (0, 1, 0, 0)T, maps to the scaled global Y sgY=(m12, m22, m32, 0)T, and similarly for global Z...

It is obvious now, that the scaling values are |sgX|, |sgY|, |sgZ|, the new orientation base is:
{sgX/|sgX|, sgY/|sgY|, sgZ/|sgZ|}, and the translation is {m14, m24, m34}.
The respective S/R/T matrices, can be constructed trivially from the above vectors and values, if they are *that* necessary...

edit:
changed the names of vectors (some were misleading)
Quote:Original post by someusername
Why should the order of individual -hardcoded- transformations, matter at all? (in finding the S/R/T components, that is)
And besides, I don't see the need for any sort of matrix decomposition here...


The order matters because matrix multiplication is not commutative. If you have nonuniform scaling S and rotation R, then generally R*S and S*R are different matrices.

When I said you need to worry about the composition of transformations, I meant the following. The first transformation is Y = S0*R0*X+T0. A second transformation applies to the output of the first, Z = S1*R1*Y+T1 = (S1*R1*S0*R0)X+(S1*R1*T0+T1) = M*X+T. It is easy enough to figure out what T is. However, M = S1*R1*S0*R0 cannot generally be decomposed into M = S*R. This was the point of my previous post. If you use a scene graph management system with a hierarchy of transformations, you run into this decomposition problem quite quickly.
Quote:Original post by someusername
It is obvious now, that the scaling values are |sgX|, |sgY|, |sgZ|, the new orientation base is:
{sgX/|sgX|, sgY/|sgY|, sgZ/|sgZ|}, and the translation is {m14, m24, m34}.
The respective S/R/T matrices, can be constructed trivially from the above vectors and values, if they are *that* necessary...
This is exactly what I described previously. However, it only works for a single (albeit common) case, whereas the decompositions suggested by the other posters are more general.

The OP did specify scale, rotation, and translation. He didn't specify the order, but I think S->R->T is a pretty good bet, which is why the aforementioned shortcut seems like a reasonable suggestion.
Quote:Original post by jyk
The OP did specify scale, rotation, and translation. He didn't specify the order, but I think S->R->T is a pretty good bet, which is why the aforementioned shortcut seems like a reasonable suggestion.


jyk's suggestion will work for the given special case. decomp_affine() will work for the general case (including extracting the scale rotation, which can be different from the rotation).

See Ken Shoemake's Matrix Animation and Polar Decomposition paper for more information. A link to this paper would also make a nice addition to the FAQ.

This topic is closed to new replies.

Advertisement