关于opengl:调用glLoadIdentity显示尴尬的行为

Calling glLoadIdentity shows awkward behaviour

我已经用c语言编写了这段代码,以绘制具有太阳和行星的行星系统

1
2
3
4
5
6
7
8
9
10
11
12
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的值时,当它在中心球体后面时会出现旋转的一半,然后再次离开"视图",并且球体的尺寸也比预期的大。如果我注释掉对glLoadIdentity()的调用,则一切正常。据我所知,glLoadIdentity()使用恒等矩阵加载当前Matrix(ModelView_Matrix),以便所有平移和旋转的效果都相反,但是为什么在这种情况下,当调用时绘制的对象在没有旋转时以不同的方式还是在调用之前执行转换?


我怀疑您在ModelView矩阵中确实还有其他转换。如果已经将其设置为标识,那么加载标识将不会更改行为。

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

如果不进行先前的视图转换,则将在与视图相同的位置绘制第一个球体-换句话说,摄影机将在球体内。


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

假设您的模型视图堆栈中有一些矩阵A。现在,您使用glPushMatrix,实际上是保存A以便稍后将其还原。在push-pop块内,您告诉GLUT使用前面提到的模型视图矩阵A来绘制球形,这是它的职责。

如果您现在调用glLoadIdentity,则A之前的所有内容都将消失,直到您调用glPopMatrix,这将恢复A的先前状态。

因此,简而言之,glLoadIdentity之后的转换调用基于身份矩阵,而不是glPushMatrix之前的矩阵状态。

看到您想要做的是绘制太阳系。最好执行以下操作:

1
2
3
4
5
6
7
8
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年?),所以我建议使用更现代的方式来拾取OpenGL。方法。

编辑:

在重新阅读问题时,另一件事引起了我的注意:

假设year指定行星围绕太阳公转的位置,并且day指定植物围绕其自身的极轴旋转了多少,则正确的转换顺序为:

  • 绕y轴旋转day
  • 翻译
  • 绕y轴旋转year
  • (现在,您正在以相反的方式进行操作,这可以解释您遇到的奇怪行为。另请参见此处。)

    根据JasonD的评论,您的转换顺序本来就是正确的,但是了解背景仍然不会有任何伤害。 ;)