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() 関数を削除しても、何も変わらないように見えます。違いはわかりません。これは本当に私を混乱させます。
これらの 2 つの例で glPushMatrix() と glPopMatrix() が何をするか説明できる人はいますか?

4

1 に答える 1

4

GL では、特に新しいマトリックス (glLoadIdentity()または同様のもの) をロードしない限り、マトリックス操作は現在アクティブなマトリックスに累積されます。glPushMatrix()現在のマトリックスをスタックに保存し、後で取得して、glPopMatrix()破棄できる変更を加えることができます。

glPushMatrix()最初の例では、 andを削除すると、回転がglPopMatrix()の回転と連結され、回転が急速に加速します (角度が 180 度を超えると、最終的に逆になり、後方に戻ると思います)。

2 番目の例では、モデル ビュー マトリックスを で再初期化しているglLoadIdentity()ため、そのような変換の蓄積はありません。

于 2013-02-23T08:52:15.030 に答える