简体   繁体   中英

OpenGL, Rotation around a point doesn't work still around the origin

I did the (translate, rotate, translate) thing but it still rotates around the origin. All I did is when you press the r key, the trick will begin which is (translate, rotate, translate). the result is that it is still rotating around the origin

#include <gl/glut.h> 

void OnKeyPress(unsigned char key, int x, int y) 
{ 
    if (key == 27)  
        exit(0); 
    switch(key) 
    { 
    case 'r': 
    case 'R': 
        // trick start here *********************
        glTranslatef(-60,-20,0);
        glRotatef(10, 0, 0, 1);
        glTranslatef(60, 20, 0);
        glutPostRedisplay();
        break; 
    };
} 

void OnDisplay()  
{  
    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3f(0.0f,0.5f,1.0f); 

    glBegin(GL_TRIANGLES); 
    glVertex2f(20, 20); 
    glVertex2f(60, 20);
    glVertex2f(20, 100);
    glEnd(); 
    glFlush();  
} 

int  main( int  argc, char *argv[]) 
{
    glutInit(&argc, argv);       
    glutInitDisplayMode(GLUT_RGBA);   
    glutInitWindowPosition(100, 100);  
    glutInitWindowSize(800, 600); 
    glutCreateWindow("OpenGL Lab1" ); 
    glutDisplayFunc(OnDisplay);
    glutKeyboardFunc(OnKeyPress); 

    glClearColor(1.0, 1.0, 1.0, 0.0);    
    glMatrixMode(GL_PROJECTION);  
    glLoadIdentity(); 
    gluOrtho2D(-100, 100,  -100, 100);  

    glutMainLoop();  

    return 0; 
}

You need to switch the order of your glTranslate calls because the last transformation done is the first one applied to the vertex. See, every transformation is a matrix, whose your current matrix is multiplied to. The resulting matrix is then multiplied to the vertex in order to determine its final position.

So if you have:

 glTranslatef(-60,-20,0); (T1)
 glRotatef(10, 0, 0, 1);  (R)
 glTranslatef(60, 20, 0); (T2)

and also have an old matrix Mo stored from the previous frame, you will have:

 M = (((Mo * T1) * R) * T2)

in the end, this M is multiplied by each vertex Vo, to determine its final position:

 V = M * Vo

Matrix multiplications are non-commutative, but they are associative, thus the parenthesis order does not matter, and all these transformations are mathematically equivalent to:

 V = Mo * T1 * R * (T2 * Vo)

Note that (T2 * Vo) is a vertex transformed by T2 (your last translation). If we call it V1, we have:

 V = Mo * T1 * (R * V1)

See that V1, your original vertex transformed by T2, is now in turn being transformed by the rotation R in (R * V1), resulting in another vertex, now translated and then rotated. Keep going on solving the expression right to left and you will have all the transformations applied to the vertex in the inverse order on where they were "called" in the OpenGL code.

I assume you know why you have to translate-rotate-untranslate in order to have the rotation around the point you want, but you got it wrong when you said that the "thing" was being rotated around the origin in your code. In fact, if you pay attention, you will notice it was being rotated around point (-60, -20).

Finally, you are not using the model-view matrix, but doing all the transformation using the perspective matrix (which incidentally works, since you are not resetting it every frame, as most applications do). You should not be doing this, but instead, using the GL_MODELVIEW to these kind of transformation. Try finishing your Initializing function with:

...
  Set_Transformations();
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glutMainLoop();
}

Flip it around (+, rot, -) instead of (-, rot, +) :

#include <gl/glut.h> 

int angle = 0;
void OnKeyPress(unsigned char key, int x, int y) 
{ 
    if (key == 27)  
        exit(0); 
    switch(key) 
    { 
    case 'r': 
    case 'R': 
        angle += 10;
        glutPostRedisplay();
        break; 
    };
} 

void OnDisplay()  
{  
    glClear(GL_COLOR_BUFFER_BIT); 
    glColor3f(0.0f,0.5f,1.0f); 

    glClearColor(1.0, 1.0, 1.0, 0.0);    
    glMatrixMode(GL_PROJECTION);  
    glLoadIdentity(); 
    gluOrtho2D(-100, 100, -100, 100);  

    glMatrixMode(GL_MODELVIEW);  
    glLoadIdentity(); 

    // trick start here *********************
    glTranslatef(60, 20, 0);
    glRotatef( angle, 0, 0, 1);
    glTranslatef(-60,-20,0);

    glBegin(GL_TRIANGLES); 
    glColor3ub(0,0,255);
    glVertex2f(20, 20); 
    glColor3ub(255,0,0);
    glVertex2f(60, 20);
    glColor3ub(0,0,255);
    glVertex2f(20, 100);
    glEnd(); 

    glFlush();  
} 

int  main( int  argc, char *argv[]) 
{
    glutInit(&argc, argv);       
    glutInitDisplayMode(GLUT_RGBA);   
    glutInitWindowPosition(100, 100);  
    glutInitWindowSize(800, 600); 
    glutCreateWindow("OpenGL Lab1" ); 
    glutDisplayFunc(OnDisplay);
    glutKeyboardFunc(OnKeyPress); 

    glutMainLoop();  

    return 0; 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM