我正在编写一个基本的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
据我所知,我的相机"滚动"不应该发生.它应该简单地向上和向下俯仰或左右摇摆.不滚.
可能是什么导致了这个?
恭喜 - 你发现了李群理论!
是的,这是可能的.一系列转换的结果取决于它们执行的顺序.做一个跟随偏航的音高与做一个偏航是不一样的,接着是一个音高.实际上,在无限小的偏航和俯仰的极限下,差异相当于一个纯粹的滚动; 一般情况稍微复杂一些.
(物理学家称之为"轮换组的换向关系".)
如果您熟悉旋转矩阵,则可以非常轻松地完成.
如果你还没有这样做,你可能需要使用四元数来组合旋转.这避免了通过绕3轴旋转定向摄像机时可以获得的万向节锁定问题.
以下是如何在它们之间进行转换.
好吧,如果你开始向前看水平到地平线,向上倾斜90度,然后向左倾斜90度,然后向下倾斜90度,你将看到与你开始时相同的方向,但地平线将是垂直的(好像你已经向前滚了90度).
编辑:我认为问题是如果相机被当作飞机对待,偏航/俯仰/滚动将是合适的.您可能想要做的是将其视为球体中的一个点,跟踪您指向相机的球体的位置.使用球面坐标来跟踪θ(纬度)和phi(经度),而不是偏航/俯仰.它们可能听起来很相似,但考虑到相机直接指向的极端情况.通过偏航/俯仰,您仍然可以从直线向上方向自由调节偏航和俯仰.使用theta/phi,你只能向下调整theta,无论你调整了多少phi,减少theta仍会给你一个与地平线平行的相机.这就是FPS相机的工作方式(你看不到那么远,你正在寻找你的背后).
编辑2:查看您链接到的摄像机代码,您希望使用rotLati(float angle)
和rotLongi(float angle)
功能.