## Mathematics for flying through a 3d space

I was hoping that someone else has succeeded because I'm having a few troubles. I'd love some advice, pointers to algorithms, tutorials or source code for examples.

My overall design basically tracks the players x,y,z location and their x,y,z angle/rotation. Is this how others do it?

Current algorithm/concept:

// Take the movement of the trackpad (DeltaHoriz and DeltaVert) to generate the change in X and Y Angles

deltaY = deltaHoriz*cos(Zrot * PI/180) + deltaVert*sin(Zrot * PI/180);

deltaX = deltaVert*cos(Zrot * PI/180) + deltaHoriz*sin(Zrot * PI/180);

(I know this is wrong, but its close and it works in some situations)

//Code to set the X and Y rotation, and cope with the transition over 360 degrees.

// Then theres the basic movement code to move the player based on their rotations (the boolean differentiates between forward and back which may be removed in future - who's ever heard of a spaceship flying backwards? )

if (Direction == true)

{

newX = X + sin(Yrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

newZ = Z - cos(Yrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

newY = Y - sin(Xrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

}

else

{

newX = X - sin(Yrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

newZ = Z + cos(Yrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

newY = Y + sin(Xrot * PI/180)*BASE_SPEED*Ind_SpeedModifier;

}

It's rather annoying - The trackpad code may work when the Zrot is up, but may be flipped at 90 degrees and fine when at 180 etc. So Im sure theres something wrong with my trackpad code's trig.

This one:

http://sacredsoftware.net/tutorials/Quat...ions.xhtml

was written by our resident tutorial writer "ThemsAllTook" -- if you have problems with it, he'll probably be around to help, at least

I found this page useful: http://www.ogre3d.org/wiki/index.php/Quaternion_and_Rotation_Primer

Correct me if I'm wrong, Im still grasping on how to apply this math to practical application: From what this tells me, is that I can use quaternions to choose an arbitrary vector and rotate on that vector (as opposed to only x y z). So what I need to do is store where the player is (in a vector), where they are pointing (in a quaternion?) and create a combined x, y and z quaternion for where they want to point. Using this quaternion create an opengl rotation matrix and then rotate the world?

Store where the player is (vector), their orientation (quaternion). Convert the inputs from Euler angles to quaternions, and multiply quaternions to get a new orientation. Convert the quaternion to a matrix for use with OpenGL.

Code:

` Vector temp;`

temp.x = 1;

temp.y = 0;

temp.z = 0;

Quaternion ChangeinX = QuaternionFromAxisAngle(temp, deltaVert);

temp.x = 0;

temp.y = 1;

temp.z = 0;

Quaternion ChangeinY = QuaternionFromAxisAngle(temp, deltaHoriz);

Quaternion NewOrient = QuaternionMultiply(&ChangeinX, &ChangeinY);

Orientation = QuaternionMultiply( &NewOrient, &Orientation);

I applied it as simply as I could but it doesnt seem to work. I did some cout debug statements after each, and it looks like the ChanginX, ChanginY are being created ok, NewOrient is being created, but when I look at the values for Orientation its always 0. Any ideas? Have I buggered it up?

(Orientation being created/defined elsewhere)

Once I started converting the trackpad input into radians it started to actually resemble a proper "looking around" function.

There is one strange problem though. As I look around there is an ever so slight change to the z rotation.

e.g. (The debug ouput of when I moved 1 degree on X and 1 degree on Y)

(X Y Z W)

ChangeinX: 0.00872654 0 0 0.999962

ChangeinY: 0 0.00872654 0 0.999962

NewOrient: 0.0087262 0.0087262 7.61524e-05 0.999924

Orientation: 0.0087262 0.0087262 7.61524e-05 0.999924

Since Im still in the dark on how quaternions work (im getting there slowly), I was wondering why the Z was changed (7.61524e-05) ever so slightly.

(Im using the quaternion/vector code from the tutorial OneSadCookie linked to )

(Apologies for the stupid questions)

Lunatic Wrote:Since Im still in the dark on how quaternions work (im getting there slowly), I was wondering why the Z was changed (7.61524e-05) ever so slightly.A true understanding of how quaternions work in the extra dimension is past my comprehension at this point. Most of us just accept the techniques and math as a black box and go with it.

I admit that I didn't read very carefully what you are describing, but floating point drift over time is pretty common in my experience with quaternions. Depending on what you're trying to do, you can periodically reset them to synch with correct values.

Code:

` deltaVert = deltaVert * PI/180;`

deltaHoriz = deltaHoriz * PI/180;

Quaternion NewOrient;

Quaternion ChangeinX;

Quaternion ChangeinY;

NewOrient.w = 1;

ChangeinY.w = 1;

ChangeinX.w = 1;

Vector temp;

temp.x = 1;

temp.y = 0;

temp.z = 0;

ChangeinX = QuaternionFromAxisAngle(temp, deltaVert);

NewOrient = QuaternionMultiply(&NewOrient, &ChangeinX);

temp.x = 0;

temp.y = 1;

temp.z = 0;

ChangeinY = QuaternionFromAxisAngle(temp, deltaHoriz);

NewOrient = QuaternionMultiply( &NewOrient, &ChangeinY);

NewOrient.z = 0;

Orientation = QuaternionMultiply( &Orientation, &NewOrient);

Orientation.z = 0;

So. This is where I am now.

I create the X Quat, and multiply it with the New Orientation.

I create the Y Quat, and multiply it with the New Orientation.

I then multiply the New Orientation with the Old Orientation.

This seems to go ok, (i.e. I can look around) although Im about to lose the rest of my hair in frustration since I still seem to get the gimble lock effect - I was really hoping that Quaternions would make it so that no matter which way I was pointing, I could move the mouse up/down/left/right and the world would move accordingly

I'm not quite sure what you're trying to accomplish by setting the Z component in NewOrient and Orientation to 0. That seems a bit dodgy. Also, if these are structs (as opposed to C++ objects with constructors that initialize everything to 0), you'll need to set the X, Y, and Z components of NewOrient, ChangeInX, and ChangeInY to 0 after you declare them. If you don't, you run the risk that they'll contain random memory garbage at runtime.

Lunatic Wrote:This seems to go ok, (i.e. I can look around) although Im about to lose the rest of my hair in frustration since I still seem to get the gimble lock effect - I was really hoping that Quaternions would make it so that no matter which way I was pointing, I could move the mouse up/down/left/right and the world would move accordinglyDon't give up hope yet - Quaternions do exhibit gimbal lock when used in certain ways, but used properly, they don't. It can take a little while to wrap your head around how to use them properly, but it's worth it when you get there.

This code is meant to handle simple mouse look. I.e. If the space ship is looking in any direction, you still should be able to look left/right/up/down. I eventually want to incorporate twisting along the Z axis once I get the mouselook working.

The setting of Z to 0 was to counter the strange increments and decrements to the Z axis that were happening when I was multiplying the Quaternians together.

You say that they do exhibit the lock effect in certain ways - is there some sort of set of rules I can use to avoid it? What can I do better to use them "properly"? Am I on the right track at least?

Looking over my own mouselook code, it looks like I rotate first on the Y axis, then on the X axis. Try multiplying NewOrient by ChangeInY before ChangeInX, and see if it helps? Also, I'd suggest commenting out NewOrient.z = 0; and Orientation.z = 0; to make sure they're not having unexpected side-effects.

The mouse look seems to be avoiding any locking effect which is good. However, one last pain exists!

There is something wierd about how the angles are being calculated that causes a Z rotation effect, without there being any Z rotation. Let me explain better..

If I perform little circles in the centre of the track pad, the screen moves around in a circle but also seems to rotate around the Z axis. The debug output of all the quaternions indicates no Z component value for any - yet somehow I can turn upside down

I did take on board the comments about applying the Y before the X, I also changed the order of the mulitplication parameters. There was also some fixing of the model view and projection matrixes, I had them in the "wrong order".