# Transformatrix matrix question

## 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 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 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 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 on other sites
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.

##### 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 on other sites
Quote:
 Original post by JohnBoltonI'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?)

##### 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 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 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.

*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 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 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.

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 on other sites
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 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 on other sites
Quote:
 Original post by jykRight. 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 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?

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627636
• Total Posts
2978319

• 10
• 12
• 22
• 13
• 33