📄 game_skinmesh.cpp
字号:
pMesh=pMeshContainer->MeshData.pMesh;
pMesh->LockVertexBuffer(0,(void**)&pV);
if(pMeshContainer->NumInfl>0){
D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[0], pMeshContainer->ppBoneMatrixPtrs[0] );
pMat=&matTemp;
}
else
pMat=&((D3DXFRAME_DERIVED*)pFrameBase)->CombinedTransformationMatrix; //只是使用第一个矩阵
DWORD nVertex=pMesh->GetNumVertices();
DWORD nStride=pMesh->GetNumBytesPerVertex();
DWORD i;
for(i=0;i<nVertex;i++){
vTransformed.x=pV->x*pMat->_11+pV->y*pMat->_21+pV->z*pMat->_31+pMat->_41;
vTransformed.y=pV->x*pMat->_12+pV->y*pMat->_22+pV->z*pMat->_32+pMat->_42;
vTransformed.z=pV->x*pMat->_13+pV->y*pMat->_23+pV->z*pMat->_33+pMat->_43;
if (vTransformed.x<pVmin->x) pVmin->x=vTransformed.x;
else if (vTransformed.x>pVmax->x) pVmax->x=vTransformed.x;
if (vTransformed.y<pVmin->y) pVmin->y=vTransformed.y;
else if (vTransformed.y>pVmax->y) pVmax->y=vTransformed.y;
if (vTransformed.z<pVmin->z) pVmin->z=vTransformed.z;
else if (vTransformed.z>pVmax->z) pVmax->z=vTransformed.z;
pV=(D3DXVECTOR3*)((BYTE*)pV+nStride);
}
pMesh->UnlockVertexBuffer();
pMeshContainer =(D3DXMESHCONTAINER_DERIVED*) pMeshContainer->pNextMeshContainer;
}
if(pFrameBase->pFrameSibling)
CalculateStaticBondingBox(pFrameBase->pFrameSibling,pVmin,pVmax);
if(pFrameBase->pFrameFirstChild)
CalculateStaticBondingBox(pFrameBase->pFrameFirstChild,pVmin,pVmax);
return S_OK;
}
//生成蒙皮网格
HRESULT Game_SkinMesh::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer){
HRESULT hr = S_OK;
if (pMeshContainer->pSkinInfo == NULL)
return hr;
SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
if (m_SkinningMethod == D3DNONINDEXED){
//生成包含顶点骨骼权重、骨骼矩阵表和索引等信息的蒙皮网格
hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh
(
pMeshContainer->pOrigMesh,
D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE,
pMeshContainer->pAdjacency,
NULL, NULL, NULL,
&pMeshContainer->NumInfl,
&pMeshContainer->NumAttributeGroups,
&pMeshContainer->pBoneCombinationBuf,
&pMeshContainer->MeshData.pMesh
);
if (FAILED(hr))
goto e_Exit;
LPD3DXBONECOMBINATION rgBoneCombinations = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
for (pMeshContainer->iAttributeSW = 0;
pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups;
pMeshContainer->iAttributeSW++){
DWORD cInfl = 0;
for (DWORD iInfl = 0; iInfl < pMeshContainer->NumInfl; iInfl++){
if (rgBoneCombinations[pMeshContainer->iAttributeSW].BoneId[iInfl] != UINT_MAX){
++cInfl;
}
}
if (cInfl > m_d3dCaps.MaxVertexBlendMatrices){
break;
}
}
if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups){
LPD3DXMESH pMeshTmp;
hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pMeshContainer->MeshData.pMesh->GetOptions(),
pMeshContainer->MeshData.pMesh->GetFVF(),
g_sGlobal.g_pDevice, &pMeshTmp);
if (FAILED(hr)){
goto e_Exit;
}
pMeshContainer->MeshData.pMesh->Release();
pMeshContainer->MeshData.pMesh = pMeshTmp;
pMeshTmp = NULL;
}
}
else if (m_SkinningMethod == D3DINDEXED){
DWORD NumMaxFaceInfl;
DWORD Flags = D3DXMESHOPT_VERTEXCACHE;
LPDIRECT3DINDEXBUFFER9 pIB;
hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB);
if (FAILED(hr))
goto e_Exit;
hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl);
pIB->Release();
if (FAILED(hr))
goto e_Exit;
NumMaxFaceInfl = min(NumMaxFaceInfl, 12);
if (m_d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl){
pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones());
pMeshContainer->UseSoftwareVP = true;
Flags |= D3DXMESH_SYSTEMMEM;
}
else{
pMeshContainer->NumPaletteEntries = min( ( m_d3dCaps.MaxVertexBlendMatrixIndex + 1 ) / 2,
pMeshContainer->pSkinInfo->GetNumBones() );
pMeshContainer->UseSoftwareVP = false;
Flags |= D3DXMESH_MANAGED;
}
hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh
(
pMeshContainer->pOrigMesh,
Flags,
pMeshContainer->NumPaletteEntries,
pMeshContainer->pAdjacency,
NULL, NULL, NULL,
&pMeshContainer->NumInfl,
&pMeshContainer->NumAttributeGroups,
&pMeshContainer->pBoneCombinationBuf,
&pMeshContainer->MeshData.pMesh);
if (FAILED(hr))
goto e_Exit;
}
else if (m_SkinningMethod == SOFTWARE){
hr = pMeshContainer->pOrigMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshContainer->pOrigMesh->GetFVF(),
g_sGlobal.g_pDevice, &pMeshContainer->MeshData.pMesh);
if (FAILED(hr))
goto e_Exit;
hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(NULL, &pMeshContainer->NumAttributeGroups);
if (FAILED(hr))
goto e_Exit;
delete[] pMeshContainer->pAttributeTable;
pMeshContainer->pAttributeTable = new D3DXATTRIBUTERANGE[pMeshContainer->NumAttributeGroups];
if (pMeshContainer->pAttributeTable == NULL){
hr = E_OUTOFMEMORY;
goto e_Exit;
}
hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(pMeshContainer->pAttributeTable, NULL);
if (FAILED(hr))
goto e_Exit;
if (m_NumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones()){
m_NumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();
delete []m_pBoneMatrices;
m_pBoneMatrices = new D3DXMATRIXA16[m_NumBoneMatricesMax];
if (m_pBoneMatrices == NULL){
hr = E_OUTOFMEMORY;
goto e_Exit;
}
}
}
else{
hr = E_INVALIDARG;
goto e_Exit;
}
e_Exit:
return hr;
}
HRESULT Game_SkinMesh::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;
}
HRESULT Game_SkinMesh::SetupBoneMatrixPointersOnMesh(LPD3DXMESHCONTAINER pMeshContainerBase){
UINT iBone, cBones;
D3DXFRAME_DERIVED *pFrame;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
//蒙皮动画,则设置骨骼的变换矩阵
//存在蒙皮数据,取出骨骼矩阵,放入矩阵表ppBoneMatrixPtrs中
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++){
//找到骨骼所在的Frame
pFrame = (D3DXFRAME_DERIVED*)D3DXFrameFind(m_pFrameRoot,
pMeshContainer->pSkinInfo->GetBoneName(iBone));
if (pFrame == NULL)
return E_FAIL;
//初始化矩阵
pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix;
}
}
return S_OK;
}
VOID Game_SkinMesh::Render(float fElapsedAppTime,D3DXVECTOR3 vPos,float angle,float scale,bool change){
if(m_BoundingBox){
D3DXVECTOR3 vMin,vMax;
vMin=m_vMin;
vMax=m_vMax;
GetBoundingBox(&vMin,&vMax);
RenderAABB(&vMin,&vMax);//画出盒子
}
// if( 0.00f == fElapsedAppTime ) return;
m_fElapsedTime = fElapsedAppTime;
D3DXMATRIXA16 matWorld,matWorld2,matWorld1;
if(change){
D3DXMatrixRotationZ(&matWorld2,angle+D3DX_PI);
D3DXMatrixScaling(&matWorld,scale,scale,scale);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixRotationX(&matWorld2,4.7f);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixRotationY(&matWorld2,1.5f);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixTranslation( &matWorld2,vPos.x,vPos.y,vPos.z);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
}
else{
D3DXMatrixRotationY(&matWorld2,angle+D3DX_PI);
D3DXMatrixScaling(&matWorld,scale,scale,scale);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixTranslation( &matWorld2, vPos.x, vPos.y,vPos.z );
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
}
m_matWorld=matWorld;
if(m_pAnimController){
if (m_bMoving)
#if (D3D_SDK_VERSION &31)
m_pAnimController->SetTime(m_pAnimController->GetTime()+m_fElapsedTime );
else
m_pAnimController->SetTime(0);
#else
m_pAnimController->AdvanceTime(m_fElapsedTime,NULL);
else
m_pAnimController->ResetTime();
#endif
}
UpdateFrameMatrices(m_pFrameRoot, &matWorld);
DrawFrame(m_pFrameRoot);
}
VOID Game_SkinMesh::DrawFrame(LPD3DXFRAME pFrame){
LPD3DXMESHCONTAINER pMeshContainer;
pMeshContainer = pFrame->pMeshContainer;
while (pMeshContainer != NULL){
DrawMeshContainer(pMeshContainer, pFrame);
pMeshContainer = pMeshContainer->pNextMeshContainer;
}
if (pFrame->pFrameSibling != NULL){
DrawFrame(pFrame->pFrameSibling);
}
if (pFrame->pFrameFirstChild != NULL){
DrawFrame(pFrame->pFrameFirstChild);
}
}
VOID Game_SkinMesh::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;
if (pMeshContainer->pSkinInfo != NULL){
if (m_SkinningMethod == D3DNONINDEXED){
AttribIdPrev = UNUSED32;
pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -