Sign in to follow this  

Transformatrix matrix question

This topic is 4571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Anyone know if its possible to pull out the rotation and scale info out of a given 4x4 affine transformation matrix? I want to take a matrix and break it into scale factors, translation info, and euler angles (or a quaternion) Thanks!

Share this post


Link to post
Share on other sites
Well, on a column mayor matrix such as the one OpenGL uses, if you define your matrix as

float matrix[16];

Translation is (matrix[12],matrix[13],matrix[14])(I am sure), scale is (matrix[0],matrix[5],matrix[10]) (I think).

rotation gets more complicated, IIRC, Matrix to Quaternion conversion is more complicated than Quaternion to matrix, and its not used much, personally, I dont do scaling in my engine, and keep a 4x4 transform matrix along with a quaternion for my entities, I manipulate the translation values directly and then apply the quaternion Matrix to the 3x3 part of the transform matrix, then use glMultMatrixf() before rendering.

Share this post


Link to post
Share on other sites
yeah, translations are not hard to get out, but I dont think you can pull out scales like that since those elements in the transformation matrix would not be purely scales if the matrix also represented a rotation.

Share this post


Link to post
Share on other sites
yes, I guess there is no way, the only option would be having a matrix for translation, one for scaling and a quaternion for rotation, then multiply them together to get the final transfromation matrix, kind of a memory costly backwards approach.

Share this post


Link to post
Share on other sites
I'm only 99% sure of this:


SxR11 SyR21 SzR31 Tx
SxR12 SyR22 SzR32 Ty = TSR
SxR13 SyR23 SzR33 Tz
0 0 0 1

1 0 0 Tx
T = 0 1 0 Ty
0 0 1 Tz
0 0 0 1

Sx 0 0 0
S = 0 Sy 0 0
0 0 Sz 0
0 0 0 1

R11 R21 R31 0
R = R12 R22 R32 0
R13 R23 R33 0
0 0 0 1


Translation: simply use the values in the 4th column.
Scale: The length of each of the basis vectors is the scale factor for that axis.
Rotation: Normalize the basis vectors.

Share this post


Link to post
Share on other sites
yeah, along the diagonals the entries would look something like
sin(x)cos(x)*scaleFactor

(probably more complicated but composed of scalars, sines and cosines..)

Which would mean solving an equation like sin(x)*cos(x)*scaleFactor = y
for x and scaleFactor....anyone know of a clever way to figure this out?

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
I'm only 99% sure of this:




1 0 0 Tx
T = 0 1 0 Ty
0 0 1 Tz
0 0 0 1

Sx 0 0 0
S = 0 Sy 0 0
0 0 Sz 0
0 0 0 1

R11 R21 R31 0
R = R12 R22 R32 0
R13 R23 R33 0
0 0 0 1


Translation: simply use the values in the 4th column.
Scale: The length of each of the basis vectors is the scale factor for that axis.
Rotation: Normalize the basis vectors.



Good idea!

Just to make sure I understand tho, the basis vectors are the first 3 columns of SR? (or are they the first three rows?)

Share this post


Link to post
Share on other sites
Quote:
Just to make sure I understand tho, the basis vectors are the first 3 columns of SR? (or are they the first three rows?)
It depends. In OpenGL it's the columns, in D3D the rows. However, since OpenGL is column-major and D3D row-major, the entries are the same:

x = [0 1 2]
y = [4 5 6]
z = [8 9 10]

If you're not using an API and don't know whether your matrix uses row or column vectors, just check the matrix code to see where the translation vector goes. With column vectors it'll be in the right column, with row vectors the bottom row.

Share this post


Link to post
Share on other sites
There are simpler methods for special cases, however Ken Shoemake's decomp_affine() can handle the general case. It extracts:

typedef struct {
HVect t; /* Translation components */
Quat q; /* Essential rotation */
Quat u; /* Stretch rotation */
HVect k; /* Stretch factors */
float f; /* Sign of determinant */
} AffineParts;

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Quote:
Just to make sure I understand tho, the basis vectors are the first 3 columns of SR? (or are they the first three rows?)
It depends. In OpenGL it's the columns, in D3D the rows. However, since OpenGL is column-major and D3D row-major, the entries are the same:

x = [0 1 2]
y = [4 5 6]
z = [8 9 10]

If you're not using an API and don't know whether your matrix uses row or column vectors, just check the matrix code to see where the translation vector goes. With column vectors it'll be in the right column, with row vectors the bottom row.


