1
#include <iostream>
#include <GL/glut.h>
#include <math.h>

using namespace std;

#define WIDTH 400
#define HEIGHT 400

#include <math.h>
#define ColoredVertex(c, v) do{ glColor3fv(c); glVertex3fv(v); }while(0)

GLfloat angle = 0.0f;

void myDisplay(void)
{
     static int list = 0;
     if( list == 0 )
     {
         // 

         GLfloat
             PointA[] = { 0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6},
             PointB[] = {-0.5f, -sqrt(6.0f)/12, -sqrt(3.0f)/6},
             PointC[] = { 0.0f, -sqrt(6.0f)/12,   sqrt(3.0f)/3},
             PointD[] = { 0.0f,    sqrt(6.0f)/4,              0};
         GLfloat
             ColorR[] = {1, 0, 0},
             ColorG[] = {0, 1, 0},
             ColorB[] = {0, 0, 1},
             ColorY[] = {1, 1, 0};

         list = glGenLists(1);
         glNewList(list, GL_COMPILE);
         glBegin(GL_TRIANGLES);
         // ABC
         ColoredVertex(ColorR, PointA);
         ColoredVertex(ColorG, PointB);
         ColoredVertex(ColorB, PointC);
         // ACD
         ColoredVertex(ColorR, PointA);
         ColoredVertex(ColorB, PointC);
         ColoredVertex(ColorY, PointD);
         // CBD
         ColoredVertex(ColorB, PointC);
         ColoredVertex(ColorG, PointB);
         ColoredVertex(ColorY, PointD);
         // BAD
         ColoredVertex(ColorG, PointB);
         ColoredVertex(ColorR, PointA);
         ColoredVertex(ColorY, PointD);
         glEnd();
         glEndList();

         glEnable(GL_DEPTH_TEST);
     }
     // 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glPushMatrix();
     glRotatef(angle, 1, 0.5, 0);
     glCallList(list);
     glPopMatrix();
     glutSwapBuffers();
}

void myIdle(void)
{
     ++angle;
     if( angle >= 360.0f )
         angle = 0.0f;
     myDisplay();
}

int main(int argc, char* argv[])
{
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
     glutInitWindowPosition(200, 200);
     glutInitWindowSize(WIDTH, HEIGHT);
     glutCreateWindow("OpenGL window");
     glutDisplayFunc(&myDisplay);
     glutIdleFunc(&myIdle);
     glutMainLoop();
     return 0;
}

这是绘制旋转四面体的一个非常基本的示例。我不明白的是glPushMatrix()glPopMatrix()的使用。如果我删除这些代码,程序仍然可以工作,但动画似乎执行得更快。我不知道是什么导致了这种加速。
我已经尝试了另一个例子来找出诀窍。我只是将 myDisplay() 函数更改如下。

void myDisplay(void){
     glEnable(GL_DEPTH_TEST);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(75, 1, 1, 400000000);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     gluLookAt(0, 0, 200000000, 0, 0, 0, 0, 1, 0);

     static int list = 0;
     static int earthList =0;

     if(list==0){
        list = glGenLists(1);

        glNewList(list, GL_COMPILE);
        glColor3f(1.0f, 0.0f, 0.0f);
        glutSolidSphere(69600000, 20, 20);
        glEndList();
     }
     if(earthList==0){
        earthList = glGenLists(1);

        glNewList(earthList, GL_COMPILE);
        glColor3f(0.0f, 0.0f, 1.0f);
        glutSolidSphere(15945000, 20, 20);
        glEndList();
     }

     // draw a red sun
     glCallList(list);

     // draw the earth
     //glPushMatrix();
     glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);
     glTranslatef(150000000, 0.0f, 0.0f);
     glCallList(earthList);

     //glPopMatrix();

     glFlush();

     glutSwapBuffers();
} 

但是这一次,即使我删除了 glPushMatrix() 和 glPopMatrix() 函数,似乎也没有任何改变。我看不出有什么不同。这真的让我很困惑。
谁能解释这两个示例中 glPushMatrix() 和 glPopMatrix() 的作用?

4

1 回答 1

4

在 GL 中,除非您专门加载新矩阵(glLoadIdentity()或类似矩阵),否则矩阵运算会与当前活动的任何矩阵一起累积。glPushMatrix()glPopMatrix()允许您将当前矩阵存储在堆栈中,并在以后检索它,允许您进行可以丢弃的修改。

在您的第一个示例中,删除glPushMatrix()andglPopMatrix()将导致旋转与前一个旋转连接,从而导致旋转快速加速(我希望它最终会在角度超过 180 度时反转并向后移动)。

在您的第二个示例中,您正在使用 a 重新初始化模型视图矩阵,glLoadIdentity()因此不会有这样的变换累积。

于 2013-02-23T08:52:15.030 回答