首先,如果您想要了解GLM lookAt算法的解释,请查看此问题提供的答案: https://dev59.com/znjZa4cB1Zd3GeqPg609#19740748
mat4x4 lookAt(vec3 const & eye, vec3 const & center, vec3 const & up)
{
vec3 f = normalize(center - eye);
vec3 u = normalize(up);
vec3 s = normalize(cross(f, u));
u = cross(s, f);
mat4x4 Result(1);
Result[0][0] = s.x;
Result[1][0] = s.y;
Result[2][0] = s.z;
Result[0][1] = u.x;
Result[1][1] = u.y;
Result[2][1] = u.z;
Result[0][2] =-f.x;
Result[1][2] =-f.y;
Result[2][2] =-f.z;
Result[3][0] =-dot(s, eye);
Result[3][1] =-dot(u, eye);
Result[3][2] = dot(f, eye);
return Result;
}
现在我将告诉您为什么我似乎对这个算法有一个概念上的问题。这个视图矩阵有两个部分,平移和旋转。平移执行了正确的反向变换,将相机位置带到原点,而不是将原点位置带到相机。同样,您希望相机定义的旋转在放入此视图矩阵之前被反转。我看不到这里发生的情况,这就是我的问题。
考虑前向矢量,这是您的相机所看的方向。因此,这个前向矢量需要映射到-Z轴,这是openGL使用的前向方向。这个视图矩阵应该工作的方式是通过在视图矩阵的列中创建正交基来实现的,因此当您在此矩阵的右侧乘以顶点时,您实际上只是将其坐标转换为不同轴的坐标。
当我在脑海中播放由此转换导致的旋转时,我看到的是非反转的旋转,而不是相机的反转旋转,这就是应该发生的事情。也就是说,我找到了相机前进被映射到-Z轴,我发现-Z轴被映射到相机前进。
如果您不理解我的意思,可以考虑一个与此处发生的相同类型的2D示例。假设前向矢量是(sqr(2)/ 2,sqr(2)/ 2),或者是45度的sin / cos,并且还假设这个2D摄像机的侧向矢量是-45度的sin / cos。我们想将这个前向矢量映射到(0,1),即正Y轴。正Y轴可以被认为是OpenGL空间中的-Z轴的类比。让我们考虑一个与我们的前向矢量方向相同的顶点,即(1,1)。通过使用GLM.lookAt的逻辑,我们应该能够使用由第一列中的前向矢量和第二列中的侧向矢量组成的2x2矩阵将(1,1)映射到Y轴。这是那个计算的等效计算http://www.wolframalpha.com/input/?i=%28sqr%282%29%2F2+%2C+sqr%282%29%2F2%29++1+%2B+%28sqr%282%29%2F2%2C+-sqr%282%29%2F2+%29+1。
请注意,您无法将(1,1)顶点映射到所需的正Y轴,而是将其映射到正X轴。如果您应用此转换,可能还要考虑在正Y轴上的顶点会发生什么情况。毫不奇怪,它被转换为向前的矢量。
因此,似乎GLM算法存在一些非常可疑的问题。但是,我怀疑该算法不正确,因为它非常流行。我错过了什么?
LookAt(...)
的探索中。 - Andon M. Coleman