📄 xskinmesh.cpp
字号:
}
}
if (cInfl > m_d3dCaps.MaxVertexBlendMatrices)
{
break;
}
}
// if there is both HW and SW, add the Software Processing flag
if (pMesh->m_iAttrSplit < pMesh->m_cpattr)
{
LPD3DXMESH pMeshTmp;
hr = pMesh->m_pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pMesh->m_pMesh->GetOptions(),
pMesh->m_pMesh->GetFVF(),
m_pD3DDevice, &pMeshTmp);
if (FAILED(hr))
{
SAFE_RELEASE( pMeshTmp );
return FALSE;
}
pMesh->m_pMesh->Release();
pMesh->m_pMesh = pMeshTmp;
pMeshTmp = NULL;
}
}
else
{
pMesh->m_iAttrSplit = pMesh->m_cpattr;
}
}
else if (m_nMethod == D3DINDEXED)
{
DWORD maxFaceInfl;
DWORD flags = D3DXMESHOPT_VERTEXCACHE;
hr = pMesh->m_pSkinMesh->GetMaxFaceInfluences(&maxFaceInfl);
if (FAILED(hr))
return FALSE;
// 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri)
// can be handled
maxFaceInfl = min(maxFaceInfl, 12);
if (m_d3dCaps.MaxVertexBlendMatrixIndex + 1 < maxFaceInfl)
{
// HW does not support indexed vertex blending. Use SW instead
pMesh->m_paletteSize = min(256, pMesh->m_pSkinMesh->GetNumBones());
pMesh->m_bUseSW = true;
flags |= D3DXMESH_SYSTEMMEM;
}
else
{
pMesh->m_paletteSize = min(m_d3dCaps.MaxVertexBlendMatrixIndex + 1, pMesh->m_pSkinMesh->GetNumBones());
pMesh->m_bUseSW = FALSE;
flags |= D3DXMESH_MANAGED;
}
hr = pMesh->m_pSkinMesh->ConvertToIndexedBlendedMesh(flags, pMesh->m_rgiAdjacency, pMesh->m_paletteSize, NULL,
&pMesh->m_cpattr, &pMesh->m_pBoneCombinationBuf, NULL, NULL, &pMesh->m_pMesh);
if (FAILED(hr))
return FALSE;
// Here we are talking of max vertex influence which we determine from
// the FVF of the returned mesh
if ((pMesh->m_pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
{
pMesh->m_maxFaceInfl = ((pMesh->m_pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2;
}
else
{
pMesh->m_maxFaceInfl = 1;
}
}
else if (m_nMethod == SOFTWARE)
{
hr = pMesh->m_pSkinMesh->GenerateSkinnedMesh(
D3DXMESH_WRITEONLY, // options
0.0f, // minimum bone weight allowed
pMesh->m_rgiAdjacency, // adjacency of in-mesh
NULL, // adjacency of out-mesh
NULL, // face remap array
NULL, // vertex remap buffer
&pMesh->m_pMesh ); // out-mesh
if (FAILED(hr))
return FALSE;
hr = pMesh->m_pMesh->GetAttributeTable(NULL, &pMesh->m_cpattr);
if (FAILED(hr))
return FALSE;
SAFE_DELETE_ARRAY(pMesh->m_pAttrTable);
pMesh->m_pAttrTable = new D3DXATTRIBUTERANGE[pMesh->m_cpattr];
if (pMesh->m_pAttrTable == NULL)
{
return FALSE;
}
hr = pMesh->m_pMesh->GetAttributeTable(pMesh->m_pAttrTable, NULL);
if (FAILED(hr))
return FALSE;
hr = pMesh->m_pSkinMesh->GetMaxFaceInfluences(&pMesh->m_maxFaceInfl);
if (FAILED(hr))
return FALSE;
// Allocate space for blend matrices
m_pBoneMatrices = new D3DXMATRIXA16[m_maxBones];
if (m_pBoneMatrices == NULL)
{
return FALSE;
}
}
pMesh->m_Method = m_nMethod;
return TRUE;
}
BOOL XSKINMESH::ReadSkinMesh(IDirectXFileData *pDataObj, Frame *pParentFrame)
{
HRESULT hr;
LPD3DXBUFFER pbufMaterials = NULL;
LPD3DXBUFFER pbufAdjacency = NULL;
LPDWORD pAdjacencyIn = NULL;
Mesh *pMesh = NULL;
DWORD cchName;
UINT nFaces;
UINT nMaterial;
pMesh = new Mesh();
if (pMesh == NULL)
{
return FALSE;
}
hr = pDataObj->GetName(NULL, &cchName);
if (FAILED(hr))
{
SAFE_DELETE(pMesh);
return FALSE;
}
if (cchName > 0)
{
pMesh->m_szName = new TCHAR[cchName];
if (pMesh->m_szName == NULL)
{
return FALSE;
}
hr = pDataObj->GetName(pMesh->m_szName, &cchName);
if (FAILED(hr))
{
SAFE_DELETE(pMesh);
return FALSE;
}
}
else
{
pMesh->m_szName = new TCHAR[9];
strcpy(pMesh->m_szName,"$Mesh$");
}
hr = D3DXLoadSkinMeshFromXof(pDataObj, m_dwMeshOptions, m_pD3DDevice, &pbufAdjacency, &pbufMaterials, &pMesh->m_cMaterials,
&pMesh->m_pBoneNamesBuf, &pMesh->m_pBoneOffsetBuf, &pMesh->m_pSkinMesh);
if (FAILED(hr))
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
if (hr == D3DXERR_LOADEDMESHASNODATA) return TRUE;
return FALSE;
}
// Calculate the bounding box and sphere
LPBYTE Ptr;
if(SUCCEEDED(pMesh->m_pSkinMesh->LockVertexBuffer(D3DLOCK_READONLY, (BYTE**)&Ptr)))
{
D3DXComputeBoundingBox((void*)Ptr, pMesh->m_pSkinMesh->GetNumVertices(), pMesh->m_pSkinMesh->GetFVF(), &pMesh->m_vMin, &pMesh->m_vMax);
D3DXComputeBoundingSphere((void*)Ptr, pMesh->m_pSkinMesh->GetNumVertices(), pMesh->m_pSkinMesh->GetFVF(), &D3DXVECTOR3(0.0f,0.0f,0.0f), &pMesh->m_fRadius);
m_vMin.x = min(m_vMin.x, pMesh->m_vMin.x);
m_vMin.y = min(m_vMin.y, pMesh->m_vMin.y);
m_vMin.z = min(m_vMin.z, pMesh->m_vMin.z);
m_vMax.x = max(m_vMax.x, pMesh->m_vMax.x);
m_vMax.y = max(m_vMax.y, pMesh->m_vMax.y);
m_vMax.z = max(m_vMax.z, pMesh->m_vMax.z);
m_fRadius = max(m_fRadius, pMesh->m_fRadius);
pMesh->m_pSkinMesh->UnlockVertexBuffer();
}
nFaces = pMesh->m_pSkinMesh->GetNumFaces();
pAdjacencyIn = static_cast<LPDWORD>(pbufAdjacency->GetBufferPointer());
pMesh->m_rgiAdjacency = new DWORD[nFaces * 3];
if (pMesh->m_rgiAdjacency == NULL)
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return FALSE;
}
memcpy(pMesh->m_rgiAdjacency, pAdjacencyIn, nFaces * 3 * sizeof(DWORD));
// Process skinning data
if ( (pMesh->m_numBoneComb = pMesh->m_pSkinMesh->GetNumBones()))
{
// Update max bones of any mesh in the app
m_maxBones = max(pMesh->m_pSkinMesh->GetNumBones(), m_maxBones);
pMesh->m_pBoneMatrix = new D3DXMATRIXA16*[pMesh->m_pSkinMesh->GetNumBones()];
if (pMesh->m_pBoneMatrix == NULL)
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return FALSE;
}
pMesh->m_pBoneOffsetMat = reinterpret_cast<D3DXMATRIXA16*>(pMesh->m_pBoneOffsetBuf->GetBufferPointer());
hr = MakeSkinMesh(pMesh);
if (FAILED(hr))
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return FALSE;
}
}
else
{
pMesh->m_pSkinMesh->GetOriginalMesh(&(pMesh->m_pMesh));
pMesh->m_pSkinMesh->Release();
pMesh->m_pSkinMesh = NULL;
pMesh->m_cpattr = pMesh->m_cMaterials;
}
if ((pbufMaterials == NULL) || (pMesh->m_cMaterials == 0))
{
pMesh->m_rgMaterials = new D3DMATERIAL8[1];
pMesh->m_pTextures = new LPDIRECT3DTEXTURE8[1];
if (pMesh->m_rgMaterials == NULL || pMesh->m_pTextures == NULL)
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return FALSE;
}
memset(pMesh->m_rgMaterials, 0, sizeof(D3DMATERIAL8));
pMesh->m_rgMaterials[0].Diffuse.r = 0.5f;
pMesh->m_rgMaterials[0].Diffuse.g = 0.5f;
pMesh->m_rgMaterials[0].Diffuse.b = 0.5f;
pMesh->m_rgMaterials[0].Specular = pMesh->m_rgMaterials[0].Diffuse;
pMesh->m_pTextures[0] = NULL;
}
else
{
pMesh->m_rgMaterials = new D3DMATERIAL8[pMesh->m_cMaterials];
pMesh->m_pTextures = new LPDIRECT3DTEXTURE8[pMesh->m_cMaterials];
if (pMesh->m_rgMaterials == NULL || pMesh->m_pTextures == NULL)
{
SAFE_DELETE(pMesh);
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return FALSE;
}
LPD3DXMATERIAL pMaterials = (LPD3DXMATERIAL)pbufMaterials->GetBufferPointer();
for (nMaterial = 0; nMaterial < pMesh->m_cMaterials; nMaterial++)
{
pMesh->m_rgMaterials[nMaterial] = pMaterials[nMaterial].MatD3D;
pMesh->m_pTextures[nMaterial] = NULL;
if (pMaterials[nMaterial].pTextureFilename != NULL)
{
TCHAR szPath[MAX_PATH];
if ( m_strFilePath )
{
wsprintf(szPath,"%s%s",m_strFilePath,pMaterials[nMaterial].pTextureFilename);
}
hr = D3DXCreateTextureFromFile(m_pD3DDevice, szPath, &(pMesh->m_pTextures[nMaterial]));
if (FAILED(hr))
pMesh->m_pTextures[nMaterial] = NULL;
}
}
}
// add the mesh to the parent frame
pMesh->m_pNext = pParentFrame->m_pMeshList;
pParentFrame->m_pMeshList = pMesh;
pMesh = NULL;
SAFE_RELEASE(pbufAdjacency);
SAFE_RELEASE(pbufMaterials);
return TRUE;
}
VOID XSKINMESH::AnimationMesh(FLOAT fTime, const D3DXMATRIXA16 & matCur,FLOAT fSpeed)
{
if ( m_pAnimationCur )
{
Animation *pAnim = m_pAnimationCur->m_pAnim;
while ( pAnim )
{
pAnim->SetAnimationCyc( fTime,fSpeed );
pAnim = pAnim->m_pNext;
}
}
UpdateFrame(m_pRootFrame, &matCur );
}
BOOL XSKINMESH::ReadMeshHierarchy(TCHAR * strFileName,
LPDIRECT3DDEVICE8 device,
DWORD dwMeshOptions,
UINT nDrawMethod)
{
IDirectXFile *pDXFile = NULL;
IDirectXFileEnumObject *pDXEnumObj = NULL;
IDirectXFileData *pDXDataObj = NULL;
SAFE_DELETE( m_pRootFrame );
m_pD3DDevice = device;
m_nMethod = nDrawMethod;
m_dwMeshOptions = dwMeshOptions;
if (FAILED(m_pD3DDevice->GetDeviceCaps(&m_d3dCaps)))
return FALSE;
if ( FAILED(DirectXFileCreate( &pDXFile ) ))
return FALSE;
if ( FAILED(pDXFile->RegisterTemplates( (LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES) ))
return FALSE;
if ( FAILED(pDXFile->CreateEnumObject( (LPVOID)strFileName, DXFILELOAD_FROMFILE, &pDXEnumObj) ))
return FALSE;
m_pRootFrame = new Frame;
// Enum DataObjects
while ( SUCCEEDED(pDXEnumObj->GetNextDataObject(&pDXDataObj) ))
{
ParseXFileData( pDXDataObj, m_pRootFrame );
SAFE_RELEASE( pDXDataObj );
}
LinkAllMesh(m_pRootFrame);
SetMeshBones(m_pRootFrame);
SetMeshAnimations(m_pRootFrame);
m_pAnimationCur = FindAnimationSet("Idle");
SAFE_RELEASE( pDXEnumObj );
SAFE_RELEASE( pDXFile );
return TRUE;
}
Frame * XSKINMESH::ReadFrame(IDirectXFileData *pDataObj, Frame *pParentFrame)
{
TCHAR *pName = NULL;
DWORD cchName;
if ( FAILED(pDataObj->GetName(NULL, &cchName ) ))
return NULL;
if ( cchName )
{
if ( NULL == (pName = new TCHAR[cchName]) )
return NULL;
pDataObj->GetName(pName, &cchName);
}else
{
pName = new TCHAR[9];
strcpy(pName, "$Frame$");
}
Frame *pFrame = new Frame;
pFrame->m_pName = pName;
pName = NULL;
pFrame->m_pParent = pParentFrame;
pFrame->m_pSibling = pParentFrame->m_pChild;
pParentFrame->m_pChild = pFrame;
return pFrame;
}
BOOL XSKINMESH::ParseXFileData(IDirectXFileData *pDataObj, Frame *pParentFrame)
{
const GUID *pType = NULL;
Frame *pSubFrame = pParentFrame;
// Get the type of the DataObject
if ( FAILED(pDataObj->GetType(&pType) ))
return FALSE;
if ( *pType == TID_D3DRMFrame )
{
pSubFrame = ReadFrame(pDataObj,pParentFrame);
}
else if ( *pType == TID_D3DRMMesh )
{
ReadSkinMesh( pDataObj, pParentFrame );
}
else if ( *pType == TID_D3DRMAnimationSet )
{
ReadAnimationSet( pDataObj, pParentFrame );
}
else if ( *pType == TID_D3DRMFrameTransformMatrix )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -