📄 game_skinmesh.cpp
字号:
#include "..\Include\Game_SkinMesh.h"
HRESULT AllocateName( LPCSTR Name, LPSTR *pNewName ){
UINT cbLength;
if( Name != NULL ){
cbLength = (UINT)strlen(Name) + 1;
*pNewName = new CHAR[cbLength];
if (*pNewName == NULL)
return E_OUTOFMEMORY;
memcpy( *pNewName, Name, cbLength*sizeof(CHAR) );
}
else{
*pNewName = NULL;
}
return S_OK;
}
HRESULT CAllocateHierarchy::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame){
HRESULT hr = S_OK;
D3DXFRAME_DERIVED *pFrame;
*ppNewFrame = NULL;
pFrame = new D3DXFRAME_DERIVED;
if (pFrame == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
//初试化帧名字
hr = AllocateName(Name, &pFrame->Name);
if (FAILED(hr))
goto e_Exit;
// initialize other data members of the frame
//初始化帧的数据
D3DXMatrixIdentity(&pFrame->TransformationMatrix);
D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
pFrame->pMeshContainer = NULL;
pFrame->pFrameSibling = NULL;
pFrame->pFrameFirstChild = NULL;
*ppNewFrame = pFrame;
pFrame = NULL;
e_Exit:
delete pFrame;
return hr;
}
LRESULT CAllocateHierarchy::CreateMeshContainer(
LPCSTR Name, //网格容器名
CONST D3DXMESHDATA *pMeshData, //网格数据
CONST D3DXMATERIAL *pMaterials, //材质
CONST D3DXEFFECTINSTANCE *pEffectInstances, //特效
DWORD NumMaterials, //传入的材质数
CONST DWORD *pAdjacency, //传入的邻接三角形面的信息
LPD3DXSKININFO pSkinInfo, //蒙皮信息
LPD3DXMESHCONTAINER *ppNewMeshContainer){ //下一个的指针
HRESULT hr;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
UINT NumFaces;//网格中的面数,在填充网格容器结构的邻接信息成员时使用
UINT iMaterial;//纹理操作时的循环变量
UINT iBone, cBones;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;
*ppNewMeshContainer = NULL;
if (pMeshData->Type != D3DXMESHTYPE_MESH){
hr = E_FAIL;
goto e_Exit;
}
pMesh = pMeshData->pMesh;
if (pMesh->GetFVF()==0){
hr = E_FAIL;
goto e_Exit;
}
//为网格容器分配内存
pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
if (pMeshContainer == NULL){
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
//填充网格容器结构D3DXMESHCONTAINER_DERIVED的成员
hr = AllocateName(Name, &pMeshContainer->Name);
if (FAILED(hr))
goto e_Exit;
//取得网格所关联的D3D设备
pMesh->GetDevice(&pd3dDevice);
NumFaces = pMesh->GetNumFaces();
//确保网格顶点包含法线
//取得网格的三角形面数
//如果没有法向量,则添加它们
if ((pMesh->GetFVF() & D3DFVF_NORMAL)){
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
//用复制的方法插入法向量数据方式
hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
pMesh->GetFVF() | D3DFVF_NORMAL,
pd3dDevice, &pMeshContainer->MeshData.pMesh );
if (FAILED(hr))
goto e_Exit;
pMesh = pMeshContainer->MeshData.pMesh;
//在网格容器中生成法向量
D3DXComputeNormals( pMesh, NULL );
}
else{//如果网格中已包含法向量数据
//为创建的网格容器添加网格数据
pMeshContainer->MeshData.pMesh = pMesh;
//设置网格容器的类型
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
//引用计数加1
pMesh->AddRef();
}
//为网格模型准备材质和纹理
pMeshContainer->NumMaterials = max(1, NumMaterials);
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
if ((pMeshContainer->pAdjacency == NULL)||(pMeshContainer->pMaterials == NULL)){
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
//如果有材质数据,生成纹理对象,并放入扩展后的网格容器中
if (NumMaterials > 0) {
//复制材质属性,设置材质环境光属性
memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
//提取纹理文件,创建纹理对象
for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++){
if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL){
WCHAR wszBuf[MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, pMeshContainer->pMaterials[iMaterial].pTextureFilename, -1, wszBuf, MAX_PATH );
wszBuf[MAX_PATH - 1] = L'\0';
if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, wszBuf,
&pMeshContainer->ppTextures[iMaterial] ) ) )
pMeshContainer->ppTextures[iMaterial] = NULL;
pMeshContainer->pMaterials[iMaterial].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;
}
//存在蒙皮信息
if (pSkinInfo != NULL){
pMeshContainer->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef();
pMeshContainer->pOrigMesh = pMesh;//备份指针
pMesh->AddRef();
cBones = pSkinInfo->GetNumBones();//取得总骨骼数
//创建骨骼的权重矩阵
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
if (pMeshContainer->pBoneOffsetMatrices == NULL){
hr = E_OUTOFMEMORY;
goto e_Exit;
}
//将骨骼的权重矩阵放置在性的位置处
for (iBone = 0; iBone < cBones; iBone++){
pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
}
//生成蒙皮网格
hr = m_pSkinMesh->GenerateSkinnedMesh(pMeshContainer);
if (FAILED(hr))
goto e_Exit;
}
//返回网格容器的指针
*ppNewMeshContainer = pMeshContainer;
//释放无用指针
pMeshContainer = NULL;
e_Exit:
SAFE_RELEASE(pd3dDevice);
//释放网格容器
if (pMeshContainer != NULL){
DestroyMeshContainer(pMeshContainer);
}
return hr;
}
HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) {
SAFE_DELETE_ARRAY( pFrameToFree->Name );
SAFE_DELETE( pFrameToFree );
return S_OK;
}
HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase){
UINT iMaterial;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
SAFE_DELETE_ARRAY( pMeshContainer->Name );
SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices );
//释放所有纹理对象
if (pMeshContainer->ppTextures != NULL){
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++){
SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] );
}
}
SAFE_DELETE_ARRAY( pMeshContainer->ppTextures );
SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs );
SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
SAFE_RELEASE( pMeshContainer->pSkinInfo );
SAFE_RELEASE( pMeshContainer->pOrigMesh );
SAFE_DELETE( pMeshContainer );
return S_OK;
}
Game_SkinMesh::Game_SkinMesh():m_vMax(0,0,0),m_vMin(0,0,0){
m_fElapsedTime=0.0f;
g_sGlobal.g_pDevice->GetDeviceCaps( &m_d3dCaps );
m_bMoving=TRUE;
m_pAnimController = NULL;
m_pFrameRoot = NULL;
m_SkinningMethod =D3DINDEXED;
m_pBoneMatrices = NULL;
m_NumBoneMatricesMax = 0;
m_bnextAnim=false;
m_vMax=D3DXVECTOR3(0,0,0);
m_vMin=D3DXVECTOR3(0,0,0);
m_vTarget = D3DXVECTOR3(0,0,0);
m_bMoving=TRUE;
m_MouseMove=false;
m_isMoving = false;
m_bLoop = false;
m_isdead = false;
m_isAttacking = false;
m_BoundingBox=false;
m_speed1 = 100.0f;
m_speed2 = 3.0f;
m_CurTime = 0.0;
m_flotFrameTime = 0;
m_fDeathTime = 0;
m_pAABBMesh=NULL;
m_vPos= D3DXVECTOR3(0,0,0);
m_fAngle=0.0f;
m_fScale=1.0f;
}
Game_SkinMesh::~Game_SkinMesh(){
CAllocateHierarchy Alloc(this);
D3DXFrameDestroy(m_pFrameRoot, &Alloc);
SAFE_RELEASE(m_pAnimController);
}
HRESULT Game_SkinMesh::LoadFromXFile(WCHAR * strFileName,float scalex, float scalez){
HRESULT hr;
CAllocateHierarchy Alloc(this);
hr = D3DXLoadMeshHierarchyFromX(strFileName, D3DXMESH_MANAGED, g_sGlobal.g_pDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController);
if (FAILED(hr))
return hr;
hr = SetupBoneMatrixPointers(m_pFrameRoot);
if (FAILED(hr))
return hr;
hr = D3DXFrameCalculateBoundingSphere(m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius);
if (FAILED(hr))
return hr;
D3DXMATRIXA16 matWorld,matWorld2,matWorld1;
D3DXMatrixRotationZ(&matWorld2,m_fAngle+D3DX_PI);
D3DXMatrixScaling(&matWorld,m_fScale,m_fScale,m_fScale);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixRotationX(&matWorld2,4.7f);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixRotationY(&matWorld2,1.5f);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
D3DXMatrixTranslation( &matWorld2,m_vPos.x,m_vPos.y,m_vPos.z);
D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
g_sGlobal.g_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
if(m_pFrameRoot){
D3DXMATRIX matIdentity;
D3DXMatrixIdentity(&matIdentity);
UpdateFrameMatrices(m_pFrameRoot,&matWorld);
CalculateStaticBondingBox(m_pFrameRoot,&m_vMin,&m_vMax);
m_vMin.x = m_vMin.x*0.5;
m_vMax.x = m_vMax.x*0.5;
m_vMin.z = m_vMin.z*0.5;
m_vMax.z = m_vMax.z*0.5;
D3DXCreateMeshFVF(4,8,D3DXMESH_MANAGED,D3DFVF_XYZ|D3DFVF_TEX1,g_sGlobal.g_pDevice,&m_pAABBMesh);
}
return S_OK;
}
//绑定盒子
HRESULT Game_SkinMesh::CalculateStaticBondingBox(LPD3DXFRAME pFrameBase, const LPD3DXVECTOR3 pVmin,
const LPD3DXVECTOR3 pVmax){
static LPD3DXMESH pMesh;
static LPD3DXMATRIX pMat;
static D3DXVECTOR3 *pV;
static D3DXVECTOR3 vTransformed;
static D3DXMATRIX matTemp;
// D3DXMATRIX **ppMat;
D3DXMESHCONTAINER_DERIVED *pMeshContainer= (D3DXMESHCONTAINER_DERIVED*)pFrameBase->pMeshContainer;
//这里如果直接使用Frame自带的CombinedTransformationMatrix,将会得到模型静止状态的方盒
while (pMeshContainer != NULL ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -