2

我正在尝试在 3d 空间中移动相机。到目前为止,我已经成功地使用以下代码移动和旋转相机:

void specialKeyHandler(int key, int x, int y) {

    float fraction = 0.05f;

switch (key) {
    case GLUT_KEY_LEFT :
        camAngle -= 0.01f;
        lX = sin(camAngle);
        lZ = -cos(camAngle);
        break;
    case GLUT_KEY_RIGHT :
        camAngle += 0.01f;
        lX = sin(camAngle);
        lZ = -cos(camAngle);
        break;
    case GLUT_KEY_UP :
        iX += lX * fraction;
        iZ += lZ * fraction;
        break;
    case GLUT_KEY_DOWN :
        iX -= lX * fraction;
        iZ -= lZ * fraction;
        break;
    default:
        break;
    }

}

当然,我已经定义了这些变量。lX、lY、lZ 用于 LookAt 变量,iX、iY 和 iZ 用于相机的眼睛。
相机根据需要移动,但现在我想在“相机的眼睛”上附加一个物体,它会随着相机移动。就像 FPS 游戏中的武器一样。
这就是我所拥有的:

void display()

{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawEarth();
    drawWalls();

    glColor3f(255,0,0);
    glPushMatrix();
    glTranslatef(iX+0.05,iY, iZ-0.05);
    glRotatef(camAngle, 0,1,0);
    glutWireCone(0.005,0.1,20,20);  // object to go with camera
    glPopMatrix();

    glutSwapBuffers();

}

此代码当前确实在上下移动时将对象与相机绑定。但是当我通过按左右键旋转相机时,物体停留在那里并且相机自行移动..有
什么解决方案吗?

如果有人想运行,这是完整的 opengl 代码:

#include <GL/glut.h>
#include<iostream>
#include<math.h>
using namespace std;

void display(void);

void reshape(int, int);
void mouseHandler(int button, int state, int x, int y);
void keyBoardHandler(unsigned char c, int x, int y);
void specialKeyHandler(int key, int x, int y);
float angle = 0;
bool camDefault = true, perspectiveOrtho = true;

float iX =0  , iY = -0.8, iZ = 0, lX = 0, lY = -0.8, lZ = -1, uX = 0, uY = 1, uZ = 0; 
float camAngle = 0;
int main(int argc, char** argv)

  {
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("FPS Camera");
glutDisplayFunc(display);
glutIdleFunc(display);
//look from negative x axis towards origin. with y on top
glutReshapeFunc(reshape);
glEnable(GL_DEPTH_TEST);
glClearColor(0,0,0,1);
glutMouseFunc(mouseHandler);
glutKeyboardFunc(keyBoardHandler);
glutSpecialFunc(specialKeyHandler);
glutMainLoop();

return 0;
   }


void drawEarth() {

    glColor3f(0,255,0);
    glBegin(GL_QUADS);
    glVertex3f(-1,-1,-1);
    glVertex3f(-1,-1,1);
    glVertex3f(1,-1,1);
    glVertex3f(1,-1,-1);
    glEnd();
}

void drawWalls() {

    glColor3f(0,0,255);
    glBegin(GL_QUADS);
    glVertex3f(-1,-1,-1);
    glVertex3f(-1,-1,1);
    glVertex3f(-1,1,1);
    glVertex3f(-1,1,-1);
    glEnd();


    glColor3f(0,234,255);
    glBegin(GL_QUADS);
    glVertex3f(-1,-1,1);
    glVertex3f(-1,1,1);
    glVertex3f(1,1,1);
    glVertex3f(1,-1,1);
    glEnd();


}

float unitVector(float dir, float x, float y, float z) {
    float sumSqr = pow(x,2) + pow(y,2) + pow(z,2);
    return dir / (sqrt(sumSqr));
}
void display()

{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawEarth();
    drawWalls();

    glColor3f(255,0,0);
    glPushMatrix();
    glTranslatef(iX+0.05,iY, iZ-0.05);
    glRotatef(camAngle, 0,1,0);
    glutWireCone(0.005,0.1,20,20);
    glPopMatrix();

    glutSwapBuffers();

}



