一.介绍
经历了之前手写立方体的痛苦过程,终于到了网格模型这一步。我们做游戏的时候肯定不能只用立方体呀,想要复杂的人物模型肯定是需要美工同学们使用专业的工具才能创建出来的,这些模型文件中定义好了网格模型的形状以及材质纹理等信息,我们所要做的只是读取这个文件,然后就可以根据文件中的信息创建复杂的模型啦!然而说白了,这些东东DX已经为我们定义好了,我们背一背API就行啦!
创建这些模型一般用3DMAX或者Maya软件,然而我作为一个程序都写不太明白的人,并不需要过多的了解这个东东,只需要知道它导出的格式就好啦。通常建模软件导出的格式为3ds,.max, .obj,.mb等,而.X为DX自带的一种格式,我们在学习阶段使用.X文件足够了。至于其他的,只是换了个识别的工具罢了,功能都是一样的。还是老套路,背API。
我们使用.X文件时,一般都是.X文件配上若干张图片,.X文件中记录了这些纹理怎么用,这个我们不需要关心。
二.过程
1.根据.X文件名读取并创建Mesh:
该函数原型如下:
HRESULT D3DXLoadMeshFromX(
__in LPCTSTR pFilename,//.X文件名
__in DWORD Options,//一般为D3DXMESH_MANAGED
__in LPDIRECT3DDEVICE9 pD3DDevice,//设备指针
__out LPD3DXBUFFER *ppAdjacency,//网格临接信息缓冲区指针
__out LPD3DXBUFFER *ppMaterials,//网格材质以及纹理信息缓冲区指针
__out LPD3DXBUFFER *ppEffectInstances,//网格特效缓冲区指针
__out DWORD *pNumMaterials,//材质信息个数
__out LPD3DXMESH *ppMesh//Mesh指针的指针
);
这里面有个新的数据类型LPD3DXBUFFER类型,我们看到好几种信息都是存在这种类型的指针所指向的缓冲区中了。如果我们想要获得特定类型的信息要肿么办呢?
DX为我们提供了一个函数:GetBufferPointer();例如,我们想要获得材质信息,就可以这样写:
D3DXMATERIAL *pMtrl = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
例如:
D3DXLoadMeshFromX(TEXT("tiger.X"), D3DXMESH_MANAGED, g_pDevice, &pAdjBuffer, &pMtrlBuffer, NULL, &g_dwNumMtrls, &g_pMesh);
从tiger.X中创建了一个Mesh模型,相关信息都存储在我们传入的参数所指向的缓冲区中啦。
2.载入材质和纹理信息:
通过上面的函数,我们获得了材质以及纹理信息,这些信息都存储在pMtrlBuffer所指向的缓冲区中,这些材质信息是使用D3DXMATERIAL结构体存储的,该结构体的定义如下:
typedef struct D3DXMATERIAL {
D3DMATERIAL9 MatD3D;//材质信息
LPSTR pTextureFilename;//纹理贴图文件名
} D3DXMATERIAL, *LPD3DXMATERIAL;
这样,我们就可以从这pMtrlBuffer指针指向的缓冲区中提取Mesh模型的材质以及纹理信息,并将之用到我们要绘制的对象中去。而这个结构体的数量就存储在g_dwNumMtrls中,我们只需要遍历一下,就可以将纹理材质设置好。
例如:
LPD3DXBUFFER pAdjBuffer = NULL; //临时缓冲区指针,存储对象模型信息
LPD3DXBUFFER pMtrlBuffer = NULL; //临时缓冲区指针,存储对象纹理材质信息
//根据.X文件创建Mesh模型
D3DXLoadMeshFromX(TEXT("tiger.X"), D3DXMESH_MANAGED, g_pDevice, &pAdjBuffer, &pMtrlBuffer, NULL, &g_dwNumMtrls, &g_pMesh);
//读取材质和纹理数据
D3DXMATERIAL *pMtrl = (D3DXMATERIAL*)pMtrlBuffer