2013-07-08 48 views
1

我在OpenGL中使用Eclipse創建了一個保齡球遊戲。gluLookAt()無法按預期工作

現在我想在按下按鍵時更改相機的視圖。

但是當我按下x按鈕時,一切都消失了。

這裏我們的代碼: -

#include <GL/glut.h> 
#include <stdlib.h> 
int refreshMillis = 30; // Refresh period in milliseconds 
int windowWidth = 640; // Windowed mode's width 
int windowHeight = 480; // Windowed mode's height 
int windowPosX = 50; // Windowed mode's top-left corner x 
int windowPosY = 50; // Windowed mode's top-left corner y 
bool fullScreenMode = false; // Full-screen or windowed mode? 
GLfloat ballTSpeed = 0.15f; // Ball's speed in y directions 
GLfloat x = 1.0f, y = 10.0f, z = 10.0f, i = 0.0f, j = 0.0f, k = 0.0f, a = 0.0f, 
     b = 0.0f, c = -1.0f; 
bool moveBallUp = false, moveBallDown = false, isCollision = false, resetCall = 
     false; 
// 
GLfloat cone1[] = { 0.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 }; 
GLfloat cone2[] = { 2.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 }; 
GLfloat cone3[] = { -2.0f, 2.5f, -11.0f, /*rotated*/30.0f, -1.5, 0.0, 0.0 }; 

GLfloat ball[] = {/* X */0.0f, /* Y */-2.0f, /* Z */-6.0f, /*sphere*/1.0f, 50.0, 
     50.0 }; 
// 

void resetGame() { 

    resetCall = true; 
    cone1[0] = 0.0f; 
    cone1[1] = 2.5f; 
    cone1[2] = -11.0f; 
    /*rotated*/ 
    cone1[3] = 30.0f; 
    cone1[4] = -1.5; 
    cone1[5] = 0.0; 
    cone1[6] = 0.0; 

    cone2[0] = 2.0f; 
    cone2[1] = 2.5f; 
    cone2[2] = -11.0f; 
    /*rotated*/ 
    cone2[3] = 30.0f; 
    cone2[4] = -1.5; 
    cone2[5] = 0.0; 
    cone2[6] = 0.0; 

    cone3[0] = -2.0f; 
    cone3[1] = 2.5f; 
    cone3[2] = -11.0f; 
    /*rotated*/ 
    cone3[3] = 30.0f; 
    cone3[4] = -1.5; 
    cone3[5] = 0.0; 
    cone3[6] = 0.0; 

} 

const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f }; 

