⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xskinmesh.cpp

📁 VC++ DEMO, used for the beginners and the amour
💻 CPP
📖 第 1 页 / 共 3 页
字号:

#include "HEADERS.H"
#include "XSKINMESH.H"
#include <rmxftmpl.h>
#include <rmxfguid.h>
#include <stdio.h>

USING NAMESPACE CGE::MODEL::XFILE;


VOID Animation::SetAnimationCyc(FLOAT fPassTime, FLOAT fSpeed )
{
	
	DWORD dwPos0, dwPos1;				
	D3DXMATRIXA16 matResult;
	D3DXMATRIXA16 matTemp;
	FLOAT fInterval = 0;
	BOOL bAnimate = FALSE;

	if ( m_pMatrixKey )
	{
		// Convert the relative time to absolute time
		FLOAT fTime = (FLOAT)fmod( fPassTime * fSpeed, (FLOAT)m_pMatrixKey[m_dwNumMatrixKey - 1].dwTime);
		dwPos0 = dwPos1 = 0;
		
		for (DWORD dwKey = 0 ;dwKey < m_dwNumMatrixKey ; dwKey++)
		{
			if ((FLOAT)m_pMatrixKey[dwKey].dwTime > fTime)
			{
				dwPos1 = dwKey;	
				if (dwKey > 0)
				{
					dwPos0= dwKey - 1;
				}
				else
				{
					dwPos0 = dwKey;
				}
				break;
			}
		}
		
		FLOAT fTime0 = (FLOAT)m_pMatrixKey[dwPos0].dwTime;
		FLOAT fTime1 = (FLOAT)m_pMatrixKey[dwPos1].dwTime;
		
		if ((fTime1 - fTime0) ==0)
		{
			fInterval = 0;
		}
		else
		{
			fInterval =  (fTime - fTime0)  / (fTime1 - fTime0);
		}
		
		matResult = m_pMatrixKey[dwPos0].mat + fInterval * (m_pMatrixKey[dwPos1].mat - m_pMatrixKey[dwPos0].mat);

		bAnimate = TRUE;
	}
	else
	{
		D3DXMatrixIdentity( &matResult );

		if ( m_pScaleKey && m_dwNumScaleKey )
		{
			FLOAT fTime = (FLOAT)fmod(fPassTime * fSpeed, m_pScaleKey[m_dwNumScaleKey - 1].dwTime );
				
			dwPos0 = dwPos1 = 0;

			for ( DWORD dwKey = 0; dwKey < m_dwNumScaleKey; dwKey++)
			{
				if ( (FLOAT)m_pScaleKey[dwKey].dwTime > fTime )
				{
					dwPos1 = dwKey;	
					if (dwKey > 0)
					{
						dwPos0= dwKey - 1;
					}
					else
					{
						dwPos0 = dwKey;
					}
					break;
				}
			}

			FLOAT fTime0 = (FLOAT)m_pScaleKey[dwPos0].dwTime;
			FLOAT fTime1 = (FLOAT)m_pScaleKey[dwPos1].dwTime;
			if ( fTime1 - fTime0 == 0 )
				fInterval = 0.0f;
			else
				fInterval = (fTime - fTime0)/(fTime1 - fTime0);

			D3DXVECTOR3 vScale;
			D3DXVec3Lerp(&vScale, &m_pScaleKey[dwPos0].vScale, &m_pScaleKey[dwPos1].vScale, fInterval );
			D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z );
			D3DXMatrixMultiply( &matResult, &matTemp, &matResult );
			bAnimate = TRUE;
		}

		if ( m_pRotateKey && m_dwNumRotateKey)
		{
			FLOAT fTime = (FLOAT)fmod(fPassTime * fSpeed, m_pRotateKey[m_dwNumRotateKey - 1].dwTime );

			for ( DWORD dwKey = 0; dwKey < m_dwNumRotateKey; dwKey++)
			{
				if ( (FLOAT)m_pRotateKey[dwKey].dwTime > fTime )
				{
					dwPos1 = dwKey;	
					if (dwKey > 0)
					{
						dwPos0= dwKey - 1;
					}
					else
					{
						dwPos0 = dwKey;
					}
					break;
				}
			}

			FLOAT fTime0 =(FLOAT)m_pRotateKey[dwPos0].dwTime;
			FLOAT fTime1 =(FLOAT)m_pRotateKey[dwPos1].dwTime;

			if ( fTime1 - fTime0 == 0 )
				fInterval = 0.0f;
			else
				fInterval = (fTime - fTime0)/(fTime1 - fTime0);

			D3DXQUATERNION quat;
			D3DXQuaternionSlerp( &quat, &m_pRotateKey[dwPos0].quatRotate, &m_pRotateKey[dwPos1].quatRotate, fInterval );
			quat.w = - quat.w;
			D3DXMatrixRotationQuaternion( &matTemp, &quat );
			D3DXMatrixMultiply( &matResult, &matTemp, &matResult );
			bAnimate = TRUE;
		}

		// 适用Translation

		if ( m_pPositionKey && m_dwNumPositionKey )
		{			
			FLOAT fTime = (FLOAT)fmod(fPassTime * fSpeed, m_pPositionKey[m_dwNumPositionKey - 1].dwTime );
			for ( DWORD dwKey = 0; dwKey < m_dwNumPositionKey; dwKey++ )
			{
				if ( (FLOAT)m_pPositionKey[dwKey].dwTime > fTime )
				{
					dwPos1 = dwKey;	
					if (dwKey > 0)
					{
						dwPos0= dwKey - 1;
					}
					else
					{
						dwPos0 = dwKey;
					}
					break;
				}
			}
			FLOAT fTime0 = (FLOAT)m_pPositionKey[dwPos0].dwTime;
			FLOAT fTime1 = (FLOAT)m_pPositionKey[dwPos1].dwTime;
			if ( fTime1 - fTime0 == 0 )
				fInterval = 0.0f;
			else
				fInterval = (fTime - fTime0 )/(fTime1 - fTime0 );
			D3DXVECTOR3 vPos;
			D3DXVec3Lerp( &vPos, &m_pPositionKey[dwPos0].vPos, &m_pPositionKey[dwPos1].vPos, fInterval );
			D3DXMatrixTranslation( &matTemp, vPos.x, vPos.y, vPos.z );
			D3DXMatrixMultiply( &matResult, &matTemp, &matResult );
			bAnimate = TRUE;
		}
	}

	if ( bAnimate )
		m_pFrame->m_matTrans = matResult;
}


