SkinMesh.cpp
上传用户:cjwanglu
上传日期:2013-07-10
资源大小:4744k
文件大小:36k
源码类别:

游戏

开发平台:

Visual C++

  1. // SkinMesh.cpp: implementation of the CSkinMesh class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SkinMesh.h"
  6. //-----------------------------------------------------------------------------
  7. // Name: AllocateName()
  8. // Desc: Allocates memory for a string to hold the name of a frame or mesh
  9. //-----------------------------------------------------------------------------
  10. HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName )
  11. {
  12.     UINT cbLength;
  13.     if (Name != NULL)
  14.     {
  15.         cbLength = lstrlen(Name) + 1;
  16.         *pNewName = new TCHAR[cbLength];
  17.         if (*pNewName == NULL)
  18.             return E_OUTOFMEMORY;
  19.         memcpy(*pNewName, Name, cbLength*sizeof(TCHAR));
  20.     }
  21.     else
  22.     {
  23.         *pNewName = NULL;
  24.     }
  25.     return S_OK;
  26. }
  27. //-----------------------------------------------------------------------------
  28. // Name: CAllocateHierarchy::CreateFrame()
  29. // Desc: 
  30. //-----------------------------------------------------------------------------
  31. HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame)
  32. {
  33.     HRESULT hr = S_OK;
  34.     D3DXFRAME_DERIVED *pFrame;
  35.     *ppNewFrame = NULL;
  36.     pFrame = new D3DXFRAME_DERIVED;
  37.     if (pFrame == NULL)
  38.     {
  39.         hr = E_OUTOFMEMORY;
  40.         goto e_Exit;
  41.     }
  42.     hr = AllocateName(Name, &pFrame->Name);
  43.     if (FAILED(hr))
  44.         goto e_Exit;
  45.     // initialize other data members of the frame
  46.     D3DXMatrixIdentity(&pFrame->TransformationMatrix);
  47.     D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
  48.     pFrame->pMeshContainer = NULL;
  49.     pFrame->pFrameSibling = NULL;
  50.     pFrame->pFrameFirstChild = NULL;
  51.     *ppNewFrame = pFrame;
  52.     pFrame = NULL;
  53. e_Exit:
  54.     delete pFrame;
  55.     return hr;
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Name: CAllocateHierarchy::CreateMeshContainer()
  59. // Desc: 
  60. //-----------------------------------------------------------------------------
  61. #if (D3D_SDK_VERSION &31) //这里是Directx9.0b的
  62. HRESULT CAllocateHierarchy::CreateMeshContainer(
  63. LPCTSTR Name, 
  64. LPD3DXMESHDATA pMeshData,
  65. LPD3DXMATERIAL pMaterials, 
  66. LPD3DXEFFECTINSTANCE pEffectInstances, 
  67. DWORD NumMaterials, 
  68. DWORD *pAdjacency, 
  69. LPD3DXSKININFO pSkinInfo, 
  70. LPD3DXMESHCONTAINER *ppNewMeshContainer) 
  71. #else //Direct9.0c
  72. LRESULT CAllocateHierarchy::CreateMeshContainer(
  73. LPCTSTR Name, 
  74. CONST D3DXMESHDATA *pMeshData,
  75. CONST D3DXMATERIAL *pMaterials, 
  76. CONST D3DXEFFECTINSTANCE *pEffectInstances, 
  77. DWORD NumMaterials, 
  78. CONST DWORD *pAdjacency, 
  79. LPD3DXSKININFO pSkinInfo, 
  80. LPD3DXMESHCONTAINER *ppNewMeshContainer) 
  81. #endif
  82. {
  83.     HRESULT hr;
  84.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
  85.     UINT NumFaces;
  86.     UINT iMaterial;
  87.     UINT iBone, cBones;
  88.     LPDIRECT3DDEVICE9 pd3dDevice = NULL;
  89.     LPD3DXMESH pMesh = NULL;
  90.     *ppNewMeshContainer = NULL;
  91.     // this sample does not handle patch meshes, so fail when one is found
  92.     if (pMeshData->Type != D3DXMESHTYPE_MESH)
  93.     {
  94.         hr = E_FAIL;
  95.         goto e_Exit;
  96.     }
  97.     // get the pMesh interface pointer out of the mesh data structure
  98.     pMesh = pMeshData->pMesh;
  99.     // this sample does not FVF compatible meshes, so fail when one is found
  100.     if (pMesh->GetFVF() == 0)
  101.     {
  102.         hr = E_FAIL;
  103.         goto e_Exit;
  104.     }
  105.     // allocate the overloaded structure to return as a D3DXMESHCONTAINER
  106.     pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
  107.     if (pMeshContainer == NULL)
  108.     {
  109.         hr = E_OUTOFMEMORY;
  110.         goto e_Exit;
  111.     }
  112.     memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
  113.     // make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
  114.     hr = AllocateName(Name, &pMeshContainer->Name);
  115.     if (FAILED(hr))
  116.         goto e_Exit;        
  117.     pMesh->GetDevice(&pd3dDevice);
  118.     NumFaces = pMesh->GetNumFaces();
  119.     // if no normals are in the mesh, add them
  120.     if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
  121.     {
  122.         pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  123.         // clone the mesh to make room for the normals
  124.         hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  125. pMesh->GetFVF() | D3DFVF_NORMAL, 
  126. pd3dDevice, &pMeshContainer->MeshData.pMesh );
  127.         if (FAILED(hr))
  128.             goto e_Exit;
  129.         // get the new pMesh pointer back out of the mesh container to use
  130.         // NOTE: we do not release pMesh because we do not have a reference to it yet
  131.         pMesh = pMeshContainer->MeshData.pMesh;
  132.         // now generate the normals for the pmesh
  133.         D3DXComputeNormals( pMesh, NULL );
  134.     }
  135.     else  // if no normals, just add a reference to the mesh for the mesh container
  136.     {
  137.         pMeshContainer->MeshData.pMesh = pMesh;
  138.         pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  139.         pMesh->AddRef();
  140.     }
  141.     // allocate memory to contain the material information.  This sample uses
  142.     //   the D3D9 materials and texture names instead of the EffectInstance style materials
  143.     pMeshContainer->NumMaterials = max(1, NumMaterials);
  144.     pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
  145.     pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
  146.     pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
  147.     if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
  148.     {
  149.         hr = E_OUTOFMEMORY;
  150.         goto e_Exit;
  151.     }
  152.     memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
  153.     memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
  154.     // if materials provided, copy them
  155.     if (NumMaterials > 0)            
  156.     {
  157.         memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
  158.         for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
  159.         {
  160.             if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
  161.             {
  162. //                TCHAR strTexturePath[MAX_PATH] = _T("");
  163. //                DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath), pMeshContainer->pMaterials[iMaterial].pTextureFilename );
  164.                 
  165. if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, pMeshContainer->pMaterials[iMaterial].pTextureFilename, 
  166. &pMeshContainer->ppTextures[iMaterial] ) ) )
  167.                     pMeshContainer->ppTextures[iMaterial] = NULL;
  168.                 // don't remember a pointer into the dynamic memory, just forget the name after loading
  169.                 pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
  170.             }
  171.         }
  172.     }
  173.     else // if no materials provided, use a default one
  174.     {
  175.         pMeshContainer->pMaterials[0].pTextureFilename = NULL;
  176.         memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
  177.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
  178.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
  179.         pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
  180.         pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
  181.     }
  182.     // if there is skinning information, save off the required data and then setup for HW skinning
  183.     if (pSkinInfo != NULL)
  184.     {
  185.         // first save off the SkinInfo and original mesh data
  186.         pMeshContainer->pSkinInfo = pSkinInfo;
  187.         pSkinInfo->AddRef();
  188.         pMeshContainer->pOrigMesh = pMesh;
  189.         pMesh->AddRef();
  190.         // Will need an array of offset matrices to move the vertices from the figure space to the bone's space
  191.         cBones = pSkinInfo->GetNumBones();
  192.         pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
  193.         if (pMeshContainer->pBoneOffsetMatrices == NULL)
  194.         {
  195.             hr = E_OUTOFMEMORY;
  196.             goto e_Exit;
  197.         }
  198.         // get each of the bone offset matrices so that we don't need to get them later
  199.         for (iBone = 0; iBone < cBones; iBone++)
  200.         {
  201.             pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
  202.         }
  203.         // GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
  204.         hr = m_pSkinMesh->GenerateSkinnedMesh(pMeshContainer);
  205.         if (FAILED(hr))
  206.             goto e_Exit;
  207.     }
  208.     *ppNewMeshContainer = pMeshContainer;
  209.     pMeshContainer = NULL;
  210. e_Exit:
  211.     SAFE_RELEASE(pd3dDevice);
  212.     // call Destroy function to properly clean up the memory allocated 
  213.     if (pMeshContainer != NULL)
  214.     {
  215.         DestroyMeshContainer(pMeshContainer);
  216.     }
  217.     return hr;
  218. }
  219. //-----------------------------------------------------------------------------
  220. // Name: CAllocateHierarchy::DestroyFrame()
  221. // Desc: 
  222. //-----------------------------------------------------------------------------
  223. HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) 
  224. {
  225.     SAFE_DELETE_ARRAY( pFrameToFree->Name );
  226.     SAFE_DELETE( pFrameToFree );
  227.     return S_OK; 
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Name: CAllocateHierarchy::DestroyMeshContainer()
  231. // Desc: 
  232. //-----------------------------------------------------------------------------
  233. HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
  234. {
  235.     UINT iMaterial;
  236.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
  237.     SAFE_DELETE_ARRAY( pMeshContainer->Name );
  238.     SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
  239.     SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
  240.     SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices );
  241.     // release all the allocated textures
  242.     if (pMeshContainer->ppTextures != NULL)
  243.     {
  244.         for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
  245.         {
  246.             SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] );
  247.         }
  248.     }
  249.     SAFE_DELETE_ARRAY( pMeshContainer->ppTextures );
  250.     SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs );
  251.     SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
  252.     SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
  253.     SAFE_RELEASE( pMeshContainer->pSkinInfo );
  254.     SAFE_RELEASE( pMeshContainer->pOrigMesh );
  255.     SAFE_DELETE( pMeshContainer );
  256.     return S_OK;
  257. }
  258. //////////////////////////////////////////////////////////////////////
  259. // Construction/Destruction
  260. //////////////////////////////////////////////////////////////////////
  261. CSkinMesh::CSkinMesh(LPDIRECT3DDEVICE9 pD3DDevice)
  262. :m_vMax(0,0,0),m_vMin(0,0,0)  
  263. {
  264. m_pD3DDevice=pD3DDevice;
  265. m_fElapsedTime=0.0f;
  266. m_pD3DDevice->GetDeviceCaps( &m_d3dCaps );
  267. m_bMoving=TRUE;
  268.     m_pAnimController = NULL;
  269.     m_pFrameRoot = NULL;
  270.     m_SkinningMethod = D3DINDEXED;
  271.     m_pBoneMatrices = NULL;
  272.     m_NumBoneMatricesMax = 0;
  273. }
  274. CSkinMesh::~CSkinMesh()
  275. {
  276. CAllocateHierarchy Alloc(this);
  277. D3DXFrameDestroy(m_pFrameRoot, &Alloc);
  278.     SAFE_RELEASE(m_pAnimController);
  279. }
  280. HRESULT CSkinMesh::LoadFromXFile(char *strFileName)
  281. {
  282.     HRESULT    hr;
  283. CAllocateHierarchy Alloc(this);
  284.     hr = D3DXLoadMeshHierarchyFromX(strFileName, D3DXMESH_MANAGED, m_pD3DDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController);
  285.     if (FAILED(hr))
  286.         return hr;
  287.     hr = SetupBoneMatrixPointers(m_pFrameRoot);
  288.     if (FAILED(hr))
  289.         return hr;
  290.     hr = D3DXFrameCalculateBoundingSphere(m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius);
  291.     if (FAILED(hr))
  292.         return hr;
  293. if(m_pFrameRoot)
  294. CalculateBondingBox(m_pFrameRoot,&m_vMin,&m_vMax);  
  295.  
  296. return S_OK;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Name: GenerateSkinnedMesh()
  300. // Desc: Called either by CreateMeshContainer when loading a skin mesh, or when 
  301. //       changing methods.  This function uses the pSkinInfo of the mesh 
  302. //       container to generate the desired drawable mesh and bone combination 
  303. //       table.
  304. //-----------------------------------------------------------------------------
  305. HRESULT CSkinMesh::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer)
  306. {
  307.     HRESULT hr = S_OK;
  308.     if (pMeshContainer->pSkinInfo == NULL)
  309.         return hr;
  310.     SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
  311.     SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
  312.     // if non-indexed skinning mode selected, use ConvertToBlendedMesh to generate drawable mesh
  313.     if (m_SkinningMethod == D3DNONINDEXED)
  314.     {
  315.         hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh
  316.                                    (
  317.                                        pMeshContainer->pOrigMesh,
  318.                                        D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, 
  319.                                        pMeshContainer->pAdjacency, 
  320.                                        NULL, NULL, NULL, 
  321.                                        &pMeshContainer->NumInfl,
  322.                                        &pMeshContainer->NumAttributeGroups, 
  323.                                        &pMeshContainer->pBoneCombinationBuf, 
  324.                                        &pMeshContainer->MeshData.pMesh
  325.                                    );
  326.         if (FAILED(hr))
  327.             goto e_Exit;
  328.         /* If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it
  329.            Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is
  330.            drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing. */
  331.         LPD3DXBONECOMBINATION rgBoneCombinations  = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
  332.         // look for any set of bone combinations that do not fit the caps
  333.         for (pMeshContainer->iAttributeSW = 0; pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups; pMeshContainer->iAttributeSW++)
  334.         {
  335.             DWORD cInfl   = 0;
  336.             for (DWORD iInfl = 0; iInfl < pMeshContainer->NumInfl; iInfl++)
  337.             {
  338.                 if (rgBoneCombinations[pMeshContainer->iAttributeSW].BoneId[iInfl] != UINT_MAX)
  339.                 {
  340.                     ++cInfl;
  341.                 }
  342.             }
  343.             if (cInfl > m_d3dCaps.MaxVertexBlendMatrices)
  344.             {
  345.                 break;
  346.             }
  347.         }
  348.         // if there is both HW and SW, add the Software Processing flag
  349.         if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups)
  350.         {
  351.             LPD3DXMESH pMeshTmp;
  352.             hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pMeshContainer->MeshData.pMesh->GetOptions(), 
  353.                                                 pMeshContainer->MeshData.pMesh->GetFVF(),
  354.                                                 m_pD3DDevice, &pMeshTmp);
  355.             if (FAILED(hr))
  356.             {
  357.                 goto e_Exit;
  358.             }
  359.             pMeshContainer->MeshData.pMesh->Release();
  360.             pMeshContainer->MeshData.pMesh = pMeshTmp;
  361.             pMeshTmp = NULL;
  362.         }
  363.     }
  364.     // if indexed skinning mode selected, use ConvertToIndexedsBlendedMesh to generate drawable mesh
  365.     else if (m_SkinningMethod == D3DINDEXED)
  366.     {
  367.         DWORD NumMaxFaceInfl;
  368.         DWORD Flags = D3DXMESHOPT_VERTEXCACHE;
  369.         LPDIRECT3DINDEXBUFFER9 pIB;
  370.         hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB);
  371.         if (FAILED(hr))
  372.             goto e_Exit;
  373.         hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl);
  374.         pIB->Release();
  375.         if (FAILED(hr))
  376.             goto e_Exit;
  377.         // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri)
  378.         // can be handled
  379.         NumMaxFaceInfl = min(NumMaxFaceInfl, 12);
  380.         if (m_d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl)
  381.         {
  382.             // HW does not support indexed vertex blending. Use SW instead
  383.             pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones());
  384.             pMeshContainer->UseSoftwareVP = true;
  385.             Flags |= D3DXMESH_SYSTEMMEM;
  386.         }
  387.         else
  388.         {
  389.             // using hardware - determine palette size from caps and number of bones
  390.             // If normals are present in the vertex data that needs to be blended for lighting, then 
  391.             // the number of matrices is half the number specified by MaxVertexBlendMatrixIndex.
  392.             pMeshContainer->NumPaletteEntries = min( ( m_d3dCaps.MaxVertexBlendMatrixIndex + 1 ) / 2, 
  393.                                                      pMeshContainer->pSkinInfo->GetNumBones() );
  394.             pMeshContainer->UseSoftwareVP = false;
  395.             Flags |= D3DXMESH_MANAGED;
  396.         }
  397.         hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh
  398.                                                 (
  399.                                                 pMeshContainer->pOrigMesh,
  400.                                                 Flags, 
  401.                                                 pMeshContainer->NumPaletteEntries, 
  402.                                                 pMeshContainer->pAdjacency, 
  403.                                                 NULL, NULL, NULL, 
  404.                                                 &pMeshContainer->NumInfl,
  405.                                                 &pMeshContainer->NumAttributeGroups, 
  406.                                                 &pMeshContainer->pBoneCombinationBuf, 
  407.                                                 &pMeshContainer->MeshData.pMesh);
  408.         if (FAILED(hr))
  409.             goto e_Exit;
  410.     }
  411.      // if software skinning selected, use GenerateSkinnedMesh to create a mesh that can be used with UpdateSkinnedMesh
  412.     else if (m_SkinningMethod == SOFTWARE)
  413.     {
  414.         hr = pMeshContainer->pOrigMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshContainer->pOrigMesh->GetFVF(),
  415.                                               m_pD3DDevice, &pMeshContainer->MeshData.pMesh);
  416.         if (FAILED(hr))
  417.             goto e_Exit;
  418.         hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(NULL, &pMeshContainer->NumAttributeGroups);
  419.         if (FAILED(hr))
  420.             goto e_Exit;
  421.         delete[] pMeshContainer->pAttributeTable;
  422.         pMeshContainer->pAttributeTable  = new D3DXATTRIBUTERANGE[pMeshContainer->NumAttributeGroups];
  423.         if (pMeshContainer->pAttributeTable == NULL)
  424.         {
  425.             hr = E_OUTOFMEMORY;
  426.             goto e_Exit;
  427.         }
  428.         hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(pMeshContainer->pAttributeTable, NULL);
  429.         if (FAILED(hr))
  430.             goto e_Exit;
  431.         // allocate a buffer for bone matrices, but only if another mesh has not allocated one of the same size or larger
  432.         if (m_NumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones())
  433.         {
  434.             m_NumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();
  435.             // Allocate space for blend matrices
  436.             delete []m_pBoneMatrices; 
  437.             m_pBoneMatrices  = new D3DXMATRIXA16[m_NumBoneMatricesMax];
  438.             if (m_pBoneMatrices == NULL)
  439.             {
  440.                 hr = E_OUTOFMEMORY;
  441.                 goto e_Exit;
  442.             }
  443.         }
  444.     }
  445.     else  // invalid m_SkinningMethod value
  446.     {        
  447.         // return failure due to invalid skinning method value
  448.         hr = E_INVALIDARG;
  449.         goto e_Exit;
  450.     }
  451. e_Exit:
  452.     return hr;
  453. }
  454. HRESULT CSkinMesh::SetupBoneMatrixPointers(LPD3DXFRAME pFrame)
  455. {
  456.     HRESULT hr;
  457.     if (pFrame->pMeshContainer != NULL)
  458.     { //左序遍历
  459.         hr = SetupBoneMatrixPointersOnMesh(pFrame->pMeshContainer);
  460.         if (FAILED(hr))
  461.             return hr;
  462.     }
  463.     if (pFrame->pFrameSibling != NULL)
  464.     {
  465.         hr = SetupBoneMatrixPointers(pFrame->pFrameSibling);
  466.         if (FAILED(hr))
  467.             return hr;
  468.     }
  469.     if (pFrame->pFrameFirstChild != NULL)
  470.     {
  471.         hr = SetupBoneMatrixPointers(pFrame->pFrameFirstChild);
  472.         if (FAILED(hr))
  473.             return hr;
  474.     }
  475.     return S_OK;
  476. }
  477. HRESULT CSkinMesh::SetupBoneMatrixPointersOnMesh(LPD3DXMESHCONTAINER pMeshContainerBase)
  478. {
  479.     UINT iBone, cBones;
  480.     D3DXFRAME_DERIVED *pFrame;
  481.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
  482.     // if there is a skinmesh, then setup the bone matrices
  483. //蒙皮动画,则设置骨骼的变换矩阵
  484.     if (pMeshContainer->pSkinInfo != NULL)
  485.     {
  486.         cBones = pMeshContainer->pSkinInfo->GetNumBones();
  487.         pMeshContainer->ppBoneMatrixPtrs = new D3DXMATRIX*[cBones]; //创建骨骼
  488.         if (pMeshContainer->ppBoneMatrixPtrs == NULL)
  489.             return E_OUTOFMEMORY;
  490.         for (iBone = 0; iBone < cBones; iBone++)
  491.         {
  492.             pFrame = (D3DXFRAME_DERIVED*)D3DXFrameFind(m_pFrameRoot, 
  493. pMeshContainer->pSkinInfo->GetBoneName(iBone));
  494.             if (pFrame == NULL)
  495.                 return E_FAIL;
  496. //初始化矩阵
  497.             pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix;
  498.         }
  499.     }
  500.     return S_OK;
  501. }
  502. void CSkinMesh::Translation(POSITION ppos)
  503. {
  504.     
  505. D3DXMATRIX matRotation,matTranslate;
  506. D3DXMatrixRotationY(&matRotation,-D3DX_PI/180*(ppos.a-90.0f));
  507. D3DXMatrixTranslation(&matTranslate,ppos.x,ppos.y+65.0f,ppos.z);
  508. D3DXMatrixMultiply(&matWorld,&matRotation,&matTranslate);
  509. m_pD3DDevice->SetTransform(D3DTS_WORLD,&matWorld);
  510. }
  511. VOID CSkinMesh::Render(float fElapsedAppTime,D3DXVECTOR3 vPos,float angle,float scale)
  512. {
  513. // Get the app's time, in seconds. Skip rendering if no time elapsed
  514. //    FLOAT fElapsedAppTime = DXUtil_Timer( TIMER_GETELAPSEDTIME );
  515.     if( 0.00f == fElapsedAppTime )    return;
  516. m_fElapsedTime = fElapsedAppTime;
  517. // Setup world matrix
  518.     D3DXMATRIXA16 matWorld,matWorld2;
  519. D3DXMatrixRotationY(&matWorld2,angle);
  520. D3DXMatrixScaling(&matWorld,scale,scale,scale);
  521. D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
  522.     D3DXMatrixTranslation( &matWorld2, vPos.x, vPos.y,vPos.z );
  523. D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
  524.   //  m_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
  525. if(m_pAnimController)
  526. {
  527. if (m_bMoving)
  528. #if (D3D_SDK_VERSION &31)
  529. m_pAnimController->SetTime(m_pAnimController->GetTime()-2);//m_fElapsedTime
  530. else
  531. m_pAnimController->SetTime(0);
  532. #else 
  533. m_pAnimController->AdvanceTime(m_fElapsedTime,NULL); 
  534. else
  535. m_pAnimController->ResetTime();
  536. #endif
  537. }
  538.     UpdateFrameMatrices(m_pFrameRoot, &matWorld);
  539. DrawFrame(m_pFrameRoot);
  540. }
  541. VOID CSkinMesh::DrawFrame(LPD3DXFRAME pFrame)
  542. {
  543.     LPD3DXMESHCONTAINER pMeshContainer;
  544.  
  545.     pMeshContainer = pFrame->pMeshContainer;
  546.     while (pMeshContainer != NULL)
  547.     {
  548.         DrawMeshContainer(pMeshContainer, pFrame);
  549.         pMeshContainer = pMeshContainer->pNextMeshContainer;
  550.     }
  551.     if (pFrame->pFrameSibling != NULL)
  552.     {
  553.         DrawFrame(pFrame->pFrameSibling);
  554.     }
  555.     if (pFrame->pFrameFirstChild != NULL)
  556.     {
  557.         DrawFrame(pFrame->pFrameFirstChild);
  558.     }
  559.   
  560. }
  561. //-----------------------------------------------------------------------------
  562. // Name: DrawMeshContainer()
  563. // Desc: Called to render a mesh in the hierarchy
  564. //-----------------------------------------------------------------------------
  565. VOID CSkinMesh::DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
  566. {
  567.     D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
  568.     D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
  569.     UINT iMaterial;
  570.     UINT NumBlend;
  571.     UINT iAttrib;
  572.     DWORD AttribIdPrev;
  573.     LPD3DXBONECOMBINATION pBoneComb;
  574.     UINT iMatrixIndex;
  575.     UINT iPaletteEntry;
  576.     D3DXMATRIXA16 matTemp;
  577.     // first check for skinning
  578.     if (pMeshContainer->pSkinInfo != NULL)
  579.     {
  580.         if (m_SkinningMethod == D3DNONINDEXED)
  581.         {
  582.             AttribIdPrev = UNUSED32; 
  583.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
  584.             // Draw using default vtx processing of the device (typically HW)
  585.             for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
  586.             {
  587.                 NumBlend = 0;
  588.                 for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
  589.                 {
  590.                     if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
  591.                     {
  592.                         NumBlend = i;
  593.                     }
  594.                 }
  595.                 if (m_d3dCaps.MaxVertexBlendMatrices >= NumBlend + 1)
  596.                 {
  597.                     // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
  598.                     for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
  599.                     {
  600.                         iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
  601.                         if (iMatrixIndex != UINT_MAX)
  602.                         {
  603.                             D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
  604.                             m_pD3DDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
  605.                         }
  606.                     }
  607.                     m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
  608.                     // lookup the material used for this subset of faces
  609.                     if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
  610.                     {
  611.                         m_pD3DDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
  612.                         m_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
  613.                         AttribIdPrev = pBoneComb[iAttrib].AttribId;
  614.                     }
  615.                     // draw the subset now that the correct material and matrices are loaded
  616.                     pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
  617.                 }
  618.             }
  619.             // If necessary, draw parts that HW could not handle using SW
  620.             if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups)
  621.             {
  622.                 AttribIdPrev = UNUSED32; 
  623.                 m_pD3DDevice->SetSoftwareVertexProcessing(TRUE);
  624.                 for (iAttrib = pMeshContainer->iAttributeSW; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
  625.                 {
  626.                     NumBlend = 0;
  627.                     for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
  628.                     {
  629.                         if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
  630.                         {
  631.                             NumBlend = i;
  632.                         }
  633.                     }
  634.                     if (m_d3dCaps.MaxVertexBlendMatrices < NumBlend + 1)
  635.                     {
  636.                         // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
  637.                         for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
  638.                         {
  639.                             iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
  640.                             if (iMatrixIndex != UINT_MAX)
  641.                             {
  642.                                 D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
  643.                                 m_pD3DDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
  644.                             }
  645.                         }
  646.                         m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
  647.                         // lookup the material used for this subset of faces
  648.                         if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
  649.                         {
  650.                             m_pD3DDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
  651.                             m_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
  652.                             AttribIdPrev = pBoneComb[iAttrib].AttribId;
  653.                         }
  654.                         // draw the subset now that the correct material and matrices are loaded
  655.                         pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
  656.                     }
  657.                 }
  658.                 m_pD3DDevice->SetSoftwareVertexProcessing(FALSE);
  659.             }
  660.             m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  661.         }
  662.         else if (m_SkinningMethod == D3DINDEXED)
  663.         {
  664.             // if hw doesn't support indexed vertex processing, switch to software vertex processing
  665.             if (pMeshContainer->UseSoftwareVP)
  666.             {
  667.                 m_pD3DDevice->SetSoftwareVertexProcessing(TRUE);
  668.             }
  669.             // set the number of vertex blend indices to be blended
  670.             if (pMeshContainer->NumInfl == 1)
  671.                 m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
  672.             else
  673.                 m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);
  674.             if (pMeshContainer->NumInfl)
  675.                 m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
  676.             // for each attribute group in the mesh, calculate the set of matrices in the palette and then draw the mesh subset
  677.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
  678.             for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
  679.             {
  680.                 // first calculate all the world matrices
  681.                 for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
  682.                 {
  683.                     iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry];
  684.                     if (iMatrixIndex != UINT_MAX)
  685.                     {
  686.                         D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
  687.                         m_pD3DDevice->SetTransform( D3DTS_WORLDMATRIX( iPaletteEntry ), &matTemp );
  688.                     }
  689.                 }
  690.                 
  691.                 // setup the material of the mesh subset - REMEMBER to use the original pre-skinning attribute id to get the correct material id
  692.                 m_pD3DDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
  693.                 m_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
  694.                 // finally draw the subset with the current world matrix palette and material state
  695.                 pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
  696.             }
  697.             // reset blending state
  698.             m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  699.             m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  700.             // remember to reset back to hw vertex processing if software was required
  701.             if (pMeshContainer->UseSoftwareVP)
  702.             {
  703.                 m_pD3DDevice->SetSoftwareVertexProcessing(FALSE);
  704.             }
  705.         }
  706.         else if (m_SkinningMethod == SOFTWARE)
  707.         {
  708.             D3DXMATRIX  Identity;
  709.             DWORD       cBones  = pMeshContainer->pSkinInfo->GetNumBones();
  710.             DWORD       iBone;
  711.             PBYTE       pbVerticesSrc;
  712.             PBYTE       pbVerticesDest;
  713.             // set up bone transforms
  714.             for (iBone = 0; iBone < cBones; ++iBone)
  715.             {
  716.                 D3DXMatrixMultiply
  717.                 (
  718.                     &m_pBoneMatrices[iBone],                 // output
  719.                     &pMeshContainer->pBoneOffsetMatrices[iBone], 
  720.                     pMeshContainer->ppBoneMatrixPtrs[iBone]
  721.                 );
  722.             }
  723.             // set world transform
  724.             D3DXMatrixIdentity(&Identity);
  725.             m_pD3DDevice->SetTransform(D3DTS_WORLD, &Identity);
  726.             pMeshContainer->pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc);
  727.             pMeshContainer->MeshData.pMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesDest);
  728.             // generate skinned mesh
  729.             pMeshContainer->pSkinInfo->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);
  730.             pMeshContainer->pOrigMesh->UnlockVertexBuffer();
  731.             pMeshContainer->MeshData.pMesh->UnlockVertexBuffer();
  732.             for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
  733.             {
  734.                 m_pD3DDevice->SetMaterial(&(pMeshContainer->pMaterials[pMeshContainer->pAttributeTable[iAttrib].AttribId].MatD3D));
  735.                 m_pD3DDevice->SetTexture(0, pMeshContainer->ppTextures[pMeshContainer->pAttributeTable[iAttrib].AttribId]);
  736.                 pMeshContainer->MeshData.pMesh->DrawSubset(pMeshContainer->pAttributeTable[iAttrib].AttribId);
  737.             }
  738.         }
  739.         else // bug out as unsupported mode
  740.         {
  741.             return;
  742.         }
  743.     }
  744.     else  // standard mesh, just draw it after setting material properties
  745.     {
  746.         m_pD3DDevice->SetTransform(D3DTS_WORLD, &pFrame->CombinedTransformationMatrix);
  747.         for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
  748.         {
  749.             m_pD3DDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D );
  750.             m_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] );
  751.             pMeshContainer->MeshData.pMesh->DrawSubset(iMaterial);
  752.         }
  753.     }
  754. }
  755. VOID CSkinMesh::UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
  756. {
  757.     D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
  758.     if (pParentMatrix != NULL)
  759.         D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);
  760.     else
  761.         pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;
  762.     if (pFrame->pFrameSibling != NULL)
  763.     {
  764.         UpdateFrameMatrices(pFrame->pFrameSibling, pParentMatrix);
  765.     }
  766.     if (pFrame->pFrameFirstChild != NULL)
  767.     {
  768.         UpdateFrameMatrices(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);
  769.     }
  770. }
  771. VOID CSkinMesh::SetAnim(BOOL bAnim)
  772. {
  773. m_bMoving=bAnim;
  774. if(!m_bMoving && m_pAnimController)
  775. {
  776. #if (D3D_SDK_VERSION & 32)
  777. m_pAnimController->ResetTime();
  778. #else m_pAnimController->SetTime(0);
  779. #endif
  780. }
  781. }
  782. BOOL CSkinMesh::SetAnimationName(char *strAnimName)
  783. {
  784. if(!m_bMoving || !m_pAnimController  ) return FALSE;
  785. DWORD nAnimSet;
  786. char strTempName[256];
  787. nAnimSet=m_pAnimController->GetNumAnimationSets();
  788. LPD3DXANIMATIONSET pAnimSet;
  789. for(DWORD i=0;i<nAnimSet;i++)
  790. {
  791. m_pAnimController->GetAnimationSet(i,&pAnimSet);
  792. strcpy(strTempName, pAnimSet->GetName());
  793. if(strcmp(strAnimName,strTempName)==0) 
  794. {
  795. m_pAnimController->SetTrackAnimationSet(0,pAnimSet);
  796.  
  797. return TRUE;
  798. }
  799. }
  800. return FALSE;
  801. };
  802. //-----------------------------------------
  803. //Name:Intersect
  804. //Desc:使用索引和顶点缓冲区,求Mesh和射线交点
  805. //2006/6/27 JohnsonFeng
  806. //Use: IntersectIndexBuffer
  807. //-----------------------------------------
  808. BOOL CSkinMesh::InterSect( D3DVECTOR *pRayOrig,
  809.  D3DVECTOR *pRayDir,D3DVECTOR* pVRet)
  810. {
  811. return S_OK;
  812. }