AllocateHierarchy.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:12k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //=============================================================================
  2. //Desc: AllocateHierarchy.cpp,CAllocateHierarchy类的实现
  3. //=============================================================================
  4. #include "AllocateHierarchy.h"
  5. //-----------------------------------------------------------------------------
  6. // 拷贝字符串
  7. //-----------------------------------------------------------------------------
  8. HRESULT CAllocateHierarchy::AllocateName( LPCSTR Name, LPSTR *pNewName )
  9. {
  10.     UINT cbLength;
  11.     if( Name != NULL )
  12.     {
  13.         cbLength = (UINT)strlen(Name) + 1;
  14.         *pNewName = new CHAR[cbLength];
  15.         if (*pNewName == NULL)
  16.             return E_OUTOFMEMORY;
  17.         memcpy( *pNewName, Name, cbLength*sizeof(CHAR) );
  18.     }
  19.     else
  20.     {
  21.         *pNewName = NULL;
  22.     }
  23.     return S_OK;
  24. }
  25. //-----------------------------------------------------------------------------
  26. // 生成蒙皮网格模型(含有每个顶点的混合权重、索引和一个骨骼组合表)
  27. //-----------------------------------------------------------------------------
  28. HRESULT CAllocateHierarchy::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer, LPDIRECT3DDEVICE9 pd3dDevice)
  29. {
  30. HRESULT hr = S_OK;
  31. if (pMeshContainer->pSkinInfo == NULL)
  32. return hr;
  33. SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
  34. SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
  35. //获取网格模型索引缓冲区
  36. LPDIRECT3DINDEXBUFFER9 pIB;
  37. if (FAILED(hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB)))
  38. return E_FAIL;
  39. //获取影响一个面(三角形)的矩阵数量
  40. DWORD NumMaxFaceInfl;
  41. hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl);
  42. pIB->Release();
  43. if (FAILED(hr))
  44. return E_FAIL;
  45. //影响一个面的矩阵数量不会超过12
  46. NumMaxFaceInfl = min(NumMaxFaceInfl, 12);
  47. //获取当前设备的能力
  48. D3DCAPS9 d3dCaps;
  49.     pd3dDevice->GetDeviceCaps( &d3dCaps );
  50. //根据当前设备能力和NumMaxFaceInfl, 设置在进行骨骼蒙皮调色时使用骨骼数量的上限
  51. if( (d3dCaps.MaxVertexBlendMatrixIndex+1)/2 < NumMaxFaceInfl )
  52. {
  53. pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones());
  54. pMeshContainer->UseSoftwareVP = true;
  55. }
  56. else
  57. {
  58. pMeshContainer->NumPaletteEntries = min( (d3dCaps.MaxVertexBlendMatrixIndex+1) / 2, 
  59.                                      pMeshContainer->pSkinInfo->GetNumBones() );
  60. pMeshContainer->UseSoftwareVP = false;
  61. }
  62. //生成蒙皮网格模型
  63. hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh
  64.                               ( pMeshContainer->pOrigMesh,
  65.                                 0,
  66.                                 pMeshContainer->NumPaletteEntries,
  67.                                 pMeshContainer->pAdjacency,
  68.                                 NULL, NULL, NULL,
  69.                                 &pMeshContainer->NumInfl,
  70.                                 &pMeshContainer->NumAttributeGroups,
  71.                                 &pMeshContainer->pBoneCombinationBuf,
  72.                                 &pMeshContainer->MeshData.pMesh);
  73. return hr;
  74. }
  75. //-----------------------------------------------------------------------------
  76. // 创建框架, 仅仅是分配内存和初始化,还没有对其成员赋予合适的值
  77. //-----------------------------------------------------------------------------
  78. HRESULT CAllocateHierarchy::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
  79. {
  80.     HRESULT hr = S_OK;
  81.     D3DXFRAME_DERIVED *pFrame;
  82.     *ppNewFrame = NULL;
  83.     pFrame = new D3DXFRAME_DERIVED;  //创建框架结构对象
  84.     if (pFrame == NULL) 
  85.     {
  86.         return E_OUTOFMEMORY;
  87.     }
  88. //为框架指定名称
  89.     hr = AllocateName(Name, (LPSTR*)&pFrame->Name);
  90. if (FAILED(hr))
  91. {
  92. delete pFrame;
  93. return hr;
  94. }
  95. //初始化D3DXFRAME_DERIVED结构其它成员变量
  96.     D3DXMatrixIdentity(&pFrame->TransformationMatrix);
  97.     D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
  98.     pFrame->pMeshContainer = NULL;
  99.     pFrame->pFrameSibling = NULL;
  100.     pFrame->pFrameFirstChild = NULL;
  101.     *ppNewFrame = pFrame;
  102.     pFrame = NULL;
  103. return hr;
  104. }
  105. //-----------------------------------------------------------------------------
  106. // 在这里是调用了成员函数 GenerateSkinnedMesh(pMeshContainer);
  107. // 是在这里加载了蒙皮信息
  108. //-----------------------------------------------------------------------------
  109. HRESULT CAllocateHierarchy::CreateMeshContainer(LPCSTR Name, 
  110.                                                 CONST D3DXMESHDATA *pMeshData,
  111.                                                 CONST D3DXMATERIAL *pMaterials, 
  112.                                                 CONST D3DXEFFECTINSTANCE *pEffectInstances, 
  113.                                                 DWORD NumMaterials, 
  114.                                                 CONST DWORD *pAdjacency, 
  115.                                                 LPD3DXSKININFO pSkinInfo, 
  116.                                                 LPD3DXMESHCONTAINER *ppNewMeshContainer) 
  117. {
  118.     HRESULT hr;
  119.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
  120.     UINT NumFaces;       //网格中的面数,在填充网格容器结构的邻接信息成员时使用
  121.     UINT iMaterial;      //纹理操作时的循环变量
  122.     UINT cBones;         //当前网格模型骨骼总数
  123.     LPDIRECT3DDEVICE9 pd3dDevice = NULL;
  124.     LPD3DXMESH pMesh    = NULL;
  125.     *ppNewMeshContainer = NULL;
  126.     if (pMeshData->Type != D3DXMESHTYPE_MESH)
  127.     {
  128.         return E_FAIL;
  129.     }
  130.     pMesh = pMeshData->pMesh;
  131.     if (pMesh->GetFVF() == 0)
  132.     {
  133.         return E_FAIL;
  134.     }
  135. //为网格容器分配内存
  136.     pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
  137.     if (pMeshContainer == NULL)
  138.     {
  139.         return E_OUTOFMEMORY;
  140.     }
  141.     memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
  142. //填充网格容器结构D3DXMESHCONTAINER_DERIVED的成员
  143. //为网格指定名称
  144. hr = AllocateName(Name, &pMeshContainer->Name);
  145. if (FAILED(hr))
  146. {
  147. DestroyMeshContainer(pMeshContainer);
  148. return hr;
  149. }      
  150.     pMesh->GetDevice(&pd3dDevice);
  151.     NumFaces = pMesh->GetNumFaces();
  152. //确保网格顶点包含法线
  153.     if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
  154.     {
  155.         pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  156.         hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  157.                       pMesh->GetFVF() | D3DFVF_NORMAL, 
  158.                       pd3dDevice, 
  159.                       &pMeshContainer->MeshData.pMesh );
  160. if (FAILED(hr))
  161. {
  162. SAFE_RELEASE(pd3dDevice);
  163. DestroyMeshContainer(pMeshContainer);
  164. return hr;
  165. }
  166. pMesh = pMeshContainer->MeshData.pMesh;
  167.         D3DXComputeNormals( pMesh, NULL );
  168.     }
  169.     else 
  170.     {
  171.         pMeshContainer->MeshData.pMesh = pMesh;
  172.         pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  173.         pMesh->AddRef();
  174.     }
  175.     //为网格模型准备材质和纹理
  176.     pMeshContainer->NumMaterials = max(1, NumMaterials); 
  177.     pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
  178.     pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
  179.     pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
  180.     if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL)
  181. || (pMeshContainer->ppTextures == NULL))
  182. {
  183. hr = E_OUTOFMEMORY;
  184. SAFE_RELEASE(pd3dDevice);
  185. DestroyMeshContainer(pMeshContainer);
  186. return hr;
  187. }
  188. memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);  
  189.     memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
  190.    if (NumMaterials > 0)            
  191.     {    
  192.         //复制材质属性, 设置材质环境光属性
  193.         memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials); 
  194. pMeshContainer->pMaterials->MatD3D.Ambient = pMeshContainer->pMaterials->MatD3D.Diffuse;
  195. // pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[NumMaterials];
  196.        
  197. //提取纹理文件, 创建纹理对象
  198.         for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++) 
  199.         {
  200.             if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
  201.             {
  202.                 if( FAILED( D3DXCreateTextureFromFileA( pd3dDevice, 
  203. (pMeshContainer->pMaterials[iMaterial].pTextureFilename),
  204.                     &pMeshContainer->ppTextures[iMaterial] ) ) )
  205.                     pMeshContainer->ppTextures[iMaterial] = NULL;
  206.                 pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
  207. }
  208.         }
  209.     }
  210.     else
  211.     {
  212.         pMeshContainer->pMaterials[0].pTextureFilename = NULL;
  213.         memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
  214.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
  215.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
  216.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
  217.         pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
  218.     }
  219. // SAFE_RELEASE(pd3dDevice);
  220.     //如果当前网格包含蒙皮信息
  221.     if (pSkinInfo != NULL)
  222.     {
  223. //加载蒙皮网格信息
  224.         pMeshContainer->pSkinInfo = pSkinInfo; 
  225.         pSkinInfo->AddRef();
  226. //保留原网格信息
  227.         pMeshContainer->pOrigMesh = pMesh;
  228.         pMesh->AddRef();
  229. //获取骨骼数量
  230.         cBones = pSkinInfo->GetNumBones();
  231. //为每块骨骼分配保存初始变换矩阵的内存空间
  232.         pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
  233.         if (pMeshContainer->pBoneOffsetMatrices == NULL) 
  234.         {
  235. hr = E_OUTOFMEMORY;
  236. DestroyMeshContainer(pMeshContainer);
  237. return hr;
  238. }
  239.         
  240. //保存每块骨骼的初始变换矩阵
  241.         for (UINT iBone = 0; iBone < cBones; iBone++)
  242.         {
  243.             pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
  244.         }
  245. //生成蒙皮网格模型
  246.         hr = GenerateSkinnedMesh(pMeshContainer, pd3dDevice); 
  247.         if (FAILED(hr))
  248. {
  249. DestroyMeshContainer(pMeshContainer);
  250. return hr;
  251. }
  252.     }
  253.     *ppNewMeshContainer = pMeshContainer;
  254.     pMeshContainer = NULL;
  255.     return hr;
  256. }
  257. //-----------------------------------------------------------------------------
  258. // 释放框架
  259. //-----------------------------------------------------------------------------
  260. HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) 
  261. {
  262. if(pFrameToFree != NULL)
  263. {
  264. SAFE_DELETE_ARRAY( pFrameToFree->Name );
  265. SAFE_DELETE( pFrameToFree );
  266. }
  267.     return S_OK; 
  268. }
  269. //-----------------------------------------------------------------------------
  270. // 释放模型容器
  271. //-----------------------------------------------------------------------------
  272. HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
  273. {
  274. if(pMeshContainerBase == NULL)
  275. return S_OK;
  276.     UINT iMaterial;
  277. // 先转为扩展型以免内存泄漏
  278.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
  279.     SAFE_DELETE_ARRAY( pMeshContainer->Name );
  280.     SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
  281.     SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
  282.     SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices );
  283.     if (pMeshContainer->ppTextures != NULL)
  284.     {
  285.         for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
  286.         {
  287.             SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] );
  288.         }
  289.     }
  290.     SAFE_DELETE_ARRAY( pMeshContainer->ppTextures );
  291.     SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs );
  292.     SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
  293.     SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
  294.     SAFE_RELEASE( pMeshContainer->pSkinInfo );
  295.     SAFE_RELEASE( pMeshContainer->pOrigMesh );
  296.     SAFE_DELETE( pMeshContainer );
  297.     return S_OK;
  298. }