LookAt函数背后的数学

时间:2012-07-10 20:55:32

标签: math matrix directx

在MSDN上(http://msdn.microsoft.com/en-us/library/windows/desktop/bb281710%28v=vs.85%29.aspx)对于LookAt函数是这个数学:

zaxis = normal(cameraTarget - cameraPosition)
xaxis = normal(cross(cameraUpVector, 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, cameraPosition)  -dot(yaxis, cameraPosition)  -dot(zaxis, cameraPosition)  1

据我所知,最后一行是翻译。你能解释一下为什么不能把cameraPosition放在这一行上并且需要点功能吗?

1 个答案:

答案 0 :(得分:3)

这是因为View矩阵将对象从世界空间转换为相机空间。将摄像机置于其位置不是转换。这将是逆变换。 考虑一个简单的2D坐标系:

Coordinate system

黑色坐标系是世界系统。蓝色的是带有系统的相机。绿色箭头是世界空间中摄像机的平移向量。

View矩阵会将相机从当前位置移回原点。第一步是旋转,以便两个系统的相应轴指向相同的方向:

Coordinate system transformed

这是通过矩阵的其他条目(m_11到m_33)来实现的。

现在剩下一个翻译。但翻译矢量被转换。幸运的是,我们知道如何。平移向量等于摄像机位置(注意,DirectX使用转置矩阵。为了显示背后的数学,我将它们转换回来):

/ xAxis.x   xAxis.y  xAxis.z   ...\    / camPos.X \   / camPos.x * xAxis.x + camPos.Y * xAxis.y + camPos.z * xAxis.z \
| yAxis.x   yAxis.y  yAxis.z   ...|    | camPos.Y |   | camPos.x * yAxis.x + camPos.Y * yAxis.y + camPos.z * yAxis.z |
| zAxis.x   zAxis.y  zAxis.z   ...|  * | camPos.Z | = | camPos.x * zAxis.x + camPos.Y * zAxis.y + camPos.z * zAxis.z |
\    0        0         0      .../    \    0     /    \                       0                                     /

如果你看一下结果:

camPos.X * xAxis.x + xamPos.Y * xAxis.y + camPos.z * xAxis.z

然后你会发现这等于

dot ( camPos, xAxis)

结论,点积用于补偿旋转。如果没有它,摄像机会稍微移位(例如在右上方太远)。