计算LookAt矩阵

时间:2008-12-08 10:04:08

标签: math graphics 3d projection

我正在编写一个3d引擎,我遇到了DirectX文档中描述的LookAt算法:

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  l

现在我了解它在旋转方面是如何工作的,但我不太明白的是为什么它将矩阵的平移组件放在那些点积上。仔细检查它似乎是根据新基础矢量投影到眼睛/相机的位置,将相机位置调整一小部分。

问题是为什么需要这样做?它完成了什么?

8 个答案:

答案 0 :(得分:49)

请注意,给出的示例是一个左手的行主矩阵

所以操作是:先转换到原点(通过 - eye 移动),然后旋转,使 eye 中的矢量 At 与+ z对齐:

如果你通过翻译预先乘以旋转矩阵,基本上会得到相同的结果 - eye

[      1       0       0   0 ]   [ xaxis.x  yaxis.x  zaxis.x 0 ]
[      0       1       0   0 ] * [ xaxis.y  yaxis.y  zaxis.y 0 ]
[      0       0       1   0 ]   [ xaxis.z  yaxis.z  zaxis.z 0 ]
[ -eye.x  -eye.y  -eye.z   1 ]   [       0        0        0 1 ]

  [         xaxis.x          yaxis.x          zaxis.x  0 ]
= [         xaxis.y          yaxis.y          zaxis.y  0 ]
  [         xaxis.z          yaxis.z          zaxis.z  0 ]
  [ dot(xaxis,-eye)  dot(yaxis,-eye)  dot(zaxis,-eye)  1 ]

附加说明:

请注意,观察变换是(有意)反转:您将每个顶点乘以此矩阵以“移动世界”,以便您想要查看的部分最终出现在规范视图体积中。

另请注意,LookAt矩阵的旋转矩阵(称为 R )组件是基础矩阵的反转变化,其中 R的行是旧基础向量的新基础向量(因此变量名称xaxis.x,... xaxis是基础发生变化后的 new x轴)。但是,由于反转,行和列被转置。

答案 1 :(得分:16)

我通过创建一个3x3旋转矩阵构建一个观察矩阵,就像你在这里做的那样然后将它扩展为带有零的4x4和右下角的单个1。然后我使用负眼点坐标(无点积)构建一个4x4平移矩阵,并将两个矩阵相乘。我的猜测是,这个乘法产生的效果相当于示例底行中的点积,但我需要在纸上进行处理才能确定。

3D旋转可以转换轴。因此,您不能直接使用眼点,也不能将其转换为新的坐标系。这就是矩阵乘法 - 或者在这种情况下,3点积值 - 完成。

答案 2 :(得分:3)

该翻译组件可以帮助您创建一个orthonormal basis,其中“眼睛”位于原点,其他所有内容都以该原点(您的“眼睛”)和三个轴表示。

概念不是矩阵正在调整摄像机位置。相反,它试图简化数学:当你想要渲染你可以从你的“眼睛”位置看到的所有东西的图片时,最容易假装你的眼睛是宇宙的中心。

所以,简短的回答是,这使得数学更加容易。

回答评论中的问题:你不仅仅从一切中减去“眼睛”位置的原因与操作的顺序有关。可以这样想:一旦你进入了新的参考框架(即由xaxis,yaxis和zaxis表示的头部位置),你现在想用这个新的(旋转的)参考框架表达距离。这就是为什么你使用新轴的点积和眼睛位置:它表示事物需要移动的距离,但它使用新的坐标系。

答案 3 :(得分:3)

只是一些一般信息:

lookat矩阵是一个矩阵,用于定位/旋转某些东西以指向(查看)空间中的某个点,从空间中的另一个点开始。

该方法采用摄像机视图所需的“中心”,一个“向上”向量,表示摄像机的“向上”方向(向上几乎总是(0,1,0),但它不是必须是)和一个“眼睛”矢量,这是相机的位置。

这主要用于相机,但也可用于其他技术,如阴影,聚光灯等。

坦率地说,我不完全确定为什么要在此方法中设置翻译组件。在gluLookAt(来自OpenGL)中,转换组件设置为0,0,0,因为相机始终被视为0,0,0。

答案 4 :(得分:2)

点积只是将一个点投射到轴上以获得眼睛的x,y或z分量。您正在向后移动相机,因此从(10,0,0)和(100000,0,0)中查看(0,0,0)会产生不同的效果。

答案 5 :(得分:1)

lookat矩阵执行以下两个步骤:

  1. 将您的模型翻译为原点,
  2. 根据向上矢量和外观设置的方向旋转它 方向。
  3. 点积意味着您首先进行平移然后旋转。点积不是将两个矩阵相乘,而是将一行与一列相乘。

答案 6 :(得分:1)

转换4x4矩阵包含两个三个组件: 旋转矩阵 2.翻译添加。 3.规模(许多引擎不直接在矩阵中使用它。)

它们的组合会将一个点从空间A变换为空间B,因此这是一个变换矩阵M_ab

现在,摄像机的位置在空间A中,因此它不是空间B的有效变换,因此您需要将此位置与旋转变换相乘。

唯一未解决的问题仍然是为什么要点? 好吧,如果你在纸上写下3个点,你会发现3个点的X,Y和Z与旋转矩阵的乘法非常相似。

第四行/列的一个例子是在世界空间中取零点 - (0,0,0)。它不是相机空间中的零点,所以你需要知道相机空间中的表示是什么,因为旋转和刻度将它保持为零!

欢呼声

答案 7 :(得分:0)

必须将视点放在轴空间中,而不是放在世界空间中。当您使用坐标单位基矢量(x,y,z之一)对矢量进行点处时,它会为您提供 空间中眼睛的坐标。您可以通过在最后一个位置应用三个翻译来转换位置,在本例中为最后一行。然后用负片向后移动眼睛相当于向前移动所有其余空间。就像在电梯里上升让你觉得世界其他地方正在从你身下辍学。

使用左手矩阵,翻译作为最后一行而不是最后一列,是一种宗教差异,与答案完全无关。但是,这是一个应该严格避免的教条。在绘制树形草图时,最好以自然阅读顺序从左到右链接全局到局部(前向运动)变换。使用左手矩阵迫使你从右到左书写这些。