www.pudn.com > Chesssource.rar > 3DMesh.cpp


#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; 
}