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


/*! 
	@file : CFrameNode.cpp 
	Contains the implementation of class CFrameNode 
 
	@author Sarmad Kh. Abdulla 
*/ 
//------------------------------------------------------------------------------ 
 
 
//////////////////////////////////////////////////////////////////////////////// 
// Header files 
#include "stdafx.h" 
 
 
/*! 
 * Initialize the object 
 * 
 * @param void :  
 * 
 * @return void  :  
 */ 
void CFrameNode::InitObject( void ) 
{ 
	D3DXMatrixIdentity( &TransformationMatrix ); 
	D3DXMatrixIdentity( &OriginalMatrix ); 
} 
 
 
/*! 
 * Load an object from the x file. 
 * 
 * @param pxofobj : Pointer to the x file data object to load from. 
 * @param pd3ddevice : Pointer to the device 
 * @param pskinmesh : Pointer to the owner skin mesh object. 
 * 
 * @return void  :  
 */ 
void CFrameNode::Load( LPDIRECTXFILEDATA pxofobj, LPDIRECT3DDEVICE8 pd3ddevice,  
	CSkinMesh * pskinmesh ) 
{ 
	HRESULT result; 
	DWORD dwsize; 
 
	// get the type of the object 
	const GUID * objecttype; 
	result = pxofobj->GetType( &objecttype ); 
	if( FAILED(result) ) 
		throw new CDXException( "Couldn't get x file data object's type", result ); 
 
	// check the type of the object to load 
    if( *objecttype == TID_D3DRMMesh ) 
	{ 
		// load a child mesh 
		CMeshNode * pmeshnode = new CMeshNode; 
		SAFEPOINTER( pmeshnode ); 
		Meshes.AttachChild( *pmeshnode ); 
		pmeshnode->Create( pxofobj, pd3ddevice ); 
	} 
    else if( *objecttype == TID_D3DRMFrameTransformMatrix ) 
    { 
		// load the transformation matrix 
		D3DXMATRIX * pmat; 
		result = pxofobj->GetData( NULL, &dwsize, (PVOID*)&pmat ); 
		TransformationMatrix = *pmat; 
		OriginalMatrix = *pmat; 
		if( FAILED(result) ) 
			throw new CDXException( "Couldn't read frame transformation matrix from an x file", result ); 
    } 
    else if( *objecttype == TID_D3DRMAnimationSet ) 
        pskinmesh->LoadAnimationSet( pxofobj ); 
    else if( *objecttype == TID_D3DRMAnimation ) 
        pskinmesh->LoadAnimation( pxofobj ); 
    else if( *objecttype == TID_D3DRMFrame ) 
    { 
		// create a new child frame 
		CFrameNode * pchildframe = new CFrameNode; 
		SAFEPOINTER( pchildframe ); 
		AttachChild( *pchildframe ); 
 
		// get the name of the child frame 
		DWORD dwnamelength; 
        result = pxofobj->GetName( NULL, &dwnamelength ); 
		if( FAILED(result) ) 
			throw new CDXException( "Couldn't get the name of the D3DRM frame", result ); 
		if( dwnamelength > 0 ) 
		{ 
			char * pname; 
			pname = new char[dwnamelength]; 
			SAFEPOINTER( pname ); 
 
			result = pxofobj->GetName( pname, &dwnamelength ); 
			if( FAILED(result) ) 
				throw new CDXException( "Couldn't get frame name from x file", result ); 
			pchildframe->SetName( pname ); 
			delete[] pname; 
		} 
 
        // Enumerate child objects. 
        // Child object can be data, data reference or binary. 
        // Use QueryInterface() to find what objecttype of object a child is. 
		LPDIRECTXFILEDATA pxofchildobj; 
		LPDIRECTXFILEOBJECT pxofchild; 
        while( SUCCEEDED( pxofobj->GetNextObject(&pxofchild) ) ) 
        { 
            // Query the child for it's FileData 
            result = pxofchild->QueryInterface( IID_IDirectXFileData,  
				(LPVOID *)&pxofchildobj ); 
            if( SUCCEEDED( result ) ) 
            { 
				// load the child's object 
				pchildframe->Load( pxofchildobj, pd3ddevice, pskinmesh ); 
				pxofchildobj->Release(); 
			} 
			pxofchild->Release(); 
		} 
	} 
} 
 
 
/*! 
 * Destory the frame and its childs 
 * 
 * @param void :  
 * 
 * @return void  :  
 */ 