const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f }; 
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; 
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; 
const GLfloat high_shininess[] = { 100.0f }; 
static void resize(int width, int height) { 
    const float ar = (float) width/(float) height; 

    glViewport(0, 0, width, height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(x, y, z, i, j, k, a, b, c); 
    // eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz 
} 
/* Called back when the timer expired */ 
void Timer(int value) { 
    glutPostRedisplay(); // Post a paint request to activate display() 
    glutTimerFunc(refreshMillis, Timer, 0); // subsequent timer call at milliseconds 
} 
void keyboard(unsigned char key, int x, int y) { 
    switch (key) { 
    case 27: // ESC key 
     exit(0); 
     break; 
    case 'r': 
     resetGame(); 
     break; 
    case 'i': 
     x += 0.5; 
     gluLookAt(x, y, z, i, j, k, a, b, c); 
     // eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz 

    } 
} 

void specialKeys(int key, int x, int y) { 
    switch (key) { 
    case GLUT_KEY_F1: // F1: Toggle between full-screen and windowed mode 
     fullScreenMode = !fullScreenMode; // Toggle state 
     if (fullScreenMode) { // Full-screen mode 
      windowPosX = glutGet(GLUT_WINDOW_X); // Save parameters for restoring later 
      windowPosY = glutGet(GLUT_WINDOW_Y); 
      windowWidth = glutGet(GLUT_WINDOW_WIDTH); 
      windowHeight = glutGet(GLUT_WINDOW_HEIGHT); 
      glutFullScreen(); // Switch into full screen 
     } else { // Windowed mode 
      glutReshapeWindow(windowWidth, windowHeight); // Switch into windowed mode 
      glutPositionWindow(windowPosX, windowPosX); // Position top-left corner 
     } 
     break; 

    case GLUT_KEY_UP: 
     if (!isCollision) 
      moveBallUp = true; 
     break; 
    case GLUT_KEY_PAGE_UP: 
     ballTSpeed *= 1.2f; 
     break; 

    } 

} 

static void display(void) { 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    if (moveBallUp) { 
     ball[1] += ballTSpeed; 
     ball[2] -= 0.02 + ballTSpeed; 
    } 

    if (ball[1] >= (cone1[1] - 0.4) && ball[1] <= cone1[1]) { 

     if (!isCollision) 

     { 
      cone1[0] -= 0.5; 
      cone1[4] -= 10.0; 
      cone1[5] += 10.0; 
      cone1[2] += -0.3; 

      cone2[0] += 0.5; 
      cone2[4] -= 10.0; 
      cone2[5] -= 10.0; 
      cone2[2] += -0.4; 

      cone3[0] += 0.5; 
      cone3[4] -= 10.0; 
      cone3[5] -= 10.0; 
      cone3[2] += -0.4; 
     } 

     isCollision = true; 
     moveBallUp = false; // stop moving the ball 

    } 

    if (resetCall) { 

     if ((ball[1] >= -2.0f && ball[1] <= -1.6f) 
       && (ball[2] >= -6.0f && ball[2] <= -5.6f)) { 
      resetCall = false; 
      isCollision = false; 

     } 

     else { 

      ball[1] -= ballTSpeed; 
      ball[2] += 0.02 + ballTSpeed; 

     } 

    } 

    glColor3d(1, 1, 0); 
    glPushMatrix(); 
    glTranslated(cone1[0], cone1[1], cone1[2]); 
    glRotated(cone1[3], cone1[4], cone1[5], cone1[6]); 
    glutSolidCone(1, 2, 50, 50); 
    glPopMatrix(); 

    glColor3d(1, 0, 1); 
    glPushMatrix(); 
    glTranslated(cone2[0], cone2[1], cone2[2]); 
    glRotated(cone2[3], cone2[4], cone2[5], cone2[6]); 
    glutSolidCone(1, 2, 50, 50); 
    glPopMatrix(); 

    glColor3d(0, 0, 1); 
    glPushMatrix(); 
    glTranslated(cone3[0], cone3[1], cone3[2]); 
    glRotated(cone3[3], cone3[4], cone3[5], cone3[6]); 
    glutSolidCone(1, 2, 50, 50); 
    glPopMatrix(); 

    glColor3d(1, 0, 0); 
    glPushMatrix(); 
    glTranslated(ball[0], ball[1], ball[2]); 
    glutSolidSphere(ball[3], ball[4], ball[5]); 
    glPopMatrix(); 
    glPushMatrix(); 
    glColor3d(0.6, 1, 0.20); 

    glBegin(GL_QUADS); 
    glVertex3f(16.0, 5.0, -25.0); 
    glVertex3f(-16.0, 5.0, -25.0); 
    glVertex3f(-6.0, -4.0, -5.0); 
    glVertex3f(6.0, -4.0, -5.0); 
    glEnd(); 
    glColor3d(1, 1, 0); 
    glBegin(GL_QUADS); 
    glVertex3f(16.0, 15.0, -25.0); 
    glVertex3f(-16.0, 15.0, -25.0); 
    glVertex3f(-16.0, -4.0, -25.0); 
    glVertex3f(16.0, -4.0, -25.0); 
    glEnd(); 

    glutSwapBuffers(); 
} 

/* Program entry point */ 

int main(int argc, char *argv[]) { 
    glutInit(&argc, argv); 
    glutInitWindowSize(windowWidth, windowHeight); // Initial window width and height 
    glutInitWindowPosition(windowPosX, windowPosY); // Initial window top-left corner (x, y) 
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 

    glutCreateWindow("Balling Game 3d"); 

    glutReshapeFunc(resize); 
    glutDisplayFunc(display); 

    glClearColor(1, 1, 1, 1); 
    glEnable(GL_CULL_FACE); 
    glCullFace(GL_BACK); 

    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LESS); 

    glEnable(GL_LIGHT0); 
    glEnable(GL_NORMALIZE); 
    glEnable(GL_COLOR_MATERIAL); 
    glEnable(GL_LIGHTING); 

    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); 
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); 
    glLightfv(GL_LIGHT0, GL_POSITION, light_position); 

    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); 
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); 
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); 
    glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); 
    glutTimerFunc(0, Timer, 0); // First timer call immediately 

    glutSpecialFunc(specialKeys); // Register callback handler for special-key event 
    glutKeyboardFunc(keyboard); // Register callback handler for special-key event 
    glutMainLoop(); 

    return EXIT_SUCCESS; 
} 

在代碼情況下,「我」:

x += 0.5; 
    gluLookAt(x, y, z, i, j, k, a, b, c); 
    // eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz 

攝影機視圖應該我猜,但可以改變我知道我做錯了。請告訴我如何做到這一點?

回答

4

切勿從輸入事件處理程序調用OpenGL函數。只有苦難和失望纔會出現。

在您的輸入事件處理程序中,從用戶輸入數據中設置變量並觸發重繪。在繪圖函數中,從這些變量中參數化渲染過程。

您可以完全刪除調整大小處理程序。設置視口和投影的顯示功能

static void display(void) { 
    int const width = glutGet(GLUT_WINDOW_WIDTH); 
    int const height = glutGet(GLUT_WINDOW_HEIGHT); 
    float const ar = (float) width/(float) height; 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glViewport(0, 0, width, height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(view_x, view_y, view_z, target_x, target_y, target_z, up_x, up_y, up_z); 
    // eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz 

    /* ... */ 

在鍵盤處理程序只需設置變量並觸發重新顯示

void keyboard(unsigned char key, int mouse_x, int mouse_y) { 
    switch (key) { 
    case 27: // ESC key 
     exit(0); 
     break; 
    case 'r': 
     resetGame(); 
     break; 
    case 'i': 
     view_x += 0.5; 
     /* don't call gluLookAt here! */ 
    } 

    glutPostRedisplay(); 
} 
+0

我照你說的,但不起作用。相機顯示沒有變化。 – Umair

+1

@UmairAyub:那是因爲你的原始變量名'x'在這種情況下被鍵盤函數'x'參數掩蓋了。重命名這些變量,以便它們不會獲得掩碼(或者使用命名空間限定符,即':: x')並且它可以工作。 – datenwolf

+1

@UmairAyub:順便說一句:你的繪圖代碼中有一個多餘的glPushMatrix,這會導致OpenGL矩陣堆棧溢出。 – datenwolf