怎么可以简单地调用Pitch()和Yaw()导致相机最终Roll()?

Kin*_*tor 2 c++ opengl camera glut

我正在编写一个基本的OpenGL游戏,我有一些代码可以在移动相机方面处理鼠标.

我正在使用以下方法:

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();

}
Run Code Online (Sandbox Code Playgroud)

然而,在环顾四周之后,你会发现相机开始"滚动"(旋转).因为我只是叫Pitch和Yaw,所以我看不出这是怎么回事.

这是我用于我的Camera类的代码:http://pastebin.com/m20d2b01e

据我所知,我的相机"滚动"不应该发生.它应该简单地向上和向下俯仰或左右摇摆.不滚.

可能是什么导致了这个?

ack*_*ckb 11

恭喜 - 你发现了李群理论!

是的,这是可能的.一系列转换的结果取决于它们执行的顺序.做一个跟随偏航的音高与做一个偏航是不一样的,接着是一个音高.实际上,在无限小的偏航和俯仰的极限下,差异相当于一个纯粹的滚动; 一般情况稍微复杂一些.

(物理学家称之为"轮换组的换向关系".)

如果您熟悉旋转矩阵,则可以非常轻松地完成.


geo*_*tnz 7

如果你还没有这样做,你可能需要使用四元数来组合旋转.这避免了通过绕3轴旋转定向摄像机时可以获得的万向节锁定问题.

以下是如何在它们之间进行转换.


Kip*_*Kip 5

好吧,如果你开始向前看水平到地平线,向上倾斜90度,然后向左倾斜90度,然后向下倾斜90度,你将看到与你开始时相同的方向,但地平线将是垂直的(好像你已经向前滚了90度).

编辑:我认为问题是如果相机被当作飞机对待,偏航/俯仰/滚动将是合适的.您可能想要做的是将其视为球体中的一个点,跟踪您指向相机的球体的位置.使用球面坐标来跟踪θ(纬度)和phi(经度),而不是偏航/俯仰.它们可能听起来很相似,但考虑到相机直接指向的极端情况.通过偏航/俯仰,您仍然可以从直线向上方向自由调节偏航和俯仰.使用theta/phi,你只能向下调整theta,无论你调整了多少phi,减少theta仍会给你一个与地平线平行的相机.这就是FPS相机的工作方式(你看不到那么远,你正在寻找你的背后).

编辑2:查看您链接到的摄像机代码,您希望使用rotLati(float angle)rotLongi(float angle)功能.


Dav*_*d Z 5

从数学上讲,其原因是 3D 空间中的旋转不会交换。这意味着,pitch() 后跟 yaw() 与 yaw() 后跟itch() 不同,但这一事实的结果是,这三种旋转是紧密相连的,您无法执行任何旋转其中两个没有得到第三个。换句话说,任何pitch()和yaw()序列都会随着时间的推移产生明显的roll()效果,除非序列的后半部分与前半部分完全相反。(其中涉及很多相当复杂的数学,但细节并不是特别相关)