DirectX SDK (August 2008).Direct3D 9.官方指导教程 (六)
Tutorial 6:使用网格(Using Meshes)
复杂的几何模型通常都是用3D建模具生成然后生成为一个文件。在这里使用的是.x格式的文件,Direct3D使用的风格都是从这类文件加载的。风格都是很复杂的,但D3DX有内建的函数使得风格的使用更简单,Meshes工程主要介绍如何载入、绘制和卸载风格模型。使用如下步骤:
Steps
Step1 – 载入网格模型(Loading a Mesh Object)
Step 2- 绘制网格模型(Rendering a Mesh Object)
Step 3- 卸载网格模型(Unloading a Mesh Object)
引教程代码和Light工程是一致的,除了没有创建材质和光照,没有处理Direct3d的初始化,消息处理,渲染,关闭等操作。
Step 1-载入网格模型(Loading a Mesh Object)
一个Direct3D工程在使用风格之前必须先载入它。Meshes工程在创建了必要的Direct3D对象之后通过调用自定义函数InitGeometry()载入网格模型。
一个网格需要一个材质缓存来存储所有要使用的材质和纹理。函数如下所示定义材质缓存:
LPD3DXBUFFER pD3DXMtrlBuffer;
下面的代码进行网格的载入工作:
//从指定的文件路径名载入网格
if( FAILED(D3DXLoadMeshFromX( “Tiger.x”, D3DXMESH_SYSTEMMEM,
g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL,
&g_dwNumMaterials, &g_pMesh)))
{
//如果模型没有在当前文件夹,试访问上一级文件夹
if( FAILED( D3DXLoadMeshFromX(“..\\Timger.x”,
D3DXMESH_SYSTEMMEM, g_pd3dDevice,
NULL, &pD3DXMtrlBuffer, NULL,
&g_dwNumMaterials, &g_pMesh)))
{
MessageBox(NULL, “Could not find tiger.x”, “Meshes.exe”, MB_OK);
return E_FAIL;
}
}
第一个参数是指向文件的指针来告诉DirectX文件从哪里载入。此工程中是从Tiger.x载入。
第二个参数指定用何种方式创建网格,例子中使用D3DXMESH_SYSTEMMEM标记相当于同时使用D3DXMESH_VB_SYSTEMMEM和D3DXMESH_IB_SYSXMESH_SYSTEMMEM标记,两种标记都是将顶点缓存和索引缓存作用到系统内存中。
第三个参数是指向将要进行网格绘制的设备环境的指针。
第四个参数是ID3DXBuffer对象的指针,此对象将会填充相邻表面的信息,在此工程中这些信息没是必须的所以设为了0。
第五个参数也是ID3DXBuffer对象的指针,此方法调用完成后ID3DXBuffer对象将会被D3DXMATERIAL网格结构体填充。
第六个参数是指向填入ppMaterials数组中D3DXMATERIAL结构体的指针并在方法完成时把回地址。
第七个参数是网格对象的地址指针,进行网格模型的重新载入。
在载入了风格模型和材质信息后你还要费力的从材质缓存中取出形体和纹理名称。
在Meshes工程中做这些工作是先从获取材质缓存的指针开始的。下面的代码使用
ID3DXBuffer::GetBufferPointre()方法获取这个指针。
D3DXMATERIAL* d3dxmaterials =
(D3DXMATERIAL*) pD3DXMtrlBuffer->GetBufferPointer();
下面的代码片段根据所有的网格材质数量来进行新网格和纹理对象的重建。
g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNummaterials];
第一个材质都进行如下步骤处理:
第一步复制材质:
g_pMeshMaterials = d3dxMaterials.MatD3D;
第二步是设定材质的环境光:
g_pMeshMaterials.Ambient = g_pMeshMaterials.Diffuse;
最后是创建材质的纹理:
//创建纹理
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
d3dxMaterials.pTextureFilename, &g_pMeshTextures)))
g_pMeshTextures = NULL;
}
在载入了所有的材质之后已经完成了材质缓存的,现在需要进行释放:
pD3DXMtrlBuffer -> Release();
除了材质和纹理的一致化外网格已经载入,现在已经准备好显示到屏幕了。
Step 2 — 显示网格对象(Rendering a Mesh Object)
第一步中网格已经载入现在它准备好了开始显示。从网格的载入是将材质分成好多子集,为了显示每一个子集,网格进行循环渲染,第一层循环是将材质分成子块:
g_pd3dDevice -> SetMaterial( &g_pMeshMaterials );
第二步是将纹理定位到子块上:
g_pd3dDevice -> SetTexture ( 0, g_pMeshTextures);
在设定了材质和纹理之后,调用ID3DXBaseMesh::DrawSubset方法来绘制子块:
g_pMesh -> DrawSubset(i);
ID3DXBaseMesh::DrawSubset方法有一个DWORD参数来指定绘制哪个子块,例子中的值会在每一圈循环中增加。
结束了使用之后,下一步是将网格对象从内在中移除。
Step 3- 卸载网格对象(Unloading a Mesh Object)
在所有的DirectX程序结束时都需要移除DirectX对象并使分配给它们的指针无效。在此例中使用的网格对象一样需要进行移除工作。在应用程序接到WM_DESTROY消息后调用Cleanup()方法来处理这些操作。
下面的代码进行材质的删除:
if( g_pMeshMaterials)
delete[] g_pMeshMaterials;
下面是单个移除载入的纹理最后删除材质:
if(g_pMeshTextures)
{
for( DWORD i=0; I < g_dwNumMaterials; i++)
{
if( g_pMeshTextures)
g_pMeshTextures ->Release();
}
delete[] g_pMeshTextures;
下面的代码进行网格的移除工作:
if(g_pMesh)
g_pMesh->Release();
此教程向你展示了如何加载和渲染一个风格模型,。这也是本章的最后一个教程。