Sign in to follow this  
Quasius

Rotating around more than 1 global axis.

Recommended Posts

I know that matrix multiplication is not commutative. So if I make a rotation matrix for x, y, and z and multiply them together, the order I multiply them will make some of the rotations dependent on others. It ends up looking like only the last rotation is around the "global" axis. So how do I rotate some amount around the global x, then some amount around the global z instead of some amount around the global x, then some amount around the new local z? I doubt there's anything particularly interesting about it, but here's the code I'm currently using:
	//rotate the verts
	Vector3f v3fRotatedVert;
	Math3D::Matrix33 mat33X, mat33Y, mat33Z, mat33Rotation;

	//First, build the rotation matrix:
	//rotation about x
	mat33X.f22 = cos(m_v3fRotation.x);
	mat33X.f23 = sin(m_v3fRotation.x);
	mat33X.f32 = -mat33X.f23;
	mat33X.f33 = mat33X.f22;

	//rotation about y
	mat33Y.f11 = cos(m_v3fRotation.y);
	mat33Y.f31 = sin(m_v3fRotation.y);
	mat33Y.f13 = -mat33Y.f31;
	mat33Y.f33 = mat33Y.f11;

	//rotation about z
	mat33Z.f11 = cos(m_v3fRotation.z);
	mat33Z.f12 = sin(m_v3fRotation.z);
	mat33Z.f21 = -mat33Z.f12;
	mat33Z.f22 = mat33Z.f11;

	//combine into final rotation matrix
	Math3D::Matrix33Multiply(mat33X, mat33Y, mat33Rotation);
	Math3D::Matrix33Multiply(mat33Rotation, mat33Z, mat33Rotation);

	sf::Vector3f v3fVertCopy;
	for (int i = 0; i < m_nNumVerts; ++i)
	{
		Math3D::RotatePoint(m_vVertices[i], mat33Rotation);
	}


Share this post


Link to post
Share on other sites
Quote:
Original post by Quasius
So how do I rotate some amount around the global x, then some amount around the global z instead of some amount around the global x, then some amount around the new local z?


One word. Quaternions.

--smw

Share this post


Link to post
Share on other sites
God I get confused when I have to translate from D3D-matrices to OpenGL-matrices in my head. [smile]

Anyway if you apply a rotation by an axis before your other rotations, you will rotate around the global axis. So you need to switch the matrices in your second matrix multiply, so that the z-rotation is about the global z-axis.

Share this post


Link to post
Share on other sites
Just wanted to mention that although you certainly can use quaternions to get the effect that you're after, there's no need to do so.

In fact, I would recommend staying away from quaternions until you're comfortable manipulating rotations in matrix form.

[Edited by - jyk on May 14, 2008 7:19:04 AM]

Share this post


Link to post
Share on other sites
I'm still missing something here. Switching around the arguments for the second matrix multiply only changed the order of dependence. Even if I do it explicitly like this:

Math3D::Matrix33Multiply(mat33Rotation, mat33X, mat33Rotation);
Math3D::Matrix33Multiply(mat33Rotation, mat33Y, mat33Rotation);
Math3D::Matrix33Multiply(mat33Rotation, mat33Z, mat33Rotation);


I still get the same problem. That is the y rotation is relative to the z rotation and the x rotation is relative to the y and z rotation. Only z is on a "global" axis. If it's unclear, the arguments for the Matrix33Multiply function are (Matrix33& matrix1, Matrix33& matrix2, Matrix33& result).
Also, I tried this with quats and got the exact same behavior.
Maybe just tell me the general method for rotating about multiple global axes and I'll adjust my code to it?

Share this post


Link to post
Share on other sites
Quote:
Original post by Quasius
I'm still missing something here. Switching around the arguments for the second matrix multiply only changed the order of dependence. Even if I do it explicitly like this:

Math3D::Matrix33Multiply(mat33Rotation, mat33X, mat33Rotation);
Math3D::Matrix33Multiply(mat33Rotation, mat33Y, mat33Rotation);
Math3D::Matrix33Multiply(mat33Rotation, mat33Z, mat33Rotation);


I still get the same problem. That is the y rotation is relative to the z rotation and the x rotation is relative to the y and z rotation. Only z is on a "global" axis. If it's unclear, the arguments for the Matrix33Multiply function are (Matrix33& matrix1, Matrix33& matrix2, Matrix33& result).
I'm not exactly sure what effect you're after, but changing the order of rotation will only change which axis exhibits which behavior (in other words, there will always appear to be one 'local' rotation, one 'global' rotation, and one rotation about what appears to be an arbitrary axis).

