【问题标题】:OpenGL FPS Camera using gluLookAt()使用 gluLookAt() 的 OpenGL FPS 相机
【发布时间】:2026-01-10 04:55:01
【问题描述】:

所以,我正在尝试创建一个 FPS 风格的相机来探索我的场景,它似乎工作正常。目前无法更改相机的俯仰角。我正在尝试创建一个函数,允许我将相机设置为一些预定义的视点,但是在使用 setPosition() 函数将相机设置为新视点后尝试旋转相机时,我遇到的不是位置而是方向的跳跃第一次按下旋转按钮时。

这是我的相机类实现。

Camera::Camera(void)
{
    angleX = 0.0;
    angleY = 0.0;
    directionX = 0.0;
    directionZ = -5.0;
    directionY = 0.0;
    xPos = 0.0;
    zPos = 1.0;
    yPos = 2.0;
}

void Camera::setPosition(float xDir, float yDir, float zDir, float posX, float posZ, float posY)
{
    directionX = xDir;
    directionZ = zDir;
    directionY = yDir;
    xPos = posX;
    zPos = posZ;
    yPos = posY;
}

Camera::~Camera(void)
{
}

以下是我的特殊按键回调函数,省略了相机移动以外的功能。

void specialKeys(int key, int xx, int yy)
{
    float fraction = 0.3f;

    switch(key)
    {
        // Camera Controls
        case GLUT_KEY_LEFT:
            camera.angleY -= 0.05f;
            camera.directionX = sin(camera.angleY);
            camera.directionZ = -cos(camera.angleY);
            break;
        case GLUT_KEY_RIGHT:
            camera.angleY += 0.05f;
            camera.directionX = sin(camera.angleY);
            camera.directionZ = -cos(camera.angleY);
            break;
        case GLUT_KEY_UP:
            camera.xPos += camera.directionX * fraction;
            camera.zPos += camera.directionZ * fraction;
            camera.yPos += camera.directionY * fraction;
            break;
        case GLUT_KEY_DOWN:
            camera.xPos -= camera.directionX * fraction;
            camera.zPos -= camera.directionZ * fraction;
            camera.yPos -= camera.directionY * fraction;
            break;
       }
}

然后显示回调函数使用 gluLookAt 具有以下代码:

glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(camera.xPos, camera.yPos, camera.zPos, camera.xPos+camera.directionX, camera.yPos+camera.directionY, camera.zPos+camera.directionZ, 0, 1, 0);

我不明白为什么会遇到这个问题。我相信这与设置相机和用于旋转它的数学之间的相互作用有关。谁能看到如何防止这种方向跳跃?

我在一个键盘回调函数中设置相机位置,代码如下:

    if(key == '1') // Default View
        camera = Camera();
    if(key == '2') // Ferris Wheel View
        camera.setPosition(-0.8, 0.0, -0.6, 3.6, 3.6, 6.5);
    if(key == '3') // Fountain Water View
        camera.setPosition(0.9, 0.0, -0.4, -0.59, -6.4, 0.6);

【问题讨论】:

    标签: opengl camera glut glulookat


    【解决方案1】:

    跳转是因为你是如何初始化你的 directionZ 变量的,看看:

       angleX = 0.0;
       angleY = 0.0;
       directionX = 0.0;
       directionZ = -5.0;
       directionY = 0.0;
    

    但稍后你将 directionX 和 directionZ 定义为:

    camera.directionX = sin(camera.angleY);
    camera.directionZ = -cos(camera.angleY);
    

    cos 以区间 [-1, 1] 为界,由于 angleY 为 0.0f,directionZ 将设置为 -1。如果您将初始化代码更改为设置directionZ = -1.0;,您应该摆脱跳转。

    不要明确设置方向。这是一个设置角度并从该角度计算方向的示例:

    void Camera::setPosition(float angle, float posX, float posZ, float posY)
    {
        xPos = posX;
        zPos = posZ;
        yPos = posY;
    
        //compute instead of set based on angle
        angleY = angle;
        camera.directionX = sin(angleY);
        camera.directionZ = -cos(angleY);
    }
    

    【讨论】:

    • 抱歉,因为我最初的问题可能不清楚,但相机在初始化后就很好了。例如,按下“1”键后,我正在调用 setPosition() 将相机设置到特定位置。设置此位置后,相机会在第一次旋转时跳跃。我会修改我原来的问题。
    • 我明白了。问题是您设置的值和您计算的值之间的跳跃。你用什么调用 setPosition()?
    • 在键盘回调中,我会将代码添加到我原来的问题中。
    • 那是你的问题,你直接设置方向。相反,您应该传入当前角度并从中计算方向。
    • 好的,我正在尝试使用与使用键盘旋转相机时使用的计算类似的计算来执行此操作,尽管我不完全确定如何去做。将进一步研究,感谢您的帮助。