www.pudn.com > DirectX source.zip > CSkinMesh.cpp


/*! 
	@file : CSkinMesh.cpp 
	Contains the implementation of class CSkinMesh 
 
	@author Sarmad Kh. Abdulla 
*/ 
//------------------------------------------------------------------------------ 
 
 
//////////////////////////////////////////////////////////////////////////////// 
// Header files 
#include "stdafx.h" 
#include  
 
 
/*! 
 * Create the skin mesh from an x file. 
 * 
 * @param filename : The name of the x file 
 * @param pd3ddevice : A pointer to the D3D device object 
 * 
 * @return void  :  
 */ 
void CSkinMesh::Create( const char * filename, LPDIRECT3DDEVICE8 pd3ddevice ) 
{ 
	HRESULT result; 
	// Create an x file 
	LPDIRECTXFILE pxofapi; 
	result = DirectXFileCreate( &pxofapi ); 
	if( FAILED(result) ) 
		throw new CDXException( "Couldn't create IDirectXFile", result ); 
    // Register templates for d3drm. 
    result = pxofapi->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES); 
    if( FAILED( result ) ) 
	{ 
		SAFERELEASE( pxofapi ); 
        throw new CDXException( "Couldn't register D3DRM templates", result ); 
	} 
	// create the enum object 
	LPDIRECTXFILEENUMOBJECT pxofenum; 
    result = pxofapi->CreateEnumObject( (LPVOID)filename, DXFILELOAD_FROMFILE, &pxofenum); 
    if( FAILED( result ) ) 
	{ 
		SAFERELEASE( pxofapi ); 
        throw new CDXException( "Couldn't create x file enum object", result ); 
	} 
 
    // Enumerate top level objects. 
    // Top level objects are always data object. 
	LPDIRECTXFILEDATA pxofobj; 
    while( SUCCEEDED(pxofenum->GetNextDataObject( &pxofobj )) ) 
    { 
		try 
		{ 
	        RootFrame.Load( pxofobj, pd3ddevice, this ); 
		} 
		catch(...) 
		{ 
			SAFERELEASE( pxofapi ); 
			SAFERELEASE( pxofenum ); 
	        SAFERELEASE( pxofobj ); 
			throw; 
		} 
		pxofobj->Release(); 
    } 
 
	// Find the bones of this hierarchy 
	FindBones(); 
 
	// release 
	SAFERELEASE( pxofapi ); 
	SAFERELEASE( pxofenum ); 
	SAFERELEASE( pxofobj ); 
} 
 
 
/*! 
 * Destroy the object 
 * 
 * @param void :  
 * 
 * @return void  :  
 */ 
void CSkinMesh::Destroy( void ) 
{ 
	RootFrame.Destroy(); 
	Animations.Destroy(); 
} 
 
 
/*! 
 * Load an animation from an x file data object 
 * 
 * @param pxofobj : The x file data object to load from 
 * @param pparent : The parent node on which to attach the new created animation node. 
 *		Specify NULL to add the animation at the root level (if the animation is not 
 *		part of an animation set). 
 * 
 * @return void  :  
 */ 
void CSkinMesh::LoadAnimation( LPDIRECTXFILEDATA pxofobj, CAnimationNode * pparent ) 
{ 
	// if no parent node is specified, take the head of the list 
	if( pparent == NULL ) 
		pparent = &Animations; 
 
	// create the new object 
	CAnimationNode * panimation = new CAnimationNode; 
	SAFEPOINTER( panimation ); 
	pparent->AttachChild( *panimation ); 
 
	// load the animation 
	LPDIRECTXFILEOBJECT pxofchildobj; 
	while( SUCCEEDED( pxofobj->GetNextObject( &pxofchildobj ) ) ) 
	{ 
		panimation->Load( pxofchildobj ); 
	} 
} 
 
 
/*! 
 * Load an animation set from an x file data object. 
 * 
 * @param pxofobj : The x file data object to load from. 
 * 
 * @return void  :  
 */ 
void CSkinMesh::LoadAnimationSet( LPDIRECTXFILEDATA pxofobj ) 
{ 
	// create the animation object 
	CAnimationNode * panimationset = new CAnimationNode; 
	SAFEPOINTER( panimationset ); 
	Animations.AttachChild( *panimationset ); 
 
	// set the name of the animation set 
	char * szname; 
	DWORD dwnamelength; 
	HRESULT result; 
 
	result = pxofobj->GetName( NULL, &dwnamelength ); 
	if( FAILED( result ) ) 
		throw new CDXException( "Couldn't get animation set name", result ); 
 
	if( dwnamelength > 0 ) 
	{ 
		szname = new char[dwnamelength]; 
		SAFEPOINTER( szname ); 
     
		result = pxofobj->GetName( szname, &dwnamelength ); 
		if( FAILED( result ) ) 
		{ 
			delete[] szname; 
			throw new CDXException( "Couldn't get animation set name", result ); 
		} 
		panimationset->SetName( szname ); 
	} 
 
	// query through the child objects to load the animations 
	LPDIRECTXFILEOBJECT pxofchildobj; 
	LPDIRECTXFILEDATA pxofchilddataobj; 
	const GUID *type; 
	while( SUCCEEDED( pxofobj->GetNextObject( &pxofchildobj ) ) ) 
	{ 
		// Query the child for it's FileData 
		result = pxofchildobj->QueryInterface( IID_IDirectXFileData,  
			(LPVOID *)&pxofchilddataobj); 
		if( SUCCEEDED( result ) ) 
		{ 
			result = pxofchilddataobj->GetType( &type ); 
			if( FAILED( result ) ) 
			{ 
				pxofchildobj->Release(); 
				pxofchilddataobj->Release(); 
				throw new CDXException( "Couldn't get object type while loading animation set", 
					result ); 
			} 
 
			if( TID_D3DRMAnimation == *type ) 
				LoadAnimation( pxofchilddataobj, panimationset ); 
 
			pxofchilddataobj->Release(); 
		} 
		pxofchildobj->Release(); 
	} 
} 
 
 
/*! 
 * Find the bones for each skin mesh 
 * 
 * @param void :  
 * 
 * @return void  :  
 */ 
void CSkinMesh::FindBones( void ) 
{ 
	RootFrame.FindBones( &RootFrame ); 
	Animations.FindBone( &RootFrame ); 
} 
 
 
/*! 
 * Render the mesh to the given device 
 * 
 * @param pd3ddevice : The device to render on 
 * @param pd3dxms : The matrix stack to get the world matrix from 
 * 
 * @return void  :  
 */ 
void CSkinMesh::Render( LPDIRECT3DDEVICE8 pd3ddevice, LPD3DXMATRIX pworldmat ) 
{ 
	// calculate world matrix of all bones 
	RootFrame.Update( pworldmat ); 
	// render the meshes 
	RootFrame.Render( pd3ddevice ); 
}