游戏开发编程基础第二章
三角形网格是构建物体模型的基本单元
通常网格中的三角形元素:
多边形(polygons),图元(primitives),网格几何元(mesh geometry)
描述三角形单元时,需要指定改三角形单元3个顶点的位置
描述物体时,需要指定构成该物体的三角形单元列表
顶点结构定义好之后,就需要用灵活顶点格式(Flexible Vertex Format,FVF)标记的组合来描述顶点的组织结构
例如:
#define FVF_COLOR (D3DFVF_XYZ|D3DFVF_DIFFUSE)//位置属性,漫反射颜色
#define FVF_NORMAL_TEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)//位置,法线,纹理
定义灵活顶点格式时必须遵循一个约定:灵活顶点格式标记的指定顺序必须与顶点结构中相应类型的数据定义的顺序保持一致
三角形单元是3D物体的基本组成部分。构建一个物体,需要创建一个描述物体形状的轮廓形状和轮廓的三角形的单元列表
三角形单元列表包含了我们所希望绘制的每个独立三角形的数据
三角形各顶点的指定顺序非常重要,我们称其为绕序(winding order)
为了解决顶点重合,引入索引的概念
我们创建一个顶点列表(vertex list)和一个索引列表(index list)
顶点列表包含了全部独立顶点,索引列表包含了指向顶点列表的索引,这些索引规定了构建三角形单元,各顶点应按何种方式来组织
摄像机指定了场景对观察者的可见部分,即将依据哪部分3d场景来创建2D图像
在世界坐标系中,摄像机有一定的位置和方向,定义了可见的空间体积(在3D图形学中也可称为视域体或视截体)
位于视域体之外的物体时不可见的,在进一步处理时将应将其丢弃,丢弃这类数据运算过程称为裁剪
投影窗口时一个2D区域,位于视域体中的3D几何体通过投影映射到该区域中,便创建了3D场景的2D表示
很重要的一点是,矩形投影窗口在X和Y方向坐标的最小值是min(-1,-1),最大值max(1,1)
Direct3D将投影平面定义为平面z = 1
要想用Direct3D来完成坐标变换,我们所必须做的是提供描述坐标变换的变换矩阵
应用一个变换矩阵的方法是使用IDirect3DDevice9->SetTransfrom方法,
改方法有两个参数:1,描述变换类型,2 描述变换矩阵
假定让一个立方体的中心位于世界坐标系中的点(-3,2,6)上,让一个球体的中心位于点(5,0,-2)上:
立方体:
D3DXMATRIX cubeWorldMatrix;
D3DXMatrixTranslation(&cubeWorldMatrix,-3.0f,2.0f,6.0f);
Device->SetTransfrom(D3DTS_WORLD,&cubeWorldMatrix);
drawCube();
球体:
D3DXMATRIX sphereWorldMatrix;
D3DXMatrixTranslation(&sphereWorldMatrix,5.0f,0.0f,-2.0f)
Device->SetTransfrom(D3DTS_WORLD,&sphereWorldMatrix);
drawSphere();
为了简化运算,我们将摄像机变换至世界坐标系的原点,并将其旋转,使摄像机的光轴与世界坐标系z轴正方向一致,
同时,世界空间中所有几何体都随着摄像机一同进行变换,以保证摄像机的视场恒定。这种变换称为取景变换,我们称变换后的几何体位
于观察坐标系中。
取景变换矩阵(观察矩阵)可由如下D3DX函数得到:
D3DXMATRIX *D3DMatrixLookAtLH(
D3DXMATRIX* pOut,
CONST D3DXVECTOR3* pEye,//摄像机在世界坐标系中的位置
CONST D3DXVECTOR3* pAt,//摄像机在世界坐标系中的被观察点
CONST D3DXVECTOR3* pUp//世界坐标系中表示”向上“方向的向量
);
例:假定摄像机位于(5,3,-10),其观察点为世界坐标系的原点(0,0,0)
D3DXVECTOR3 position(5.0f,3.0f,-10.0f);
D3DXVECTOR3 targetPoint(0.0f,0.0f,0.0f);
D3DXVECTOR3 worolUp(0.0f,1.0f,0.0f);
D3DXMATRIX V;
D3DMatrixLookAtLH(&V,&position,&targetPoint,&worldUp);
// 取景变换需要用IDirect3DDevice9::SetTransform方法来设定,其中对应于变换类型的参数需指定为D3DTS_VIEW:
Device->SetTransform(D3DTS_VIEW,&V);
为了实现背面消隐,Direct3D需要区分哪些多边形是正面,哪些是背面朝向。默认状态下,Direct3D认为顶点排列顺序为顺时针(观察坐标
系中)的三角形单元时正面朝向的,顶点排列顺序为逆时针(观察坐标系中)的三角形单元时背面朝向的
通过修改绘制状态(render state)D3DRS_CULLMODE来达到目的
Device->SetRenderState(D3DRS_CULLMODE,
Value//D3DCULL_NONE 禁用背面消隐,//D3DCULL_CW只对顺时针绕序的三角形单元进行消隐//D3DCULL_CCW默认
值,只对逆时针绕序的三角形单元进行消隐
);
投影变换定义了视域体,并负责将视域体中的几何体投影到投影窗口中。投影矩阵比较复杂,我们将使用D3DX函数:
//其功能是依据视域体的描述信息创建一个投影矩阵
D3DXMATRIX* D3DXMatrixPerspectiveFovLH(
D3DXMATRIX& pOut,//指向D3DXMATRIX 结构的操作结果矩阵。
FLOAT fovY,//观察时y 轴方向的角度(弧度),就是观察范围夹角
FLOAT Aspect,//纵横比
FLOAT zn,//近裁剪面位置Z值。
FLOAT zf//远裁剪面位置Z值
);
投影矩阵应用要用方法:IDirect3DDevice::SetTransform来实现,其中对应变换类型的参数需指定为D3DTS_PROJECTION
例:
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj,PI*0.5f,(float)width/(float)height,1.0f,1000.0f);
Device->SetTransform(D3DTS_PROJECTION,&proj);
视口变换的任务是将顶点坐标从投影窗口转换到屏幕的一个矩形区域中,该矩形区域称为视口
Direct3D中,视口用结构D3DVIEWPORT9来表示
typedef struct D3DVIEWPORT9{
DWORD X;
DWORD Y;
DWORD Width;
DWORD Height;
DWORD MinZ;//指定深度缓存中的最小深度值
DWORD MaxZ;//指定深度缓存中的最大深度值
}D3DVIEWPORT9;
该结构前4个数据成员定义了视口矩形相对于其父窗口的位置及大小。
Direct3D将深度缓存的深度范围设在[0,1]区间内,所以除非想要追求某种特效,MinZ和MaxZ应限制在指定区间内
例:
D3DVIEWPORT9 vp = {0,0,640,480,0,1};
Device->SetViewport(&vp);