2011-05-12 44 views
2

我一直在試圖解決這個圖像OpenGL顯示問題:C++對gluLookAt

程序繪製顏色立方體,並允許用戶適當地移動相機以透視觀察進行試驗。立方體也應該旋轉。

我已經完成了編碼,它在這裏。看來除了1個簡單的問題,做工精細:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing 
#include <stdio.h> 
#include <glut.h> 

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}}; 
void drawPolygon(float a[3],float b[3],float c[3],float d[3]) 
{ 
    glBegin(GL_POLYGON); 
     glVertex3fv(a); 
     glVertex3fv(b); 
     glVertex3fv(c); 
     glVertex3fv(d); 
    glEnd(); 
    glFlush(); 
} 
void drawCube(float v[8][3]) 
{ 
    glColor3f(1,0,0); 
    drawPolygon(v[0],v[1],v[2],v[3]); 
    glColor3f(0,1,0); 
    drawPolygon(v[0],v[1],v[6],v[7]); 
    glColor3f(0,0,1); 
    drawPolygon(v[7],v[6],v[5],v[4]); 
    glColor3f(1,1,0); 
    drawPolygon(v[2],v[3],v[4],v[5]); 
    glColor3f(0,1,1); 
    drawPolygon(v[1],v[2],v[5],v[6]); 
    glColor3f(1,0,1); 
    drawPolygon(v[0],v[3],v[4],v[7]); 

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

    glColor3f(1,0,0); 
    //glRotatef(60,1,1,0); 
    drawCube(v); 
    glFlush(); 
} 

void reshape(int width,int height) 
{ 
    glViewport(0,0,width,height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-2,2,-2,2,-2,2); 
    glMatrixMode(GL_MODELVIEW); 
    glutPostRedisplay(); 
} 

void mouse(int btn,int state,int x,int y) 
{ 
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
     glRotatef(2,1,0,0); 
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) 
     glRotatef(2,0,1,0); 
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 
     glRotatef(2,0,0,1); 

    glutPostRedisplay(); 
} 
float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0; 
void keyboard(unsigned char key,int x,int y) 
{ 
    if(key == 'x') 
     ex += 0.1; 
    if(key == 'X') 
     ex -= 0.1; 
    if(key == 'y') 
     ey += 0.1; 
    if(key == 'Y') 
     ey -= 0.1; 
    if(key == 'z') 
     ez += 0.1; 
    if(key == 'Z') 
     ez -= 0.1; 
    glMatrixMode(GL_PROJECTION); 
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz); 
    glutPostRedisplay(); 
} 
void main(int argc,char** argv) 
{ 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(800,800); 
    glutCreateWindow("spin cube"); 

    glClearColor(1,1,1,0); 

    glEnable(GL_DEPTH_TEST); 

    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutMouseFunc(mouse); 
    glutKeyboardFunc(keyboard); 

    glutMainLoop(); 
} 

鼠標立方體旋轉點擊

通過X/X Y/Y Z/Z

相機移動,但問題是,當我第一次按下鍵時,顯示屏消失。然後第二次它正確地移動相機。爲什麼?我希望相機能夠移動而不會消失。哪裏不對?

回答

2

有你的程序中兩個錯誤:

  • 你治療的OpenGL像的持久化的場景圖 - 但是OpenGL剛纔只繪製圖片。
  • 將視點變換應用於投影矩陣。

兩者都是根本錯誤的。這是你的代碼的修正版本:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing 
#include <stdio.h> 
#include <glut.h> 

float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}}; 
void drawPolygon(float a[3],float b[3],float c[3],float d[3]) 
{ 
    glBegin(GL_POLYGON); 
     glVertex3fv(a); 
     glVertex3fv(b); 
     glVertex3fv(c); 
     glVertex3fv(d); 
    glEnd(); 
} 

void drawCube(float v[8][3]) 
{ 
    glColor3f(1,0,0); 
    drawPolygon(v[0],v[1],v[2],v[3]); 
    glColor3f(0,1,0); 
    drawPolygon(v[0],v[1],v[6],v[7]); 
    glColor3f(0,0,1); 
    drawPolygon(v[7],v[6],v[5],v[4]); 
    glColor3f(1,1,0); 
    drawPolygon(v[2],v[3],v[4],v[5]); 
    glColor3f(0,1,1); 
    drawPolygon(v[1],v[2],v[5],v[6]); 
    glColor3f(1,0,1); 
    drawPolygon(v[0],v[3],v[4],v[7]); 
} 

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0; 
void display() 
{ 
    int win_width, win_height; 
    win_width = glutGet(GLUT_WINDOW_WIDTH); 
    win_height = glutGet(GLUT_WINDOW_HEIGHT); 

    glViewport(0,0,width,height); 

    glClearColor(1,1,1,0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glEnable(GL_DEPTH_TEST); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-2,2,-2,2,-2,2); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz); 

    glRotatef(rot_x,1,0,0); 
    glRotatef(rot_y,0,1,0); 
    glRotatef(rot_z,0,0,1); 

    glColor3f(1,0,0); 
    //glRotatef(60,1,1,0); 
    drawCube(v); 

    glFinish(); 
} 

