在MVP(模型-视图-投影)变换的过程中,模型变换实际上就是对物体本身的变换,如平移、旋转物体。视图变换,就是计算出物体相对摄像机的位置,因为模型变换变换的是物体的绝对位置,那从摄像机作为原点出发,去看物体的位置,肯定就不是物体的绝对位置,所以视图变换做的就是这件事。
那么怎么算出一个矩阵M,使得任意的物体应用了该矩阵得出的坐标是相对摄像机的呢?
很容易知道,计算物体的相对摄像机的坐标,实际上就是在摄像机的位置为原点,去看各个物体。所以很容易我们可以把问题转为计算摄像机到原点的矩阵(因为摄像机变换了,那物体也应用这个矩阵算出的结果,实际就是以摄像机视角看到的坐标)。当然我们还要旋转摄像机,让摄像机能看向-z轴的方向,并且向上方向是(0, 1, 0),为什么要这样做主要是方便后面的计算。
首先,根据摄像机的坐标,我们可以很轻松推导出把摄像机移动到原点的矩阵(pos是摄像机坐标):
Mtransform=100001000010−pos.x−pos.y−pos.z1
然后就是旋转,首先要让镜头对准-z方向,所以要让镜头的朝向指向 (0, 0, -1)。假设原来朝向是 look(x,y,z), 所以 M ·( look.x, look.y, look.z ,1) = (0, 0, -1, 1)。
这样解M是很难解的,但是有个特性是:
如果 A∙B=C, 那 A−1∙C=B.
那么我们可以算出矩阵的逆:
M−1=???0???0−look.x−look.y−look.z00001
同理,原来的向上方向up(x,y,z) 要旋转到 (0, 1, 0), 可以更新M−1:
M−1=???0up.xup.yup.z0−look.x−look.y−look.z00001
那还有第一列还没有的出来。这个时候根据右手定理,-z方向叉乘y方向,实际上是x轴正方向。所以原来的x轴方向是 −look×up=cross 这里定为 cross, 所以cross要旋转到 (1, 0, 0)。 所以我们又可以更新M−1
M−1=cross.xcross.ycross.z0up.xup.yup.z0−look.x−look.y−look.z00001
然后我们再取矩阵的逆,正交矩阵的逆就是转置,所以直接转置就可以算出矩阵M:
Mrotate=cross.xup.x−look.x0cross.yup.y−look.y0cross.zup.z−look.z00001
最后我们再结合平移矩阵(先平移再旋转,所以平移矩阵放在右边):
Mview=cross.xup.x−look.x0cross.yup.y−look.y0cross.zup.z−look.z00001100001000010−pos.x−pos.y−pos.z1=cross.xup.x−look.x0cross.yup.y−look.y0cross.zup.z−look.z0−dot(cross,pos)−dot(up,pos)dot(look,pos)1
到此,视图矩阵的推导过程就结束了。刚开始确实很难入手,手推一遍后,实际并不会特别难。
完)