void CFrameNode::Destroy( void ) 
{ 
	DeleteChilds(); 
	Meshes.DeleteChilds(); 
} 
 
 
/*! 
 * Compute the world matrix of the frame by combining the transformation 
 * matrix of this frame with the parent's matrix 
 * 
 * @param mat : A pointer to the parent's world matrix 
 * 
 * @return void  :  
 */ 
void CFrameNode::Update( D3DXMATRIX * pmat ) 
{ 
    D3DXMatrixMultiply( &CombinedMatrix, &TransformationMatrix, pmat ); 
	// update child frames 
	CFrameNode * pframe = static_cast(GetFirstChild()); 
	while( pframe ) 
	{ 
		pframe->Update( &CombinedMatrix ); 
		pframe = static_cast(pframe->GetNextSibling()); 
	} 
} 
 
 
/*! 
 * Render the frame's contents 
 * 
 * @param pd3ddevice : The device to render on. 
 * 
 * @return void  :  
 */ 
void CFrameNode::Render( LPDIRECT3DDEVICE8 pd3ddevice ) 
{ 
	// if we have child meshes, set the world matrix 
	if( Meshes.GetFirstChild() ) 
		pd3ddevice->SetTransform( D3DTS_WORLD, &CombinedMatrix ); 
 
	// render meshes 
	CMeshNode * pmesh = static_cast(Meshes.GetFirstChild()); 
	while( pmesh ) 
	{ 
		pmesh->Render( pd3ddevice ); 
		pmesh = static_cast(pmesh->GetNextSibling()); 
	} 
 
	// render child frames 
	CFrameNode * pframe = static_cast(GetFirstChild()); 
	while( pframe ) 
	{ 
		pframe->Render( pd3ddevice ); 
		pframe = static_cast(pframe->GetNextSibling()); 
	} 
} 
 
 
/*! 
 * Find a frame in this frame hierarchy with the specified name. 
 * 
 * @param framename : The name of the frame 
 * 
 * @return CFrameNode * : Pointer to the found frame. 
 */ 
CFrameNode * CFrameNode::FindFrame( const char * framename ) 
{ 
	if( Name == framename ) 
		return this; 
	else 
	{ 
		// loop through the child objects 
		CFrameNode * pframe = static_cast(GetFirstChild()); 
		while( pframe ) 
		{ 
			CFrameNode * foundframe = pframe->FindFrame( framename ); 
			if( foundframe ) 
				return foundframe; 
			pframe = static_cast(pframe->GetNextSibling()); 
		} 
		return NULL; 
	} 
} 
 
 
/*! 
 * Find the bones of the child meshes. 
 * 
 * @param prootframe : The root of the frame hierarchy to search in for the bones. 
 * 
 * @return void  :  
 */ 
void CFrameNode::FindBones( CFrameNode * prootframe ) 
{ 
	// find the bones of the meshes 
	CMeshNode * pmesh = static_cast(Meshes.GetFirstChild()); 
	while( pmesh ) 
	{ 
		pmesh->FindBones( prootframe ); 
		pmesh = static_cast(pmesh->GetNextSibling()); 
	} 
	// find the bones in the child frames 
	CFrameNode * pframe = static_cast(GetFirstChild()); 
	while( pframe ) 
	{ 
		pframe->FindBones( prootframe ); 
		pframe = static_cast(pframe->GetNextSibling()); 
	} 
}