D3D座标转换浅析

在开始介绍前还有一些问题需要提前声明,以下的介绍都以左手座标系为基准,因为D3D就是采用的左手座标系。在左手座标系下,涉及到旋转时的正方向是指:从座标轴的正方向向负方向看,顺时针方向为正方向。

(1)世界变换

把物体的本地座标变换成世界座标,这个座标变换称为世界变换(World Transformation)。例如我们要在世界座标系中放置一个立方体定位在(-3,2,6),在D3D环境下我们可以这样写程序:

// Build the cube world matrix that only consists of a translation
D3DXMATRIX cubeWorldMatrix;
D3DXMatrixTranslation(&cubeWorldMatrix, -3.0f, 2.0f, 6.0f); 
// Set the cube’s transformation
Device->SetTransform(D3DTS_WORLD, &cubeWorldMatrix);
drawCube(); // draw the cube

以上提到的cubeWorldMatrix实际上为4X4矩阵:

 1 0 0 0
 0 1 0 0
 0 0 1 0
-1 2 6 1
假如某点在本地(物体)座标系中座标为P = (x,y,z,1),则经过转换后获得该点在世界座标系中的座标,即P' = P*cubeWorldMatrix。
以上是以物体平移举例子,相似的世界变换还有绕轴旋转。

(2)视角变换

把物体从世界空间转换到视角空间,这个座标变换称为视角变换(View Transformation)。

我们可以通过调用D3DXMATRIX *D3DXMatrixLookAtLH(D3DXMATRIX* pOut, CONST D3DXVECTOR3* pEye, CONST D3DXVECTOR3* pAt, CONST D3DXVECTOR3* pUp),来获得相应的转换矩阵,在函数中pEye 参数指定摄相机在世界座标系中的位置,pAt 参数指定摄相机所观察的世界座标系中的一个目标点,pUp参数指定3D世界中的上方向,通常设Y轴正方向为上方向,即取值为(0,1,0),pOut获得相应的转换矩阵。例如:假设我们要把摄相机放在点(0,3,-4),并且目标点为世界座标系的中点(0,0,0),我们可以这样获得视图变换矩阵:

        D3DXVECTOR3 eye( 0.0f, 3.0f,-4.0f ); 
        D3DXVECTOR3 lookat( 0.0f, 0.0f, 0.0f ); 
        D3DXVECTOR3 up( 0.0f, 1.0f, 0.0f ); 
        D3DXMATRIX matView;
        ::D3DXMatrixLookAtLH( &matView, &eye, &lookat, &up );
        Device->SetTransform( D3DTS_WORLD, &matWorld );

上面的matView矩阵为:
        1    0    0   0
        0  0.8 -0.6 0
        0  0.6  0.8  0
        0    0    5    1
在该例子中相当于把世界座标系顺时针旋转α度,其中α满足tanα=3/4,在把旋转后的世界座标沿z轴负方向移动5,最后获得的座标系相当于摄像机座标系(视角空间),还以点P为例,转换后点的新座标(在摄像机座标系的座标)为P' = P*matView。

(3)投影变换

把物体从视角空间投影到投影窗口中,这个座标变换称为投影变换(Perspective Transformation)。

 投影变换的实质就是定义可视体并将可视体内的几何图形投影到投影窗口上去,我们通过以下的函数来求得投影矩阵:
D3DXMATRIX *D3DXMatrixPerspectiveFovLH( D3DXMATRIX* pOut, FLOAT fovY, FLOAT Aspect, FLOAT zn, FLOAT zf );
其中forY是Y方向上的可视角,Aspect参数为投影平面的宽高比例值,zn为前(near)裁剪平面的z座标,zf为后(far)裁剪平面的z座标。
投影矩阵的计算比较复杂可以先不追究(我也还没弄懂O(∩_∩)O~),下面再以实例说明:

    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
        &proj, 
        D3DX_PI * 2 / 3, // 120 - degree
        (float)Width / (float)Height,
        1.0f,                   // distance to near plane
        1000.0f);               // distance to far plane
    Device->SetTransform(D3DTS_PROJECTION, &proj);
上面程序中fovY为120°,即Y轴方向上的视角为120°,XZ平面上下各有60°,Width / Height为投影平面的宽高比例值,总体上来说就是将视角空间中从z=1到z=1000,摄像机从上到下120°范围内的物体显示到投影窗口上(在Direct3D 中定义的投影平面(即投影窗口所在的平面)是 Z = 1 的平面)。要注意的是程序中的Width和Height代表要显示相应图像的窗口客户区的宽和高,对Aspect进行这样的设置可以使得要显示的物体保持原来的比例。下面举例进行解释:

假设显示图像的窗口Width = 480,Height = 480,而Aspect不为Width / Height而是Aspect = 0.5,其他参数不变这就相当于摄像机Y方向(上下方向)的范围是120°,而X方向(左右方向)上的范围是60°,即要把宽和高比值为1:2的图像显示到比值为Width / Height = 1:1的窗口上,显示的结果相当于图像被左右拉伸了。

发布了5 篇原创文章 · 获赞 6 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章