📄 game_skinmesh.cpp
字号:
#include "Game_User.h"
//-----------------------------------------------------------------------------
// Name: AllocateName()
// Desc: Allocates memory for a string to hold the name of a frame or mesh
//-----------------------------------------------------------------------------
HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName )
{
UINT cbLength;
if (Name != NULL)
{
cbLength = lstrlen(Name) + 1;
*pNewName = new TCHAR[cbLength];
if (*pNewName == NULL)
return E_OUTOFMEMORY;
memcpy(*pNewName, Name, cbLength*sizeof(TCHAR));
}
else
{
*pNewName = NULL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateFrame()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR 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;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateMeshContainer()
// Desc:
//-----------------------------------------------------------------------------
#if (D3D_SDK_VERSION &31) //这里是Directx9.0b的
HRESULT CAllocateHierarchy::CreateMeshContainer(
LPCTSTR Name,
LPD3DXMESHDATA pMeshData,
LPD3DXMATERIAL pMaterials,
LPD3DXEFFECTINSTANCE pEffectInstances,
DWORD NumMaterials,
DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
#else //Direct9.0c
LRESULT CAllocateHierarchy::CreateMeshContainer(
LPCTSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
#endif
{
HRESULT hr;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
UINT NumFaces;
UINT iMaterial;
UINT iBone, cBones;
LPDIRECT3DDEVICE9 pd3dDevice = NULL;
LPD3DXMESH pMesh = NULL;
*ppNewMeshContainer = NULL;
// this sample does not handle patch meshes, so fail when one is found
if (pMeshData->Type != D3DXMESHTYPE_MESH)
{
hr = E_FAIL;
goto e_Exit;
}
// get the pMesh interface pointer out of the mesh data structure
pMesh = pMeshData->pMesh;
// this sample does not FVF compatible meshes, so fail when one is found
if (pMesh->GetFVF() == 0)
{
hr = E_FAIL;
goto e_Exit;
}
// allocate the overloaded structure to return as a D3DXMESHCONTAINER
pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
if (pMeshContainer == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
// make sure and copy the name. All memory as input belongs to caller, interfaces can be addref'd though
hr = AllocateName(Name, &pMeshContainer->Name);
if (FAILED(hr))
goto e_Exit;
pMesh->GetDevice(&pd3dDevice);
NumFaces = pMesh->GetNumFaces();
// if no normals are in the mesh, add them
if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
{
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
// clone the mesh to make room for the normals
hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
pMesh->GetFVF() | D3DFVF_NORMAL,
pd3dDevice, &pMeshContainer->MeshData.pMesh );
if (FAILED(hr))
goto e_Exit;
// get the new pMesh pointer back out of the mesh container to use
// NOTE: we do not release pMesh because we do not have a reference to it yet
pMesh = pMeshContainer->MeshData.pMesh;
// now generate the normals for the pmesh
D3DXComputeNormals( pMesh, NULL );
}
else // if no normals, just add a reference to the mesh for the mesh container
{
pMeshContainer->MeshData.pMesh = pMesh;
pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
pMesh->AddRef();
}
// allocate memory to contain the material information. This sample uses
// the D3D9 materials and texture names instead of the EffectInstance style materials
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 materials provided, copy them
if (NumMaterials > 0)
{
memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
{
if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
{
// TCHAR strTexturePath[MAX_PATH] = _T("");
// DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath), pMeshContainer->pMaterials[iMaterial].pTextureFilename );
if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, pMeshContainer->pMaterials[iMaterial].pTextureFilename,
&pMeshContainer->ppTextures[iMaterial] ) ) )
pMeshContainer->ppTextures[iMaterial] = NULL;
// don't remember a pointer into the dynamic memory, just forget the name after loading
pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
}
}
}
else // if no materials provided, use a default one
{
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 there is skinning information, save off the required data and then setup for HW skinning
if (pSkinInfo != NULL)
{
// first save off the SkinInfo and original mesh data
pMeshContainer->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef();
pMeshContainer->pOrigMesh = pMesh;
m_pSkinMesh->m_pMesh=pMesh;//保存骨骼动化的MESH
pMesh->AddRef();
// Will need an array of offset matrices to move the vertices from the figure space to the bone's space
cBones = pSkinInfo->GetNumBones();
pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
if (pMeshContainer->pBoneOffsetMatrices == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
// get each of the bone offset matrices so that we don't need to get them later
for (iBone = 0; iBone < cBones; iBone++)
{
pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
}
// GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
hr = m_pSkinMesh->GenerateSkinnedMesh(pMeshContainer);
if (FAILED(hr))
goto e_Exit;
}
*ppNewMeshContainer = pMeshContainer;
pMeshContainer = NULL;
e_Exit:
SAFE_RELEASE(pd3dDevice);
// call Destroy function to properly clean up the memory allocated
if (pMeshContainer != NULL)
{
DestroyMeshContainer(pMeshContainer);
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::DestroyFrame()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
SAFE_DELARRAY( pFrameToFree->Name );
SAFE_DELETE( pFrameToFree );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CAllocateHierarchy::DestroyMeshContainer()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
UINT iMaterial;
D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
SAFE_DELARRAY( pMeshContainer->Name );
SAFE_DELARRAY( pMeshContainer->pAdjacency );
SAFE_DELARRAY( pMeshContainer->pMaterials );
SAFE_DELARRAY( pMeshContainer->pBoneOffsetMatrices );
// release all the allocated textures
if (pMeshContainer->ppTextures != NULL)
{
for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
{
SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] );
}
}
SAFE_DELARRAY( pMeshContainer->ppTextures );
SAFE_DELARRAY( 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;
}
CSkinMesh::CSkinMesh(LPDIRECT3DDEVICE9 pD3DDevice)
{
m_pd3dDevice=pD3DDevice;
m_fElapsedTime=0.0f;
m_pd3dDevice->GetDeviceCaps( &m_d3dCaps );
m_bMoving= TRUE;
m_pAnimController = NULL;
m_pFrameRoot = NULL;
m_SkinningMethod = D3DNONINDEXED;
m_pBoneMatrices = NULL;
m_NumBoneMatricesMax = 0;
m_vMax = D3DXVECTOR3(0,0,0);
m_vMin = D3DXVECTOR3(0,0,0);
m_vTarget = D3DXVECTOR3(0,0,0);
m_vTarget = D3DXVECTOR3(0,0,0);
/*m_vPos=D3DXVECTOR3(-1000.0f,25.0f,1110.0f);*/
m_isMoving = false;
m_isdead = false;
m_bLoop = false;
m_isAttacking = false;
m_speed1 = 0;
m_speed2 = 0;
m_CurTime = 0.0f;
m_pXangle=0.0f;
#ifndef NO_USE_LOCALPOSITION
m_vPos = D3DXVECTOR3(0,0,0);
m_fAngle = 0.0f;
m_fScale = 1.0f;
n=1.0f;
#endif
}
CSkinMesh::~CSkinMesh()
{
CAllocateHierarchy Alloc(this);
D3DXFrameDestroy(m_pFrameRoot, &Alloc);
SAFE_RELEASE(m_pAnimController);
}
//读入.x文件,strFileName是.x文件路径, scalex,scalez是做碰撞盒时使用
//scalex为最左下和右上点X方向上缩小数值
//scalez为最左下和右上点Z方向上缩小数值
HRESULT CSkinMesh::LoadFromXFile(char *strFileName, float scalex, float scalez)
{
HRESULT hr;
CAllocateHierarchy Alloc(this);
hr = D3DXLoadMeshHierarchyFromX(strFileName, D3DXMESH_MANAGED, m_pd3dDevice, &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;
if( m_pFrameRoot )
{
D3DXMATRIX matIdentity;
D3DXMatrixIdentity(&matIdentity);
UpdateFrameMatrices(m_pFrameRoot,&matIdentity);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -