📄 skinnedmesh.h
字号:
//-----------------------------------------------------------------------------
// Name: DrawFrame()
// Desc: Called to render a frame in the hierarchy
//-----------------------------------------------------------------------------
void UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
{
D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
if (pParentMatrix != NULL)
D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);
else
pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;
if (pFrame->pFrameSibling != NULL)
{
UpdateFrameMatrices(pFrame->pFrameSibling, pParentMatrix);
}
if (pFrame->pFrameFirstChild != NULL)
{
UpdateFrameMatrices(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);
}
}
//-----------------------------------------------------------------------------
// Name: SetupBoneMatrixPointersOnMesh()
// Desc: Called to setup the pointers for a given bone to its transformation matrix
//-----------------------------------------------------------------------------
HRESULT SetupBoneMatrixPointersOnMesh(LPD3DXMESHCONTAINER pMeshContainerBase)
{
UINT iBone, cBones;
D3DXFRAME_DERIVED *pFrame;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
// if there is a skinmesh, then setup the bone matrices
if (pMeshContainer->pSkinInfo != NULL)
{
cBones = pMeshContainer->pSkinInfo->GetNumBones();
pMeshContainer->ppBoneMatrixPtrs = new D3DXMATRIX*[cBones];
if (pMeshContainer->ppBoneMatrixPtrs == NULL)
return E_OUTOFMEMORY;
for (iBone = 0; iBone < cBones; iBone++)
{
pFrame = (D3DXFRAME_DERIVED*)D3DXFrameFind(m_pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName(iBone));
if (pFrame == NULL)
return E_FAIL;
pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix;
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: SetupBoneMatrixPointers()
// Desc: Called to setup the pointers for a given bone to its transformation matrix
//-----------------------------------------------------------------------------
HRESULT SetupBoneMatrixPointers(LPD3DXFRAME pFrame)
{
HRESULT hr;
if (pFrame->pMeshContainer != NULL)
{
hr = SetupBoneMatrixPointersOnMesh(pFrame->pMeshContainer);
if (FAILED(hr))
return hr;
}
if (pFrame->pFrameSibling != NULL)
{
hr = SetupBoneMatrixPointers(pFrame->pFrameSibling);
if (FAILED(hr))
return hr;
}
if (pFrame->pFrameFirstChild != NULL)
{
hr = SetupBoneMatrixPointers(pFrame->pFrameFirstChild);
if (FAILED(hr))
return hr;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DrawMeshContainer()
// Desc: Called to render a mesh in the hierarchy
//-----------------------------------------------------------------------------
void DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
{
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
UINT iMaterial;
UINT NumBlend;
UINT iAttrib;
DWORD AttribIdPrev;
LPD3DXBONECOMBINATION pBoneComb;
UINT iMatrixIndex;
UINT iPaletteEntry;
D3DXMATRIXA16 matTemp;
// first check for skinning
if (pMeshContainer->pSkinInfo != NULL)
{
if (m_SkinningMethod == D3DNONINDEXED)
{
AttribIdPrev = UNUSED32;
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
// Draw using default vtx processing of the device (typically HW)
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
NumBlend = 0;
for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
{
if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
{
NumBlend = i;
}
}
if (m_d3dCaps.MaxVertexBlendMatrices >= NumBlend + 1)
{
// first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
Device->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
}
}
Device->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
// lookup the material used for this subset of faces
if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
{
Device->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
Device->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
AttribIdPrev = pBoneComb[iAttrib].AttribId;
}
// draw the subset now that the correct material and matrices are loaded
pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
}
}
// If necessary, draw parts that HW could not handle using SW
if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups)
{
AttribIdPrev = UNUSED32;
Device->SetSoftwareVertexProcessing(TRUE);
for (iAttrib = pMeshContainer->iAttributeSW; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
NumBlend = 0;
for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
{
if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
{
NumBlend = i;
}
}
if (m_d3dCaps.MaxVertexBlendMatrices < NumBlend + 1)
{
// first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
Device->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
}
}
Device->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
// lookup the material used for this subset of faces
if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
{
Device->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
Device->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
AttribIdPrev = pBoneComb[iAttrib].AttribId;
}
// draw the subset now that the correct material and matrices are loaded
pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
}
}
Device->SetSoftwareVertexProcessing(FALSE);
}
Device->SetRenderState(D3DRS_VERTEXBLEND, 0);
}
else if (m_SkinningMethod == D3DINDEXED)
{
// if hw doesn't support indexed vertex processing, switch to software vertex processing
if (pMeshContainer->UseSoftwareVP)
{
Device->SetSoftwareVertexProcessing(TRUE);
}
// set the number of vertex blend indices to be blended
if (pMeshContainer->NumInfl == 1)
Device->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
else
Device->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);
if (pMeshContainer->NumInfl)
Device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
// for each attribute group in the mesh, calculate the set of matrices in the palette and then draw the mesh subset
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
// first calculate all the world matrices
for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry];
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
Device->SetTransform( D3DTS_WORLDMATRIX( iPaletteEntry ), &matTemp );
}
}
// setup the material of the mesh subset - REMEMBER to use the original pre-skinning attribute id to get the correct material id
Device->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
Device->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
// finally draw the subset with the current world matrix palette and material state
pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
}
// reset blending state
Device->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
Device->SetRenderState(D3DRS_VERTEXBLEND, 0);
// remember to reset back to hw vertex processing if software was required
if (pMeshContainer->UseSoftwareVP)
{
Device->SetSoftwareVertexProcessing(FALSE);
}
}
else if (m_SkinningMethod == D3DINDEXEDVS)
{
// Use COLOR instead of UBYTE4 since Geforce3 does not support it
// vConst.w should be 3, but due to COLOR/UBYTE4 issue, mul by 255 and add epsilon
D3DXVECTOR4 vConst( 1.0f, 0.0f, 0.0f, 765.01f );
// D3DXVECTOR4 vConst( 1.0f, 0.0f, 0.0f, 2.01f );
if (pMeshContainer->UseSoftwareVP)
{
Device->SetSoftwareVertexProcessing(TRUE);
}
Device->SetVertexShader(m_pIndexedVertexShader[pMeshContainer->NumInfl - 1]);
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
// first calculate all the world matrices
for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry];
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply(&matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex]);
D3DXMatrixMultiplyTranspose(&matTemp, &matTemp, &m_matView);
Device->SetVertexShaderConstantF(iPaletteEntry*3 + 9, (float*)&matTemp, 3);
}
}
// Sum of all ambient and emissive contribution
D3DXCOLOR color1(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient);
D3DXCOLOR color2(.25, .25, .25, 1.0);
D3DXCOLOR ambEmm;
D3DXColorModulate(&ambEmm, &color1, &color2);
ambEmm += D3DXCOLOR(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Emissive);
// set material color properties
Device->SetVertexShaderConstantF(8, (float*)&(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Diffuse), 1);
Device->SetVertexShaderConstantF(7, (float*)&ambEmm, 1);
vConst.y = pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Power;
Device->SetVertexShaderConstantF(0, (float*)&vConst, 1);
Device->SetTexture(0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId]);
// finally draw the subset with the current world matrix palette and material state
pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
}
// remember to reset back to hw vertex processing if software was required
if (pMeshContainer->UseSoftwareVP)
{
Device->SetSoftwareVertexProcessing(FALSE);
}
Device->SetVertexShader(NULL);
}
else if (m_SkinningMethod == D3DINDEXEDHLSLVS)
{
if (pMeshContainer->UseSoftwareVP)
{
Device->SetSoftwareVertexProcessing(TRUE);
}
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
// first calculate all the world matrices
for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry];
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply(&matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex]);
D3DXMatrixMultiply(&m_pBoneMatrices[iPaletteEntry], &matTemp, &m_matView);
}
}
m_pEffect->SetMatrixArray( "mWorldMatrixArray", m_pBoneMatrices, pMeshContainer->NumPaletteEntries);
// Sum of all ambient and emissive contribution
D3DXCOLOR color1(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient);
D3DXCOLOR color2(.25, .25, .25, 1.0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -