0

Imagine a 3D rectangle at origin. It is first rotated along Y-axis. So good so far. Now, it is rotated around X-axis. However, OpenGL (API: glrotatef) interprets the X-axis to be the global X-axis. How can I ensure that the "axes move with the object"?

This is very much like an airplane. For example, if yaw (Y rotation) is applied first, and then pitch (X-rotation), a correct pitch would be X-rotation along the plane's local axes.

EDIT: I have seen this called gimbal lock problem, but I don't think it is though.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Iceman
  • 4,202
  • 7
  • 26
  • 39
  • 1
    GL doesn't care about any local or global axes stuff. `glRotatef (...)` does nothing more than multiply the ***current*** matrix by a rotation matrix defined by your rotation axis and angle. What does, however, matter is the order you call `glTranslate` and `glRotate`. GL uses column-major matrices and post-multiplication, so you need to rotate <1> and then translate <2> if you want the rotation to be relative to <2>. The math behaves in reverse order. The accepted answer for [this question](http://stackoverflow.com/questions/9702867/opengl-rotation-local-vs-global-axes) explains this. – Andon M. Coleman Apr 30 '14 at 21:11
  • @AndonM.Coleman: But right now, I am not translating at all... – Iceman Apr 30 '14 at 21:15
  • @AndonM.Coleman: Yes, I am using ModelView matrix, and gluLookAt to move the eyepoint at (0, 0, 1). – Iceman Apr 30 '14 at 21:18
  • Then how do you expect the rotation axis to "move with the object" if you are not moving the object? – Andon M. Coleman Apr 30 '14 at 21:31
  • @AndonM.Coleman: I mean when rotated around Y first, the X-axis is still 90 degrees to the plane of the object. – Iceman Apr 30 '14 at 21:37

1 Answers1

0

You cannot consistently describe an aeroplane's orientation as one x rotation and one y rotation. Not even if you also store and one z rotation. That's exactly the gimbal lock problem.

The crux of it is that you have to apply the rotations in some order. Say it's x then y then z for the sake of argument. Then what happens if the x rotation is by 90 degrees? That folds the y axis onto where the z axis was. Then say the y rotation is also by 90 degrees. That's now bent the z axis onto where the x axis was. So now what effect does any z rotation have?

That's just an easy to grasp example. It's not a special case. You can't wave your hands out of it by saying "oh, I'll detect when to do z rotations first" or "I'll do 90 degree rotations with a special pathway" or any other little hack. Trying to store and update orientations as three independent scalars doesn't work.

In classic OpenGL, a call to glRotatef means "... and then rotate the current matrix like this". It's not relative to world coordinates or to model coordinates or to any other space that you're thinking in.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • How can I achieve the "folding" of the axes though, since this is what I am looking for. – Iceman Apr 30 '14 at 22:10
  • Just `glRotatef` three times, specifying vectors of (1, 0, 0), (0, 1, 0) and (0, 0, 1). Your assertion that OpenGL somehow keeps track of some sort of global basis is false. Try changing the order of your rotations to prove it to yourself. – Tommy Apr 30 '14 at 22:27
  • the behavior I see after (1, 0, 0) is as expected. After adding y, (0, 1, 0), the object revolves, as if it's around a global y-axis, instead of spinning around it's local y. – Iceman May 01 '14 at 01:21
  • ... and tell me what you see if you do the rotations the other way around? I'll repeat it again: you're not going to be able to get aeroplane-style rotations if you're trying to keep separate axial rotations. The camera in a first-person shooter is about the limit. – Tommy May 01 '14 at 05:43
  • So should I be using the generic 3D rotation matrix? In general would you recommend rotating the object using glRotatef, or the camera using gluLookAt? – Iceman May 01 '14 at 12:07
  • I am still not convinced that this is gimbal lock. with glRotatef, each rotating will change the axes and they will still be orthonormal.. i never run into a lock.. i.e., I can always rotate along all 3 axes.. – Iceman May 01 '14 at 14:16
  • No, each rotation is an atomic operation that changes the axes *subsequently*. So they *are no longer orthogonal to those that you have already rotated around*. Gimbal lock is something a lot of people have difficulty grasping so don't worry about it being non-obvious but I absolutely promise you that you cannot simulate an aeroplane as discrete axial rotations. – Tommy May 01 '14 at 18:01
  • `gluLookAt` doesn't really do rotations in the 'here's an angle' sense but if you inherently have viewer position + target position + up vector then it's a smart bet. But if you're looking to mutate an orientation over time then you should look either at storing it as a matrix directly, then mutating that matrix (being careful to keep it orthonormal versus rounding errors), or using a quaternion — especially if interpolation is important to you. – Tommy May 01 '14 at 18:04
  • Thanks for replies.. I understand it cannot be discrete axial rotations. Would direction do you suggest though? Generic 3D rotation matrices? – Iceman May 01 '14 at 18:25
  • 1
    Generic matrices are easy to grasp, easy to inspect and easy to implement; you can even use `glGetFloatv` and `glLoadMatrix` to use GL's matrix manipulation for mutation if you really want. So I'm a big fan. It's really only interpolation and, in extreme situations, storage size that favour quaternions, so you'll tend to use those for scripted animations (as you can store key frames far apart, in a small amount of space so you can store lots of them, and interpolate between). – Tommy May 01 '14 at 18:45