I have some questions that may or may not be entirely related to OpenGL, but certainly are related to graphics programming, so maybe some of you might be able to help me:

1- Is it OK to use glRotatef with quaternions instead of constructing the rotation matrix and loading it manually?

2- Can I call glRotatef twice without fear of something being wrong because of Gimbal Lock?

3- Suppose the following scenario:

- I have a top down view where there is an object in the center of the screen

- I want to rotate my object over the Z axis by using the mouse's position in relation to the middle of the screen. I do this by normalizing the vector and calling atan2 to get the angle needed to rotate the object.

- Then, I also want to rotate the object so that it is parallel to the plane it is sitting on. I do this by constructing a quaternion that shifts the world up vector (0, 0, 1) to the normal of the plane.

- Finally, I came up with the following set of rotations:

- Is this right?

- Does the order of rotations matter here?

- If not, what should I be doing instead?

1- Is it OK to use glRotatef with quaternions instead of constructing the rotation matrix and loading it manually?

2- Can I call glRotatef twice without fear of something being wrong because of Gimbal Lock?

3- Suppose the following scenario:

- I have a top down view where there is an object in the center of the screen

- I want to rotate my object over the Z axis by using the mouse's position in relation to the middle of the screen. I do this by normalizing the vector and calling atan2 to get the angle needed to rotate the object.

- Then, I also want to rotate the object so that it is parallel to the plane it is sitting on. I do this by constructing a quaternion that shifts the world up vector (0, 0, 1) to the normal of the plane.

- Finally, I came up with the following set of rotations:

1 2 3 4 | glTranslatef(slime.pos.x, slime.pos.y, slime.pos.z); // From AllegroGL`s math.c glRotatef((2*acos(slime.rotation.w)) * 180 / M_PI, slime.rotation.x, slime.rotation.y, slime.rotation.z); glRotatef(mouse_angle, 0, 0, 1); |

- Is this right?

- Does the order of rotations matter here?

- If not, what should I be doing instead?

Edited by Italo
on
Reason: Initial post

1. Yes, but you should avoid using glRotatef. It is a deprecated function. While it works fine now, you'll have trouble later when moving to different platform or upgrading GL version. You should implement math in your code and just load final matrix to OpenGL. This way you'll also have more control over what's happening with math and it will be much easier to debug.

2. Yes, you can call it as many time as you want. But Gimbal lock can still happen depending on the way how you manage and apply rotations.

Order always matters. Matrix multiplication is not commutative.

2. Yes, you can call it as many time as you want. But Gimbal lock can still happen depending on the way how you manage and apply rotations.

Order always matters. Matrix multiplication is not commutative.

Edited by Mārtiņš Možeiko
on

I see, but what does "depending on the way how you manage and apply rotations" mean?

For instance, in the code I provided, is there some configuration of those two glRotatef calls giving wrong results due to Gimbal Lock? I ask this because the code is working for me right now, but I wanna know if there is a better way to achieve what I'm doing in immediate mode.

To make it more clear, should I somehow combine those two rotations into one and call glRotatef just once? If so, what does combine mean here?

For instance, in the code I provided, is there some configuration of those two glRotatef calls giving wrong results due to Gimbal Lock? I ask this because the code is working for me right now, but I wanna know if there is a better way to achieve what I'm doing in immediate mode.

To make it more clear, should I somehow combine those two rotations into one and call glRotatef just once? If so, what does combine mean here?

nyeecola

I see, but what does "depending on the way how you manage and apply rotations" mean?

For instance, in the code I provided, is there some configuration of those two glRotatef calls giving wrong results due to Gimbal Lock? I ask this because the code is working for me right now, but I wanna know if there is a better way to achieve what I'm doing in immediate mode.

To make it more clear, should I somehow combine those two rotations into one and call glRotatef just once? If so, what does combine mean here?

gimbal lock is a consequence of how you combine rotations. It's a situation where 2 or more stages of rotations end up in a way that creates instability.

And we are telling you to avoid glRotatef altogether and instead create the rotation matrix yourself and use glLoadMatrixf (if you still want to use legacy pipeline) or glUniformMatrix4fv once you switch over to shaders.

ratchetfreak

instead create the rotation matrix yourself and use glLoadMatrixf (if you still want to use legacy pipeline) or glUniformMatrix4fv once you switch over to shaders.

But here's the thing. I have those two rotations, one is around the (0, 0, 1) axis and the other is around another axis that is orthogonal to (0, 0, 1). How would I create the rotation matrix from these two things?

I know that supposedly I can just multiply them together, but why doesn't that have the Gimbal Lock problem?

Sorry if this is a dumb question, I just don't understand what exactly I have to do to avoid Gimbal Lock.

Combining rotations from euler angles (i.e. rotations around 3 orthogonal axes) you can always end up in a gimbal lock scenario. It happens when one rotation (or a group of rotations) align one axis parallel to another one, effectively loosing one degree of freedom.

In this case, it doesn't matter whether you use calls to glRotatef or you use your own matrices, e.g. mat4 xRot = RotateX(float degrees); and multiply these matrices, the result is the same.

Quaternions are a way to solve the gimbal lock problem. Simply combine rotations using quaternions and just before rendering, create a matrix with the final rotation in the quaternion and send it to OpenGL.

In this case, it doesn't matter whether you use calls to glRotatef or you use your own matrices, e.g. mat4 xRot = RotateX(float degrees); and multiply these matrices, the result is the same.

Quaternions are a way to solve the gimbal lock problem. Simply combine rotations using quaternions and just before rendering, create a matrix with the final rotation in the quaternion and send it to OpenGL.

marcc

Simply combine rotations using quaternions and just before rendering, create a matrix with the final rotation in the quaternion and send it to OpenGL.

I guess this is the core part of my misunderstanding of this whole thing.

How does combining quaternions solve gimbal lock?

Let's say for instance that I have three quaternions representing 3 rotations on axis X Y Z, if I combine them all the result is susceptible to gimbal lock, right?

I guess the answer for that question must be yes.

So, how can I ever combine any amount of quaternions and be 100% sure that there is no way a gimbal lock can occur if I just told you a certain configuration in which it does happen?

Edited by Italo
on

Yes, you are right. By simply using quaternions it does not solve gimbal lock. GL happens due to way how you store/process rotations. If you will store three angles and use them to calculate three quaternions, then combine them to final rotation matrix - you will still have a problem with gimbal lock. The problem is with storing/using rotation around each axis individually. Does not matter if you use three angles, three matrices or three quaternions - they all represent same thing. You should not do that. Instead you should store only one matrix for representing whole orientation - that includes all three axis. Or alternatively - one quaternion, which represents same thing. And when you want to rotate by specific amount - look up 30 degrees, or turn left 90 degrees, etc - then you would multiple this matrix or quaternion with new matrix/quaternion. That will avoid gimbal lock.

Edited by Mārtiņš Možeiko
on