📄 xskinmesh.cpp
字号:
DWORD size;
D3DXMATRIXA16 *pMatrix;
if (SUCCEEDED(pDataObj->GetData(NULL, &size, (VOID **)&pMatrix )))
{
pParentFrame->m_matOrig = *pMatrix;
pParentFrame->m_matTrans = *pMatrix;
}
}
// Load the child DataObjects
IDirectXFileObject *pFileObj;
IDirectXFileData *pFileData;
IDirectXFileDataReference *pFileRef;
while (SUCCEEDED( pDataObj->GetNextObject(&pFileObj)))
{
if ( SUCCEEDED( pFileObj->QueryInterface(IID_IDirectXFileDataReference, (VOID **)&pFileRef)))
{
if ( SUCCEEDED( pFileRef->Resolve( &pFileData) ))
{
ParseXFileData( pFileData, pSubFrame );
SAFE_RELEASE(pFileData);
}
SAFE_RELEASE(pFileRef);
}
else if ( SUCCEEDED( pFileObj->QueryInterface(IID_IDirectXFileData, (VOID **)&pFileData)))
{
ParseXFileData( pFileData, pSubFrame );
SAFE_RELEASE(pFileData);
}
SAFE_RELEASE( pFileObj );
}
return TRUE;
}
BOOL XSKINMESH::ReadAnimationSet(IDirectXFileData * pDataObj,Frame * pParentFrame )
{
const GUID *pType = NULL;
IDirectXFileObject *pFileObj = NULL;
IDirectXFileData *pFileData = NULL;
TCHAR *pName = NULL;
DWORD cchName;
if (FAILED(pDataObj->GetName(NULL, &cchName )))
{
return FALSE;
}
if( cchName )
{
if ( NULL == (pName = new TCHAR[cchName] ) )
{
return FALSE;
}
if (FAILED(pDataObj->GetName(pName, &cchName ) ))
{
return FALSE;
}
}
else
{
pName = new TCHAR[15];
strcpy(pName, "$AnimationSet$" );
}
AnimationSet * pAnimationSet = new AnimationSet;
pAnimationSet->m_pParent = pParentFrame;
pAnimationSet->m_pName = pName;
pName = NULL;
pAnimationSet->m_pNext = m_pAnimationSet;
m_pAnimationSet = pAnimationSet;
while (SUCCEEDED(pDataObj->GetNextObject(&pFileObj)))
{
if (SUCCEEDED(pFileObj->QueryInterface( IID_IDirectXFileData, (LPVOID *)&pFileData)))
{
if (FAILED(pFileData->GetType( &pType)))
{
SAFE_RELEASE(pFileData);
return FALSE;
}
if ( *pType == TID_D3DRMAnimation )
{
ReadAnimation(pFileData, pAnimationSet );
}
SAFE_RELEASE(pFileData);
}
SAFE_RELEASE(pFileObj);
}
return TRUE;
}
VOID XSKINMESH::DrawSkinMesh()
{
DrawFrame(m_pRootFrame);
}
VOID XSKINMESH::DrawFrame(Frame *pFrame)
{
if ( NULL == pFrame )
return;
Mesh *pMesh = pFrame->m_pMeshList;
while ( pMesh )
{
DrawOriginalMesh(pMesh);
pMesh = pMesh->m_pNext;
}
DrawFrame( pFrame->m_pChild );
DrawFrame( pFrame->m_pSibling);
}
VOID XSKINMESH::DrawOriginalMesh(Mesh * pMesh)
{
UINT ipattr;
HRESULT hr = S_OK;
LPD3DXBONECOMBINATION pBoneComb;
DWORD AttribIdPrev;
if (pMesh->m_pSkinMesh)
{
if (m_nMethod != pMesh->m_Method)
{
MakeSkinMesh(pMesh);
}
if (m_nMethod == D3DNONINDEXED)
{
AttribIdPrev = UNUSED32;
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMesh->m_pBoneCombinationBuf->GetBufferPointer());
// Draw using default vtx processing of the device (typically HW)
for (ipattr = 0; ipattr < pMesh->m_cpattr; ipattr++)
{
DWORD numBlend = 0;
for (DWORD i = 0; i < pMesh->m_maxFaceInfl; ++i)
{
if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
{
numBlend = i;
}
}
if (m_d3dCaps.MaxVertexBlendMatrices >= numBlend + 1)
{
for (DWORD i = 0; i < pMesh->m_maxFaceInfl; ++i)
{
DWORD matid = pBoneComb[ipattr].BoneId[i];
if (matid != UINT_MAX)
{
m_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), pMesh->m_pBoneMatrix[matid]);
m_pD3DDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pMesh->m_pBoneOffsetMat[matid]);
}
}
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32))
{
m_pD3DDevice->SetMaterial(&(pMesh->m_rgMaterials[pBoneComb[ipattr].AttribId]));
m_pD3DDevice->SetTexture(0, pMesh->m_pTextures[pBoneComb[ipattr].AttribId]);
AttribIdPrev = pBoneComb[ipattr].AttribId;
}
hr = pMesh->m_pMesh->DrawSubset( ipattr );
if(FAILED(hr))
return;
}
}
// If necessary, draw parts that HW could not handle using SW
if (pMesh->m_iAttrSplit < pMesh->m_cpattr)
{
AttribIdPrev = UNUSED32;
m_pD3DDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
for (ipattr = pMesh->m_iAttrSplit; ipattr < pMesh->m_cpattr; ipattr++)
{
DWORD numBlend = 0;
for (DWORD i = 0; i < pMesh->m_maxFaceInfl; ++i)
{
if (pBoneComb[ipattr].BoneId[i] != UINT_MAX)
{
numBlend = i;
}
}
if (m_d3dCaps.MaxVertexBlendMatrices < numBlend + 1)
{
for (DWORD i = 0; i < pMesh->m_maxFaceInfl; ++i)
{
DWORD matid = pBoneComb[ipattr].BoneId[i];
if (matid != UINT_MAX)
{
m_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), pMesh->m_pBoneMatrix[matid]);
m_pD3DDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pMesh->m_pBoneOffsetMat[matid]);
}
}
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, numBlend);
if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32))
{
m_pD3DDevice->SetMaterial(&(pMesh->m_rgMaterials[pBoneComb[ipattr].AttribId]));
m_pD3DDevice->SetTexture(0, pMesh->m_pTextures[pBoneComb[ipattr].AttribId]);
AttribIdPrev = pBoneComb[ipattr].AttribId;
}
hr = pMesh->m_pMesh->DrawSubset( ipattr );
if(FAILED(hr))
return;
}
}
m_pD3DDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
}
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
}
else if (m_nMethod == D3DINDEXED)
{
if (pMesh->m_bUseSW)
{
m_pD3DDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
}
if (pMesh->m_maxFaceInfl == 1)
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
else
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, pMesh->m_maxFaceInfl - 1);
if (pMesh->m_maxFaceInfl)
m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMesh->m_pBoneCombinationBuf->GetBufferPointer());
for (ipattr = 0; ipattr < pMesh->m_cpattr; ipattr++)
{
for (DWORD i = 0; i < pMesh->m_paletteSize; ++i)
{
DWORD matid = pBoneComb[ipattr].BoneId[i];
if (matid != UINT_MAX)
{
m_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), pMesh->m_pBoneMatrix[matid]);
m_pD3DDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pMesh->m_pBoneOffsetMat[matid]);
}
}
m_pD3DDevice->SetMaterial(&(pMesh->m_rgMaterials[pBoneComb[ipattr].AttribId]));
m_pD3DDevice->SetTexture(0, pMesh->m_pTextures[pBoneComb[ipattr].AttribId]);
hr = pMesh->m_pMesh->DrawSubset( ipattr );
if(FAILED(hr))
return;
}
m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
if (pMesh->m_bUseSW)
{
m_pD3DDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
}
}
else if (m_nMethod == SOFTWARE)
{
D3DXMATRIX Identity;
DWORD cBones = pMesh->m_pSkinMesh->GetNumBones();
// set up bone transforms
for (DWORD iBone = 0; iBone < cBones; ++iBone)
{
D3DXMatrixMultiply
(
&m_pBoneMatrices[iBone], // output
&pMesh->m_pBoneOffsetMat[iBone],
pMesh->m_pBoneMatrix[iBone]
);
}
// set world transform
D3DXMatrixIdentity(&Identity);
hr = m_pD3DDevice->SetTransform(D3DTS_WORLD, &Identity);
if (FAILED(hr))
return;
// generate skinned mesh
hr = pMesh->m_pSkinMesh->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pMesh->m_pMesh);
if (FAILED(hr))
return;
for (ipattr = 0; ipattr < pMesh->m_cpattr; ipattr++)
{
m_pD3DDevice->SetMaterial(&(pMesh->m_rgMaterials[pMesh->m_pAttrTable[ipattr].AttribId]));
m_pD3DDevice->SetTexture(0, pMesh->m_pTextures[pMesh->m_pAttrTable[ipattr].AttribId]);
hr = pMesh->m_pMesh->DrawSubset(pMesh->m_pAttrTable[ipattr].AttribId);
if (FAILED(hr))
return;
}
return;
}
}
else
{
for (ipattr = 0; ipattr < pMesh->m_cpattr; ipattr++)
{
m_pD3DDevice->SetMaterial(&(pMesh->m_rgMaterials[ipattr]));
m_pD3DDevice->SetTexture(0, pMesh->m_pTextures[ipattr]);
hr = pMesh->m_pMesh->DrawSubset( ipattr );
if(FAILED(hr))
return;
}
}
}
VOID XSKINMESH::UpdateFrame(Frame *pFrame, const D3DXMATRIXA16 * matCur)
{
if ( pFrame == NULL )
return;
if ( matCur )
{
D3DXMatrixMultiply(&pFrame->m_matCombined, &pFrame->m_matRot, matCur);
D3DXMatrixMultiply(&pFrame->m_matCombined, &pFrame->m_matTrans,&pFrame->m_matCombined );
}
else
{
pFrame->m_matCombined = pFrame->m_matTrans;
}
Frame *pChild = pFrame->m_pChild;
while (pChild != NULL)
{
UpdateFrame(pChild, &pFrame->m_matCombined);
pChild = pChild->m_pSibling;
}
}
VOID XSKINMESH::SetMeshBones(Frame * pParentFrame)
{
if ( pParentFrame == NULL )
return;
Mesh *pMesh = pParentFrame->m_pMeshList;
while ( pMesh )
{
if ( pMesh->m_pSkinMesh )
{
for (DWORD i = 0; i <pMesh->m_numBoneComb; i++ )
{
TCHAR **pNames = (TCHAR **)pMesh->m_pBoneNamesBuf->GetBufferPointer();
Frame *pFrame = m_pRootFrame->FindFrame( pNames[i] );
if ( pFrame )
{
pMesh->m_pBoneMatrix[i] = &pFrame->m_matCombined;
}
else
pMesh->m_pBoneMatrix[i] = NULL;
}
}
pMesh = pMesh->m_pNext;
}
SetMeshBones( pParentFrame->m_pChild );
SetMeshBones( pParentFrame->m_pSibling );
}
VOID XSKINMESH::SetMeshAnimations(Frame *pParentFrame)
{
if ( pParentFrame )
{
AnimationSet *pAnimSet = m_pAnimationSet;
while ( pAnimSet )
{
Animation *pAnim = pAnimSet->m_pAnim;
while ( pAnim )
{
pAnim->m_pFrame = m_pRootFrame->FindFrame( pAnim->m_pFrameName );
pAnim = pAnim->m_pNext;
}
pAnimSet = pAnimSet->m_pNext;
}
}
}
AnimationSet * XSKINMESH::FindAnimationSet(const TCHAR *szName)
{
if ( NULL == szName )
return NULL;
AnimationSet *pAnimSet = m_pAnimationSet;
while ( pAnimSet )
{
if( _tcscmp(szName, pAnimSet->m_pName ) == 0 )
return pAnimSet;
pAnimSet = pAnimSet->m_pNext;
}
return NULL;
}
VOID XSKINMESH::SetAnimationSet(TCHAR *szName)
{
m_pAnimationCur = FindAnimationSet(szName);
}
VOID XSKINMESH::LinkAllMesh(Frame *pParentFrame)
{
if ( pParentFrame == NULL )
return;
Mesh *pMesh = pParentFrame->m_pMeshList;
Mesh *pHeadMesh = pMesh;
while ( pMesh != NULL && pMesh->m_pNext != NULL )
{
pMesh = pMesh->m_pNext;
}
if ( pMesh != NULL )
{
pMesh->m_pNext = m_pMeshList;
m_pMeshList = pHeadMesh;
}
LinkAllMesh( pParentFrame->m_pChild );
LinkAllMesh( pParentFrame->m_pSibling );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -