0

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

4

2 回答 2

1

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

假设您的模型视图堆栈上有一些矩阵A。现在您使用glPushMatrix,本质上是保存A以便以后恢复它。在 push-pop 块中,您告诉 GLUT 使用前面提到的模型视图矩阵A绘制一个球体,它有义务这样做。

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

所以简而言之,转换调用之后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 年?),所以我建议使用更现代的方法来选择 OpenGL 。

编辑:

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

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

  1. day绕 y 轴旋转
  2. 翻译
  3. year绕 y 轴旋转

(现在,您正在以相反的方式进行操作,这可以解释您遇到的奇怪行为。另请参见此处。)

根据 JasonD 的评论,您的转换顺序一开始是正确的,但了解背景仍然没有什么坏处。;)

于 2013-03-17T10:13:40.253 回答
1

我怀疑您在 ModelView 矩阵中确实有其他转换。如果它已经设置为身份,那么加载身份不会改变行为。

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

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

于 2013-03-19T09:39:20.880 回答