PDA

View Full Version : Is it possible to extract rotation,translation,scale given a matrix?



remedios79
04-16-2004, 05:27 AM
Hi all,

I'm thinking about calculating the transformations I applied to my modelview matrix at a certain point of the elaboration... is there a clean way to find rotation, translation and scale given a matrix retrieved with glGet(GL_MODELVIEW_MATRIX)?

The real question is: is it possible? I mean, I can think that the solution won't be unique, but I need only a good one!

Thanks,

Remedios

V-man
04-16-2004, 07:03 AM
Yes, do a search for matrix decomposition.

The way I do it that I assume the transforms are in a certain order which leads to that matrix :

translate
rotate_about_Z
rotate_about_Y
rotate_about_X

something like that.
It works fine but for other more complex transforms, it's simply not possible to solve.

remedios79
04-16-2004, 07:53 AM
I found the code of Graphic Gems... but I wonder if it works always, or just in some cases... what do you think?

Remedios

plasmonster
04-17-2004, 04:48 PM
V-man is right. You have to make certain assumptions about the order of transformations; but even then, rotations are inherently ambiguous, as there is always more that one sequence of rotations to achieve a desired basis. This is where your knowledge of the order of transforms comes in handy.

Here's some code that assumes the order is
yaw(z), pitch(y), roll(x):


void columnMatrixToAngles( Angles& angles, float colMatrix[4][4] )
{
double sinPitch, cosPitch, sinRoll, cosRoll, sinYaw, cosYaw;

sinPitch = -colMatrix[2][0];
cosPitch = sqrt(1 - sinPitch*sinPitch);

if ( abs(cosPitch) > EPSILON )
{
sinRoll = colMatrix[2][1] / cosPitch;
cosRoll = colMatrix[2][2] / cosPitch;
sinYaw = colMatrix[1][0] / cosPitch;
cosYaw = colMatrix[0][0] / cosPitch;
}
else
{
sinRoll = -colMatrix[1][2];
cosRoll = colMatrix[1][1];
sinYaw = 0;
cosYaw = 1;
}

angles.yaw = atan2(sinYaw, cosYaw) * 180 / PI;
angles.pitch = atan2(sinPitch, cosPitch) * 180 / PI;
angles.roll = atan2(sinRoll, cosRoll) * 180 / PI;
}

remedios79
04-18-2004, 07:45 AM
I'm not understanding...

This is what I need to do:

I'm displaying a hierarchy of objects, and to do this I push matrixes in the stack while I'm going down in the hierarchy, and pop then when I go up.

Then (let's say I'm in a leaf of my hierarchy), I want to take the accumulated matrix and store it, then retrieve the translation or the rotation or the scale in that matrix.

I need to do this because I have to perform some calculation with this info (like I have 3 matrixes, and I want to find the baricenter of their translation).

Another way to achieve my goal is to accumulate the transformation while I go through the hierarchy, but it looks even more difficult, and I don't really know how to do it.

So, I was thinking if there is a way to retrieve the info I need from the final matrix.

I tried with the algorithm of Graphic Gems
Graphic Gems (http://http://www1.acm.org/pubs/tog/GraphicsGems/gemsii/unmatrix.c)
but the matrix come out to be singular... that shouldn't be!

So... no idea... :(
Thank you,
Remedios

capn_midnight
04-18-2004, 08:35 AM
say M is your matrix, then M has the form:

[sXr11 r12 r13 t1]
|r21 sYr22 r23 t2|
|r31 r32 sZr33 t3|
[ 0 0 0 1]extracting the translate is easy, you multiply M by a matrix A and add the Identity Matrix, A is of the form

[ 0 0 0 1]
| 0 0 0 1|
| 0 0 0 1|
[ 0 0 0 0]extracting the scale and rotate is a little more difficult. Instead of trying to treat the rotate as 3 individual rotates in the component axises, treat it as a single rotation about an arbitrary axis. That's all I have for now, check out mathworld (http://mathworld.wolfram.com)

remedios79
04-18-2004, 11:17 PM
That sounds good! :)

I check the math website, but I found nothing useful to retrieve the rotation and scale transformation... I will go on checking.

However this is exactly what I need!

If you have any hints about rotation and scale, just let me know.

Thank you,
Remedios

capn_midnight
04-19-2004, 04:02 AM
like I said, extracting the rotate and the scale from the matrix is a problem of a whole different level. To begin, your scale matrix is of the form

[sx 0 0 0]
| 0 sy 0 0|
| 0 0 sz 0|
[ 0 0 0 1]which is simple enough, however, your rotation has the form:

[ ax*ax*(1-c)+c ax*ay*(1-c)+az*s ax*az*(1-c)-ay*s 0]
|ax*ay*(1-c)-az*s ay*ay*(1-c)+c ay*az*(1-c)+ax*s 0|
|ax*az*(1-c)+ay*s ay*az*(1-c)-ax*s az*az*(1-c)+c 0|
[ 0 0 0 1]where (ax, ay, az) defines a unitized axis of rotation, and c and s are the cosine and sine of the angle of rotation.
Now, depending on the order in which you originally multiplied your matrix, this could result in two different matrices:
R*S


|SxRyx SyRyy SzRyz 0|
|SxRzx SyRzy SzRzz 0|
[ 0 0 0 1]


S*R

[SxRxx SxRxy SxRxz 0]
|SyRyx SyRyy SyRyz 0|
|SzRzx SzRzy SzRzz 0|
[ 0 0 0 1]I hope you can see and appreciate the subtle difference between the two.

The problem is, there are so many unknown values in the equations (i.e. ALL of them). With the translate, it was sitting out their all by itself, only one unknown value. But here, there are so many more, it's probably impossible.

remedios79
04-19-2004, 05:15 AM
Searching in the net I found a couple of interesting things:

This is an algorithm to do exactly what I need, as you suggested it extract first the translation info and then decompose the scale and rotation:

Matrix decomposition (http://www.geocrawler.com/archives/3/297/1998/10/50/1668476/)

The algorithm uses a well known algebrical decomposition called Singular Value Decomposition.
I found many link about that, the most interesting are the following:
MathWorld (http://mathworld.wolfram.com/SingularValueDecomposition.html)
Math (http://www.uwlax.edu/faculty/will/svd/svd/index.html)
SVDCode (http://www.cs.caltech.edu/~arvo/software.html)
The last link is great, there is a lot of math code, I'm trying to check if it works.

So, I think I need to implement (or to use) the SVD algorithm.
It would be great! :)

Maybe this is the solution...