Rotating an object around its local origin

Well, I bit the bullet and decided to try to write my own matrix math function. Right now I’m only doing it for the x-axis until I can get it working. It’s pretty fugly, but I think the math is right. The issue is that nothing displays, so I think I’m doing it wrong with the OpenGL functions somewhere.

Here’s my rotateX and related declarations:

private float[] xMatrix = {0, 0, 0, 0,
                               0, 0, 0, 0,
                               0, 0, 0, 0,
                               0, 0, 0, 0};
.
.
.

    private float[] rotationMatrixX = {1.0f, 0, 0, 0, 
                                        0, (float)Math.cos(degreesX), (float)Math.sin(degreesX), 0,
                                        0,-((float)Math.sin(degreesX)), (float)Math.cos(degreesX), 0, 
                                        0, 0, 0, 1.0f};
.
.
.
public void rotateX()
    {
        float[] tempMatrixX = new float[16];
        
        tempMatrixX[0] = (xMatrix[0] * rotationMatrixX[0]) + (xMatrix[4] * rotationMatrixX[1]) + (xMatrix[8] * rotationMatrixX[2]) + (xMatrix[12] * rotationMatrixX[3]);
        tempMatrixX[1] = (xMatrix[1] * rotationMatrixX[0]) + (xMatrix[5] * rotationMatrixX[1]) + (xMatrix[9] * rotationMatrixX[2]) + (xMatrix[13] * rotationMatrixX[3]);
        tempMatrixX[2] = (xMatrix[2] * rotationMatrixX[0]) + (xMatrix[6] * rotationMatrixX[1]) + (xMatrix[10] * rotationMatrixX[2]) + (xMatrix[14] * rotationMatrixX[3]);
        tempMatrixX[3] = (xMatrix[3] * rotationMatrixX[0]) + (xMatrix[7] * rotationMatrixX[1]) + (xMatrix[11] * rotationMatrixX[2]) + (xMatrix[15] * rotationMatrixX[3]);

        tempMatrixX[4] = (xMatrix[0] * rotationMatrixX[4]) + (xMatrix[4] * rotationMatrixX[5]) + (xMatrix[8] * rotationMatrixX[6]) + (xMatrix[12] * rotationMatrixX[7]);
        tempMatrixX[5] = (xMatrix[1] * rotationMatrixX[4]) + (xMatrix[5] * rotationMatrixX[5]) + (xMatrix[9] * rotationMatrixX[6]) + (xMatrix[13] * rotationMatrixX[7]);
        tempMatrixX[6] = (xMatrix[2] * rotationMatrixX[4]) + (xMatrix[6] * rotationMatrixX[5]) + (xMatrix[10] * rotationMatrixX[6]) + (xMatrix[14] * rotationMatrixX[7]);
        tempMatrixX[7] = (xMatrix[3] * rotationMatrixX[4]) + (xMatrix[7] * rotationMatrixX[5]) + (xMatrix[11] * rotationMatrixX[6]) + (xMatrix[15] * rotationMatrixX[7]);

        tempMatrixX[8] = (xMatrix[0] * rotationMatrixX[8]) + (xMatrix[4] * rotationMatrixX[9]) + (xMatrix[8] * rotationMatrixX[10]) + (xMatrix[12] * rotationMatrixX[11]);
        tempMatrixX[9] = (xMatrix[1] * rotationMatrixX[8]) + (xMatrix[5] * rotationMatrixX[9]) + (xMatrix[9] * rotationMatrixX[10]) + (xMatrix[13] * rotationMatrixX[11]);
        tempMatrixX[10] = (xMatrix[2] * rotationMatrixX[8]) + (xMatrix[6] * rotationMatrixX[9]) + (xMatrix[10] * rotationMatrixX[10]) + (xMatrix[14] * rotationMatrixX[11]);
        tempMatrixX[11] = (xMatrix[3] * rotationMatrixX[8]) + (xMatrix[7] * rotationMatrixX[9]) + (xMatrix[11] * rotationMatrixX[10]) + (xMatrix[15] * rotationMatrixX[11]);

        tempMatrixX[12] = (xMatrix[0] * rotationMatrixX[12]) + (xMatrix[4] * rotationMatrixX[13]) + (xMatrix[8] * rotationMatrixX[14]) + (xMatrix[12] * rotationMatrixX[15]);
        tempMatrixX[13] = (xMatrix[1] * rotationMatrixX[12]) + (xMatrix[5] * rotationMatrixX[13]) + (xMatrix[9] * rotationMatrixX[14]) + (xMatrix[13] * rotationMatrixX[15]);
        tempMatrixX[14] = (xMatrix[2] * rotationMatrixX[12]) + (xMatrix[6] * rotationMatrixX[13]) + (xMatrix[10] * rotationMatrixX[14]) + (xMatrix[14] * rotationMatrixX[15]);
        tempMatrixX[15] = (xMatrix[3] * rotationMatrixX[12]) + (xMatrix[7] * rotationMatrixX[13]) + (xMatrix[11] * rotationMatrixX[14]) + (xMatrix[15] * rotationMatrixX[15]);
        
        for(int i = 0; i < xMatrix.length; i++)
        {
            xMatrix[i] = tempMatrixX[i];
        }
    }
    
    //this is called in the main display() method
    public void finalizeRotation(GL gl)
    {
        gl.glMultMatrixf(FloatBuffer.wrap(xMatrix));
    }

