取景变换
取景变换(也称观察变换)是在世界空间下架设一个摄像机,把各个顶点坐标从世界空间变换到摄影空间(观察空间)。在摄影空间里,摄像机或者说观察点位于原点,向着z轴正方向。因为Direct3D采用左手坐标系,所以z轴正方向指向屏幕里面。设三维顶点在世界坐标系的坐标为Pworld,在摄影空间内的坐标为Pview,则:
Pview = Pworld * Mview
矩阵Mview称为观察矩阵。观察矩阵根据摄像机在世界空间中的位置(即摄影空间的原点在世界坐标系中的相对位置)和摄像机的观察方向在世界空间中的方向,将世界坐标系下的对象重新定位。在Direct3D中设置观察矩阵非常简单,首先调用Direct3D扩展实用库提供的函数D3DXMatrixLookAtLH(),生成一个基于左手坐标系的观察矩阵,该函数声明如下:
Builds a left-handed, look-at matrix.
D3DXMATRIX * D3DXMatrixLookAtLH(
D3DXMATRIX * pOut,
CONST D3DXVECTOR3 * pEye,
CONST D3DXVECTOR3 * pAt,
CONST D3DXVECTOR3 * pUp
);
Parameters
- pOut
- [in, out] Pointer to the D3DXMATRIX structure that
is the result of the operation.
- pEye
- [in] Pointer to the D3DXVECTOR3 structure that
defines the eye point. This value is used in translation.
- pAt
- [in] Pointer to the D3DXVECTOR3 structure
that defines the camera look-at target.
- pUp
- [in] Pointer to the D3DXVECTOR3 structure
that defines the current world's up, usually [0, 1, 0].
Return Values
Pointer to a D3DXMATRIX structure that is a
left-handed, look-at matrix.
Remarks
The return value for this function is the same value
returned in the pOut parameter. In this way, the D3DXMatrixLookAtLH
function can be used as a parameter for another function.
This function uses the following formula to compute the
returned matrix.
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) 1
然后调用函数IDirect3DDevice9::SetTransform(D3DTS_VIEW,
&mat_view)设置观察矩阵,其中mat_view为函数D3DXMatrixLookAtLH()生成的观察矩阵。
当然,也可以使用函数D3DXMatrixLookAtRH()建立一个基于右手坐标系的观察矩阵,但因为Direct3D采用左手坐标系,所以通常不使用此函数。
创建并设置一个观察矩阵的方法很容易,但真正理解构造观察矩阵原理却不像理解构造世界变换矩阵那么容易。有多种方法可以建立观察矩阵,但无论对于哪种情况,摄像机都有自己在世界空间下的逻辑位置和方向。观察矩阵的任务就是完成对象的平移和旋转,从而把它们定位在摄影空间里,而此时摄像机位于摄影空间的原点。所以,一种创建观察矩阵的方法是用一个平移矩阵以及各个轴的旋转矩阵来实现。下面以这种方法为例较简单介绍构造观察矩阵的原理。这种方法使用下面的矩阵运算公式:
V = T * Rz * Ry * Rx
在这个公式里,V是将要创建的观察矩阵,T是世界坐标系下的一个平移矩阵,Rx、Ry和Rz是绕x、y和z轴的旋转矩阵。这些平移矩阵和旋转矩阵以世界空间下摄影机的逻辑位置和方向为基础。所以,如果一个摄影机在世界空间下的逻辑位置是(10,
20, 100),平移矩阵的作用是将对象沿x轴移动10个单位,沿y轴移动20个单位,沿z轴移动100个单位。公式中的旋转矩阵以摄像机的方向为基础,表示摄影空间里的坐标轴相对于世界空间坐标轴应该旋转多少度。例如,如果摄像机的方向垂直向下时,摄影空间的z轴偏离世界空间z轴90度。那么就需要用公式中的旋转矩阵对场景里的所有对象绕x轴旋转负90度,也就是说,这时的旋转是与偏离程度是等大反向的。把前面的平移矩阵和这个旋转矩阵连接起来,就创建了一个观察矩阵V。用它来调整场景里对象的位置和方向,使得它们的顶部冲着摄影机的镜头,就好像摄像机从对象的顶部向下拍摄一样。