2013-01-17 103 views
4

我已经能够使用模型视图矩阵和像glTranslatef()gluLookAt()这样的函数来转换对象或整个场景的视角,但是当我尝试去做这两件事时,我会遇到问题。关于使用OpenGL模型视图矩阵和矩阵变换的说明

看来,无论我用于gluLookAt()的参数如何,我绘制的对象都从相同的角度显示。我试着根据我在其他线索中读到的运气,根据glPushMatrix()glPopMatrix的不同用途调用函数。这是我现在拥有的。他们应该移动的物体,但我只能让他们从一个角度出现。例如,因为它们应该在xy平面上移动,并且逆时针旋转,所以我认为将z_0更改为-30会使它们看起来像是顺时针移动,但它似乎没有任何区别。在它之前有一长串的常量,我将被忽略。最终目标是制作一个简单的太阳系模型。

GLfloat time = 0.0; 
GLfloat inc = 0.01; 

// viewing parameters 
GLint winWidth = 600, winHeight = 600; 
GLfloat x_0 = 0.0, y_0 = 0.0, z_0 = 30.0; 
GLfloat xref = 0.0, yref = 0.0, zref = 0.0; 
GLfloat Vx = 0.0, Vy= 1.0, Vz = 0.0; 
GLfloat xwMin = -50.0, ywMin = -50.0, xwMax = 50.0, ywMax = 50.0; 
GLfloat dnear = .3, dfar = 10.0; 

void view(void) { 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(xwMin, xwMax, ywMin, ywMax, dnear, dfar); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(x_0, y_0, z_0, xref, yref, zref, Vx, Vy, Vz); 
} 

void init(void) { 
    view(); 
    glEnable(GL_DEPTH_TEST); 
} 

void drawPlanet(GLfloat maj, GLfloat min, GLfloat x0, GLfloat theta, 
     GLfloat size) { 
    GLfloat x = maj * cosf(theta) + x0; 
    GLfloat y = min * sinf(theta); 
    glMatrixMode(GL_MODELVIEW); 
    glPushMatrix(); 
    glLoadIdentity(); 
    glTranslatef(x, y, 0); 
    glutSolidSphere(size, 25, 25); 
    glPopMatrix(); 
} 

void display(void) { 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glColor3f(1.0, 1.0, 1.0); 

    drawPlanet(MERCURY_MAJOR, MERCURY_MINOR, MERCURY_CENTER, 
     time/MERCURY_YEAR, MERCURY_SIZE); 

    drawPlanet(MARS_MAJOR, MARS_MINOR, MARS_CENTER, 
     time/MARS_YEAR, MARS_SIZE); 

    drawPlanet(URANUS_MAJOR, URANUS_MINOR, URANUS_CENTER, 
     time/URANUS_YEAR, URANUS_SIZE); 

    glFlush(); 
} 

void idle(void) { 
    time += inc; 
    display(); 
    glutSwapBuffers(); 
} 

int main (int argc, char **argv) { 
    glutInit(&argc, argv); 
    glutInitWindowSize(500,500); 
    glutInitWindowPosition(0,0); 
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH); 
    glutCreateWindow(""); 

    init(); 

    glutDisplayFunc(display); 
    glutIdleFunc(idle); 

    glutMainLoop(); 
} 

如果有人看到的东西我失踪我真的appreaciate一些额外的阅读,这将帮助我解决这个问题的解释或方向。

+1

当你调用'drawPlanet'时,你用'glLoadIdentity'清除了由'gluLookAt'设置的矩阵。 – yiding

回答

4

你制作了典型的OpenGL新手错误,并将你的矩阵操作散布在各处。你从来没有初始化 OpenGL矩阵状态。进入显示功能时始终将其设置为新的。这使事情变得更容易发现。

另外,您可能会错误地将OpenGL用于带有glPush/PopMatrix的场景图形“神奇地”建立变换层次。

glPushMatrix - 正如你可能知道的那样 - 制作堆栈矩阵当前顶部的一个副本并将其推入堆栈。这个想法是做出临时副本,进一步转换可以成倍增加。

现在,让我们看看你的代码以稍微不同的形式:

void display(void) { 
    glViewport(…); 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(xwMin, xwMax, ywMin, ywMax, dnear, dfar); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(x_0, y_0, z_0, xref, yref, zref, Vx, Vy, Vz); 

    glColor3f(1.0, 1.0, 1.0); 

    { 
     GLfloat x = maj * cosf(theta) + x0; 
     GLfloat y = min * sinf(theta); 
     glMatrixMode(GL_MODELVIEW); 
     glPushMatrix(); 
     glLoadIdentity(); // <<<<<<<<< 

     glTranslatef(x, y, 0); 
     glutSolidSphere(size, 25, 25); 
     glPopMatrix(); 
    } 

你看看这里发生了什么?您将重置您的模型视图矩阵以识别,然后将其转换。之前创建的查看矩阵完全被丢弃,并且对球体绘图没有影响。

删除那glLoadIdentity()我标记和事情应该工作得很好。

+0

好的,这是有道理的。我重新组织了我的代码来整合矩阵转换,这也有所帮助。感谢您的答复。 – user1986358