Translation & Rotation Matrix

Started by
13 comments, last by haegarr 18 years, 1 month ago
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!
Reject the basic asumption of civialisation especially the importance of material possessions
Advertisement
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
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!
Reject the basic asumption of civialisation especially the importance of material possessions
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 shape

As 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...
Thanks for the help, I will investigate my axis calculations!
Reject the basic asumption of civialisation especially the importance of material possessions
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.
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 ;)
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?
Reject the basic asumption of civialisation especially the importance of material possessions
Quote:Original post by Cacks
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?
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 matrix
If 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.)
Quote:Original post by Cacks
So 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 Cacks
Then 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 :/

This topic is closed to new replies.

Advertisement