rotate around own axis

Im trying to create an space shooter style game in OpenGL/objectC. Ive not done much opengl before so you'll have to forgive me. Ive created a virtual camera where i move objects in the universe around the central point to make it appear im moving. ive also got it working so that i move in the direction that im pointing. however, say if i move upwards and then look down and try to rotate around the y axis the object in front of me kinda wobbles. I think this is because its rotating me around the real y axis rather than the y axis of where i am now facing.

3D rotations are a pretty complex subject. The answer will depend on how you're representing/applying your rotations. Are you keeping a quaternion or a matrix that accumulates rotations as you move your camera, or doing something else?

My angles are changed based on where i click in the screen.
From the tutorials, I think I need to create a direction vector about which to rotate and then get the quaternion from this, and then get the x,y,z from this to then pass into the glRotate function. If Im right about any of that, then how should i work out the direction vector to rotate around from the 3 angles i have? Also, what angle should I be passing into the quaternion function? or would that be the difference in angles of where i was pointing before to where im wanting to point now?

Sounds like you want to do something similar to Apple's Cocoa OpenGL sample. In particular, check out trackball.c. That sample uses quaternions to rotate a cube based on where the user clicks and drags on the screen.

BTW, instead of dividing by RAD_TO_DEG, you should multiply by DEG_TO_RAD, so it's less confusing, and possibly a little faster doing a multiply instead of divide (I think).

Ah, it looks like you've fallen into the same pitfall almost everyone does when they're first learning about this stuff. Euler angles (using one rotation angle for X, one for Y, and one for Z) basically don't work no matter what you do. From an e-mail exchange I had a while back trying to explain this to someone:

Quote:I understand your confusion. This is exactly the same difficulty I ran into when trying to understand the difference between rotations with quaternions or matrices and rotations with Euler angles. The main difference between doing them one at a time and doing all three at once is the order of operations. Let's see if I can demonstrate with a simple example:

Now, once I've done that, I want to rotate 90 degrees on the local X axis, which now points at the world's -Z axis. So, what I want is this result:
Local X axis: {0, 0, -1}
Local Y axis: {1, 0, 0}
Local Z axis: {0, -1, 0}

If you compare the final rotated values to our expected result in the above example, you'll see that they don't match. What happened here? Well, since we applied our new X axis rotation after we'd already applied our Y axis rotation, we expected it to be on the local X axis, which at the time was {0, 0, -1}. This isn't what happens, though: Since X is applied before Y, we actually end up rotating on the WORLD X axis of {1, 0, 0}! The only way out of this is to rearrange the order of our rotation operations. It might be possible to write the Euler rotation function to rearrange itself so that the most recently rotated axis is the last one applied, but this would involve recalculating the other two axes' values to something that gives the same rotation result when applied in a completely different order, which is a nontrivial problem to solve in code. A much easier thing to do is to only apply one axis's rotation at a time, and apply that to the current cumulative rotation rather than starting from a blank slate.

As for gluLookAt, you could substitute something like this, where you'd be keeping an orientation quaternion and a position vector (see my tutorial for a Quaternion_toMatrix implementaton):

wonza Wrote:thanks, ive just had a look at that app, and it seems to be using gluLookAt, which would be ideal, but im using opengl es on the iPhone which doesnt have that function.

It's just a UVN rotate and translate. I constructed (er, borrowed) this from the Mesa source. (I haven't tested it much (definitely not on iPhone yet), but it is known to have worked for me in the past).

Ive realised Im still going to need the quat functionality though, as ill need to rotate other ships around their own axis too.

I've tried the Quaternion_toMatrix(orientation) but seem to be getting a strange compilation error: "incompatible types in assignment", Im passing in a Quaternion and that should be what its expecting. Its annoying when silly errors get in the way.

It would be a good idea to completely tear apart trackball.c to fully understand how they're using quaternions there. The reason I mention this is that if you do, they don't use matrices, but rather angle axis conversions and glRotatef to get to and from quaternions. It is a very simple and straight-forward way to use quaternions.

I don't know if this will add to your confusion or not, but here's some pseudo-code for one way to implement quaternion rotations. It appears to be similar to how they're doing it in trackball.c:

wonza Wrote:I've tried the Quaternion_toMatrix(orientation) but seem to be getting a strange compilation error: "incompatible types in assignment", Im passing in a Quaternion and that should be what its expecting. Its annoying when silly errors get in the way.

That's odd. Well, since it's saying there are incompatible types in assignment, the problem is more likely what you're doing with the function's return value than its parameter. As defined in my example code, it takes one of these:

Code:

struct Quaternion {
float x;
float y;
float z;
float w;
};

...and returns one of these:

Code:

struct Matrix {
float m[16];
};

You might want to check that what you're assigning to is a struct Matrix and not something else (like struct Matrix * or float[16]).