0

I have a basic OpenGL program written in LWJGL for java. I'm just starting to look into rotation matrices after reading up on why it's a bad idea to use pitch, yaw and roll variables. However, as matrices are more difficult to work with, I am writing a function that takes yaw, pitch and roll and converts them into a rotation matrix, which is then multiplied with the Modelview matrix. My code is as follows:

public static void loadRotationalMatrix(double pitch, double yaw, double roll)
{
    FloatBuffer Ry = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();
    FloatBuffer Rx = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();
    FloatBuffer Rz = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();

    Rx.put(new float[]
        {
            1, 0, 0, 0,
            0, (float) cos(pitch), (float) sin(pitch), 0,
            0, (float) -sin(pitch), (float) cos(pitch), 0,
            0, 0, 0, 1
        });
    Ry.put(new float[]
        {
            (float) cos(yaw), 0, (float) -sin(yaw),  0,
            0, 1, 0, 0,
            (float) sin(yaw), 0, (float) cos(yaw), 0,
            0, 0, 0, 1
        });
    Rz.put(new float[]
        {
            (float) cos(roll), (float) sin(roll), 0, 0,
            (float) -sin(roll), (float) cos(roll), 0, 0, 
            0, 0, 1, 0,
            0, 0, 0, 1
        });

    GL11.glMultMatrix(Rx);
    GL11.glMultMatrix(Ry);
    GL11.glMultMatrix(Rz);
}

To begin, I passed 0, 0, 0 to this function, which I expected to have no effect on the rendered scene. However, the simple square I was drawing disappeared after the function call. To debug, I used glGetFloat to access the modelview matrix and see what happened.

This is where things get strange (for me at least): before I call my function, the retrieved FloatBuffer storing the modelview matrix is

4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41, 

or, more readable,

4.6006E-41, 0.0, 0.0, 0.0, 
0.0, 4.6006E-41, 0.0, 0.0, 
0.0, 0.0, 4.6006E-41, 0.0, 
0.0, 0.0, 0.0, 4.6006E-41, 

and everything renders normally.

After my call, the matrix becomes

0.0, 0.0, 0.0, 0.0, 
0.0, 0.0, 0.0, 0.0, 
0.0, 0.0, 0.0, 0.0, 
0.0, 0.0, 0.0, 0.0, 

and my test square disappears.

What is happening? Are my matrices created incorrectly? Is there something I do not understand about glMultMatrix? Is there something I need to enable or disable? Why does the normal matrix have those weird floats in it? Isn't it supposed to be the identity matrix (with 1's)?

EDIT:

If BufferUtils.createFloatBuffer(16 * Float.SIZE); is used instead of ByteBuffer.allocateDirect(16 * Float.SIZE).asFloatBuffer();, the the byte-ordering problems mentioned go away and the 4.6006E-41's becomes 1.0 as expected. However, the matrix still transforms from the identity to pure zeroes.

ApproachingDarknessFish
  • 14,133
  • 7
  • 40
  • 79
  • You probably need to flip your buffers before you call GL11.glMultMatrix(...). – Nathan Feb 13 '13 at 22:29
  • Maybe I meant that you should rewind the buffer. Try that. It looks like your matrices and buffer allocations are solid to me. I haven't used LWJGL very much, but I imagine that GL11.glMultMatrix() is multiplying the modelview matrix by the passed in matrix. If there's no change with rewinding the buffer, post some code so I can see where you call this loadRotationMatrix(...) function. – Nathan Feb 13 '13 at 22:35
  • It won't matter if all your angles are zero, but FYI there's a sign error in your yaw matrix (one of the `sin`s should have a plus sign and one a minus sign, so that taking the transpose of the matrix is equivalent to flipping the sign of the angle). – Mike Dinsdale Feb 13 '13 at 22:37
  • @MikeDinsdale Thanks. Fixed that, but it didn't solve the problem. – ApproachingDarknessFish Feb 13 '13 at 23:18
  • @Nathan After applying the fixes mentioned in my edits, this worked. Thank you; the problem is solved! – ApproachingDarknessFish Feb 13 '13 at 23:40

1 Answers1

2

(This is really an extended comment, with code)

There is definitely a byte order problem here. I ran the following:

public class Test {
  public static void main(String[] args) {
    float f = (float)4.6006E-41;
    System.out.println(Integer.toHexString(Float.floatToIntBits(f)));
  }
}

and got output 803f

Float 1.0 is big-endian 0x3f800000.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75