📄 game_skinmesh.cpp
字号:
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] );
m_pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
}
}
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
// lookup the material used for this subset of faces
if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
{
m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
m_pd3dDevice->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;
m_pd3dDevice->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] );
m_pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
}
}
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
// lookup the material used for this subset of faces
if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
{
m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
m_pd3dDevice->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);
}
}
m_pd3dDevice->SetSoftwareVertexProcessing(FALSE);
}
m_pd3dDevice->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)
{
m_pd3dDevice->SetSoftwareVertexProcessing(TRUE);
}
// set the number of vertex blend indices to be blended
if (pMeshContainer->NumInfl == 1)
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
else
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);
if (pMeshContainer->NumInfl)
m_pd3dDevice->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] );
m_pd3dDevice->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
m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
m_pd3dDevice->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
m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
// remember to reset back to hw vertex processing if software was required
if (pMeshContainer->UseSoftwareVP)
{
m_pd3dDevice->SetSoftwareVertexProcessing(FALSE);
}
}
else if (m_SkinningMethod == SOFTWARE)
{
D3DXMATRIX Identity;
DWORD cBones = pMeshContainer->pSkinInfo->GetNumBones();
DWORD iBone;
PBYTE pbVerticesSrc;
PBYTE pbVerticesDest;
// set up bone transforms
for (iBone = 0; iBone < cBones; ++iBone)
{
D3DXMatrixMultiply
(
&m_pBoneMatrices[iBone], // output
&pMeshContainer->pBoneOffsetMatrices[iBone],
pMeshContainer->ppBoneMatrixPtrs[iBone]
);
}
// set world transform
D3DXMatrixIdentity(&Identity);
m_pd3dDevice->SetTransform(D3DTS_WORLD, &Identity);
pMeshContainer->pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc);
pMeshContainer->MeshData.pMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesDest);
// generate skinned mesh
pMeshContainer->pSkinInfo->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);
pMeshContainer->pOrigMesh->UnlockVertexBuffer();
pMeshContainer->MeshData.pMesh->UnlockVertexBuffer();
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
m_pd3dDevice->SetMaterial(&(pMeshContainer->pMaterials[pMeshContainer->pAttributeTable[iAttrib].AttribId].MatD3D));
m_pd3dDevice->SetTexture(0, pMeshContainer->ppTextures[pMeshContainer->pAttributeTable[iAttrib].AttribId]);
pMeshContainer->MeshData.pMesh->DrawSubset(pMeshContainer->pAttributeTable[iAttrib].AttribId);
}
}
else // bug out as unsupported mode
{
return;
}
}
else // standard mesh, just draw it after setting material properties
{
m_pd3dDevice->SetTransform(D3DTS_WORLD, &pFrame->CombinedTransformationMatrix);
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
{
m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D );
m_pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] );
pMeshContainer->MeshData.pMesh->DrawSubset(iMaterial);
}
}
}
VOID CSkinMesh::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);
}
}
VOID CSkinMesh::SetAnim(BOOL bAnim)
{
m_bMoving=bAnim;
if(!m_bMoving && m_pAnimController)
{
#if (D3D_SDK_VERSION & 32)
m_pAnimController->ResetTime();
#else m_pAnimController->SetTime(0);
#endif
}
}
BOOL CSkinMesh::SetAnimationName(char *strAnimName)
{
DWORD i=0;
if(!m_bMoving || !m_pAnimController ) return FALSE;
DWORD nAnimSet;
char strTempName[256];
nAnimSet=m_pAnimController->GetNumAnimationSets();
//LPD3DXANIMATIONSET pAnimSet;
if( strcmp( strAnimName, "wait") == 0
|| strcmp( strAnimName, "attak") == 0
|| strcmp( strAnimName, "run") == 0
|| strcmp( strAnimName, "idle") == 0
|| strcmp( strAnimName, "walk") == 0
|| strcmp( strAnimName, "stand") == 0)
{
m_bLoop = true;
}
else if( strcmp( strAnimName, "skil1") == 0
|| strcmp( strAnimName, "skill2") == 0
|| strcmp( strAnimName, "death") == 0
|| strcmp( strAnimName, "die") == 0
|| strcmp( strAnimName, "attack") == 0)
{
m_bLoop = false;
}
for(DWORD i=0;i<nAnimSet;i++)
{
m_pAnimController->GetAnimationSet(i,&m_pCurAnimSet);
strcpy(strTempName, m_pCurAnimSet->GetName());
if(strcmp(strAnimName,strTempName)==0)
{
m_pAnimController->SetTrackAnimationSet(0,m_pCurAnimSet);
return TRUE;
}
}
return FALSE;
};
//-----------------------------------------
//Name:Intersect
//Desc:使用索引和顶点缓冲区,求Mesh和射线交点
//2006/6/27 JohnsonFeng
//Use: IntersectIndexBuffer
//-----------------------------------------
BOOL CSkinMesh::InterSect( D3DVECTOR *pRayOrig,
D3DVECTOR *pRayDir,D3DVECTOR* pVRet)
{
return S_OK;
}
HRESULT CSkinMesh::CalculateStaticBondingBox(LPD3DXFRAME pFrameBase, const LPD3DXVECTOR3 pVmin,
const LPD3DXVECTOR3 pVmax)
{
static LPD3DXMESH pMesh;
static LPD3DXMATRIX pMat;
static D3DXVECTOR3 *pV;
static D3DXVECTOR3 vTransformed;
static D3DXMATRIX matTemp;
D3DXMESHCONTAINER_DERIVED *pMeshContainer= (D3DXMESHCONTAINER_DERIVED*)pFrameBase->pMeshContainer;
//这里如果直接使用Frame自带的CombinedTransformationMatrix,将会得到模型静止状态的方盒
while (pMeshContainer != NULL )
{
pMesh=pMeshContainer->MeshData.pMesh;
pMesh->LockVertexBuffer(0,(void**)&pV);
if(pMeshContainer->NumInfl>0)
{// pMat=*pMeshContainer->ppBoneMatrixPtrs;
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;
}
D3DXVECTOR3 CSkinMesh::MoveTo(D3DXVECTOR3 IntersectPoint, float tFrameTime, float Speed1)
{
float dist = 0.0f, Yaw = 0.0f;
dist = DistanceOfTwoVec3(IntersectPoint, m_vPos);
Yaw = GetYaw(IntersectPoint, m_vPos);
m_vPosOld = m_vPos;
m_vPos.x += tFrameTime*Speed1*sin(Yaw);
m_vPos.z += tFrameTime*Speed1*cos(Yaw);
if(dist <= tFrameTime*Speed1)
{
m_isMoving = false;
//this->m_fAngle = Yaw;
this->SetAnimationName("wait");
}
return m_vPos;
}
//找到节点的矩阵
LRESULT CSkinMesh::GetFrameMatrix(LPD3DXFRAME pFrameBase, char *strFrameName,D3DMATRIX *pMat)
{
D3DXFRAME *pFrame ;
if(pFrameBase!=NULL)
pFrame = pFrameBase;
else
pFrame = m_pFrameRoot;
if(pFrame->Name!=NULL && 0==strcmp(pFrame->Name,strFrameName))
{
*pMat=((D3DXFRAME_DERIVED*)pFrame)->CombinedTransformationMatrix;
return S_OK;
}
if (pFrame->pFrameSibling != NULL)
{
if(S_OK == GetFrameMatrix(pFrame->pFrameSibling,strFrameName,pMat))
return S_OK;
}
if (pFrame->pFrameFirstChild != NULL)
{
if(S_OK == GetFrameMatrix(pFrame->pFrameFirstChild,strFrameName,pMat))
return S_OK;
}
return E_FAIL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -