0
votes

I'm developing some game in order to learn OpenGL.

I'm trying to implement a method to pick objects (e.g. pick axe, gun, etc).

The idea is that this object would lay fixed infront of the camera, even after camera moves or rotates.

What I achieved so far

I can make the object follow me around when I move forward, backward, left, right, up or down, by setting it's position right infront of the camera.

However... when camera rotates / tilts (looking up, down, left, right...) the problems start.

In this case, everything works fine (looking up, down, left, right, tilting right, tilting left... all those operations translates to rotation around x,y,z axes), until I combine several rotations, e.g. rotate 180 degrees backward and then trying to rotate upward (in our language: rotation of 180 degrees over Z axis and then rotation on X axis).

The object starts to rotate around itself in a strange behavior. If I rotate back -180 degress on the Z axis (=looking forward again) and then looking up (rotating around X axis) then the object rotates well.

My game implementation

I have 4 vectors for the camera and 4 vectors for each object: origin, x, y and z (to represent the objects coordinate system).

To move the camera forward, I substract z axis from my current position

Same for other directions.

In order to tilt the camera, for example to the right, I just calculate rotation around Z axis and apply to X,Y axes.

Note: Movement in the world works good, in all directions and angles.

Here's the (the relevant) code I use to position objects in the world. Before drawing them I first put them in their origin (recall: I save an origin and x,y,z axes to all my objects), then do some scale to fit my desired size:

// translate to position
gl.glTranslatef((float)origin.x, (float)origin.y, (float)origin.z);
// scale to size
gl.glScalef((float)size.x, (float)size.y, (float)size.z);
// apply rotation around the object's axes
gl.glRotatef(xrot, (float)x.x, (float)x.y, (float)x.z);
gl.glRotatef(yrot, (float)y.x, (float)y.y, (float)y.z);
gl.glRotatef(zrot, (float)z.x, (float)z.y, (float)z.z);

Edited:

This is how I calculate the angle:

Math.toDegrees(Math.acos(v1.dot(v2))) // dot is a simple dot product
1
So, when you asked this question yesterday but didn't get an answer, why did you feel that it was appropriate to delete that question and ask it again? - Nicol Bolas
I thought the explanation was lack. I re posted with more clarified explanation. - Jjang
@NicolBolas I've had a breakthrough and edited question. - Jjang
I don’t know why you’re choosing to complicate matters with sequential rotation vectors. However, since you’re not showing us HOW you “calculate the difference in angle between theold and new Z axis”, that might very well be the where your problem lies. - Entropy

1 Answers

2
votes

Let me introduce you to something called a “matrix”:

float matrix[16];

A matrix is a simple array, designed to store all four of your vectors in one neat package, in a format OpenGL understands. You can store your vectors in a matrix in the following manner:

matrix[0] = getAxisX().getX();
matrix[1] = getAxisX().getY();
matrix[2] = getAxisX().getZ();
matrix[3] = 0.0;

matrix[4] = getAxisY().getX();
matrix[5] = getAxisY().getY();
matrix[6] = getAxisY().getZ();
matrix[7] = 0.0;

matrix[8] = getAxisZ().getX();
matrix[9] = getAxisZ().getY();
matrix[10] = getAxisZ().getZ();
matrix[11] = 0.0;

matrix[12] = getOrigin().getX();
matrix[13] = getOrigin().getY();
matrix[14] = getOrigin().getZ();
matrix[15] = 1.0;

You can either copy your data into a matrix each time you want to pass it to OpenGL, or you can save yourself a lot of trouble later by adopting the matrix as the standard way of storing the data in your objects now.

(Note that the 0.0 and 1.0 constants are important, for reasons I won’t digress into here.)

Then simply replace:

gl.glTranslatef((float)origin.x, (float)origin.y, (float)origin.z);

With this:

gl.glMultMatrixf(matrix);

If your version of OpenGL works the way I’d expect, that should do the translation and rotation for you.