我正在编写一个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
现在我了解它在旋转方面是如何工作的,但我不太明白的是为什么它将矩阵的平移组件放在那些点积上。仔细检查它似乎是根据新基础矢量投影到眼睛/相机的位置,将相机位置调整一小部分。
问题是为什么需要这样做?它完成了什么?
答案 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矩阵执行以下两个步骤:
点积意味着您首先进行平移然后旋转。点积不是将两个矩阵相乘,而是将一行与一列相乘。
答案 6 :(得分:1)
转换4x4矩阵包含两个三个组件: 旋转矩阵 2.翻译添加。 3.规模(许多引擎不直接在矩阵中使用它。)
它们的组合会将一个点从空间A变换为空间B,因此这是一个变换矩阵M_ab
现在,摄像机的位置在空间A中,因此它不是空间B的有效变换,因此您需要将此位置与旋转变换相乘。
唯一未解决的问题仍然是为什么要点? 好吧,如果你在纸上写下3个点,你会发现3个点的X,Y和Z与旋转矩阵的乘法非常相似。
第四行/列的一个例子是在世界空间中取零点 - (0,0,0)。它不是相机空间中的零点,所以你需要知道相机空间中的表示是什么,因为旋转和刻度将它保持为零!
欢呼声
答案 7 :(得分:0)
必须将视点放在轴空间中,而不是放在世界空间中。当您使用坐标单位基矢量(x,y,z之一)对矢量进行点处时,它会为您提供 空间中眼睛的坐标。您可以通过在最后一个位置应用三个翻译来转换位置,在本例中为最后一行。然后用负片向后移动眼睛相当于向前移动所有其余空间。就像在电梯里上升让你觉得世界其他地方正在从你身下辍学。
使用左手矩阵,翻译作为最后一行而不是最后一列,是一种宗教差异,与答案完全无关。但是,这是一个应该严格避免的教条。在绘制树形草图时,最好以自然阅读顺序从左到右链接全局到局部(前向运动)变换。使用左手矩阵迫使你从右到左书写这些。