space flight rotation with quaternions

Started by
5 comments, last by alvaro 13 years, 1 month ago
I've been searching around for a way to understand how to rotate a a mesh in 6dof without suffering from the issue described Here. So far that is the only thread that i've come across while googling around that approaches the problem i'm facing. I'm sure that if I were a bit more knowledgeable in these areas of math, i could figure it but alas I am not so i come before you all.

I'm currently messing around in mogre using a physx wrapper and i'm trying to get space flight working correctly. Just as in the thread that I linked above, once I rotate out of my initial orientation, the rest of my rotations continue to be based off of that initial orientation instead of coming from the new position.

Currently I adjust the angular velocity of my ship in a way that I know must be wrong but I'll show it anyways. pitchVAl yaw Val and rollVal are all floats between 0 and 1 that determine the pressure recieved from the joystick.

actorNodeList[0].actor.LinearVelocity = ((mEngine.Camera.DerivedDirection * 2000) * movespeed) * _frameTime;
actorNodeList[0].actor.AngularVelocity = (new Mogre.Vector3(pitchVal * -20, -20 * yawVal, -30 * rollVal)) * _frameTime;


Then after physx simulates the frame, I adjust my mesh using

sceneNode.Orientation = actor.GlobalOrientationQuaternion;

At first I had thought it was this second part that was causing my woes but after exploring around on here and in other places, I've come to believe that I'm feeding the angular velocity wrongly. I'm just unsure as to what math goes into getting the right information.
Advertisement
You need to extract the local coordinate axes from the object's rotation matrix. This is very simple as they are just the 3 component column vectors of the matrix. Now if you want the object to roll in local space, you just rotate the object around the local z axis. Note that the initial state of the rotation matrix is the identity matrix, indicating a non-rotated object where the local and world axes are the same.

It's important to know that quaternions are in no way required to implement this solution. They're merely a way of representing an axis-angle rotation. Your objective is to build a matrix that rotates an object x radians around a certain axis, and it doesn't matter how this matrix is formed. Your API will have functions that do this for you, with or without the use of a quaternion.





You need to extract the local coordinate axes from the object's rotation matrix. This is very simple as they are just the 3 component column vectors of the matrix. Now if you want the object to roll in local space, you just rotate the object around the local z axis. Note that the initial state of the rotation matrix is the identity matrix, indicating a non-rotated object where the local and world axes are the same.

It's important to know that quaternions are in no way required to implement this solution. They're merely a way of representing an axis-angle rotation. Your objective is to build a matrix that rotates an object x radians around a certain axis, and it doesn't matter how this matrix is formed. Your API will have functions that do this for you, with or without the use of a quaternion.


First off, thanks for the reply taz. I'm pretty sure that i understand what you're saying at least to some extent. At least in theory, but clearly my understanding of matrix math is very rusty as i'm still having a hard time grasping this.

My assumption is this. I need to first get the orientation matrix of the object that I want to rotate, M1 lets call it. then I need get the objects initial state matrix which is the identity, M2 we'll say. Then perform the desired rotation on M2 and then add M1 back into M2?

[
First off, thanks for the reply taz. I'm pretty sure that i understand what you're saying at least to some extent. At least in theory, but clearly my understanding of matrix math is very rusty as i'm still having a hard time grasping this.

My assumption is this. I need to first get the orientation matrix of the object that I want to rotate, M1 lets call it. then I need get the objects initial state matrix which is the identity, M2 we'll say. Then perform the desired rotation on M2 and then add M1 back into M2?


If Mi is the inital matrix, and M1 the matrix after the first rotation, you want the second rotation local to m1. So instead of using XYZ rotation matrices, you use an axis angle rotation instead. The axis you wish to rotate around for m2 can be gleaned from m1.


X.x X.y X.z 0
Y.x Y.y Y.z 0
Z.x Z.y Z.z 0
T.x T.y T.z 1


An X axis rotation would rotate along the Xaxis of the identity matrix, or V(1,0,0). what we want to do is rotate around the new Xaxis which would be stored in the first row of your DX matrix, or column if GL.


RotationMatrix *= AxisAngleRotation(RotationMatrix[0], Radians); // Build a rotation matrix using local X axis, and transform current orientation.
My assumption is this. I need to first get the orientation matrix of the object that I want to rotate, M1 lets call it. then I need get the objects initial state matrix which is the identity, M2 we'll say. Then perform the desired rotation on M2 and then add M1 back into M2?[/quote]

A matrix can represent a range of different transformations - position, rotation, scaling, etc. An object's "world matrix" is the result of applying all these operations to produce the final geometric state of the object in world space. To calculate this matrix, it's convenient to store the following information about each object:

Position vector
Scaling vector
Rotation matrix


To make the object rotate in local space, you extract the local z axis from the rotation matrix, and create a matrix which rotates x radians around this axis. You then multiply this matrix by the rotation matrix to yield the object's new rotation matrix. The order is API specific, with DirectX using left-to-right. Here's an example using a fictional API.


float rollAmount = Pi / 4; // Will rotate 45 degrees
Vec3 localZAxis = obj.rotationMatrix.getLocalZAxis(); // Extracts the first 3 values from the 3rd column vector of the matrix
Matrix4x4 roll = AxisAngleRotationMatrix(localZAxis, rollAmount); // Builds a matrix that rotates around the specified axis
obj.rotationMatrix = obj.rotationMatrix * roll; // Perform rotation (most c++ APIs overload the multiplication operator to perform matrix multiplication)


To render the object in it's correct position and correct size, you generally apply the transformations in the order: scaling, rotation, translation. Order is very important since rotation and scaling operate around the origin.


Matrix4x4 scaleM = ScalingMatrix(obj.scale);
Matrix4x4 translationM = TranslationMatrix(obj.position);
Matrix4x4 worldMatrix = scaleM * obj.rotationMatrix * translationM;
obj.render(worldMatrix);



Either i'm still woolheaded or maybe i didn't explain my issue well enough because i'm not sure how I take what you've shown me and apply it to my case. I'll re-explain and hopefully things might get cleared up. Again, thank you for taking the time to respond.

If I want to rotate my mesh around with 6dof, I can no problem and the issue that i have doesn't show itself. However, once I introduce my physics engine into it, the problems crop up. I simply feed physx a vector3 for angular velocity each frame. As I've discovered, that vector3 is based in worldspace and not local space relative to the object, so each frame, the rotation tends to get messed up as I am currently only calculating the vector based on an unrotated object.

So that being said, how does that you have shown me apply to my circumstances?
I'll give it a try. Pick either matrices or quaternions for representing rotations; you can convert this into whatever representation your Physics API wants when you call it. Keep a rotation that indicates the current attitude of your mesh. Perform small rotations on top of that one by composing the current rotation with a small rotation in the desired axis. The order in which you perform the composition matters, and if you get it wrong, you'll get the behavior you describe: So just reverse it!

This topic is closed to new replies.

Advertisement