http://hi.baidu.com/zyb_debug/blog/item/d2ee04171d48ab5bf2de32d7.html
利用上篇文章的D3DXMESHCONTAINER_EX,LoadMesh和DrawMesh都是简单的基础类函数,
以后就不用每次载入的时候都写那一大堆平凡的代码。
HRESULT LoadMesh(
D3DXMESHCONTAINER_EX **ppMesh,
IDirect3DDevice9 *pDevice,
char *Filename, char *TexturePath /* = */,
DWORD NewFVF /* = 0 */, DWORD LoadFlags /* = D3DXMESH_SYSTEMMEM */
)
{
ID3DXMesh *pLoadMesh = NULL;
HRESULT hr;
// Error checking
if(!ppMesh || !pDevice || !Filename || !TexturePath)
return E_FAIL;
// Use system memory if converting FVF
DWORD TempLoadFlags = LoadFlags;
if(NewFVF)
TempLoadFlags = D3DXMESH_SYSTEMMEM;
// Load the mesh using D3DX routines
ID3DXBuffer *MaterialBuffer = NULL, *AdjacencyBuffer = NULL;
DWORD NumMaterials;
if(FAILED(hr=D3DXLoadMeshFromXA(Filename, TempLoadFlags,
pDevice, &AdjacencyBuffer,
&MaterialBuffer, NULL,
&NumMaterials, &pLoadMesh)))
return hr;
// Convert to new FVF first as needed
if(NewFVF) {
ID3DXMesh *pTempMesh;
// Use CloneMeshFVF to convert mesh
if(FAILED(hr=pLoadMesh->CloneMeshFVF(LoadFlags, NewFVF, pDevice, &pTempMesh))) {
ReleaseCOM(AdjacencyBuffer);
ReleaseCOM(MaterialBuffer);
ReleaseCOM(pLoadMesh);
return hr;
}
// Free prior mesh and store new pointer
ReleaseCOM(pLoadMesh);
pLoadMesh = pTempMesh; pTempMesh = NULL;
}
// Allocate a D3DXMESHCONTAINER_EX structure
D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX();
*ppMesh = pMesh;
// Store mesh name (filename), type, and mesh pointer
pMesh->Name = _strdup(Filename);
pMesh->MeshData.Type = D3DXMESHTYPE_MESH;
pMesh->MeshData.pMesh = pLoadMesh; pLoadMesh = NULL;
// Store adjacency buffer
DWORD AdjSize = AdjacencyBuffer->GetBufferSize();
if(AdjSize) {
pMesh->pAdjacency = new DWORD[AdjSize];
memcpy(pMesh->pAdjacency, AdjacencyBuffer->GetBufferPointer(), AdjSize);
}
ReleaseCOM(AdjacencyBuffer);
// Build material list
if(!(pMesh->NumMaterials = NumMaterials)) {
// Create a default material
pMesh->NumMaterials = 1;
pMesh->pMaterials = new D3DXMATERIAL[1];
pMesh->pTextures = new IDirect3DTexture9*[1];
ZeroMemory(pMesh->pMaterials, sizeof(D3DXMATERIAL));
pMesh->pMaterials[0].MatD3D.Diffuse.r = 1.0f;
pMesh->pMaterials[0].MatD3D.Diffuse.g = 1.0f;
pMesh->pMaterials[0].MatD3D.Diffuse.b = 1.0f;
pMesh->pMaterials[0].MatD3D.Diffuse.a = 1.0f;
pMesh->pMaterials[0].MatD3D.Ambient = pMesh->pMaterials[0].MatD3D.Diffuse;
pMesh->pMaterials[0].MatD3D.Specular = pMesh->pMaterials[0].MatD3D.Diffuse;
pMesh->pMaterials[0].pTextureFilename = NULL;
pMesh->pTextures[0] = NULL;
} else {
// Load the materialsx
D3DXMATERIAL *Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer();
pMesh->pMaterials = new D3DXMATERIAL[pMesh->NumMaterials];
pMesh->pTextures = new IDirect3DTexture9*[pMesh->NumMaterials];
for(DWORD i=0;i<pMesh->NumMaterials;i++) {
pMesh->pMaterials[i].MatD3D = Materials[i].MatD3D;
pMesh->pMaterials[i].MatD3D.Ambient = pMesh->pMaterials[i].MatD3D.Diffuse;
// Load the texture if one exists
pMesh->pTextures[i] = NULL;
if(Materials[i].pTextureFilename) {
char TextureFile[MAX_PATH];
sprintf_s(TextureFile,MAX_PATH, "%s%s", TexturePath,
Materials[i].pTextureFilename);
D3DXCreateTextureFromFileA(pDevice,
TextureFile,
&pMesh->pTextures[i]);
}
}
}
ReleaseCOM(MaterialBuffer);
// Optimize the mesh for better attribute access
pMesh->MeshData.pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);
// Clear pMesh pointer just in case
pMesh = NULL;
return S_OK;
}
// Draw the first mesh in a linked list of objects
HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh)
{
IDirect3DDevice9 *pD3DDevice;
DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;
// Error checking
if(!pMesh)
return E_FAIL;
if(!pMesh->MeshData.pMesh)
return E_FAIL;
if(!pMesh->NumMaterials || !pMesh->pMaterials)
return E_FAIL;
// Get the device interface
pMesh->MeshData.pMesh->GetDevice(&pD3DDevice);
// Release vertex shader if being used
pD3DDevice->SetVertexShader(NULL);
pD3DDevice->SetVertexDeclaration(NULL);
// Save render states
pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &OldAlphaState);
pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &OldSrcBlend);
pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &OldDestBlend);
LastState = OldAlphaState;
// Setup pointer for mesh to draw, either regular or skinned
ID3DXMesh *pDrawMesh = (!pMesh->pSkinMesh)?pMesh->MeshData.pMesh:pMesh->pSkinMesh;
// Look through all subsets
for(DWORD i=0;i<pMesh->NumMaterials;i++) {
// Set material and texture
pD3DDevice->SetMaterial(&pMesh->pMaterials[i].MatD3D);
pD3DDevice->SetTexture(0, pMesh->pTextures[i]);
// Enable or disable alpha blending per material
if(pMesh->pMaterials[i].MatD3D.Diffuse.a != 1.0f) {
if(LastState != TRUE) {
LastState = TRUE;
pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCCOLOR);
pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
}
} else {
if(LastState != FALSE) {
LastState = FALSE;
pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
}
// Draw the mesh subset
pDrawMesh->DrawSubset(i);
}
// Restore alpha blending states
if(LastState != OldAlphaState) {
pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, OldAlphaState);
pD3DDevice->SetRenderState(D3DRS_SRCBLEND, OldSrcBlend);
pD3DDevice->SetRenderState(D3DRS_DESTBLEND, OldDestBlend);
}
// Make sure to release the device object!
pD3DDevice->Release();
// Return success
return S_OK;
}