向上或向下查看LookAt矩阵会扭曲

时间:2015-05-23 05:44:46

标签: java opengl matrix lwjgl

我正在使用在我为LWJGL找到的开源数学库中计算的lookAt矩阵,在我的游戏中为JOML提供免费凸轮。左右旋转时效果很好,但向上和向下看似乎会导致严重的扭曲问题,类似于大幅增加FOV。

直截了当: Regular

但是在查找时: Looking up

俯视时: Looking down

我还没能找到有类似错误的人,没有人使用JOML报告过这个。我在矩阵数学方面不是最好的,所以我计算自己的lookAt矩阵的所有尝试都失败了。 如果有人可以使用JOML查看矩阵,或者说我的(最可能的)任何一个可能的错误,那将非常感谢,谢谢。

1 个答案:

答案 0 :(得分:3)

那么,该库提供的lookAt代码就是这样(我将实际的源代码保留下来,只保留注释,因为它们很好地解释了已完成的步骤):

public final static void lookAt(Vector3f position, Vector3f centre, Vector3f up, Matrix4f dest) {
        // Compute direction from position to lookAt
        // Normalize direction
        // Normalize up
        // right = direction x up
        // up = right x direction
        // Set matrix elements
    }

此代码只是错误。有趣的是,我之前见过这个错误。它实际上是"official" gluLookAt() manpage仍然包含的错误(实际的glu实现没有错误,只是文档错误)。

此代码的作用是构建标准正交基础。问题是,在计算right的叉积之前,向上矢量被规范化。假设似乎是在构建两个单位长度向量的叉积时,结果也将是单位长度向量。但这是一种常见的误解。真正实现的是:

length( cross( a, b) ) == lenght(a) * length(b) * sin(alpha)

其中alpha是ab之间的角度。因此,如果向量已经是正交,则单位长度假设仅保持。由于矢量在交叉乘积之后从未重新归一化,因此得到的基础不是正交的,而是会引入一些非均匀缩放。 lookAt假设反转可以通过转置矩阵计算,在这种情况下完全失败。

当观察方向与向上矢量之间的角度偏离90度时,您看到的失真会变得更加严重。

处理这个问题的正确方法就是在不同的点进行规范化。不要在交叉乘积之前对向上矢量进行标准化,而是将其结果标准化。然后,您有两个相互正交的单位长度矢量,第二个交叉乘积也将按预期工作。所以实际的lookAt函数应该是:

        // Compute direction from position to lookAt
        // Normalize direction
        // right = direction x up
        // Normalize right
        // up = right x direction
        // Set matrix elements