📄 xskinmesh.cpp
字号:
#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 + -