indigox3 122 Report post Posted May 24, 2005 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! 0 Share this post Link to post Share on other sites
Kwizatz 1392 Report post Posted May 24, 2005 Well, on a column mayor matrix such as the one OpenGL uses, if you define your matrix asfloat 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. 0 Share this post Link to post Share on other sites
indigox3 122 Report post Posted May 24, 2005 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. 0 Share this post Link to post Share on other sites
Kwizatz 1392 Report post Posted May 24, 2005 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. 0 Share this post Link to post Share on other sites
JohnBolton 1372 Report post Posted May 24, 2005 I'm only 99% sure of this:S_{x}R_{11} S_{y}R_{21} S_{z}R_{31} T_{x}S_{x}R_{12} S_{y}R_{22} S_{z}R_{32} T_{y} = TSRS_{x}R_{13} S_{y}R_{23} S_{z}R_{33} T_{z} 0 0 0 1 1 0 0 T_{x}T = 0 1 0 T_{y} 0 0 1 T_{z} 0 0 0 1 S_{x} 0 0 0S = 0 S_{y} 0 0 0 0 S_{z} 0 0 0 0 1 R_{11} R_{21} R_{31} 0R = R_{12} R_{22} R_{32} 0 R_{13} R_{23} R_{33} 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. 0 Share this post Link to post Share on other sites
indigox3 122 Report post Posted May 24, 2005 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 = yfor x and scaleFactor....anyone know of a clever way to figure this out? 0 Share this post Link to post Share on other sites
indigox3 122 Report post Posted May 24, 2005 Quote:Original post by JohnBoltonI'm only 99% sure of this: 1 0 0 T_{x}T = 0 1 0 T_{y} 0 0 1 T_{z} 0 0 0 1 S_{x} 0 0 0S = 0 S_{y} 0 0 0 0 S_{z} 0 0 0 0 1 R_{11} R_{21} R_{31} 0R = R_{12} R_{22} R_{32} 0 R_{13} R_{23} R_{33} 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?) 0 Share this post Link to post Share on other sites
jyk 2094 Report post Posted May 24, 2005 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. 0 Share this post Link to post Share on other sites
John Schultz 811 Report post Posted May 24, 2005 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; 0 Share this post Link to post Share on other sites
John Schultz 811 Report post Posted May 24, 2005 Quote:Original post by jykQuote: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] 0 Share this post Link to post Share on other sites
jyk 2094 Report post Posted May 24, 2005 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. 0 Share this post Link to post Share on other sites
John Schultz 811 Report post Posted May 24, 2005 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. 0 Share this post Link to post Share on other sites
Guest Anonymous Poster Report post Posted May 26, 2005 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? 0 Share this post Link to post Share on other sites
jyk 2094 Report post Posted May 26, 2005 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. 0 Share this post Link to post Share on other sites
indigox3 122 Report post Posted May 26, 2005 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 0 Share this post Link to post Share on other sites
indigox3 122 Report post Posted June 9, 2005 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? 0 Share this post Link to post Share on other sites