|
|

楼主 |
发表于 2007-4-3 16:38:00
|
显示全部楼层
Re:为什么我渲染的一个骨骼动画角色会是乱的,头脚不分. ?
CSkinMesh::CSkinMesh(LPDIRECT3DDEVICE9 pD3DDevice)
{
m_pAnimController=NULL;
m_pd3dDevice=pD3DDevice;
m_pFrameRoot=NULL;
D3DXMatrixIdentity(&m_matMoveMatrices);
m_fStartTime=0.0f;
}
CSkinMesh::~CSkinMesh()
{
}
HRESULT CSkinMesh: oadFromXFile(TCHAR* strFileName)
{
CAllocateHierarchy Alloc(this);
if(D3DXLoadMeshHierarchyFromX(strFileName, D3DXMESH_MANAGED, m_pd3dDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
if(m_pFrameRoot==NULL)
{
return D3DERR_INVALIDCALL;
}
if(SetupBoneMatrixPointers(m_pFrameRoot)!=D3D_OK)
return D3DERR_INVALIDCALL;
if(D3DXFrameCalculateBoundingSphere(m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
return D3D_OK;
}
HRESULT CSkinMesh::SetupBoneMatrixPointers( LPD3DXFRAME pFrame )
{
if(pFrame->pMeshContainer!=NULL)
{
if(SetupBoneMatrixPointersOnMesh(pFrame->pMeshContainer)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
}
if(pFrame->pFrameSibling!=NULL)
{
if( SetupBoneMatrixPointers(pFrame->pFrameSibling)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
}
if(pFrame->pFrameFirstChild!=NULL)
{
if(SetupBoneMatrixPointers(pFrame->pFrameFirstChild)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
}
return D3D_OK;
}
HRESULT CSkinMesh::SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase )
{
D3DXFRAME_DERIVED* pFrame=NULL;
D3DXMESHCONTAINER_DERIVED* pMeshContainer=(D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
if(pMeshContainer->pSkinInfo!=NULL)
{
UINT Bones=pMeshContainer->pSkinInfo->GetNumBones();
pMeshContainer->ppBoneMatrixPtrs =new D3DXMATRIX*[Bones];
if(pMeshContainer==NULL)
{
return E_OUTOFMEMORY;
}
for(UINT I=0;I<Bones;I++)
{
pFrame=(D3DXFRAME_DERIVED*)D3DXFrameFind(m_pFrameRoot,pMeshContainer->pSkinInfo->GetBoneName(I));
pMeshContainer->ppBoneMatrixPtrs[I]=&pFrame->matCombined;
}
}
return D3D_OK;
}
HRESULT CSkinMesh::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED* pMeshContainer)
{
LPDIRECT3DINDEXBUFFER9 pIB;
if(pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
DWORD maxFaceInfluences;
if(pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB,pMeshContainer->pOrigMesh->GetNumFaces(),&maxFaceInfluences)!=D3D_OK){
return D3DERR_INVALIDCALL;
}
//sSAFE_RELEASE(pIB);
pMeshContainer->NumPaletteEntries=min(128,pMeshContainer->pSkinInfo->GetNumBones());
pMeshContainer->MeshData.pMesh=NULL;
pMeshContainer->pBoneCombinationBuf=NULL;
if(pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(pMeshContainer->pOrigMesh,NULL,
pMeshContainer->NumPaletteEntries,
pMeshContainer->pAdjacency,
NULL, NULL, NULL,
&pMeshContainer->NumInfl,
&pMeshContainer->NumAttributeGroups,
&pMeshContainer->pBoneCombinationBuf,
&pMeshContainer->MeshData.pMesh)!=D3D_OK)
{
return D3DERR_INVALIDCALL;
}
return D3D_OK;
}
VOID CSkinMesh::UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix )
{
D3DXFRAME_DERIVED* pFrame=(D3DXFRAME_DERIVED*)pFrameBase;
if(pParentMatrix!=NULL)
{
D3DXMatrixMultiply(&pFrame->matCombined,&pFrame->TransformationMatrix,pParentMatrix);
}else{
pFrame->matCombined=pFrame->TransformationMatrix;
}
if(pFrame->pFrameSibling!=NULL)
{
UpdateFrameMatrices(pFrame->pFrameSibling,pParentMatrix);
}
if(pFrame->pFrameFirstChild!=NULL)
{
UpdateFrameMatrices(pFrame->pFrameFirstChild,pParentMatrix);
}
}
VOID CSkinMesh::Render()
{
double fElapsedTime=0.0;
fElapsedTime=fElapsedTime+30.0 ;);//先做测试型简单的变化
D3DXMATRIXA16 matWorld,matWorld2;
//先将角色的中心点平移到世界坐标系的原点
D3DXMatrixTranslation(&matWorld, -m_vObjectCenter.x,
-m_vObjectCenter.y,
-m_vObjectCenter.z );
//将角色的中心点向上提高,保证角色的脚站在地面上
D3DXMatrixTranslation( &matWorld2, 0,m_fObjectRadius,0);
//以上两个变换的合成矩阵
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
//角色绕Y轴旋转m_fRotateAngle角
D3DXMatrixRotationY(&matWorld2,m_fRotateAngle); //旋转矩阵
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2); //旋转变换
//与移步矩阵相乘得到最终的合成矩阵
D3DXMatrixMultiply(&matWorld,&matWorld,&m_matMoveMatrices);
//设置渲染管道流水线的世界坐标变换矩阵
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
m_pAnimController->AdvanceTime(fElapsedTime,NULL);//先做测试型简单的变化
UpdateFrameMatrices(m_pFrameRoot, &matWorld);
//渲染一帧
DrawFrame(m_pFrameRoot);
}
VOID CSkinMesh: rawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
{
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
UINT iMaterial;
UINT iAttrib;
LPD3DXBONECOMBINATION pBoneComb;
UINT iMatrixIndex;
UINT iPaletteEntry;
D3DXMATRIXA16 matTemp;
if (pMeshContainer->pSkinInfo != NULL)
{
if (pMeshContainer->NumInfl)
m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
if (pMeshContainer->NumInfl == 1)
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
else
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);
//取得网格子集的组合属性表(包括子集内的各个骨骼id)
pBoneComb =(LPD3DXBONECOMBINATION)pMeshContainer->pBoneCombinationBuf->GetBufferPointer();
//每子集
for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
{
//每个子集内的每个骨骼,逐个计算世界坐标变换矩阵
for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
{
iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry]; //取出骨骼id
if (iMatrixIndex != UINT_MAX)
{
D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
m_pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( iPaletteEntry ), &matTemp );
}
}
//设置材质
m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
m_pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
//用当前的矩阵调板渲染网格子集
pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
}
//恢复渲染状态标志
m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
}
else //网格没有骨骼动画数据
{
m_pd3dDevice->SetTransform(D3DTS_WORLD, &pFrame->matCombined);
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::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);
}
}
当我建该对象成功之后,随之调用Render() 就是那样罗 |
|