调用glLoadIdentity会显示出尴尬的行为

时间:2013-03-17 09:31:04

标签: opengl graphics glut

我在c中编写了这段代码来绘制一个带有太阳和行星的行星系统

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW_MATRIX);
glPushMatrix();
glutWireSphere(1.0, 20, 16);
glLoadIdentity();
glRotatef((GLfloat) year ,0.0,1.0,0.0);
glTranslatef(2.0, 0.0, 0.0);
glRotatef((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8);
glPopMatrix();
glutSwapBuffers();

但是当我编译并运行代码时,第二个球体不在视图中。在我增加y的值之后,当它在中心球体后面然后再次离开View时,它出现旋转的一半,同时球体的大小也大于预期。如果我注释掉对glLoadIdentity()的调用,一切正常。据我所知,glLoadIdentity()使用单位矩阵加载当前矩阵(ModelView_Matrix),以便所有平移和旋转的效果相反,但为什么在这种情况下,当没有旋转时被调用的对象以不同的方式绘制还是在电话会议之前进行转换?

2 个答案:

答案 0 :(得分:1)

我怀疑您的问题与glPushMatrixglPopMatrixglLoadIdentity结合使用的方式有关:

假设您的modelview堆栈上有一些矩阵 A 。现在您使用glPushMatrix,基本上保存 A 以便稍后恢复。在push-pop块中,你告诉GLUT使用前面提到的模型视图矩阵 A 来绘制一个有意义的球体。

如果您现在致电glLoadIdentity,那么 A 以前的任何内容都会消失,直到您拨打glPopMatrix,这会恢复以前的 A

简而言之,glLoadIdentity之后的转换调用基于单位矩阵而不是glPushMatrix之前的矩阵状态。

看到你想要做的是绘制太阳系。做这样的事情可能是最好的:

glPushMatrix();
    /* Transformations positioning the sun */
    /* Draw the sun */
    glPushMatrix();
        /* Transformations for getting from the sun to the planet */
        /* Draw the planet */
    glPopMatrix();
glPopMatrix();

顺便说一句,固定功能管道(glTranslate,glRotate,glPushMatrix,...)已经被弃用了很长一段时间(大约10年?),所以我建议使用更多的{ {3}}

修改

在重读这个问题的同时,另一件事引起了我的注意:

假设year指定行星围绕太阳旋转的位置,day指定植物围绕其自身极轴旋转的程度,正确的变换顺序为:

  1. 围绕y轴旋转day
  2. 翻译
  3. 围绕y轴旋转year
  4. (现在,你正在以相反的方式这样做,这可以解释你正在经历的奇怪行为。另见modern approach。)

    根据JasonD的评论,你的转型订单首先是正确的,但是了解背景仍然不会有什么坏处。 ;)

答案 1 :(得分:1)

我怀疑你在ModelView矩阵中有其他转换。如果已将其设置为标识,则加载标识不会改变行为。

您提供的代码仅设置本地模型转换。没有应用投影或视图转换,因此必须在其他地方进行。也许在初始化时。

如果没有先前的视图转换,第一个球体将在与视图相同的位置绘制 - 换句话说,相机将位于球体内。