OpenGL,围绕一个点的旋转仍然不能在原点周围工作

时间:2012-03-20 21:55:56

标签: c++ visual-c++ opengl

我做了(翻译,旋转,翻译)的事情,但它仍然围绕原点旋转。我所做的就是当你按下r键时,技巧将开始,即翻译,旋转,翻译。结果是它仍然围绕原点旋转

#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; 
}

2 个答案:

答案 0 :(得分:4)

您需要切换glTranslate次调用的顺序,因为上次完成的转换是应用于顶点的第一次转换。看,每个变换都是一个矩阵,其当前矩阵乘以。然后将得到的矩阵乘以顶点,以确定其最终位置。

所以如果你有:

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

并且还有一个从前一帧存储的旧矩阵Mo,您将拥有:

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

最后,这个M乘以每个顶点Vo,以确定它的最终位置:

 V = M * Vo

矩阵乘法是非交换的,但它们是关联的,因此括号顺序无关紧要,所有这些转换在数学上等同于:

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

请注意,(T2 * Vo)是由T2(您的上一次翻译)转换的顶点。如果我们称之为V1,我们有:

 V = Mo * T1 * (R * V1)

看到V1,由T2转换的原始顶点现在又被(R * V1)中的旋转R转换,产生另一个顶点,现在被翻译然后旋转。继续从右到左解决表达式,你将把所有的变换应用于它们在OpenGL代码中被“调用”的相反顺序的顶点。

我假设您知道为什么必须翻译 - 旋转 - 未翻译才能围绕您想要的点进行旋转,但是当您说代码中的“东西”围绕原点旋转时,您就错了。事实上,如果你注意,你会注意到它在点(-60,-20)附近旋转。

最后,您没有使用模型视图矩阵,而是使用透视矩阵进行所有变换(顺便说一下,因为您不像大多数应用程序那样每帧都重置它)。您不应该这样做,而是使用GL_MODELVIEW进行这种转换。尝试使用以下方法完成初始化功能:

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

答案 1 :(得分:1)

翻转(+, rot, -)而不是(-, 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; 
}