Here’s my display function:

public void display(GLAutoDrawable drawable) 
    {
        GL gl = drawable.getGL();

        // Clear the drawing area
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        // Reset the current matrix to the "identity"
        gl.glLoadIdentity();
        
        gl.glPushMatrix();
        
        cube.finalizeTranslate(gl);
        cube.finalizeRotation(gl);
        cube.finalizeScaling(gl);
        
        //Here's where we start drawing. ORDER MATTERS.
        //In case you want to do textures or something, you need to draw
        //everything in counter-clockwise order.
        // Draw A Quad
        gl.glBegin(GL.GL_QUADS);
        
            gl.glColor4f(0.5f, 0.5f, 1.0f, 0.2f);    // Set the current drawing color to light blue            
            cube.stackMaker(gl);
            
        // Done Drawing The Quad
        gl.glEnd();

        // Flush all drawing operations to the graphics card
        gl.glFlush();
        
        gl.glPopMatrix();
    }

You’ve initialized xMatrix incorrectly, you’ve set it to all 0’s, so when you multiply it by your x rotation matrix, it will never change. Instead set it so that its the 4 dimensional identity matrix (1’s along the diagonals). Based on the way you wrote your rotationMatrixX, it also looks like you’re storing the matrices row-major. Opengl wants matrices that are column major, so the first four elements in the array would be the first column, etc.

facepalm Ok, now it’s displaying, but still not rotating. When you say it’s row-order, is it all of my matrices, or just the math in the function that’s set up improperly? I know of glLoadTransposeMatrix, but it would probably be faster if I just fix everything.

Edit: Totally a quick fix, because I put glRotate back and the cube grid’s still rotating around the point at which it started to be drawn, but it is rotating around a local point. Yay glPushMatrix and glPopMatrix in the right places. I still want it to rotate around the cube grid’s centre, though.

Also, I tried transposing everything (the rotation matrix, my math, both) and none of the combinations I tried worked.

IMHO, I don’t think doing what you are doing is the correct solution in the long run…the reason I attached my comments to this thread was because I wanted to do what you did and I found that applying the general rotation as you are doing caused me so many problems and eventual jitter that I found it is better to move the object of focus to the origin and the remaining objects are to be moved by the same vector so that they are correct relative to each other…and then use gluLookAt() to focus on the 0,0,0 point and do your rotations…I think this has to be the better solution.

the problem you are facing is known as the “Gimbal Lock” which is a known mathematical behaviour when using euler angle rotation.

To overcome this you have to use quaternion based roation. If you are new to this term, quat. rotation is based on complex numbers and its much more percise. Simply you can define a rotation around an arbitrary axis in space without needing to decompose to euler angles.

One more thing using float computation to define the euler angle rotations is prone to errors.

[quote]IMHO, I don’t think doing what you are doing is the correct solution in the long run…the reason I attached my comments to this thread was because I wanted to do what you did and I found that applying the general rotation as you are doing caused me so many problems and eventual jitter that I found it is better to move the object of focus to the origin and the remaining objects are to be moved by the same vector so that they are correct relative to each other…and then use gluLookAt() to focus on the 0,0,0 point and do your rotations…I think this has to be the better solution.
[/quote]
Right, I’m trying not to use glRotate. I want to get my matricies working, but I don’t know where they’re broken. I only have 1 object, since this is a 3D graph, not a game. I’ll try using gluLookAt(), though. Do you make any of your own matricies?

no I haven’t made my own matrices…yet. I need to create my gluLookAt() look,eye,up vectors right now and I don’t think I need to create a matrix so I’m lucky. I only use matrices for setting the position of my Sun in the background (not in demo) but that’s about it…sorry.

