glPushMatrix()glPopMatrix()不起作用

时间:2019-06-16 08:39:20

标签: c++ opengl opengl-compat

我尝试编写两个独立的对象移动代码,这意味着两个对象都沿两个不同的方向工作,但是不能连续移动。当我将glTranslatef()放在glPushMatrix() ... glPopMatrix()外面时,它可以正常工作。

void display()
{
    glClearColor(0.356, 0.701, 0.0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

        // if put gltransate() at here the object will moving continuous

    glPushMatrix();
      glTranslatef(.5, 0, 0);
        glBegin(GL_QUADS);
        glColor3f(1.0, 1.0, 1.0);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.8, 0.8);
        glVertex2f(-0.2, 0.8);
        glVertex2f(-0.2, 0.5);
      glEnd();
    glPopMatrix();

    glPushMatrix();
          glTranslatef(-.5, 0, 0);
      glBegin(GL_QUADS);
        glColor3f(.0, .0, .0);
        glVertex2f(-0.8, 0.2);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.2, 0.5);
        glVertex2f(-0.2, 0.2);
        glEnd();
    glPopMatrix();

}

我希望第一个正方形对象的会不断向右移动,但似乎只是平移一次然后停在该位置。

1 个答案:

答案 0 :(得分:2)

请注意,通常我建议使用OpenGL Mathematics之类的数学库进行矩阵计算,并使用glLoadMatrix()将类型glm::mat4的矩阵加载到当前矩阵。

无论如何,类似glTranslatef()的操作会创建一个新矩阵,并将当前矩阵乘以新矩阵。这就是为什么连续调用glTranslatef会导致渐进的“移动”的原因。

glPushMatrix / glPopMatrix存储并恢复矩阵堆栈中的矩阵。因此连续运动无法进行,因为当前矩阵在每一帧开始时都保持不变。


一种解决方案是将翻译存储到变量中并增加变量:

GLfloat trans_a = 0.0f;
GLflaot trans_b = 0.0f;

void display()
{
    glClearColor(0.356, 0.701, 0.0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glPushMatrix();

      trans_a += 0.5f;
      glTranslatef(trans_a, 0, 0);

      glBegin(GL_QUADS);
        glColor3f(1.0, 1.0, 1.0);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.8, 0.8);
        glVertex2f(-0.2, 0.8);
        glVertex2f(-0.2, 0.5);
      glEnd();
    glPopMatrix();

    glPushMatrix();

      trans_b += 0.5f;
      glTranslatef(trans_b, 0, 0);

      glBegin(GL_QUADS);
        glColor3f(.0, .0, .0);
        glVertex2f(-0.8, 0.2);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.2, 0.5);
        glVertex2f(-0.2, 0.2);
      glEnd();
    glPopMatrix();
}

更通用的解决方案是通过glGetFloatv(GL_MODELVIEW_MATRIX, ...)获取并存储当前矩阵(在转换后),并通过glLoadMatrix()重新加载:

// init identity matrices
GLfloat mat_a[16] = {1, 0, 0, 0,    0, 1, 0, 0,    0, 0, 1, 0,    0, 0, 0, 1 };
GLfloat mat_b[16] = {1, 0, 0, 0,    0, 1, 0, 0,    0, 0, 1, 0,    0, 0, 0, 1 };

void display()
{
    glClearColor(0.356, 0.701, 0.0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glPushMatrix();

      glLoadMatrixf(mat_a)
      glTranslatef(0.5f, 0, 0);
      glGetFloatv(GL_MODELVIEW_MATRIX, mat_a);

      glBegin(GL_QUADS);
        glColor3f(1.0, 1.0, 1.0);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.8, 0.8);
        glVertex2f(-0.2, 0.8);
        glVertex2f(-0.2, 0.5);
      glEnd();
    glPopMatrix();

    glPushMatrix();

      glLoadMatrixf(mat_b)
      glTranslatef(0.5f, 0, 0);
      glGetFloatv(GL_MODELVIEW_MATRIX, mat_b);

      glBegin(GL_QUADS);
        glColor3f(.0, .0, .0);
        glVertex2f(-0.8, 0.2);
        glVertex2f(-0.8, 0.5);
        glVertex2f(-0.2, 0.5);
        glVertex2f(-0.2, 0.2);
      glEnd();
    glPopMatrix();
}

请注意,在这种情况下,mat_amat_b应该在视图矩阵初始化之后加载,并且当视图矩阵更改时,矩阵不会考虑这一点。