向上或向下看时LookAt矩阵变形 [英] LookAt matrix distorts when looking up or down

查看:65
本文介绍了向上或向下看时LookAt矩阵变形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是在为LWJGL找到的开源数学库中计算的lookAt矩阵,名为仍然包含(实际的glu实现没有错误,只是说明文件有误).

这段代码的作用是建立一个标准正交基.问题是,向上向量在计算乘积<右> 的叉积之前 被归一化.假设似乎是,当构建两个单位长度向量的叉积时,结果也将是单位长度向量.但这是一个普遍的误解.真正成立的只是:

  length(cross(a,b))==长度(a)*长度(b)* sin(alpha) 

其中alpha是 a b 之间的夹角.因此,只要向量已经正交,单位长度假设就成立.由于矢量永远不会在叉积后重新归一化,因此所得的基数不是正交的,而是会引入一些不均匀的缩放比例. lookAt 假定可以通过转置矩阵来计算逆旋转,在这种情况下这将完全失败.

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

解决此问题的正确方法是在另一点进行标准化.不要对叉积前的上向量进行归一化处理,而要对结果进行归一化处理.然后,您有两个相互正交的单位长度向量,第二个叉积也将按预期工作.因此,实际的lookAt函数应为:

 //计算从位置到lookAt的方向//归一化方向//右=方向x向上//归一化右//向上=向右x方向//设置矩阵元素 

I am using a lookAt matrix calculated in an open source math library I found for LWJGL called JOML for free cam in my game. It works well when rotating left and right, but looking up and down seems to cause major distortions issues similar to heavily increasing the FOV.

Looking straight forward:

But when looking up:

And when looking down:

I haven't been able to find someone with a similar error, and no one using JOML has reported this. I'm not the best at matrix math, so all my tries at calculating my own lookAt matrix were fails. If someone could make a lookAt matrix using JOML, or say any one of my (most likely) possible errors, that would be much appreciated, thank you.

解决方案

Well, the lookAt code provided by that library is just this (I'm leaving the actual source code out and only keep the comments, as they nicely explain the steps which are done):

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
    }

And this code is just wrong. Interestingly, I've seen this mistake before. It is actually the same error that that the "official" gluLookAt() manpage still contains (the actual glu implementations do not have the error, just that documentation is wrong).

What this code does is building an orthonormal basis. And the problem is that the up vector is normalized before the cross product for calculating right. The assumption seems to be that when building the cross product of two unit length vectors, the result will also be a unit lenght vector. But that is a common misconception. What's actually holding true is just:

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

where alpha is the angle between a and b. So the unit lenght assumption only holds if the vectors are already orthogonal. As the vectors are never re-normalized after the cross product, the resulting basis is not orthonormal, but will introduce some non-uniform scaling. The lookAt assumes that the inverse rotation can be calculated by the transposed matrix, which will completely fail in this case.

The distortion you see will get more severe when the angle between the viewing direction and your up vector will move away from 90 degrees.

The correct way to deal with this is just doing the normalization at a different point. Don't normalize the up-vector before the cross-product, but normalize it's result instead. Then, you have two unit-lenght vectors orthogonal to each other, and the second cross-product will also work as expected. So the actual lookAt function should be:

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

这篇关于向上或向下看时LookAt矩阵变形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