void mouse(int btn,int state,int x,int y) 
{ 
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
     rot_x += 2; 

    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) 
     rot_y += 2; 

    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 
     rot_z += 2; 

    glutPostRedisplay(); 
} 

void keyboard(unsigned char key,int x,int y) 
{ 
    if(key == 'x') 
     ex += 0.1; 
    if(key == 'X') 
     ex -= 0.1; 
    if(key == 'y') 
     ey += 0.1; 
    if(key == 'Y') 
     ey -= 0.1; 
    if(key == 'z') 
     ez += 0.1; 
    if(key == 'Z') 
     ez -= 0.1; 

    glutPostRedisplay(); 
} 

void main(int argc,char** argv) 
{ 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(800,800); 
    glutCreateWindow("spin cube"); 

    glutDisplayFunc(display); 
    glutMouseFunc(mouse); 
    glutKeyboardFunc(keyboard); 

    glutMainLoop(); 
} 
1

gluLookAt不應進入投影矩陣,而是進入模型視圖。我也建議你保持你的立方體旋轉和眼睛位置的跟蹤和應用它們的顯示功能,而不是內部:

//Program to draw a color cube and allow the user to move the camera suitably to experiment with perspective viewing 
#include <stdio.h> 
#include <glut.h> 

float ex=0,ey=0,ez=-10,cx=0,cy=0,cz=0,ux=0,uy=1,uz=0; 
float cubex=0,cubey=0,cubez=0; 
float v[][3] = {{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1},{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}}; 
void drawPolygon(float a[3],float b[3],float c[3],float d[3]) 
{ 
    glBegin(GL_POLYGON); 
     glVertex3fv(a); 
     glVertex3fv(b); 
     glVertex3fv(c); 
     glVertex3fv(d); 
    glEnd(); 
} 
void drawCube(float v[8][3]) 
{ 
    glColor3f(1,0,0); 
    drawPolygon(v[0],v[1],v[2],v[3]); 
    glColor3f(0,1,0); 
    drawPolygon(v[0],v[1],v[6],v[7]); 
    glColor3f(0,0,1); 
    drawPolygon(v[7],v[6],v[5],v[4]); 
    glColor3f(1,1,0); 
    drawPolygon(v[2],v[3],v[4],v[5]); 
    glColor3f(0,1,1); 
    drawPolygon(v[1],v[2],v[5],v[6]); 
    glColor3f(1,0,1); 
    drawPolygon(v[0],v[3],v[4],v[7]); 
} 
void display() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 


    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(ex,ey,ez,cx,cy,cz,ux,uy,uz); 
    glRotatef(cubex, 1, 0, 0); 
    glRotatef(cubey, 0, 1, 0); 
    glRotatef(cubez, 0, 0, 1); 

    glColor3f(1,0,0); 
    //glRotatef(60,1,1,0); 
    drawCube(v); 
    glFinish(); 
} 

void reshape(int width,int height) 
{ 
    glViewport(0,0,width,height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(-2,2,-2,2,-2,2); 
    glutPostRedisplay(); 
} 

void mouse(int btn,int state,int x,int y) 
{ 
    if(btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) 
     cubex += 2; 
    if(btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) 
     cubey += 2; 
    if(btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) 
     cubez += 2; 

    glutPostRedisplay(); 
} 

void keyboard(unsigned char key,int x,int y) 
{ 
    if(key == 'x') 
     ex += 0.1; 
    if(key == 'X') 
     ex -= 0.1; 
    if(key == 'y') 
     ey += 0.1; 
    if(key == 'Y') 
     ey -= 0.1; 
    if(key == 'z') 
     ez += 0.1; 
    if(key == 'Z') 
     ez -= 0.1; 
    glutPostRedisplay(); 
} 
void main(int argc,char** argv) 
{ 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(800,800); 
    glutCreateWindow("spin cube"); 

    glClearColor(1,1,1,0); 

    glEnable(GL_DEPTH_TEST); 

    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutMouseFunc(mouse); 
    glutKeyboardFunc(keyboard); 

    glutMainLoop(); 
} 

這並不等於100%你最初嘗試實現,因爲它將三種圍繞x,y和z軸分別累積連續旋轉而不是增量旋轉。

另外你並不需要所有的glFlush調用,單個調用glFinish在渲染結束時應該是足夠的,甚至更好;交換到雙重緩衝渲染並使用glutSwapBuffers代替。

+0

感謝您的解釋:)偏偏是那種渲染髮生的一切......任何解釋將是有益的。我的意思是什麼錯在調用gluLookAt分開? – footy 2011-05-12 14:22:24

+2

@footy:投影矩陣是OpenGL「相機」的「鏡頭」(OpenGL沒有定義術語「相機」,它只是在整個世界中移動)。在投影矩陣中進行gluLookAt,就好像你在沒有相機其餘部分的情況下在鏡頭周圍移動一樣;這樣做有它的應用程序(傾斜/移位攝影,你可以在OpenGL中完成,也可以通過傾斜/平移投影矩陣來完成),但是對於設置視點並非有用。 – datenwolf 2011-05-12 16:45:45