简体   繁体   中英

gluLookAt() doesn't work as expected

I have created a bowling game in OpenGL using Eclipse.

Now I want to change the view of camera upon key-pressed.

But When I press x button, everything disappears.

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':

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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