I'm working on a college Graphics project using LWJGL (OpenGL in Java). I've done most of the scene but I got a problem in figuring out the jet's orientation.

Here's how I tried it at the very beginning: (After translate it to the desired position)

        GL11.glRotatef(xRotation, 1, 0, 0);
        GL11.glRotatef(yRotation, 0, 1, 0);

Then I found the I came across the gimbal lock problem? For example: the jet roll 90 degrees to the right, then it pitch up so that it will make a right turn. But if I pitch up 90 degrees first, then roll at some angle, it look like it's Yawing ! It's still rotate along the original X-axis.
Roll -> Pitch looks fine.
But Pitch -> Roll looks BAD.

Then I tried another way:

        GL11.glRotatef(xRotation, 1, 0, (float)Math.tan(Math.toRadians(-yRotation)));   
        GL11.glRotatef(yRotation, 0, 1, 0);

This time the problem actually inverses! The case I just described is inversed.
Roll -> Pitch looks BAD.
But Pitch -> Roll looks fine.

I can't even imagine what might happen when I add the Yaw Rotation into this.

The jet should be able to orient at any direction and Roll,Yaw,Pitch should not interfere with each other

I've done lot of research, it appears to me that I have to aggregate the Roll-Pitch-Yaw 3 rotations into one which is represented by Quaternions. But I'm really confused about the term. If someone has experience in doing a similar work plz give me some hints(examples are much appreciated!), I'm really really frustrated by this. Thank you !

  • \$\begingroup\$ Any particular reason why you're using GL11 instead of GL20 or greater? The old pipeline is pretty much deprecated, you'll be much better of learning GL20 and shaders, \$\endgroup\$ Dec 25 '15 at 15:18
  • \$\begingroup\$ To Gustavo: ehh My lecturer gave me this as the platform ... \$\endgroup\$
    – LIn
    Dec 25 '15 at 16:49

After a whole weekend research and trying, I finally managed it somehow, thanks to jbridon on his blog. So Quaternions is definitely the way to do it. U may have to use a Point3f to record ur object's coordinates, a Vector3f to represent its motion per frame.
And in each update of rendering, first get ur Euler angles of Roll, Pitch, and Yaw. Then calculate their effect on the Motion Vector3f. That's where your object gonna go in the next update.

Here's the tricky point:
You still have to choose a order of XYZ, they do matter but not that bad when using Euler Angles. In my case of a flight simulator, I choose Y->X (No Z at the moment) as the order.

Now you want to find out how your Model Coordinates System looks like right now (since you rolled then pitched the object). In my case jbridon gives me a way like this: (Mostly his code,so thanks him again)

    Velocity.scale((float) Math.cos(perPitch));
    UpDirection.scale((float) Math.sin(perPitch));
    Velocity = Vector3f.add(Velocity, UpDirection, null);
    UpDirection = Vector3f.cross(yDirection, Velocity, null);


    yDirection.scale((float) Math.cos(perRoll));
    UpDirection.scale((float) Math.sin(perRoll));
    yDirection= Vector3f.add(yDirection, UpDirection, null);
    UpDirection= Vector3f.cross(yDirection, Velocity, null);

    // Normalize

    Vector3f.add(Position, Velocity, Position);

    // here build two quaternion to represent two rotations, then multiply them together
    Quaternion RollQuat = new Quaternion();
    QRoll.setFromAxisAngle(new org.lwjgl.util.vector.Vector4f(v.x, v.y, v.z, perRoll));
    Quaternion PitchQuat = new Quaternion();
    QPitch.setFromAxisAngle(new org.lwjgl.util.vector.Vector4f(yDir.x, yDir.y, yDir.z, -perPitch));

    // Note: we must explicitly multiply out each dQ, not just the total
    Quaternion.mul(ResultQuat, RollQuat, ResultQuat);
    Quaternion.mul(ResultQuat, PitchQuat, ResultQuat);

Then bingo, you're done. You now get the Quaternion that describes the rotation for you. Then you can use multiple ways to apply this to your local coordinates. For example, I use Java OpenGL Math Library's code to transform a quaterion into matrixes for multiplication in my model view. The gimbal lock is avoided in this way.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .