本节为《introduce to D3D Game Programming》第10,11章学习笔记,代码(本章工程文件)下载点击这里
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在Direct3D中,微软为我们提供了ID3DXMesh的接口表示网格,这个接口继承自ID3DBaseMesh接口。网格模型接口ID3DXMesh实际上是三维物体的顶点缓存的集合,他将创建顶点缓存,定义顶点格式和绘制顶点缓冲区等功能封装在一个COM接口对象中,这个接口使用后要释放。
Subsets and the attribute buffer
subset 是一组可以使用同一种 attribute 进行渲染的三角形。比如房子中的 floor, walls, windows 都可以作为house 的subset。 同subset 的
三角形可以有同样的 attibuteID,所有三角形面片的ID,都存储在 attibute buffer中。使用Mesh->DrawSubset(i); (0<=i<=n-1)可以画出整个mesh
for(int i = 0; i < NumSubsets; i++)
{
Device->SetTexture( 0, Textures[i] );
Mesh->DrawSubset( i );
}
Optimizing
使用OptimizeInplace重新组织mesh 的顶点和索引信息可以高效的渲染mesh。
//
// Optimize the mesh to generate an attribute table.
//
std::vector<DWORD> adjacencyBuffer(Mesh->GetNumFaces() * 3);
Mesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);
hr = Mesh->OptimizeInplace(
D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT |
D3DXMESHOPT_VERTEXCACHE,
&adjacencyBuffer[0],
0, 0, 0);
D3DXMESHOPT_COMPACT 消除没使用的顶点和索引信息
D3DXMESHOPT_ATTRSORT 通过attibute对三角形面片排序生成表格
Adjacency info
在mesh优化的过程中,需要知道相邻三角形面片的信息,这样渲染时可以节省搜索时间
loading an xFile
HRESEULT D3DXLoadMeshFromX(
LPCSTR pFilename, // the filename of the XFile to load
DWORD Options, // D3DSMESH_32BIT D3DxMESH_MANGED D3DXMESH_DYNAMIC
LPDIRECT3DDEVICE9 pDevice,
LPD3DXBUFFER *ppAdjacency, // returns an ID3DXBUffer containing a DWORD array that describes the adjacency info
LPD3DXBUFFER* ppMaterials, //ID3DXBuffer containing an array of D3DXMATERIAL structures
LPD3DBUFFER *ppEffectInstances,
PDWORD pNumMaterials,
LPD3DSMESH *ppMesh
)
XFile materials
通过创建ID3DXMesh 对象把XFile 数据下载
typedef struct D3DXMATERIAL{
D3DMATERIAL9 MatD3D; // struct
LPSTR pTexureFilename; // a reference to the image file that contains the actual texture data
}
golbal variables
ID3DXMesh* Mesh = 0;
std::vector<D3DMATERIAL9> Mtrls(0);
std::vector<IDirect3DTexture9*> Textures(0);
After we have loaded the XFile data, we must iterate through the D3DXMATERIAL array and load any textures that the meseh
referencts:
//
// Extract the materials, and load textures.
//
if( mtrlBuffer != 0 && numMtrls != 0 )
{
D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
for(int i = 0; i < numMtrls; i++)
{
// the MatD3D property doesn't have an ambient value set
// when its loaded, so set it now:
mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
// save the ith material
Mtrls.push_back( mtrls[i].MatD3D );
// check if the ith material has an associative texture
if( mtrls[i].pTextureFilename != 0 )
{
// yes, load the texture for the ith subset
IDirect3DTexture9* tex = 0;
D3DXCreateTextureFromFile(
Device,
mtrls[i].pTextureFilename,
&tex);
// save the loaded texture
Textures.push_back( tex );
}
else
{
// no texture for the ith subset
Textures.push_back( 0 );
}
}
}
Generating Vertex Normals
XFile 中也可能没有顶点的法线信息,这种情况下,需要计算法线从而才可以使用光照。
HRESULT D3DXComputeNormals(
LPD3DXBASEMESH pMesh,
const DWORD *pAdjacency
)