Rotating an object based on position and direction

Started by
6 comments, last by phalaris 14 years, 3 months ago
I'm going crazy with this.. sorry for the stupid question, seems like such a simple thing to do. Basically the player has a position, direction and up vector. He shoots a bullet. I want to rotate the bullet so that it points towards the view vector as the player fires it. I already have the azimuth and elevation and I already have the xz rotation working correctly. BUT I cannot get the elevation working properly. Here is my code:

// First translate to the bullet position
Gl.glTranslatef(Pos.x, Pos.y, Pos.z);

// Find the azimuth and rotate around the y axis. Works perfectly..
float theta = (float)Math.Atan2(Dir.x, Dir.z) / (float)Math.PI * 180;
Gl.glRotatef(theta, 0, 1, 0);

// Find the elevation. This also works correctly.
// phi is between -90 and 90. Think FPS shooters:
// If the player is facing straight down then the angle is -90.
// If he is facing straight ahead then the angle is 0. 
// If he is facing straight up then the angle is 90
float phi = -((float)Math.Acos(Dir.y) / (float)Math.PI * 180) + 90;

// Now this part is confusing me! I tried everything, but it comes out wrong!
Gl.glRotatef(?, ?, ?, ?);
Thank you and Happy Christmas [Edited by - phalaris on December 23, 2009 8:45:36 AM]
Advertisement
I'm not sure in which order OpenGL applies the rotations, so perhaps try changing the order.

Where's your bullet pointing at in model coordinates?

EDIT: Shouldn't it be `Math.Asin(Dir.y)'? And then you don't need to add 90. RE-EDIT: Oh, I think your formula is just a roundabout way of saying the same thing.
Thanks for the reply.

I tried that. Doesn't work properly. The problem is I don't know which axis to rotate around. If I try
Gl.glRotatef(phi, 1, 0, 0);

then it works fine for some values of theta but not for others,

same for
Gl.glRotatef(phi, 0, 0, 1);

I have a feeling that it should be something like
Gl.glRotatef(phi, Cos(something), 0, Sin(something));

but nothing I tried works.

EDIT: yes, thanks for the correction. It is simply Asin(Dir.y).
As you can probably tell, I am deriving this (poorly) from first principles..

I'm not sure what you mean by model co-ordinates. Once I translate to the bullet position it points wherever Dir is pointing. Unless I am missing something? (I'm quite new to OpenGL)
alvaro meant presumably: It is required that the bullet, if not transformed (i.e. it is in "normal orientation") points into the same direction as the gun does. If not, then an offset rotation is needed.

However, as ever in such a use case I'd go away from using trigonometric functions at all. Instead I'd use the local frame of the gun (best choice), the gun hand, or perhaps the player itself (what ever is available for you), relate another local frame as child to it, and use this frame further as initial frame of any fired bullet. I.e. when firing, resolve the said frame w.r.t. the global frame, and copy the result as local frame of the freshly created bullet.

That way the motion of the player's avatar, its hand or gun (if modeled so fine) will be considered correctly.
Hi.

When my bullet is fired it takes geometry values from the player, as you say. So the bullet's position and direction is set to the player's position and direction.

You kind of lost me after that. Am I not creating a local frame for the bullet by translating and rotating it? How can I achieve this without without using trigonometry?

Many thanks,
Quote:Original post by phalaris
Hi.

When my bullet is fired it takes geometry values from the player, as you say. So the bullet's position and direction is set to the player's position and direction.

You kind of lost me after that. Am I not creating a local frame for the bullet by translating and rotating it? How can I achieve this without without using trigonometry?

You can build the matrix on your own and use `glLoadMatrixf()'. You can build the matrix if you know the translation and where you want to map (1,0,0), (0,1,0) and (0,0,1).
rotation always occurs around the origin. When you make your bullet model you should make it such that its center is at 0, 0, 0 and it is facing in some standard "forward" direction (usually z). As long as the forward direction is consistant it doesn't matter.

First you want to do the rotation, if you only have rotation about 2 axis then I don't think the order matters (but if it still looks weird try swapping them). Finally you want to put the bullet in the correct place so do the translation.

elevation
bearing
translation

Multiple rotations gets confusing.

Personally I think you should take your direction vector, your up vector and work out a right vector (all normalized). That will give you an orthogonal matrix which you can load somehting like:

float matrix[16];
matrix[0] = right.x;
matrix[4] = right.y;
matrix[8] = right.z;
matrix[12] = 0;
matrix[1] = up.x;
matrix[5] = up.y;
matrix[9] = up.z;
matrix[13] = 0;
matrix[2] = dir.x;
matrix[6] = dir.x;
matrix[10] = dir.x;
matrix[14] = 0;
matrix[3] = 0;
matrix[7] = 0;
matrix[11] = 0;
matrix[15] = 1;

Then you can do

glMultMatrixf(matrix);
glTranslatef(Pos.x, Pos.y, Pos.z);

// Render bullet

I'm sure I've got something there wrong (off the top of my head) but thats the general idea anyway. Angles are best avoided if possible and since you have vectors you can make do without resorting to ugly angles.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Great, thanks for the replies. I guess it's not as trivial as I thought, but I'll try to get my head around the rotation matrix method..

Happy Christmas

This topic is closed to new replies.

Advertisement