5

当我尝试改变方向时,我的相机会围绕一个点旋转。如果我旋转我的相机,比如在 Y 轴上旋转 30 度,而不是相机向右看 30 度,相机围绕它正在看的点旋转。

o is the camera, A and B are 3D models. The lines show line-of-sight.
This is what I expect:
     A    B
     | > /
     |  /
     | /
     |/
     o

This is what actually happens:
     A    B
     |\
     | \
     |  \
     | > \
          o

现在,根据我的理解,为了移动相机,我必须将世界移动该数量的倒数。因此,如果我想在 Z 轴上移动 +1,我会在 Z 轴上平移世界 -1。因为我使用四元数来表示方向,所以我使用相机四元数的逆(因为方向总是单位四元数,我通过使用共轭而不是计算逆来优化)将世界旋转适量。

这是我将四元数转换为矩阵的方法,其中 q 是倒四元数:

[1 - 2 * (q.y * q.y + q.z * q.z)   2 * (q.x * q.y - q.w * q.z)       2 * (q.x * q.z + q.w * q.y)         0]
|2 * (q.x * q.y + q.w * q.z)       1 - 2 * (q.x * q.x + q.z * q.z)   2 * (q.y * q.z - q.w * q.x)         0|
|2 * (q.x * q.z - q.w * q.y)       2 * (q.y * q.z + q.w * q.z)       1 - 2 * (q.x * q.x + q.y * q.y)     0|
[0                                 0                                 0                                   1]

之后,我设置了矩阵的平移分量:

[...   ...   ...  -x]
|...   ...   ...  -y|
|...   ...   ...  -z|
[0     0     0     1]

最后,我将它乘以模型视图矩阵堆栈,然后渲染我的所有对象。我很确定这个数学是正确的,但它不会产生我期望的结果。显然,前向向量和右向向量是问题所在,所以我唯一的问题是为什么它们是错误的,如果我想得到我期望的结果,应该如何设置它们。谢谢。

编辑:我从这个人的四元数相机类中找到了解决方案。首先,我像以前一样构造一个旋转矩阵,然后我从第一列、第二列和第三列(分别为 xa、ya 和 za)中获取矩阵的列向量。然后我像这样设置矩阵的平移分量:

[...  ...  ...  -xa.dotProduct(cameraPos)]
|...  ...  ...  -ya.dotProduct(cameraPos)|
|...  ...  ...  -za.dotProduct(cameraPos)|
[...  ...  ...  ...                      ]

然后可以将生成的矩阵乘以模型视图矩阵堆栈,并且可以完美运行。

4

2 回答 2

2

编辑:我从这个人的四元数相机类中找到了解决方案。首先,我像以前一样构造一个旋转矩阵,然后我从第一列、第二列和第三列(分别为 xa、ya 和 za)中获取矩阵的列向量。然后我像这样设置矩阵的平移分量:

[...  ...  ...  -xa.dotProduct(cameraPos)]
|...  ...  ...  -ya.dotProduct(cameraPos)|
|...  ...  ...  -za.dotProduct(cameraPos)|
[...  ...  ...  ...                      ]

然后可以将生成的矩阵乘以模型视图矩阵堆栈,并且可以完美运行。

是的,这正是我所建议的,只是有点不同。您必须了解,OpenGL 没有相机,而是您只是将世界朝相反的方向移动,因此您需要找到逆变换矩阵。

相机只是旋转和移动。这使事情变得非常简单。平移的逆向是符号相反的同一个向量,而旋转矩阵的逆向是它的转置(列和行交换)。现在看看像 OpenGL 这样的齐次变换矩阵使用它们:

R t
0 1

左上角 3×3 是旋转部分,最右列是平移向量。我想剩下的你自己已经想好了。

于 2012-02-02T08:45:43.063 回答
0

老实说,试图找到一个矩阵来乘以模块视图矩阵确实很复杂并且很容易出错。有很多混乱和特殊情况。例如,如果您向上看 90 度,则您的两个轴变得相同。一个合乎逻辑的问题是:如果你向后转头,所以你通过了顶点,你的向上向量应该是反转的,对吧?但是如果你错过了 0.0001 度呢?那么你应该把头转向那个点,这样你的向上向量仍然是向上的。

在我看来,最好的方法是从另一个角度来处理这个问题。让我们假设两种情况:

  • 颠倒是不可能的:
    • 为您的相机位置和方向的纬度/经度保留一个点。通过简单的 sin/cos 运算,您可以获得方向向量。你的向上向量是 (0, 1, 0)
    • 转身就是简单的改变经纬度
  • 倒置可能:
    • 除了相机位置之外,还要保持向上和目标向量。
    • 转弯时,计算 right=target x up 然后将 target 改为 x*right+y*up
    • 然后,您需要标准化目标向量并计算新的。不过要处理的案件很多。

在所有这些之后,您只需调用gluLookAt.

于 2012-02-02T02:01:04.247 回答