The rows and columns make up two different orthonormal basis vector sets. Depending on row/column convention, only one interpretation is geometric. Thus, (not sure if I'm going against convention, but) I consider the basis vectors to be the vectors that make up the geometric orthonormal basis, and can be drawn on screen as simple vectors. For example, a lookAt* matrix will point the z basis vector at the target (+/- depending on left/right handedness). Thus, the geometric basis vectors that make up a lookAt matrix are directly inserted into the appropriate rows/columns of a matrix depending on row/column orientation. The same concept can be used to move or rotate an object (along/around the local principle axies) by extracting the appropriate rows/columns from an orientation (rotation) matrix.

The geometric orthonormal basis vectors are always transposed from the row/column orientation. For a column oriented matrix, the rows are the geometric orthonormal basis vectors, for a row oriented matrix, the columns are the geometric orthonormal basis vectors.

See also my comments here.

Edit per jyk's comments below:

*lookAt matrix defined as a matrix that orients an object (defined in local space) towards a target in world space. To use a lookAt matrix as a view matrix, it would be transposed (inverted).

[Edited by - John Schultz on May 24, 2005 4:02:50 PM]

Share this post


Link to post
Share on other sites
Following on John's post, here's some futher clarification:

Whether you want the rows or columns is determined not only by row or column vector convention, but by whether your matrix is a 'forward' (object) or 'reverse' (view) transform.

For an object (local-to-parent) transform, the geometric basis vectors are the rows (for row vectors) or columns (for column vectors). The translation vector is simply the bottom row (row vectors) or right column (column vectors).

For a view (parent-to-local) transform, the geometric basis vectors are the columns (for row vectors) or rows (for column vectors), that is, the upper-left 3x3 matrix is the transpose of its local-to-parent counterpart (we're ignoring non-uniform scale for the moment). The translation vector is no longer simply the right column or bottom row, but can be derived if needed.

So to extract the basis vectors you need to know a) if the library uses row or column vectors, b) whether the matrix is a local-to-parent or parent-to-local transform, and, for matrices stored as a 1d array, c) whether the matrix is row- or column-major.

If I got any of that wrong, corrections or clarifications are welcome.

Share this post


Link to post
Share on other sites
Quote:

In the case one does not know if the system is row or column oriented, left or right handed, it's easy to figure out: it's either the row or the column (x,y,z), and +/- the extracted z direction vector.


Again, more info here.

jyk,

When not discussing concatenated matrices, I would describe an object matrix as local-to-world, and a view matrix as world-to-local, as the view matrix "transforms the world around us into our local view".

local-to-parent/parent-to-local makes sense when talking about concatenated matrix transforms. Thus, to draw an object in the world, the rendering matrix is a concatenation of the local matrix (put into world space) and the view matrix (put into the local view space of the camera).

In the case of a compound object, such as a tank turret, the turret is first rotated around the local up axis, then the tank chassis transform is concatenated (parent to the turret), and finally the view matrix is concatenated (a parent by order, but not by structure), allowing the turret to be drawn in the correct location.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Thanks for all the info guys,

[QUOTE]
So to extract the basis vectors you need to know a) if the library uses row or column vectors, b) whether the matrix is a local-to-parent or parent-to-local transform, and, for matrices stored as a 1d array, c) whether the matrix is row- or column-major.
[/QUOTE]

In the context of the matricies I'm getting, they use column vectors and are local-to-parent.

I have one more question. I'm normalize the basis vectors, and sticking them back into a matrix, giving me a pure rotational matrix. Say I want to convert these into Euler angles in the order XYZ. Does this mean I should factor the matrix into Rx*Ry*Rz or the reverse since I've got column vectors?

Rx*Ry*Rz*v would mean the z rotation gets applied first right?

Share this post


Link to post
Share on other sites
Quote:
Rx*Ry*Rz*v would mean the z rotation gets applied first right?
Right. So you have to decide whether XYZ means order of multiplication (from left to right), or order of application. If the former, you factor as Rx*Ry*Rz; if the latter, Rz*Ry*Rx.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Right. So you have to decide whether XYZ means order of multiplication (from left to right), or order of application. If the former, you factor as Rx*Ry*Rz; if the latter, Rz*Ry*Rx.


Awesome, thanks again

Share this post


Link to post
Share on other sites
It just occurs to me that if you take the length of the basis vectors as your scale factors you will not be able to tell if your original scales were positive or negative. Is there a quick way to figure this out?

Share this post


Link to post
Share on other sites

This topic is 4571 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this