【问题标题】:LookAt matrix distorts when looking up or down向上或向下看时 LookAt 矩阵扭曲
【发布时间】:2015-05-23 05:44:45
【问题描述】:

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

向前看:

但是抬头看:

向下看时:

我找不到有类似错误的人,也没有使用 JOML 的人报告此问题。我不是最擅长矩阵数学的,所以我计算自己的lookAt矩阵的所有尝试都失败了。 如果有人可以使用 JOML 制作一个 lookAt 矩阵,或者说出我的任何一个(最有可能的)可能的错误,那将不胜感激,谢谢。

【问题讨论】:

    标签: java opengl matrix lwjgl


    【解决方案1】:

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

    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
    

    【讨论】:

    • 另一种方法是通过使用它们之间的点积使上向量与方向向量正交。像up -= dot(up, dir) * dir 这样的东西。然后对向上向量进行归一化,向上和方向的叉积将给出正确的右向量,无需任何额外的归一化。在重要的情况下可能更有效。
    • 是的,成功了!将向上向量作为参数时已经对其进行了规范化,但我将其注释掉以防万一并将其规范化。感谢您的宝贵时间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 2021-02-28
    相关资源
    最近更新 更多