Rotate an object on its own axes in OpenGL

2019-08-08 14:44发布

So I have a cube that I wish to rotate around any of its three axes (the axes of the cube, not the window). As many other similar questions have stated, my rotations work as long as I am only rotating in one direction, but when I start mixing them, I get strange results. In particular, the rotation about the y-axis always rotates about the y-axis of the window, regardless of how the cube has been rotated.

My drawing code is as follows:

glMatrixMode(GL_MODELVIEW) ;
glLoadIdentity();
gluLookAt(0.0, 5.0, 15.0,  
          0.0, 0.0, 0.0,  
          0.0, 1.0, 0.0);
glPushMatrix();
glRotatef(theta_y,0,1,0); 
glRotatef(theta_x,1,0,0);
glRotatef(theta_z,0,0,1);
draw_cube();
glPopMatrix();

This question seems to describe pretty much exactly what I am trying to do, and the accepted answer seems to be what I want to do, however the link he provides is dead.

From what I can gather in the linked question, my z-rotation is performed first, which means in my x-rotation (which would be next) I need to, instead of rotating about (1,0,0), I would rotate about (-sin(theta_z),cos(theta_z),0). But then for the third rotation, he only gives the link, saying it gets "very complicated." Now that the link is dead, I'm not sure how to go about this third rotation.

EDIT: Based on the replies, I have added three vectors: cube_x, cube_y, and cube_z to hold the current axes of my cube.They are initialized as follows:

float cube_x[] = {1.0f,0.0f,0.0f,0.0f};
float cube_y[] = {0.0f,1.0f,0.0f,0.0f};
float cube_z[] = {0.0f,0.0f,1.0f,0.0f};

Back in my drawing function, I have changed it so that the rotations are done around these axes rather than the global axes as I had previously. After performing the three rotations, I call glGetFloatv to get the current matrix and use a new function, update_vector to fill my cube vectors with their new values. This all is included below:

void update_vector(float vector[],float matrix[]) {
    vector[0] = matrix[0]*vector[0] + matrix[1]*vector[1] + matrix[2]*vector[2] + matrix[3]*vector[3];
    vector[1] = matrix[4]*vector[0] + matrix[5]*vector[1] + matrix[6]*vector[2] + matrix[7]*vector[3];
    vector[2] = matrix[8]*vector[0] + matrix[9]*vector[1] + matrix[10]*vector[2] + matrix[11]*vector[3];
    vector[3] = matrix[12]*vector[0] + matrix[13]*vector[1] + matrix[14]*vector[2] + matrix[15]*vector[3];

}

void my_display(void) {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) ;

    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity();
    gluLookAt(0.0, 5.0, 15.0,  
          0.0, 0.0, 0.0,  
          0.0, 1.0, 0.0); 
    glPushMatrix();
    glRotatef(theta_y,cube_y[0],cube_y[1],cube_y[2]); 
    glRotatef(theta_x,cube_x[0],cube_x[1],cube_x[2]);
    glRotatef(theta_z,cube_z[0],cube_z[1],cube_z[2]);

    //get the current matrix
    float my_matrix[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, my_matrix);

    //Multiply the matrix by each of my vectors
    update_vector(cube_x,my_matrix);
    update_vector(cube_y,my_matrix);
    update_vector(cube_z, my_matrix);

    make_cube();
    glPopMatrix();

    /* buffer is ready */
    glutSwapBuffers();

    return ;
}

Now when I try to rotate about the y axis, the cube seems to wobble around along a few axes for a little bit before finally settling into a rotation about the x-axis. Rotating about Z does the same thing. Only rotating about the x-axis seems to work.

EDIT: SOLUTION:

In his comment below, Gavin mentioned that the Y-axis rotation was always happening first. This is the whole issue. By adding a flag ROT and setting it based on which axis I am attempting to rotate around, I am able to order the rotations so that the axis being rotated about is done last.

2条回答
唯我独甜
2楼-- · 2019-08-08 14:50

After your LookAt you must translate by the negative position of the cube, do the rotations, then translate back to the cube's position.

查看更多
等我变得足够好
3楼-- · 2019-08-08 15:14

I don't know what's supposed to be complicated. OpenGL does the matrix math for you. Remember matrix multiplication is associative so if Rx etc are rotations about the coordinate axes, then Rx.Ry means rotate about y then x. It's always about the coordinate axes no matter where your shape has ended up in the meantime. BTW, OpenGL ES is right handed, unlike traditional OpenGL.

查看更多
登录 后发表回答