您的位置:首页 > 其它

DirectX学习笔记(十三):取景变换矩阵计算及3D世界摄像机的原理分析和实现

2016-09-24 14:07 597 查看

前言:

在玩3D游戏中,我们对于整个游戏场景的视野获取就是通过摄像机来完成的。由此可见摄像机的重要性。前面的所有例子都是针对于摄像机固定来说的。这一次我们来设计一个摄像机(模拟游戏场景中的摄像机)。

取景变换计算过程:

在前面我们讲过取景变换。在当摄像机的位置和朝向任意时,进行一些操作会造成效率低下很是麻烦。为了简化运算,我们将摄像机变换到世界坐标系的原点,并旋转摄像机使其光轴与世界坐标系的z轴正方向朝向一致。要特别注意的是,世界中的所有物体都会随之摄像机变换,以保证摄像机的视场恒定。

如下图:



由此可见,我们要描述一个摄像机必须有四个向量:右向量(right)、上向量(up)、观察向量(look)、位置向量(position)。实际上,这些向量的定义意味着我们定义了一个局部的坐标系。

这样,我们就可以通过这四个向量来进行以下变换:

绕向量right的旋转

绕向量up的旋转

绕向量look的旋转

沿向量right方向的扫视

沿向量up的升降

沿向量look的平动

如下图所示:



那么,我们怎么才能实现这些变换呢?答案:通过矩阵运算!!

 

为了讲解方便,我们令向量

                                 p = (px,py,pz)表示位置向量,position
 
  r = (rx,ry,rz) 向量表示右向量, right
         u = (ux,uy,uz)  向量表示上向量,up
     
   d = (dx,dy,dz)  向量表示观察向量。look

我们知道,取景变换所解决的其实就是世界坐标系中的物体在以摄像机为中心的坐标系中如何来表示的问题。这就是说,需要将世界坐标系中的物体随着摄像机一起进行变换,这样摄像机的坐标系就与世界坐标系完全重合了。        

第一张图中的的(a)图到(b)图,是一个平移的过程,而(b)图到(c)图则是一个旋转的过程。另外需要注意的一点是,空间中的物体也应该随着摄像机一同进行变换,这样摄像机中看到景物才没有变化。

我们的目的,就是通过一系列的矩阵变换,得到最终的取景变换矩阵V。

我们要得到取景变换矩阵V,说白了就是能够满足如下的条件: 

pV=(0,0,0) 矩阵V将摄像机移动到世界坐标系的原点

rV=(1,0,0)矩阵V将摄像机的右向量与世界坐标系的x轴重合

uV=(0,1,0)矩阵V将摄像机的上向量与世界坐标系的y轴重合

lV=(0,0,1)矩阵V将摄像机的观察向量与世界坐标系的z轴重合

所以,想得到这个取景变换矩阵V,就是进行了先平移,后旋转。

摄像机操作:

1.平移:

将摄像机的位置向量p平移到原点就是实现这个式子:pV=(0,0,0),即摄像机的位置分量乘以V之后等于(0,0,0)。那么很简单,我们假设取景变换矩阵V实现平移操作的的中间矩阵为T来简化一下。

而将摄像机的位置向量p平移到原点可以通过把他和它大小相等,方向相反的-p向量做加法轻松实现,即p-p=0,所以描述取景变换中的平移



2.旋转:

想要让摄像机的各分量与世界坐标系的各轴重合,

即满足之前我们列出的这三个式子:

rV=(1,0,0)

uV=(0,1,0)

lV=(0,0,1)

实现起来,求出如下的一个3x3的矩阵A:



我们可以看出A是B矩阵的逆矩阵。而矩阵B刚好是个正交矩阵,那么因为:正交矩阵的逆矩阵等于其转置矩阵。也就是说B矩阵的逆矩阵等于B矩阵的转置矩阵,而B矩阵的逆矩阵就是A矩阵,那么就是说A矩阵等于B矩阵的转置矩阵。

那么我们求一下B矩阵的转置矩阵,就是求出A矩阵了。

也就是:



最后我们需要把A矩阵扩展成4X4的,然后计算一下两矩阵的值TA=V:



以上就是取景变换的求法也就是以前我们经常用到的D3DXMatrixLookAtLH函数的计算过程。

摄像机旋转实现:

实现摄像机的旋转,我们需要用到DX中的自带函数:

D3DXMATRIX *WINAPI D3DXMatrixRotationAxis(
D3DXMATRIX *pOut,
CONST D3DXVECTOR3 *pV,
FLOAT Angle
);

创建一个绕任意轴旋转的旋转矩阵。

参数:

pOut

[in, out] 指向D3DXMATRIX 结构的操作结果矩阵。

pV

[in] 指向任意轴向量。请参考 D3DXVECTOR3。

Angle

[in] 绕着任意轴旋转的角度(单位是弧度)。角度计算方法是当朝着旋转轴的原点看去时,顺时针方向为正值。

返回值:

指向绕着任意轴旋转的旋转矩阵。

说明:

函数返回值跟pOut 参数返回值是一样的。这样可以让函数D3DXMatrixRotationAxis作为其它函数的参数使用。


如果我们要绕向量(0.7,0.07,0.7)所确定的轴旋转90度:

D3DXMATRIX R;
D3DXVECTOR3 axis(0.7f, 0.7f, 0, 7f);
D3DXMatrixRotationAxis(&R, &axis, D3DX_PI / 2.0f);

摄像机的俯仰、偏航、滚动:

请先看以下几张图:







俯仰:绕摄像机的right向量旋转图1

偏航:绕摄像机的up向量旋转图2

滚动:绕摄像机的look向量旋转图3

摄像机的升降、行走和扫视:



行走:沿着摄像机的观察方向(即:沿着向量look方向)的平动。

扫视:沿着right方向从一边走到另一边

升降:沿着up方向的平动。

附加注释代码

点击打开链接

运行效果:



有问题的朋友请留言交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DirectX
相关文章推荐