If you don't want the rotations to be dependent on one another, you'll need to store the orientation between frames/updates and update it incrementally as you go. (Since I'm not sure what you're doing though I can't really be more specific - can you tell us what the context is? That is, what is the object that you want to rotate, and how do you want it to behave?)
Quote:
Also, I tried this with quats and got the exact same behavior.
Correct. Whether you use quaternions or matrices in this case makes absolutely no difference.

Share this post


Link to post
Share on other sites
Alright, I'll try to be more specific. I'm trying to make an editor that allows the user to place and orient a simple 3D primitive (box in this case). Since the game is actually isometric 2D, this is just for some internal 3D collision volumes. So I'm doing these 3D calculations "by hand" instead of using OpenGL. (Positioning/orienting the verts in internal 3D, then projecting to 2D screen coords.) Everything is working fine, except that it's nearly impossible to correctly orient the object when 2 of the axes are dependent on the others and appear to be changing/arbitrary axes instead of global x, y , and z.
I'm tracking a variable between frames, m_v3fRotation, that contains rotations between 0 and 2*PI for x, y, and z. So I need to take those 3 values and calculate an orientation matrix/quat/whatever that treats each of those values as rotations about a global axis. (I actually want to rotate around the y axis and then an axis straight into/out of the screen and a third perpendicular to that instead of using the isometric x and z that don't correlate intuitively to mouse movements. But that should just be some manipulations of the x and z axis at the same time if I can figure out how to rotate x, y, and z independently. So I don't think this is relevant to my question.)
Hopefully that was clearer for what I'm trying to do. Thanks.

Share this post


Link to post
Share on other sites
Do me a favor. Take a book, and place it on the desk in front of you, the front cover facing up. (Yeah, guys! It's one of Sneftel's book rotations! Gather 'round, y'all!)

Now some axes. I'm going to denote the book's local X axis as coming straight out of the edges of the pages opposite the spine, so (when the book is oriented like this) to the right. The global X axis is to the right. I'll denote the local Y axis as coming straight out of the cover, and the global Y axis as up. I'll denote the local Z axis as coming out of the bottom edges of the book, and the global Z axis as towards you. These are right-handed systems, BTW.

Now let's do two rotations: An X rotation and a Y rotation, both 90 degrees. Let's do them both globally and locally, and both X-then-Y and Y-then-X. Let's see where the book ends up.

Local X,Y: book standing on its spine on the desk, cover facing backwards towards you.
Local Y,X: book standing on edge on the desk, spine facing backwards towards you.
Global X,Y: book standing on edge on the desk, spine facing backwards towards you.
Global Y,X: book standing on its spine on the desk, cover facing backwards towards you.

As you can see, reversing the order of rotations is equivalent to switching between local and global axes. This works for any number and any types of affine transformations.

[Edited by - Sneftel on May 14, 2008 11:13:47 AM]

Share this post


Link to post
Share on other sites
Well, the good news is it works now. The bad news is I have no idea why and that makes me nervous. What worked was "If you don't want the rotations to be dependent on one another, you'll need to store the orientation between frames/updates and update it incrementally as you go" suggested by jyk.
I was actually shocked when it worked since I don't see how


Matrix33 IncrementalRot = GenerateRotationMatrixX(fAngle);
Matrix33Multiply(m_mat33Rotation, IncrementalRot, m_mat33Rotation);

...frame...

Matrix33 IncrementalRot = GenerateRotationMatrixZ(fAngle);
Matrix33Multiply(m_mat33Rotation, IncrementalRot, m_mat33Rotation);

...frame...

Matrix33 IncrementalRot = GenerateRotationMatrixX(fAngle);
Matrix33Multiply(m_mat33Rotation, IncrementalRot, m_mat33Rotation);

for (int i = 0; i &lt; nNumVerts; ++i)
{
RotatePoint(m_vVertices[i], m_mat33Rotation, m_vVertices[i]);
}



is different from


Matrix33 mat33X, mat33Z, mat33Rotation;

//rotation about x
mat33X.f22 = cos(2 * fAngle);
mat33X.f23 = sin(2 * fAngle);
mat33X.f32 = -mat33X.f23;
mat33X.f33 = mat33X.f22;

//rotation about z
mat33Z.f11 = cos(fAngle);
mat33Z.f12 = sin(fAngle);
mat33Z.f21 = -mat33Z.f12;
mat33Z.f22 = mat33Z.f11;

//combine into final rotation matrix
Matrix33Multiply(mat33Rotation, mat33X, mat33Rotation);
Matrix33Multiply(mat33Rotation, mat33Z, mat33Rotation);

for (int i = 0; i &lt; nNumVerts; ++i)
{
RotatePoint(m_vVertices[i], mat33Rotation, m_vVertices[i]);
}



Also, I looked at your post Sneftel. Isn't what you're doing just switching around which axis is dependent on another? When I was shuffling around rotation orders all I achieved was changing which axis was global, not making them all global. Or am I misunderstanding you? (I probably am.)
Thanks for your help, guys. I think I'm getting closer to wrapping my head around this...

Share this post


Link to post
Share on other sites
Quote:
Original post by Quasius
Also, I looked at your post Sneftel. Isn't what you're doing just switching around which axis is dependent on another? When I was shuffling around rotation orders all I achieved was changing which axis was global, not making them all global. Or am I misunderstanding you? (I probably am.)

You are misunderstanding me. Do the thing with the book. Like, with an actual book. This is not a thought experiment. Once you've done XY/YX rotations, try more complicated series of 90 degree rotations; say, +X,-Z,-Y in global space and -Y,-Z,+X in local space. I know the results are counterintuitive. That's why I'm telling you to use an actual, physical book.

Share this post


Link to post
Share on other sites

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