www.pudn.com > Chesssource.rar > 3DMesh.cpp, change:2007-04-17,size:10453b
#include "stdafx.h"
#include "rmxfguid.h"
#include "rmxftmpl.h"
cMesh::cMesh()
{
m_pGraphics = NULL;
m_dwNumMeshes = 0;
m_pMeshes = NULL;
m_dwNumFrames = 0;
m_pFrames = NULL;
m_vecMin.x = m_vecMin.y = m_vecMin.z = m_vecMax.x = m_vecMax.y = m_vecMax.z = 0.0f;
m_fRadius = 0.0f;
}
cMesh::~cMesh()
{
Free();
}
BOOL cMesh::Load( cGraphics *pGraphics, char *strFilename, char *strTexturePath )
{
IDirectXFile *pDXFile = NULL;
IDirectXFileEnumObject *pDXEnum = NULL;
IDirectXFileData *pDXData = NULL;
sFrame *pTempFrame, *pFramePtr;
sMesh *pMesh;
Free();
if(( m_pGraphics = pGraphics ) == NULL || strFilename == NULL )
return FALSE;
if( FAILED( DirectXFileCreate( &pDXFile )))
return FALSE;
if( FAILED( pDXFile->RegisterTemplates(( LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES )))
{
SAFE_RELEASE( pDXFile );
return FALSE;
}
if( FAILED( pDXFile->CreateEnumObject((LPVOID)strFilename, DXFILELOAD_FROMFILE, &pDXEnum )))
{
SAFE_RELEASE( pDXFile );
return FALSE;
}
pTempFrame = new sFrame();
while( SUCCEEDED( pDXEnum->GetNextDataObject( &pDXData )))
{
ParseXFileData( pDXData, pTempFrame, strTexturePath );
SAFE_RELEASE( pDXData );
}
SAFE_RELEASE( pDXEnum );
SAFE_RELEASE( pDXFile );
if( pTempFrame->m_pMeshList != NULL )
{
m_pFrames = pTempFrame;
m_pFrames->m_strName = new char[7];
strcpy( m_pFrames->m_strName, "%ROOT%" );
}
else
{
m_pFrames = pTempFrame->m_pChild;
pFramePtr = m_pFrames;
while( pFramePtr != NULL )
{
pFramePtr->m_pParent = NULL;
pFramePtr = pFramePtr->m_pSibling;
}
pTempFrame->m_pChild = NULL;
delete pTempFrame;
}
MapFramesToBones( m_pFrames );
if(( pMesh = m_pMeshes ) != NULL )
{
while( pMesh != NULL )
{
m_vecMin.x = min( m_vecMin.x, pMesh->m_vecMin.x );
m_vecMin.y = min( m_vecMin.y, pMesh->m_vecMin.y );
m_vecMin.z = min( m_vecMin.z, pMesh->m_vecMin.z );
m_vecMax.z = max( m_vecMax.x, pMesh->m_vecMax.x );
m_vecMax.y = max( m_vecMax.y, pMesh->m_vecMax.y );
m_vecMax.z = max( m_vecMax.z, pMesh->m_vecMax.z );
m_fRadius = max( m_fRadius, pMesh->m_fRadius );
pMesh = pMesh->m_pNext;
}
}
return TRUE;
}
void cMesh::ParseXFileData( IDirectXFileData *pDataObj, sFrame *pParentFrame, char *strTexturePath )
{
IDirectXFileObject *pSubObj = NULL;
IDirectXFileData *pSubData = NULL;
IDirectXFileDataReference *pDataRef = NULL;
const GUID *Type = NULL;
char *strName = NULL;
DWORD Size;
sFrame *pSubFrame = NULL;
char strPath[MAX_PATH];
sFrame *pFrame = NULL;
D3DXMATRIX *matFrameMatrix = NULL;
sMesh *pMesh = NULL;
ID3DXBuffer *pMaterialBuffer = NULL;
D3DXMATERIAL *pMaterials = NULL;
ID3DXBuffer *pAdjacency = NULL;
DWORD *dwAdjacencyIn = NULL;
DWORD *dwAdjacencyOut = NULL;
DWORD i;
BYTE **Ptr;
// 得到模板类型
if( FAILED( pDataObj->GetType( &Type )))
return;
// 得到模板名
if( FAILED( pDataObj->GetName( NULL, &Size )))
return;
if( Size )
{
if(( strName = new char[Size] ) != NULL )
pDataObj->GetName( strName, &Size );
}
if( strName == NULL )
{
if(( strName = new char[9] ) == NULL )
return;
strcpy( strName, "$NoName$");
}
pSubFrame = pParentFrame;
if( *Type == TID_D3DRMFrame )
{
pFrame = new sFrame();
pFrame->m_strName = strName;
strName = NULL;
pFrame->m_pParent = pParentFrame;
pFrame->m_pSibling = pParentFrame->m_pChild;
pParentFrame->m_pChild = pFrame;
m_dwNumFrames++;
pSubFrame = pFrame;
}
if( *Type == TID_D3DRMFrameTransformMatrix )
{
if( FAILED( pDataObj->GetData( NULL, &Size, (PVOID*)&matFrameMatrix )))
return;
pParentFrame->m_matOriginal = *matFrameMatrix;
}
if( *Type == TID_D3DRMMesh )
{
if( m_pMeshes == NULL || m_pMeshes->FindMesh( strName ) == NULL )
{
pMesh = new sMesh();
pMesh->m_strName = strName;
strName = NULL;
if( FAILED( D3DXLoadSkinMeshFromXof( pDataObj, 0, m_pGraphics->Get3DDevice(),
&pAdjacency, &pMaterialBuffer, NULL,
&pMesh->m_dwNumMaterials,
&pMesh->m_pSkinInfo,
&pMesh->m_pMesh )))
{
delete pMesh;
return;
}
if( SUCCEEDED( pMesh->m_pMesh->LockVertexBuffer( D3DLOCK_READONLY, (void**)&Ptr )))
{
D3DXComputeBoundingBox((D3DXVECTOR3*)Ptr, pMesh->m_pMesh->GetNumVertices(),
pMesh->m_pMesh->GetNumBytesPerVertex(), &pMesh->m_vecMin, &pMesh->m_vecMax );
D3DXComputeBoundingSphere((D3DXVECTOR3*)Ptr, pMesh->m_pMesh->GetNumVertices(),
pMesh->m_pMesh->GetNumBytesPerVertex(),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), &pMesh->m_fRadius );
pMesh->m_pMesh->UnlockVertexBuffer();
}
if( pMesh->m_pSkinInfo )
pMesh->m_dwNumBones = pMesh->m_pSkinInfo->GetNumBones();
if( pMesh->m_pSkinInfo != NULL && pMesh->m_dwNumBones != 0 )
{
if( FAILED( pMesh->m_pMesh->CloneMeshFVF( 0, pMesh->m_pMesh->GetFVF(),
m_pGraphics->Get3DDevice(), &pMesh->m_pSkinMesh )))
SAFE_RELEASE( pMesh->m_pSkinInfo );
}
if( pMesh->m_pSkinInfo != NULL && pMesh->m_dwNumBones != 0 )
{
pMesh->m_matMatrices = new D3DXMATRIX[pMesh->m_dwNumBones];
for( i=0; im_dwNumBones; i++ )
D3DXMatrixIdentity( &pMesh->m_matMatrices[i]);
pMesh->m_matFrameMatrices = new D3DXMATRIX*[pMesh->m_dwNumBones];
for( i=0; im_dwNumBones; i++ )
pMesh->m_matFrameMatrices[i] = NULL;
}
if( !pMesh->m_dwNumMaterials )
{
pMesh->m_pmatMaterials = new D3DMATERIAL9[1];
pMesh->m_pTextures = new LPDIRECT3DTEXTURE9[1];
ZeroMemory( pMesh->m_pmatMaterials, sizeof(D3DMATERIAL9));
pMesh->m_pmatMaterials[0].Diffuse.r = 1.0f;
pMesh->m_pmatMaterials[0].Diffuse.g = 1.0f;
pMesh->m_pmatMaterials[0].Diffuse.b = 1.0f;
pMesh->m_pmatMaterials[0].Diffuse.a = 1.0f;
pMesh->m_pmatMaterials[0].Ambient = pMesh->m_pmatMaterials[0].Diffuse;
pMesh->m_pmatMaterials[0].Specular = pMesh->m_pmatMaterials[0].Diffuse;
pMesh->m_pTextures = NULL;
pMesh->m_dwNumMaterials = 1;
}
else
{
pMaterials = (D3DXMATERIAL*)pMaterialBuffer->GetBufferPointer();
pMesh->m_pmatMaterials = new D3DMATERIAL9[pMesh->m_dwNumMaterials];
pMesh->m_pTextures = new LPDIRECT3DTEXTURE9[pMesh->m_dwNumMaterials+1/*多加一种纹理*/];
for(i=0; im_dwNumMaterials; i++ )
{
pMesh->m_pmatMaterials[i] = pMaterials[i].MatD3D;
pMesh->m_pmatMaterials[i].Specular = pMesh->m_pmatMaterials[i].Diffuse;
pMesh->m_pmatMaterials[i].Ambient.r = 0.3f;
pMesh->m_pmatMaterials[i].Ambient.g = 0.3f;
pMesh->m_pmatMaterials[i].Ambient.b = 0.3f;
pMesh->m_pmatMaterials[i].Power = 50;
sprintf( strPath, "%s%s", strTexturePath, pMaterials[i].pTextureFilename );
if( FAILED( D3DXCreateTextureFromFileEx( m_pGraphics->Get3DDevice(),
strPath, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8,
D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE,
D3DX_FILTER_TRIANGLE, D3DCOLOR_RGBA(0,0,0,255), NULL, NULL,&pMesh->m_pTextures[i])))
{
pMesh->m_pTextures[i] = NULL;
}
sprintf( strPath, "%s%s", strTexturePath, "BUBING_2.bmp" );
if( FAILED( D3DXCreateTextureFromFile( m_pGraphics->Get3DDevice(),
strPath, &pMesh->m_pTextures[i+1])))
{
pMesh->m_pTextures[i+1] = NULL;
}
}
}
SAFE_RELEASE( pMaterialBuffer );
// link in mesh
pMesh->m_pNext = m_pMeshes;
m_pMeshes = pMesh;
m_dwNumMeshes++;
}
else
{
pMesh = m_pMeshes->FindMesh( strName );
}
// Add mesh to frame
if( pMesh != NULL )
pParentFrame->AddMesh( pMesh );
}
if( *Type == TID_D3DRMAnimationSet || *Type == TID_D3DRMAnimation || *Type == TID_D3DRMAnimationKey )
{
delete [] strName;
return;
}
delete [] strName;
while( SUCCEEDED( pDataObj->GetNextObject( &pSubObj )))
{
if( SUCCEEDED( pSubObj->QueryInterface( IID_IDirectXFileDataReference, (void**)&pDataRef )))
{
if( SUCCEEDED( pDataRef->Resolve( &pSubData )))
{
ParseXFileData( pSubData, pSubFrame, strTexturePath );
SAFE_RELEASE( pSubData );
}
SAFE_RELEASE( pDataRef );
}
if( SUCCEEDED( pSubObj->QueryInterface( IID_IDirectXFileData, (void**)&pSubData )))
{
ParseXFileData( pSubData, pSubFrame, strTexturePath );
SAFE_RELEASE( pSubData );
}
SAFE_RELEASE( pSubObj );
}
return;
}
void cMesh::MapFramesToBones( sFrame *pFrame )
{
sMesh *pMesh;
DWORD i;
if( pFrame == NULL || pFrame->m_strName == NULL )
return;
pMesh = m_pMeshes;
while( pMesh != NULL )
{
if( pMesh->m_pSkinInfo && pMesh->m_dwNumBones && pMesh->m_matMatrices != NULL && pMesh->m_matFrameMatrices != NULL )
{
for( i=0; im_dwNumBones; i++ )
{
if( !strcmp( pFrame->m_strName, pMesh->m_pSkinInfo->GetBoneName(i)))
{
pMesh->m_matFrameMatrices[i] = &pFrame->m_matCombined;
break;
}
}
}
pMesh = pMesh->m_pNext;
}
MapFramesToBones( pFrame->m_pChild );
MapFramesToBones( pFrame->m_pSibling );
}
void cMesh::Free()
{
m_pGraphics = NULL;
m_dwNumMeshes = 0;
delete m_pMeshes;
m_pMeshes = NULL;
m_dwNumFrames = 0;
delete m_pFrames;
m_pFrames = NULL;
m_vecMin.x = m_vecMin.y = m_vecMin.z = m_vecMax.x = m_vecMax.y = m_vecMax.z = 0.0f;
m_fRadius = 0.0f;
}
BOOL cMesh::IsLoaded()
{
if( m_pMeshes != NULL && m_pFrames != NULL )
return TRUE;
return FALSE;
}
DWORD cMesh::GetNumFrames()
{
return m_dwNumFrames;
}
sFrame *cMesh::GetParentFrame()
{
return m_pFrames;
}
sFrame *cMesh::GetFrame( char *strName )
{
if( m_pFrames == NULL )
return NULL;
return m_pFrames->FindFrame( strName );
}
DWORD cMesh::GetNumMeshes()
{
return m_dwNumMeshes;
}
sMesh *cMesh::GetParentMesh()
{
return m_pMeshes;
}
sMesh *cMesh::GetMesh( char *strName )
{
if( m_pMeshes == NULL )
return NULL;
return m_pMeshes->FindMesh( strName );
}
BOOL cMesh::GetBounds( D3DXVECTOR3 *vecMin, D3DXVECTOR3 *vecMax, float *fRadius )
{
if( vecMin != NULL )
*vecMin = m_vecMin;
if( vecMax != NULL )
*vecMax = m_vecMax;
if( fRadius != NULL )
*fRadius = m_fRadius;
return TRUE;
}