3

我已经从教程等在线使用 OpenGL 和 C++ 组装了一个第三人称相机系统,但我似乎无法找出具体问题。当我使用鼠标移动转动时,我的角色围绕相机旋转,而不是相机围绕角色旋转并且角色原地转动。我应该怎么做才能让角色原地转身?

// variables ..

void checkMouse(){
    if (mouseXPos > SCREEN_WIDTH/2){
        // turn right
        yrot += abs(mouseXPos - SCREEN_WIDTH/2) * .005;
    } else if (mouseXPos < SCREEN_WIDTH/2){
        // turn left
        yrot -= abs(mouseXPos - SCREEN_WIDTH/2) * .005;
    }
    if (mouseYPos > SCREEN_HEIGHT/2){
        // look up
        xrot += abs(mouseYPos - SCREEN_HEIGHT/2) * .005;
    } else if (mouseYPos < SCREEN_HEIGHT/2){
        // look down
        xrot -= abs(mouseYPos - SCREEN_HEIGHT/2) * .005;
    }
}

void checkKeys(){
    if(keys['t'] == true){
        wireframe=!wireframe;
        if(wireframe){
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }
        else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    if (keys['w'] == true){
        float xrotrad, yrotrad;
        yrotrad = (yrot / 180 * 3.141592654f);
        xrotrad = (xrot / 180 * 3.141592654f); 
        xpos += float(sin(yrotrad)) * 10 ;
        zpos -= float(cos(yrotrad)) * 10 ;
    }

    if (keys['s'] == true){
        float xrotrad, yrotrad;
        yrotrad = (yrot / 180 * 3.141592654f);
        xrotrad = (xrot / 180 * 3.141592654f); 
        xpos -= float(sin(yrotrad)) * 10;
        zpos += float(cos(yrotrad)) * 10;
    }

    if (keys['a'] == true){
        float yrotrad;
        yrotrad = (yrot / 180 * 3.141592654f);
        xpos -= float(cos(yrotrad)) * 10;
        zpos -= float(sin(yrotrad)) * 10;
    }

    if (keys['d'] == true){
        float yrotrad;
        yrotrad = (yrot / 180 * 3.141592654f);
        xpos += float(cos(yrotrad)) * 10;
        zpos += float(sin(yrotrad)) * 10;
    }
}

void renderScene(){

    // Clear framebuffer & depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Reset Modelview matrix       
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // Set view position & direction
    gluLookAt(0,0,5,  0,0,-1,  0,1,0);

    checkKeys();
    checkMouse();

    // 3rd person object
    // draw body
    glPushMatrix();
    glRotatef(xrot,1.0,0.0,0.0); // keeps object on ground level rather than always in front of camera
    glTranslatef(0,-90,-400.0); // keep object 400 away from camera
    glRotatef(-90,0.0,1.0,0.0);
    glutSolidCube(20);
    glPopMatrix();

    // CAMERA
    glRotatef(xrot,1.0,0.0,0.0);  //rotate our camera on the x-axis (left and right)
        glRotatef(yrot,0.0,1.0,0.0);  //rotate our camera on the y-axis (up and down)
    glTranslated(-xpos,-ypos-200,-zpos);

    // rest of world
    glPushMatrix();
    glutSolidCube(30);
    glPopMatrix();

    // ..

    glDisable(GL_TEXTURE_2D);
    // Swap double buffer for flicker-free animation
    glutSwapBuffers();

}

void updateScene(){

    // Wait until at least 16ms passed since start of last frame
    // Effectively caps framerate at ~60fps
    while(timeGetTime()-lastTickCount<16);
    lastTickCount=timeGetTime();

    // Draw the next frame
    glutPostRedisplay();

}

void keypress (unsigned char key, int x, int y) {

    keys[key] = true;

    // Test if user pressed ESCAPE (ascii 27)
    // If so, exit the program
    if(key==27){
        exitScene();
    }
}

void keypressup (unsigned char key, int x, int y) {

    keys[key] = false;
    wheel_turn = 0;
}

void mouseMovement(int x, int y) {

    mouseXPos = x;
    mouseYPos = y;
}

void mouseClick(int button, int state, int x, int y){
    if (button == GLUT_LEFT_BUTTON){
        if (state == GLUT_DOWN)
            lButton = true;
        else
            lButton = false;
    }
}

void setupScene(){

    forwards = 0;
    strafe = 0;
    turn = 0;

    std::cout<<"Initializing scene..."<<std::endl;

    //Set up Lighting Stuff
    glLightfv(GL_LIGHT0, GL_POSITION, left_light_position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, white_light);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
    glShadeModel(GL_SMOOTH);

    glEnable(GL_DEPTH_TEST);
}

void exitScene(){

    std::cout<<"Exiting scene..."<<std::endl;

    // Close window
    glutDestroyWindow(windowId);

    // Free any allocated memory

    // Exit program
    exit(0);
}

void setViewport(int width, int height) {

    // Work out window ratio, avoid divide-by-zero
    if(height==0)height=1;
    float ratio = float(width)/float(height);

    // Reset projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Fill screen with viewport
    glViewport(0, 0, width, height);

    // Set a 45 degree perspective
    gluPerspective(45, ratio, .1, 200000);

}

int main(int argc, char *argv[]){

    // Initialise OpenGL
    glutInit(&argc, argv); 

    // Set window position, size & create window
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(50,50);
    glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT);
    windowId = glutCreateWindow("3rd person cam");

    // Set GLUT callback functions
    glutReshapeFunc(setViewport);
    glutDisplayFunc(renderScene);
    glutIdleFunc(updateScene);
    glutKeyboardFunc(keypress);
    glutKeyboardUpFunc(keypressup);
    glutPassiveMotionFunc(mouseMovement); //check for mouse movement
    glutMotionFunc(mouseMovement);
    glutMouseFunc(mouseClick);
    // Setup OpenGL state & scene resources (models, textures etc)
    setupScene();

    // Show window & start update loop
    glutMainLoop();    

    return 0;

}
4

1 回答 1

4

您正在围绕自身旋转相机 - 这类似于您转过头。您想更改相机位置,围绕您感兴趣的对象旋转。

1.找到你的相机位置

  • 为此查找“球坐标”
  • 根据鼠标 x 移动,您的水平角度应在(0 到 2*PI)之间变化
  • 您的垂直角度应根据鼠标 y 移动在(0 和 PI)之间变化
  • 您可以使用一个值缩放找到的 (x,y,z) 位置,以改变相机和对象之间的距离
  • 将对象位置添加到这个找到的位置
  • 您现在在对象周围有一个有效的相机位置

2.查找视图矩阵

  • 有一个方便的 glut 方法称为 gluLookAt,只需使用它来找到您的最终相机矩阵。它需要(相机位置、物体位置和世界向上(0,1,0))
于 2012-12-04T22:47:52.420 回答