Okay, well I got gluLookAt to act like a camera (albeit a broken camera). I’ve also changed my approach a little, so now all I’m doing is trying to orbit around the object rather than moving the object itself. I’m doing this by changing the eyeX, eyeY, and eyeZ parameters of gluLookAt (so it acts like Alt+left mouse drag in 3ds Max, i.e. viewport camera orbiting around the point in focus, which in my case is the origin).

I’ve taken the plunge with quaternions and wrote a class for them, though I’m still a little lost as to how exactly I’m supposed to use them properly. I’ll post whatever bugs crawl out of my code or if it works (LOL.) once I have something that’s really using the quaternion class I wrote.

I’m trying to implement this code into my java … it is a First Person Shooter “observer/fly through” emulation that you see in FPS games (obviously)

http://www.codesampler.com/oglsrc/oglsrc_5.htm#ogl_fps_controls

This example has source and executable…basically you use the mouse to control your lookAt point and the fwd/back/left/right keys to control the motion of the camera into/outof/left/right in the scene…so you can basically fly through the system. The other thing I will try to implement is the attached version of the FPS observer where you attach yourself to an object and your mouse motions no longer change your lookAt point but make you rotate about the object that you are attached to…the last one is easy but that FPS fly through is giving me problems.

The code above doesn’t use gluLookAt() but rather it calculates the lookAt, eye/camera and Up vectors and create a matrix by which the modelview matrix is multiplied…I think you can instead take the calculated LookAt,eye and up vectors and use them in gluLookAt() if I wanted to and that’s my plan once I get the first method working…effectively trying to port the code above to Java. I’m obviously doing something a little off because I can’t seem to get it quite right and I’m not sure if it is the mouse listener implementation that I have is not a good copy or if JOGL matrices have different ordering than OpenGL matrices - ie row major vs column major…I have no clue - I hope not.

I can’t wait to see your code…please post it if you get it working.

I was finally able to get the FPS code (link in previous) code converted to Java and it works…I wasted 2 days chasing a stupid problem and all it was a plus sign instead of multiplication in my dot product…doh!

Now that I have it in my Java code I find it kind of lacking. The FPS code is exactly what you see in FPS games as an observer but I realized I need one more component to this view and that is the ability to roll around the lookat vector, which is not available in the code above or in FPS games either (from what I can remember, I usually play and not spectate :slight_smile: ).

On additional thing, instead of using gluLookAt() as I intended, I used what the code did, and that was using the glMultMatrix() call. Anyway, if you are interested I can provide my code in Java.

I got my rotations working! YAAAY

I’m going to see if I can do nice things with the camera too (I just got the object rotating). Thanks for everyone’s help so far! I used quaternions for the rotations, which are horrible at first, but are pretty ok after you figure them out.

I hope you can share your work with us at some time…pretty please.

Here are the files for the FPS Fly Through code that I converted to JAVA…this is not an exact conversion because I’m currently not using the ‘speed’ components that the original OpenGL code has and so if you use the mouse and keyboard at the same time it might appear that the scene is choppy…but overall it works pretty well…attached are the files.

I update the code to now include roll control capability and corrected mouse motion.

You can do either FPS style or modified FPS with roll rotation capability.

and here are the last files since I can only attach 4 at a time.

Controls are:
Keyboard UP - moves the camera into the screen
Keyboard DOWN - moves the camera back
Keyboard LEFT - moves the camera to the left (teapot goes to the right)
Keyboard RIGHT - moves the camera to the right (teapot to left)
Keyboard PAGE_UP - moves the camera up along global Y axis (teapot goes down) (not “current” y axis of the view)
Keyboard PAGE_DOWN - moves the camera down along global Y axis

Keyboard F - toggle between FPS and Modified FPS modes
Keyboard COMMA - roll left (valid only in the modified FPS view)
Keyboard PERIOD - roll right (valid only in the modified FPS view)

Mouse Controls - Click and Hold left mouse button to orient the view vector.

Combination of holding down mouse button and keyboard up/down/left/right keys makes you fly through the scene.

If you rotate the view in the FPS mode then the left-right mouse motion causes a rotation about the fixed vertical axis of the original scene.

If you rotate the view in the Modified FPS mode then the left-right mouse motion causes a rotation about the current UP vector of the view…this lets you basically fly through the scene and rotate in all different directions…it is awesome (I think)

It’s probably not perfect, but it seems to work just fine.

Use this with glMultMatrix() in your display function when modelview matrix is your current matrix.