嘿伙计们我正在尝试使用glm库中的lookAt做一个Camera类。我有4个点,第一个是眼睛,即太空中的相机位置,第二个是外观,即相机正在看的点,第三个是upp,设置相机的方向,第四个是侧面,这是一个眼睛和upp -eye的交叉产品。
所以最后我得到了一个3个向量的基础,所有这些向量的起点都在眼点。我有一个相机的坐标系。
在我的相机课上,我希望能够围绕相机的坐标系旋转,而不是围绕世界的坐标系。所以我正在做的是围绕相机坐标系的一个轴旋转。
我用这样的初始值构造类:
void Observer::initialize(glm::vec3 eye, glm::vec3 look, glm::vec3 upp, glm::vec3 side)
{
this->eye = eye; // (0.0, 0.0, 0.0)
this->look = look; // (0.0, 0.0, -1.0)
this->upp = upp; // (0.0, 1.0, 0.0)
this->side = side; // (1.0, 0.0, 0.0)
}
当我想围绕x轴旋转坐标系时,例如我从glm调用函数,如下所示:
void Observer::pitch(GLfloat pitch)
{
glm::mat4 rotate(1.0f);
rotate = glm::rotate(rotate, pitch, side - eye);
look = glm::vec3(rotate * glm::vec4(look, 1.0f));
upp = glm::vec3(rotate * glm::vec4(upp, 1.0f));
}
到目前为止,我理解我的所有点仍然形成了相机的坐标系,所有矢量都是相互垂直的。
然后我使用lookAt功能获得的这些点,将相机定位在世界上。
glm::mat4 view = glm::lookAt(eye, look, upp);
将此矩阵与OpenGL中的modelview矩阵相乘
如果我开始旋转很多,几次旋转后的相机会“反射”旋转,就像我在另一个方向旋转一样(我不知道如何以更好的方式描述真正发生的事情= s )。
我真的不明白发生了什么。我应用旋转后应该对矢量进行标准化吗?我有万向节锁的问题(我不太了解万向节锁)?
答案 0 :(得分:2)
当您对矢量执行增量旋转时,会出现数值错误。当错误导致向上和观察向量指向几乎相同的方向或彼此相反时,摄像机变换计算是不稳定的,并且可能发生严重的事情。万向节锁。长度变化会导致不同的问题。
对我有用的解决方案是在每次旋转后重新正交化向上和看向向量。为此,计算它们的叉积L,然后通过将L与lookAt交叉来调整(实际替换)向上矢量。在所有这些之后,重新规范化向上和观察单位长度。
虽然正交化归一化是一种快速操作,但您并不需要对每个摄像机动作都这样做。
请注意,当您更正这样的向量时,您实际上正在执行lookAt矩阵计算的一部分,因此请考虑实现自己的以避免不必要的交叉积。参见例如this prior SO article on this topic