Cacks 179 Report post Posted March 4, 2006 Hi guys, I'm having trouble with my object rotations. When I rotate my objects a few times they become increasingly more deformed out of shape. I store a single 4x4 matrix for each of my objects objects, called "transformationMatrix". This matrix describes their position & orientation. I'm using OpenGL, So the matrix indexes are: 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15 I render each object like this: glPushMatrix(); //multiply the current matrix by my transformation matrix glMultMatrixf(transformationMatrix.matrix); RenderObject... glPopMatrix(); Translate like this: void Brick::translateBrick(float _x, float _y, float _z) { Matrix4x4 multMatrix; multMatrix.matrix[12] = _x; //x-axis multMatrix.matrix[13] = _y; //y axis multMatrix.matrix[14] = _z; transformationMatrix = transformationMatrix * multMatrix; } Rotate like this: //I pass a normalised vector which is 1 of my camera axis void Brick::rotate(BrickRotation rotationType, SceneVector3 axis) { float x = axis.x; float y = axis.y; float z = axis.z; float r = 1.0f-cos(rotationAng); //rotationAng = rotation Angle float c = cos(rotationAng); float s = sin(rotationAng); float t = 1.0f - c; Matrix4x4 rotationMarix(t*x*x+c, t*x*y-s*z, t*x*z+s*y, 0, t*x*y+s*z, t*y*y+c, t*y*z-s*x, 0, t*x*z-s*y, t*y*z+s*x, t*z*z+c, 0, 0 , 0 , 0 , 1); transformationMatrix = transformationMatrix*rotationMarix; } Can any1 see where Im going wrong? Thanks for any help given! 0 Share this post Link to post Share on other sites
someusername 427 Report post Posted March 4, 2006 I can't understand some openGL syntax, however the effect you describe (objects being skewed) comes from the fact that the axes in the final model/world matrix are not exactly unit vectors. Try normalizing all axes before plugging them in matrices, even those that should obviously be unit vectors. (e.g. cross products of already normalized vectors) Even do it each frame, for each object, if you have to...Another thing I noticed (2nd snippet) is that, you use an un-initialized matrix to multiply by the current one... this will be catastrophic in the release build.Furthermore, you don't even set the major diagonal to "1"s. This way, you don't "pass" the translation into the matrix, you just set its first three columns to zero.I don't think I see any other potential problems, but as I said I can only make assumptions about the openGL syntax...edit:Quote:This way, you don't "pass" the translation into the matrix, you just set its first three columns to zero.Ignore this. This is the case with DX multiplication. Still, though, you won't get the desired result 0 Share this post Link to post Share on other sites
Cacks 179 Report post Posted March 4, 2006 Hi someusername,when I declare my transformationMatrix, I get it's constructor to intialise it all to zero then make it an identity matrix by adding 1's in the correct place. Should I be re-initialising it somewhere else? or is that what u meant?Thanks for the help! 0 Share this post Link to post Share on other sites
someusername 427 Report post Posted March 4, 2006 oops... I didn't realize it was your own class... :)I'm sorry, I don't see anything weird...Quote:When I rotate my objects a few times they become increasingly more deformed out of shapeAs I said, I can only interpret this as vectors passed for axes into matrices, that are not either precisely mutually perpendicular, or precisely unit vectors...I'm afraid I can't help you with this... 0 Share this post Link to post Share on other sites
Cacks 179 Report post Posted March 4, 2006 Thanks for the help, I will investigate my axis calculations! 0 Share this post Link to post Share on other sites
someusername 427 Report post Posted March 4, 2006 Don't mention it... To begin with, make sure that the determinants of all world matrices are as equal to 1.f as they can get, and most importantly, that there is no numerical error accumulating in the matrices, from repeated calculations that result to loss of precision. 0 Share this post Link to post Share on other sites
haegarr 7374 Report post Posted March 4, 2006 Please notice that the limited numerical resolution will in general prevent you from passing a perfect rotation basis. Importantly, you concatenate the partial transformation matrices to the global one over and over again. That will introduce errors into the global matrix in two ways: The basis vectors may become scaled (say no longer being of unit length) and they may become non-orthogonal. As soon as one or both of this happens the matrix will no longer provide a proper rotation but a rotation/scaling/shearing combination. It is not a question whether this happens but when.So, if you follow this way, you have to do 2 things from time to time: Re-normalize the basis column vectors of transformationMatrix.matrix and re-orthogonalize them.EDIT: someusername has written it ~40 seconds earlier ;) 0 Share this post Link to post Share on other sites
Cacks 179 Report post Posted March 4, 2006 So to Re-normalize the basis column vectors I would just normalise each of them like I would a vector?Then to re-orthogonalize them take their cross products once more? 0 Share this post Link to post Share on other sites
jyk 2094 Report post Posted March 4, 2006 Quote:Original post by CacksSo to Re-normalize the basis column vectors I would just normalise each of them like I would a vector?Then to re-orthogonalize them take their cross products once more?Here's a quick and easy way to orthogonalize:// Extract the basis vectors intro three vector objects, x, y and znormalize(z);x = normalize(cross(y,z));y = cross(z,x);// Load the basis vectors back into the matrixIf numerical drift is the only problem you're having, this should take care of it. (There are other ways to orthogonalize that have different characteristics, but the above should suffice.) 0 Share this post Link to post Share on other sites
haegarr 7374 Report post Posted March 4, 2006 Quote:Original post by CacksSo to Re-normalize the basis column vectors I would just normalise each of them like I would a vector?Yep. The vectors denotes by the indices {0,1,2}, {4,5,6}, and {8,9,10} when following your above index scheme. Notice that this is good only if you actually don't use scaling/shearing, or course.Quote:Original post by CacksThen to re-orthogonalize them take their cross products once more?You could assume that the basis is close to orthogonality. So, computing the new z basis vector as the cross product of the old x and y, and then the new y vector as the cross product of the new z and old x basis vector should do the job.There are more complex methods out there, but perhaps the above one is sufficient.EDIT: Damned. It seems I'm too late a second time in this thread :/ 0 Share this post Link to post Share on other sites
someusername 427 Report post Posted March 4, 2006 seems like it's not your day, haegarr :)Oh, and btw, thanks for clarifying the part on scaling the axes to scale the model. The discussion begun with rotations and I totally neglected to mention that later on 0 Share this post Link to post Share on other sites
Cacks 179 Report post Posted March 4, 2006 That has worked great!but each time I rotate one of my objects they translate back to the origin. Should I hold my translation co-ordinates seperate from my rotation matrix. Currently I am using one matrix to hold both translation and rotation.Thanks for the help! 0 Share this post Link to post Share on other sites
haegarr 7374 Report post Posted March 4, 2006 You have to be aware of what happens if you multiply a combined rotation/translation matrix with another rotation or translation. E.g. a concatenated rotation will be done around the position denoted by the combined matrix. That may or may not be what you desire. If you want local rotations you have to embrace the new rotation by translations to do a position correction.However, it seems that you drop the homogeneous part in your matrix multiplication routine? The 1 at index 15 in your indexing scheme is responsible for preserving the translation. Please post your matrix class routines if you are not sure. 0 Share this post Link to post Share on other sites
someusername 427 Report post Posted March 4, 2006 This is from you rotation snippet:Quote: Matrix4x4 rotationMarix(t*x*x+c, t*x*y-s*z, t*x*z+s*y, 0, t*x*y+s*z, t*y*y+c, t*y*z-s*x, 0, t*x*z-s*y, t*y*z+s*x, t*z*z+c, 0, 0 , 0 , 0 , 1); transformationMatrix = transformationMatrix*rotationMarix;This code should not "erase" the translation in "transformationMatrix". I don't know what the problem is, but ...Quote:Should I hold my translation co-ordinates seperate from my rotation matrix.this is generally a good idea, IMHO. 0 Share this post Link to post Share on other sites
haegarr 7374 Report post Posted March 4, 2006 Quote:Original post by someusernameQuote:Should I hold my translation co-ordinates seperate from my rotation matrix.this is generally a good idea, IMHO.I agree: A "rotation matrix" (if really defined as such) should have nothing to do with a translation (perhaps w/ the one exception of a free defineable rotation center).I personally has solved this simply by using different classes for the jobs:class Vector is for translation,class Rotation is for ... rotations, ahem, (also it implements a quaternion and not a matrix), andclass AffineMap is for the assembly of them (also considering scaling).So aRotation * Rotation =: Rotationsimply yields in another rotation (i.e. it is done like a local rotation), whileAffineMap * Rotation =: AffineMapactually will rotate around the current center (say the position stored inside the AffineMap).Analogously the translation and scaling is working locally as long as not applied to an AffineMap. 0 Share this post Link to post Share on other sites