简体   繁体   English

gluLookAt()无法按预期工作

[英]gluLookAt() doesn't work as expected

I have created a bowling game in OpenGL using Eclipse. 我使用Eclipse在OpenGL中创建了一个保龄球游戏。

Now I want to change the view of camera upon key-pressed. 现在我想按键时更改相机的视图。

But When I press x button, everything disappears. 但是当我按下x按钮时,一切都消失了。

Here us the code: - 我们这里的代码: -

#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;
}

In the code case 'i': 在代码案例'i'中:

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

Camera view should be changed as I guess but I know that I am doing wrong. 应该改变相机视图,但我知道我做错了。 Please tell me how to do this? 请告诉我怎么做?

Never call OpenGL functions from input event handlers. 切勿从输入事件处理程序调用OpenGL函数。 Only misery and dispair comes out of this. 只有苦难和绝望才会出现。

In your input event handlers set variables from the user input data and trigger a redraw. 在输入事件处理程序中,从用户输入数据中设置变量并触发重绘。 In the drawing function parameterize the rendering process from those variables. 在绘图功能中,从这些变量参数化渲染过程。

You can remove the resize handler entirely. 您可以完全删除调整大小处理程序。 Setup viewport and projection in the display function 在显示功能中设置视口和投影

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

   /* ... */

In the keyboard handler just set variables and trigger a redisplay 在键盘处理程序中,只需设置变量并触发重新显示

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM