我正在编写一个基本的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();
}
然而,在环顾四周后,你会发现相机开始“滚动”(旋转)。因为我只称Pitch和Yaw,所以我看不出这是怎么回事。
以下是我用于我的Camera类的代码:http://pastebin.com/m20d2b01e
据我所知,我的相机“滚动”不应该发生。它应该简单地向上和向下俯仰或左右摇摆。不滚动。
导致这种情况的原因是什么?
答案 0 :(得分:11)
是的,这是可能的。一系列变革的结果 取决于它们执行的顺序。做一个球场 接下来是偏航与做偏航不一样 一个球场。事实上,在无限小的雅司病的极限 和音高,差异相当于一个纯粹的滚动;一般 案件有点复杂。
(物理学家称之为“交换关系” 轮换组“。)
如果你熟悉旋转矩阵,你可以解决它 很容易
答案 1 :(得分:7)
如果你还没有这样做,你可能需要使用quaternions来组合旋转。这样可以避免在通过围绕3个轴旋转定向摄像机时可以获得gimbal lock的问题。
答案 2 :(得分:5)
好吧,如果你开始向前看水平到地平线,向上倾斜90度,然后向左倾斜90度,然后向下倾斜90度,你将看到与你开始时相同的方向,但地平线将是垂直的(就好像你向左倾90度)。
编辑:我认为问题是,如果将相机当作飞机对待,则偏航/俯仰/翻滚是合适的。您可能想要做的是将其视为球体中的一个点,跟踪您指向相机的球体的位置。使用球面坐标来跟踪θ(纬度)和phi(经度),而不是偏航/俯仰。它们可能听起来很相似,但考虑到相机直接指向的极端情况。通过偏航/俯仰,您仍然可以从直线向上方向自由调整偏航和俯仰。使用theta / phi,你只能向下调整theta,无论你调整了多少phi,减少theta仍会给你一个与地平线平行的相机。这就是FPS相机的工作原理(你不能看得太远,以至于你正在寻找你的背后)。
编辑2 :查看您关联的相机代码,您希望使用 rotLati(float angle)
和 rotLongi(float angle)
< / strong>功能。
答案 3 :(得分:4)
数学上,其原因是3D空间中的旋转不会通勤。这意味着,后跟yaw()的pitch()与yaw()后跟pitch()不同,但这个事实的结果是三种旋转是密不可分的,你不能执行任何其中两个没有获得第三个。换句话说,任何pitch()es和yaw()s序列都会随着时间的推移产生明显的roll()效果,除非序列的后半部分与前半部分完全相反。 (这里涉及很多相当复杂的数学,但细节并不是特别相关)
答案 4 :(得分:3)
俯仰/偏航/侧倾都与您车辆的方向有关。当您向上/向下俯仰时,您可以改变偏航轴。同样,当您偏航时,您可以更改俯仰轴。因此,可以通过组合和俯仰和放大来改变您的方向,类似于滚动操作。偏航演习。
答案 5 :(得分:3)
我相信这种情况被称为Gimbal Lock - 在维基百科页面上有插图的例子。