Transformatrix matrix question

Started by
14 comments, last by indigox3 18 years, 10 months ago
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!
Advertisement
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.
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.

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.
I'm only 99% sure of this:

SxR11 SyR21 SzR31 TxSxR12 SyR22 SzR32 Ty  = TSRSxR13 SyR23 SzR33 Tz  0    0    0   1        1  0  0  TxT = 0  1  0  Ty    0  0  1  Tz    0  0  0  1        Sx 0  0  0S = 0  Sy 0  0    0  0  Sz 0    0  0  0  1        R11 R21 R31 0R = 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.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
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?
Quote:Original post by JohnBolton
I'm only 99% sure of this:

        1  0  0  TxT = 0  1  0  Ty    0  0  1  Tz    0  0  0  1        Sx 0  0  0S = 0  Sy 0  0    0  0  Sz 0    0  0  0  1        R11 R21 R31 0R = 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?)
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.
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;
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]

This topic is closed to new replies.

Advertisement