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;
}
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;
}
Posted on 2009-09-12 16:04 zyb_debug 阅读(1139) 评论(1) 编辑 收藏 引用