【问题标题】:How to move around camera using mouse in OpenGL?如何在OpenGL中使用鼠标移动相机?
【发布时间】:2015-12-20 05:15:34
【问题描述】:

我意识到这个问题之前在 stackoverflow 上被问过,但我还没有找到一个我完全理解的答案,所以我想我会得到一些针对我的具体情况的帮助。

我基本上希望能够使用鼠标绕 y 轴旋转。以下是我用于实际旋转的函数(角度以度为单位)。

void CCamera::RotateY (GLfloat Angle)
{
    RotatedY += Angle;

    //Rotate viewdir around the up vector:
    ViewDir = Normalize3dVector(ViewDir*cos(Angle*PIdiv180)
                    - RightVector*sin(Angle*PIdiv180));

    //now compute the new RightVector (by cross product)
    RightVector = CrossProduct(&ViewDir, &UpVector);
}

由于我使用的是 GLUT,所以我使用被动函数来获取光标的 x,y 坐标。然后在我的显示中我有以下内容:

void display(void) {
    ...
    mouseDisplacement = mouseX - oldMouseX;

    if (mouseDisplacement > 0) Camera.RotateY(-1.0*abs(mouseDisplacement));
    else if (mouseDisplacement < 0) Camera.RotateY(1.0*abs(mouseDisplacement));

    oldMouseX = mouseX;
    glutWarpPointer(centerWindowX, centerWindowY);  // move the cursor to center of window
    ...    
}

现在问题很明显,因为显示功能每秒运行 60 次,所以每当我尝试移动鼠标光标时,它就会卡在中间。如果我没有显示功能循环,那么旋转真的很滞后。那么这样做的正确方法是什么?

再次注意,我只是想让相机使用鼠标在左右方向移动。虽然如果我能让它像正常的 fps 一样工作那就太棒了,但这并不是必需的。

非常感谢任何帮助。

【问题讨论】:

    标签: c++ opengl camera glut freeglut


    【解决方案1】:

    您可能希望使用 glutPassiveMotionFunc 和自定义回调来处理鼠标位置增量:

    void handlerFunc(int x, int y) 
    { 
        /* code to handle mouse position deltas */ 
    }
    
    int main()
    {
         /* [...] */
    
         glutPassiveMotionFunc(handlerFunc);  // before glutMainLoop.
    
         /* [...] */
    
         return 0;
    }
    

    文档:glutPassiveMotionFunc

    -

    此外,我认为您的增量计算有问题。您应该计算当前光标位置和窗口中心之间的差异(光标将在每一帧之后设置)。

    mouseDisplacement = mouseX - centerWindowX;

    这是我在引擎中用于获取 FPS 相机的一些代码(请随意调整):

    void update(float delta)  // delta is usually 1.0/60.0
    {
        // Mouse.
        MouseState mouse = InputDevices.get_mouse_state();
    
        // - Movement
        camera->yaw += camera->speed * mouse.dx * delta;
        camera->pitch -= camera->speed * mouse.dy * delta;
    
        // Regular FPS camera.
        // TODO(Clem): Move this to a class.
    
        // Clamp.
        if (camera->pitch > math::PI_OVER_TWO) {
            camera->pitch = math::PI_OVER_TWO - 0.0001f;
        }
        else if (camera->pitch < -math::PI_OVER_TWO) {
            camera->pitch = -math::PI_OVER_TWO + 0.0001f;
        }
    
        float pitch = camera->pitch;
        float yaw = camera->yaw;
    
        // Spherical coordinates (r=1).
        camera->forward.x = -sin(yaw) * cos(pitch);
        camera->forward.y = -sin(pitch);
        camera->forward.z = -cos(yaw) * cos(pitch);
    
        camera->right.x = -cos(yaw);
        camera->right.y = 0.0;
        camera->right.z = sin(yaw);
    
        camera->up = cross(camera->forward, camera->right);
    
        camera->forward = normalize(camera->forward);
        camera->right = normalize(camera->right);
        camera->up = normalize(camera->up);
    }
    

    【讨论】:

    • 我不清楚。我已经在使用 glutPassiveMotionFunc(...) 来更新全局变量 mouseX。当我想在将鼠标保持在窗口中心的同时在相机周围移动时,就会出现问题。
    • 好的,明白了。我相信问题来自您的增量计算。您应该计算当前光标位置与窗口中心(每帧后将设置光标的位置)之间的差异。
    • 感谢您抽出宝贵时间帮助我。我还尝试了你上面所说的,通过相对于中心坐标进行位移。但是,由于我将光标更新为停留在中间,因此位移始终为 0 或非常接近 0。因此不会像应有的那样移动相机。
    • 伙计们,一个基本问题:如何运行这段代码?你能评论一下要包含的库吗?
    猜你喜欢
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多