3

昨天我问:简单地调用 Pitch 和 Yaw 怎么会导致相机滚动?

基本上,我发现是因为“Gimbal Lock”,如果你俯仰+偏航,你将不可避免地产生滚动效果。有关更多信息,您可以阅读该问题。

我正试图阻止这种情况发生。当您在普通的 FPS 射击游戏中环顾四周时,您的相机不会到处滚动!

这是我当前的被动鼠标功能:

int windowWidth = 640;
int windowHeight = 480;

int oldMouseX = -1;
int oldMouseY = -1;

void mousePassiveHandler(int x, int y)
{
    int snapThreshold = 50;

    if (oldMouseX != -1 && oldMouseY != -1)
    {
        cam.yaw((x - oldMouseX)/10.0);
        cam.pitch((y - oldMouseY)/10.0);


        oldMouseX = x;
        oldMouseY = y;

        if ((fabs(x - (windowWidth / 2)) > snapThreshold) || (fabs(y - (windowHeight / 2)) > snapThreshold))
        {
            oldMouseX = windowWidth / 2;
            oldMouseY = windowHeight / 2;
            glutWarpPointer(windowWidth / 2, windowHeight / 2);
        }
    }
    else
    {
        oldMouseX = windowWidth / 2;
        oldMouseY = windowHeight / 2;
        glutWarpPointer(windowWidth / 2, windowHeight / 2);
    }


    glutPostRedisplay();

}

这会导致相机根据鼠标移动进行俯仰/偏航(同时将光标保持在中心)。我还在这里发布了我原来的相机课程。

该线程中的某个人建议我使用四元数来防止这种效果发生,但在阅读了关于它们的维基百科页面后,我根本不了解它们。

如何在我的 OpenGL/Glut 应用程序中创建四元数,这样我就可以正确地让我的“相机”环顾四周而不会出现不必要的滚动?

4

4 回答 4

2

一个简单的基于四元数的相机,设计用于 gluLookAt。

http://www.gamedev.net/reference/articles/article1997.asp

于 2009-04-25T04:35:50.187 回答
1

保持你的三角洲变化低以避免这种情况(即<45度)

只需计算一个带有每帧旋转的小“增量”矩阵,将其折叠到每帧的相机矩阵中。(折叠的意思是:cam = cam * delta)

如果长时间运行,可能会出现一些数值错误,因此需要重新正交化。(如果这似乎发生了,请查看)

这是在玩东西时避免云台锁定的最简单方法。等你熟练了,剩下的就懂了。

至于四元数,只需为它们找到一个可以将它们转换为旋转矩阵的好的库,然后使用相同的技术(计算 delta quat,乘以 main quat)。

于 2009-05-20T20:41:23.323 回答
0

我会用极坐标表示一切。维基百科页面应该让你开始。

于 2009-04-25T04:45:07.437 回答
0

对于这种简单的情况,您实际上并不需要四元数,您需要将航向和俯仰输入到 3 维矩阵计算中:

  1. 使用带有 Y 轴旋转的航向值来计算 MY

  2. 使用在 X 轴上旋转的俯仰值来计算 MX

  3. 对于每个点 P,计算 R = MX * MY * P

计算可以通过两种方式完成:

  1. T = MY * P,然后 R = MX * T

  2. T = MX * MY,然后 R = T * P

第一种方法较慢但一开始更容易编码,第二种方法更快,但您需要编写矩阵矩阵乘法函数。

附言。有关矩阵,请参见http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three

于 2009-04-25T06:03:12.850 回答