void reshape(int width, int height)

{

    glViewport(0,0,width,height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90,1, 0.001, 1000);
    gluLookAt(iX,iY,iZ,iX+lX,lY,iZ+lZ,uX,uY,uZ);
    glMatrixMode(GL_MODELVIEW);

}

void updateLookAt() {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective (90, 1 ,0.001, 1000);
    gluLookAt(iX,iY,iZ,iX+lX,lY,iZ+lZ,uX,uY,uZ);
    glMatrixMode(GL_MODELVIEW);
}


void keyBoardHandler(unsigned char c, int x, int y) {
    switch(c) {
    case 'f':  // go left
        iX-=0.01;
        lX -= 0.01;
        cout<<endl<<"S pressed";
        break;

    case 's':  // go right
        iX += 0.01;
        lX += 0.01;
        break;

    case 'e': // go up
        iZ += 0.01;
        lZ += 0.01;
        break;

    case 'd': // go down
        iZ -= 0.01;
        lZ -= 0.01;
        break;

    default:
        break;
    }

    updateLookAt();

}

void mouseHandler(int button, int state, int x, int y) {
    if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        if(camDefault) {
            glLoadIdentity();
            gluLookAt(-1,0,0,0.0,0.0,0.0,0.0,1,0);
            camDefault = false;
        }

        else {
            glLoadIdentity();
            gluLookAt(0,0,0,0.0,0.0,0.0,0.0,1,0);
            camDefault = true;
        }
    }

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { 
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        if(perspectiveOrtho) {
            gluPerspective (90, 1 ,0.00001, 1000);
            perspectiveOrtho = false;
        }

        else {

            glOrtho(-1,1,-1,1, -1,100);
            perspectiveOrtho = true;

        }
        glMatrixMode(GL_MODELVIEW);

        glLoadIdentity();
        if(camDefault)
                gluLookAt(0,0,1,0.0,0.0,0.0,0.0,1,0);
            else 
                gluLookAt(-1,0,0,0.0,0.0,0.0,0.0,1,0);


    }
}



void specialKeyHandler(int key, int x, int y) {

    float fraction = 0.05f;

switch (key) {
    case GLUT_KEY_LEFT :
        camAngle -= 0.01f;
        lX = sin(camAngle);
        lZ = -cos(camAngle);
        break;
    case GLUT_KEY_RIGHT :
        camAngle += 0.01f;
        lX = sin(camAngle);
        lZ = -cos(camAngle);
        break;
    case GLUT_KEY_UP :
        iX += lX * fraction;
        iZ += lZ * fraction;
        break;
    case GLUT_KEY_DOWN :
        iX -= lX * fraction;
        iZ -= lZ * fraction;
        break;
    default:
        break;
    }


    updateLookAt();
}
4

1 回答 1

2

你有两个问题。

第一个问题是你的坐标系。

申请时:

glTranslatef(iX+0.05,iY, iZ-0.05);

您将对象放置在相机位置,并添加偏移量以查看他。但这是在世界坐标系中。因此,当您旋转相机时,对象不会移动,因为它不遵循相机的坐标系。

您需要平移到相机中心,旋转相机,然后添加偏移量。

第二个问题是关于旋转的。您的“camAngle”变量是弧度的,因为您将它与 cos() 和 sin() 一起使用。但是在 OpenGL 中, glRotate 将角度作为度数。您需要将此角度转换为角度:角度 *= 180/PI。(180/PI ~= 57.2957795)

这里更正的显示功能:

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

    glColor3f(255,0,0);

    glPushMatrix();
        glTranslatef(iX,iY,iZ); // Translation to the camera center
        glRotatef(-camAngle * 57.2957795, 0,1,0); // Rotate to correspond to the camera
        glTranslatef(0.05,0,-0.05); // Offset to draw the object

        glutWireCone(0.005,0.1,20,20);
    glPopMatrix();

    drawEarth();
    drawWalls();
    glutSwapBuffers();
}
于 2013-11-16T15:47:53.980 回答