
我们知道改变观察矩阵可以移动场景,为了更好描述场景移动,一般会模拟出一个摄像机。场景向后移动相当于摄像机向前移动,通过这种相对性可以产生一种我们在移动而不是场景在移动的感觉。
摄像机/观察空间
当我们讨论摄像机/观察空间(Camera/View Space)的时候,是在讨论以摄像机的视角作为场景原点时场景中所有的顶点坐标:观察矩阵把所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。要定义一个摄像机,我们需要它在世界空间中的位置、观察的方向、一个指向它右侧的向量以及一个指向它上方的向量。实际上创建了一个三个单位轴相互垂直的、以摄像机的位置为原点的坐标系。

摄像机位置
获取摄像机位置很简单。摄像机位置简单来说就是世界空间中一个指向摄像机位置的向量。不要忘记正z轴是从屏幕指向你的,如果我们希望摄像机向后移动,我们就沿着 z 轴的正方向移动。
QVector3D cameraPos(0.0f, 0.0f, 3.0f);
摄像机方向
下一个需要的向量是摄像机的方向,这里指的是摄像机指向哪个方向。现在我们让摄像机指向场景原点:(0, 0, 0)。将两个矢量相减,我们就能得到这两个矢量的差,用场景原点向量减去摄像机位置向量的结果就是摄像机的指向向量。由于我们知道摄像机指向 z 轴负方向,但我们希望方向向量(Direction Vector)指向摄像机的 z 轴正方向。如果我们交换相减的顺序,我们就会获得一个指向摄像机正 z 轴方向的向量:
QVector3D cameraTarget(0.0f, 0.0f, 0.0f);
QVector3D cameraDirection = cameraPos - cameraTarget;
cameraDirection.normalize();
右轴
需要的另一个向量是一个右向量(Right Vector),它代表摄像机空间的 x 轴的正方向。为获取右向量需要先使用一个小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此会得到指向 x 轴正方向的那个向量(如果我们交换两个向量叉乘的顺序就会得到相反的指向 x 轴负方向的向量):
QVector3D up(0.0f, 1.0f, 0.0f);
QVector3D cameraRight = QVector3D::crossProduct(up, cameraDirection);
cameraRight.normalize();
上轴
现在已经有了 x 轴向量和 z 轴向量,获取一个指向摄像机的正 y 轴向量就相对简单了,把右向量和方向向量进行叉乘:
QVector3D cameraUp = QVector3D::crossProduct(cameraDirection, cameraRight);
在叉乘和一些小技巧的帮助下,我们创建了所有构成观察/摄像机空间的向量。使用这些摄像机向量我们就可以创建一个 LookAt 矩阵了,它在创建摄像机的时候非常有用。
Look At
使用矩阵的好处之一是如果你使用 3 个相互垂直的轴定义了一个坐标空间,可以用这 3 个轴外加一个平移向量来创建一个矩阵,并且你可以用这个矩阵乘以任何向量来将其变换到那个坐标空间。这正是 LookAt 矩阵所做的,现在有了 3 个相互垂直的轴和一个定义摄像机空间的位置坐标,可以创建我们自己的 LookAt 矩阵了:
L o o k A t = [ R x R y R z 0 U x U y U z 0 D x D y D z 0 0 0 0 1 ] ∗ [ 1 0 0 − P x 0 1 0 − P y 0 0 1 − P z 0 0 0 1 ] LookAt=\begin{bmatrix} R_x& R_y& R_z& 0\\ U_x& U_y& U_z& 0\\ D_x& D_y& D_z& 0\\ 0& 0& 0& 1\end{bmatrix} * \begin{bmatrix} 1& 0& 0& -P_x\\ 0& 1& 0& -P_y\\ 0& 0& 1& -P_z\\ 0& 0& 0& 1\end{bmatrix} LookAt= RxUx

最低0.47元/天 解锁文章
1004

被折叠的 条评论
为什么被折叠?



