Sign in to follow this  

Translation & Rotation Matrix

This topic is 4300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ;)

Share this post


Link to post
Share on other sites
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 z
normalize(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.)

Share this post


Link to post
Share on other sites
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 :/

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by someusername
Quote:
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), and
class AffineMap is for the assembly of them (also considering scaling).

So a
Rotation * Rotation =: Rotation
simply yields in another rotation (i.e. it is done like a local rotation), while
AffineMap * Rotation =: AffineMap
actually 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.

Share this post


Link to post
Share on other sites

This topic is 4300 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this