XSKINMESH::XSKINMESH()
{
	m_pD3DDevice = 0;
	m_dwMeshOptions = 0;
	m_nMethod = 0;
	m_pBoneMatrices = 0;
	m_maxBones = 0;
	m_pRootFrame = 0;
	m_pAnimationSet = 0;
	m_pAnimationCur = 0;
	m_fRadius = 0;
	m_vMax.x = m_vMax.y = m_vMax.z = 0;
	m_vMin.x = m_vMin.y = m_vMin.z = 0;
	m_strFilePath[0] = '\0';
	m_pMeshList = 0;
}

XSKINMESH::~XSKINMESH()
{
	SAFE_DELETE( m_pAnimationSet );
	SAFE_DELETE_ARRAY( m_pBoneMatrices );
	SAFE_DELETE(m_pRootFrame);
}

BOOL XSKINMESH::ReadAnimation(IDirectXFileData * pDataObj,AnimationSet * pAnimationSet)
{
	TCHAR			*pName = NULL;
	LPBYTE			 pData = NULL;

	IDirectXFileObject		*pDXFileObj = NULL;
	IDirectXFileData	*pDXDataObj = NULL;
	IDirectXFileDataReference * pDXDataRef = NULL;

	const GUID * pType = NULL;

	DWORD			cchName;
	
	if ( FAILED(pDataObj->GetName(NULL, &cchName ) ))
		return FALSE;
	
	if ( cchName )
	{
		if ( NULL == (pName = new TCHAR[cchName]) )
			return FALSE;
		pDataObj->GetName(pName, &cchName);
	}else
	{
		pName = new TCHAR[9];
		strcpy(pName, "$Animation$");
	}
	
	Animation * pCurAnim = new Animation;
	pCurAnim->m_pName = pName;
	pName = NULL;
	
	pCurAnim->m_pNext = pAnimationSet->m_pAnim;
	pAnimationSet->m_pAnim = pCurAnim;
	
	while ( SUCCEEDED( pDataObj->GetNextObject(&pDXFileObj) )) 
	{
		if ( SUCCEEDED( pDXFileObj->QueryInterface(IID_IDirectXFileDataReference,(LPVOID *)&pDXDataRef)))
		{
			if ( FAILED( pDXDataRef->Resolve(&pDXDataObj)))
				return FALSE;
			
			if ( FAILED( pDXDataObj->GetType( &pType ) ))
				return FALSE;
			
			if ( *pType == TID_D3DRMFrame )
			{
				if ( FAILED(pDXDataObj->GetName( NULL, &cchName )))
					return FALSE;
				
				pName = new TCHAR[cchName];
				if ( FAILED( pDXDataObj->GetName(pName, &cchName)))
					return FALSE;
				
				pCurAnim->m_pFrameName = pName;
				pName = NULL;
			}
		}
		else if ( SUCCEEDED( pDXFileObj->QueryInterface(IID_IDirectXFileData,(LPVOID*)&pDXDataObj)))
		{
			if ( FAILED( pDXDataObj->GetType(&pType)))
				return FALSE;
			
			if ( *pType == TID_D3DRMFrame )
			{
				ParseXFileData(pDXDataObj,pAnimationSet->m_pParent);
			}
			
			if ( *pType == TID_D3DRMAnimationKey )
			{				
				if ( FAILED( pDXDataObj->GetData( NULL, &cchName, (VOID **)&pData ) ))
					return FALSE;
				
				pCurAnim->m_dwKeyType = ((DWORD *)pData)[0];
				
				if ( pCurAnim->m_dwKeyType == 0 )
				{
					RotateKeyXFile * pFileKey = ( RotateKeyXFile * )(pData + sizeof(DWORD) * 2 );							
					pCurAnim->m_dwNumRotateKey = ((DWORD *)pData)[1];
					
					if ( NULL == (pCurAnim->m_pRotateKey = new RotateKey[pCurAnim->m_dwNumRotateKey] ) )
						return FALSE;
					
					for ( DWORD i = 0; i < pCurAnim->m_dwNumRotateKey; i++)
					{
						pCurAnim->m_pRotateKey[i].dwTime = pFileKey->dwTime;
						pCurAnim->m_pRotateKey[i].quatRotate.x = -pFileKey->x;
						pCurAnim->m_pRotateKey[i].quatRotate.y = -pFileKey->y;
						pCurAnim->m_pRotateKey[i].quatRotate.z = -pFileKey->z;
						pCurAnim->m_pRotateKey[i].quatRotate.w = pFileKey->w;
						pFileKey++;
					}
				}
				
				if ( pCurAnim->m_dwKeyType == 1 )
				{
					ScaleKeyXFile *pFileKey = (ScaleKeyXFile *)(pData + sizeof(DWORD) * 2 );
					
					pCurAnim->m_dwNumScaleKey = ((DWORD *)pData)[1];
					
					if ( NULL == (pCurAnim->m_pScaleKey = new ScaleKey[pCurAnim->m_dwNumScaleKey] ))
						return FALSE;
					
					for ( DWORD i = 0; i < pCurAnim->m_dwNumScaleKey; i++)
					{
						pCurAnim->m_pScaleKey[i].dwTime = pFileKey->dwTime;
						pCurAnim->m_pScaleKey[i].vScale = pFileKey->vScale;
						pFileKey++;
					}
				}
				
				if ( pCurAnim->m_dwKeyType == 2 )
				{
					PositionKeyXFile * pFileKey = (PositionKeyXFile *)(pData + sizeof(DWORD) * 2);
					
					pCurAnim->m_dwNumPositionKey = ((DWORD *)pData)[1];
					
					if ( NULL == (pCurAnim->m_pPositionKey = new PositionKey[pCurAnim->m_dwNumPositionKey] ))
						return FALSE;
					
					for ( DWORD i = 0; i < pCurAnim->m_dwNumPositionKey; i++ )
					{
						pCurAnim->m_pPositionKey[i].dwTime = pFileKey->dwTime;
						pCurAnim->m_pPositionKey[i].vPos  = pFileKey->vPos;
						pFileKey++;
					}
				}
				
				if ( pCurAnim->m_dwKeyType == 4 )
				{
					MatrixKeyXFile *pFileKey = (MatrixKeyXFile *)(pData + sizeof(DWORD) * 2);
					pCurAnim->m_dwNumMatrixKey = ((DWORD *)pData)[1];
					if ( NULL == (pCurAnim->m_pMatrixKey = new MatrixKey[pCurAnim->m_dwNumMatrixKey]))
						return FALSE;
					for ( DWORD i = 0; i < pCurAnim->m_dwNumMatrixKey; i++)
					{
						pCurAnim->m_pMatrixKey[i].dwTime = pFileKey->dwTime;
						pCurAnim->m_pMatrixKey[i].mat = pFileKey->mat;
						pFileKey++;
					}
				}
			}		
			
			if ( *pType == TID_D3DRMAnimationOptions )
			{
				if ( FAILED(pDXDataObj->GetData(NULL, &cchName, (VOID **)&pData)))
					return FALSE;
				if ( !((DWORD *)pData)[0] )
					pCurAnim->m_bLoop = FALSE;
				else
					pCurAnim->m_bLoop = TRUE;
				if ( !((DWORD *)pData)[1] )
					pCurAnim->m_bLinear = FALSE;
				else
					pCurAnim->m_bLinear = TRUE;
			}
		}
	}
	return TRUE;
}

