HLSL实现蒙皮动画.docx
《HLSL实现蒙皮动画.docx》由会员分享,可在线阅读,更多相关《HLSL实现蒙皮动画.docx(23页珍藏版)》请在冰豆网上搜索。
![HLSL实现蒙皮动画.docx](https://file1.bdocx.com/fileroot1/2023-5/27/35a89ba7-0fd1-460a-a7e2-a541b4539a0e/35a89ba7-0fd1-460a-a7e2-a541b4539a0e1.gif)
HLSL实现蒙皮动画
这两天在做 3D蒙皮动画时遇到些问题,折腾了一天半,嗨!
很郁闷啊!
我要大叫来发泄一下。
本来打算用D3D设备直接设置世界坐标矩阵来实现动画的,但发现有一个问题,当我不使用D3DXEFFECT来设置渲染效果的时候就可以正常显示动画;当我使用它来设置渲染效果的时候,动画就没了。
我想可能是用D3DXEFFECT来设置渲染效果的时候把D3D设备的SetTransform功能屏蔽掉了(其实我不理解这个渲染过程^_^)。
下面说一下加载和渲染蒙皮动画的大概流程吧。
首先继承2个结构:
D3DXFRAME、D3DMESHCONTAINER和一个接口:
ID3DXAllocateHierarchy。
//------------------------------------------------------------
//说明:
框架
//------------------------------------------------------------
structGFrame:
publicD3DXFRAME
{
D3DXMATRIXA16 CombinedTransformationMatrix;//最终变换矩阵
};
//------------------------------------------------------------
//说明:
网格容器
//------------------------------------------------------------
structGMeshContainer:
publicD3DXMESHCONTAINER
{
LPDIRECT3DTEXTURE9* _ppTexs; //纹理列表
LPD3DXMESH _pOrigMesh; //原mesh
DWORD _dwNumAttrGroups;//属性组个数
DWORD _dwMaxNumInfl; //一个面最多受多少骨骼影响
DWORD _dwNumPaletteEntries;//样色个数
LPD3DXBUFFER _pBoneCombBuf; //邻接矩阵列表
D3DXMATRIX** _ppBoneMatrixPtr;//骨骼矩阵列表
D3DXMATRIX* _pBoneOffsetMatrices;//骨骼矩阵引用
DWORD _iAttrSW; //用户GenerateSkinnedMesh
};
//------------------------------------------------------------
//说明:
封装网格的创建类
//------------------------------------------------------------
classGAllocateHierarchy:
publicID3DXAllocateHierarchy
{
public:
//下面4个方法是对父类的实现
STDMETHOD(CreateFrame)(THIS_LPCSTRName,LPD3DXFRAME*ppNewFrame);
STDMETHOD(CreateMeshContainer)(THIS_
LPCSTRName,
CONSTD3DXMESHDATA*pMeshData,
CONSTD3DXMATERIAL*pMaterials,
CONSTD3DXEFFECTINSTANCE*pEffectInstances,
DWORDNumMaterials,
CONSTDWORD*pAdjacency,
LPD3DXSKININFOpSkinInfo,
LPD3DXMESHCONTAINER*ppNewMeshContainer);
STDMETHOD(DestroyFrame)(THIS_LPD3DXFRAMEpFrameToFree);
STDMETHOD(DestroyMeshContainer)(THIS_LPD3DXMESHCONTAINERpMeshContainerBase);
};
//----------------------------------------------------
//创建框架
//----------------------------------------------------
HRESULTGAllocateHierarchy:
:
CreateFrame(LPCSTRName,LPD3DXFRAME*ppNewFrame)
{
HRESULThr;
GFrame*pFrame;
pFrame=newGFrame();
*ppNewFrame=NULL;
if(!
pFrame)
{
hr=E_OUTOFMEMORY;
gotoe_Exit;
}
//复制框架名称
hr=HeapCopy(Name,&pFrame->Name);
if(FAILED(hr))
gotoe_Exit;
//初始化其它属性
D3DXMatrixIdentity(&pFrame->TransformationMatrix);
D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
pFrame->pMeshContainer=NULL;
pFrame->pFrameFirstChild=NULL;
pFrame->pFrameSibling=NULL;
//复制到新框架
*ppNewFrame=pFrame;
pFrame=NULL;
e_Exit:
deletepFrame;
returnhr;
}
//----------------------------------------------------
//创建Mesh
//----------------------------------------------------
HRESULTGAllocateHierarchy:
:
CreateMeshContainer(
LPCSTRName,
CONSTD3DXMESHDATA*pMeshData,
CONSTD3DXMATERIAL*pMaterials,
CONSTD3DXEFFECTINSTANCE*pEffectInst,
DWORDdwNumMaterials,
CONSTDWORD*pAdjacency,
LPD3DXSKININFOpSkinInfo,
LPD3DXMESHCONTAINER*ppNewMeshContainer)
{
HRESULThr;
GMeshContainer*pMeshContainer=NULL;
UINTiNumFaces;
LPDIRECT3DDEVICE9pDev=NULL;
LPD3DXMESHpMesh=NULL;
*ppNewMeshContainer=NULL;
//----------------------------
//验证异常
if(pMeshData->Type!
=D3DXMESHTYPE_MESH)
{
hr=E_FAIL;
gotoe_Exit;
}
pMesh=pMeshData->pMesh;
if(pMesh->GetFVF()==0)
{
hr=E_FAIL;
gotoe_Exit;
}
pMeshContainer=newGMeshContainer();
if(pMeshContainer==NULL)
{
hr=E_OUTOFMEMORY;
gotoe_Exit;
}
//-------------------------
//初始化pMeshContainer,复制名字,获取pDev,获取面信息
memset(pMeshContainer,0,sizeof(GMeshContainer));
hr=HeapCopy(Name,&pMeshContainer->Name);
if(FAILED(hr))
gotoe_Exit;
pMesh->GetDevice(&pDev);
iNumFaces=pMesh->GetNumFaces();
//--------------------------
//判断是否要处理法向量,并复制Mesh
if(!
(pMesh->GetFVF()&D3DFVF_NORMAL))//如果没有法向量,则添加法向量
{
pMeshContainer->MeshData.Type=D3DXMESHTYPE_MESH;
hr=pMesh->CloneMeshFVF(pMesh->GetOptions(),
pMesh->GetFVF()|D3DFVF_NORMAL,
pDev,
&pMeshContainer->MeshData.pMesh);
if(FAILED(hr))
gotoe_Exit;
pMesh=pMeshContainer->MeshData.pMesh;
D3DXComputeNormals(pMesh,NULL);
}
else//如果有法向量,则直接复制Mesh
{
pMeshContainer->MeshData.pMesh=pMesh;
pMeshContainer->MeshData.Type=D3DXMESHTYPE_MESH;
pMesh->AddRef();
}
//----------------------------
//获取材质个数,并初始化材质、纹理、邻接矩阵信息
pMeshContainer->NumMaterials=max(1,dwNumMaterials);
pMeshContainer->pMaterials=newD3DXMATERIAL[pMeshContainer->NumMaterials];
pMeshContainer->_ppTexs=newLPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
pMeshContainer->pAdjacency=newDWORD[iNumFaces*3];
if(pMeshContainer->pMaterials==NULL||pMeshContainer->pAdjacency==NULL)
{
hr=E_OUTOFMEMORY;
gotoe_Exit;
}
memcpy(pMeshContainer->pAdjacency,pAdjacency,sizeof(DWORD)*iNumFaces*3);
memset(pMeshContainer->_ppTexs,0,sizeof(LPDIRECT3DTEXTURE9)*pMeshContainer->NumMaterials);
//--------------------------------
//复制材质,创建纹理
if(dwNumMaterials>0)//如果有材质,则复制材质
{
memcpy(pMeshContainer->pMaterials,pMaterials,sizeof(D3DXMATERIAL)*dwNumMaterials);
for(UINTi=0;i {
//如果有纹理则加载纹理
if(pMeshContainer->pMaterials[i].pTextureFilename!
=NULL)
{
LPSTRpFileName=pMeshContainer->pMaterials[i].pTextureFilename;
if(FAILED(D3DXCreateTextureFromFileA(pDev,pFileName,&pMeshContainer->_ppTexs[i])))
pMeshContainer->_ppTexs[i]=NULL;
//清除纹理文件名
pMeshContainer->pMaterials[i].pTextureFilename=NULL;
}
}
}
else//如果没有材质则初始化默认值
{
pMeshContainer->pMaterials[0].pTextureFilename=NULL;
memset(&pMeshContainer->pMaterials[0].MatD3D,0,sizeof(D3DMATERIAL9));
pMeshContainer->pMaterials[0].MatD3D.Diffuse.r=0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.g=0.5f;
pMeshContainer->pMaterials[0].MatD3D.Diffuse.b=0.5f;
pMeshContainer->pMaterials[0].MatD3D.Specular=pMeshContainer->pMaterials[0].MatD3D.Diffuse;
}
//----------------------------
//如果有Skin则创建Skin,并创建拷贝它的骨骼矩阵信息
if(pSkinInfo!
=NULL)
{
pMeshContainer->pSkinInfo=pSkinInfo;
pSkinInfo->AddRef();
pMeshContainer->_pOrigMesh=pMesh;
pMesh->AddRef();
UINTiTotalBones=pSkinInfo->GetNumBones();
pMeshContainer->_pBoneOffsetMatrices=newD3DXMATRIX[iTotalBones];
if(pMeshContainer->_pBoneOffsetMatrices==NULL)
{
hr=E_OUTOFMEMORY;
gotoe_Exit;
}
for(UINTi=0;i {
pMeshContainer->_pBoneOffsetMatrices[i]=*(pSkinInfo->GetBoneOffsetMatrix(i));
}
hr=GenerateSkinnedMesh(pDev,pMeshContainer);
if(FAILED(hr))
gotoe_Exit;
}
//--------------------------
//赋值MeshContainer
*ppNewMeshContainer=pMeshContainer;
pMeshContainer=NULL;
e_Exit:
SAFE_RELEASE(pDev);
if(pMeshContainer!
=NULL)
DestroyMeshContainer(pMeshContainer);
returnhr;
}
//----------------------------------------------------
//销毁Frame
//----------------------------------------------------
HRESULTGAllocateHierarchy:
:
DestroyFrame(LPD3DXFRAMEpFrameToFree)
{
SAFE_DELETE_ARRAY(pFrameToFree->Name);
SAFE_DELETE(pFrameToFree);
returnS_OK;
}
//----------------------------------------------------
//销毁MeshContainer
//----------------------------------------------------
HRESULTGAllocateHierarchy:
:
DestroyMeshContainer(LPD3DXMESHCONTAINERpMeshContainerToFree)
{
GMeshContainer*pMeshContainer=(GMeshContainer*)pMeshContainerToFree;
SAFE_DELETE_ARRAY(pMeshContainer->Name);
SAFE_DELETE_ARRAY(pMeshContainer->pAdjacency);
SAFE_DELETE_ARRAY(pMeshContainer->pMaterials);
SAFE_DELETE_ARRAY(pMeshContainer->_pBoneOffsetMatrices);
if(pMeshContainer->_ppTexs!
=NULL)
{
for(UINTi=0;iNumMaterials;++i)
{
SAFE_RELEASE(pMeshContainer->_ppTexs[i]);
}
}
SAFE_DELETE_ARRAY(pMeshContainer->_ppTexs);
SAFE_DELETE_ARRAY(pMeshContainer->_ppBoneMatrixPtr);
SAFE_RELEASE(pMeshContainer->_pBoneCombBuf);
SAFE_RELEASE(pMeshContainer->MeshData.pMesh);
SAFE_RELEASE(pMeshContainer->pSkinInfo);
SAFE_RELEASE(pMeshContainer->_pOrigMesh);
SAFE_DELETE(pMeshContainer);
returnS_OK;
}
//----------------------------------------------------
//为MeshContainer生成纹理
//----------------------------------------------------
//pNumBoneMatrixMax为最大受骨骼影响的数目
HRESULTGAllocateHierarchy:
:
GenerateSkinnedMesh(IDirect3DDevice9*pDev,GMeshContainer*pMeshContainer)
{
HRESULThr=S_OK;
D3DCAPS9caps;
pDev->GetDeviceCaps(&caps);
if(pMeshContainer->pSkinInfo==NULL)
returnhr;
SAFE_RELEASE(pMeshContainer->MeshData.pMesh);
SAFE_RELEASE(pMeshContainer->_pBoneCombBuf);
UINTiMaxMatrices=26;
pMeshContainer->_dwNumPaletteEntries=min(iMaxMatrices,pMeshContainer->pSkinInfo->GetNumBones());
DWORDFlags=D3DXMESHOPT_VERTEXCACHE;
Flags|=D3DXMESH_MANAGED;
SAFE_RELEASE(pMeshContainer->MeshData.pMesh);
hr=pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(
pMeshContainer->_pOrigMesh,
Flags,
pMeshContainer->_dwNumPaletteEntries,
pMeshContainer->pAdjacency,
NULL,NULL,NULL,
&pMeshContainer->_dwMaxNumInfl,
&pMeshContainer->_dwNumAttrGroups,
&pMeshContainer->_pBoneCombBuf,
&pMeshContainer->MeshData.pMesh);
if(FAILED(hr))
gotoe_Exit;
DWORDNewFVF=(pMeshContainer->MeshData.pMesh->GetFVF()&D3DFVF_POSITION_MASK)|D3DFVF_NORMAL|D3DFVF_TEX1|D3DFVF_LASTBETA_UBYTE4;
if(NewFVF!
=pMeshContainer->MeshData.pMesh->GetFVF())
{
LPD3DXMESHpMesh;
hr=pMeshContainer->MeshData.pMesh->CloneMeshFVF(pMeshContainer->MeshData.pMesh->GetOption