VOID XSKINMESH::SetMediaFilePath(TCHAR * strFilePath)
{
	if ( strFilePath != NULL )
	{
		wsprintf(m_strFilePath,"%s",strFilePath);
	}
}

BOOL XSKINMESH::MakeSkinMesh( Mesh * pMesh)
{
	HRESULT hr;
	DWORD cFaces = pMesh->m_pSkinMesh->GetNumFaces();

	SAFE_RELEASE(pMesh->m_pMesh);
	SAFE_DELETE_ARRAY(m_pBoneMatrices);
	
	pMesh->m_pMesh      = NULL;
	m_pBoneMatrices     = NULL;
	
	if (m_nMethod == D3DNONINDEXED)
	{
		LPD3DXBONECOMBINATION   rgBoneCombinations;
		
		hr = pMesh->m_pSkinMesh->ConvertToBlendedMesh(
			D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, 
			pMesh->m_rgiAdjacency, 
			NULL, 
			&pMesh->m_cpattr, 
			&pMesh->m_pBoneCombinationBuf, 
			NULL,
			NULL,
			&pMesh->m_pMesh);
		
		if (FAILED(hr))
			return FALSE;
		
		// calculate the max face influence count
		
		if ((pMesh->m_pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
		{
			pMesh->m_maxFaceInfl = 1 + ((pMesh->m_pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2;
		}
		else
		{
			pMesh->m_maxFaceInfl = 1;
		}
		
		/* If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it
		Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is
		drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing. */
		if (m_d3dCaps.MaxVertexBlendMatrices <= 2)       
		{
			// calculate the index of the attribute table to split on
			rgBoneCombinations  = reinterpret_cast<LPD3DXBONECOMBINATION>(pMesh->m_pBoneCombinationBuf->GetBufferPointer());
			
			for (pMesh->m_iAttrSplit = 0; pMesh->m_iAttrSplit < pMesh->m_cpattr; pMesh->m_iAttrSplit++)
			{
				DWORD   cInfl   = 0;
				
				for (DWORD iInfl = 0; iInfl < pMesh->m_maxFaceInfl; iInfl++)
				{
					if (rgBoneCombinations[pMesh->m_iAttrSplit].BoneId[iInfl] != UINT_MAX)
					{
						++cInfl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -