zoukankan      html  css  js  c++  java
  • X文件的动画类及基本使用方法

    ------------------------------Animation.h--------------------------------------没有Animation.cpp-----------

    #ifndef __AnimationH__
    #define __AnimationH__

    #include <d3d9.h>
    #include <d3dx9.h>

    //struct D3DXFRAME_DERIVED & D3DXMESHCONTAINER_DERIVED
    struct D3DXFRAME_DERIVED : public D3DXFRAME
    {
     D3DXMATRIXA16 CombinedTransformationMatrix;
    };
    struct D3DXMESHCONTAINER_DERIVED : public D3DXMESHCONTAINER
    {
     LPDIRECT3DTEXTURE9* ppTextures;       // array of textures, entries are NULL if no texture specified   

     // SkinMesh info            
     LPD3DXMESH pOrigMesh;
     LPD3DXATTRIBUTERANGE pAttributeTable;
     DWORD NumAttributeGroups;
     DWORD NumInfl;
     LPD3DXBUFFER pBoneCombinationBuf;
     D3DXMATRIX** ppBoneMatrixPtrs;
     D3DXMATRIX* pBoneOffsetMatrices;
     DWORD NumPaletteEntries;
     bool UseSoftwareVP;
     DWORD iAttributeSW;     // used to denote the split between SW and HW if necessary for non-indexed skinning
    };

    //class CAllocateHierarchy
    class CAllocateHierarchy : public ID3DXAllocateHierarchy
    {
    public:
     STDMETHOD( CreateFrame )( THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame );
     STDMETHOD( CreateMeshContainer )( THIS_
      LPCSTR Name,
      CONST D3DXMESHDATA *pMeshData,
      CONST D3DXMATERIAL *pMaterials,
      CONST D3DXEFFECTINSTANCE *pEffectInstances,
      DWORD NumMaterials,
      CONST DWORD *pAdjacency,
      LPD3DXSKININFO pSkinInfo,
      LPD3DXMESHCONTAINER *ppNewMeshContainer );
     STDMETHOD( DestroyFrame )( THIS_ LPD3DXFRAME pFrameToFree );
     STDMETHOD( DestroyMeshContainer )( THIS_ LPD3DXMESHCONTAINER pMeshContainerBase );
     HRESULT AllocateName( LPCSTR Name, LPSTR* pNewName );
     HRESULT GenerateSkinnedMesh( IDirect3DDevice9* pd3dDevice, D3DXMESHCONTAINER_DERIVED* pMeshContainer );
     CAllocateHierarchy()
     {
     }
    };
    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;
    }
    HRESULT 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;

     // 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 )
       {
        WCHAR strTexturePath[MAX_PATH];
        MultiByteToWideChar( CP_ACP, 0, pMeshContainer->pMaterials[iMaterial].pTextureFilename, -1, strTexturePath, MAX_PATH );
        strTexturePath[MAX_PATH - 1] = L'\0';
        if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexturePath,
         &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;
      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 = GenerateSkinnedMesh( pd3dDevice, 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;
    }
    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 );

     // release all the allocated textures
     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;
    }
    HRESULT CAllocateHierarchy::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::GenerateSkinnedMesh( IDirect3DDevice9* pd3dDevice, D3DXMESHCONTAINER_DERIVED* pMeshContainer )
    {
     HRESULT hr = S_OK;
     D3DCAPS9 d3dCaps;
     pd3dDevice->GetDeviceCaps( &d3dCaps );

     if( pMeshContainer->pSkinInfo == NULL )
      return hr;

     SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
     SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );

     hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh
      (
      pMeshContainer->pOrigMesh,
      D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
      pMeshContainer->pAdjacency,
      NULL, NULL, NULL,
      &pMeshContainer->NumInfl,
      &pMeshContainer->NumAttributeGroups,
      &pMeshContainer->pBoneCombinationBuf,
      &pMeshContainer->MeshData.pMesh
      );
     if( FAILED( hr ) )
      goto e_Exit;


     // If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it
     // Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is
     // drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing.
     LPD3DXBONECOMBINATION rgBoneCombinations = reinterpret_cast<LPD3DXBONECOMBINATION>(
      pMeshContainer->pBoneCombinationBuf->GetBufferPointer() );

     // look for any set of bone combinations that do not fit the caps
     for( pMeshContainer->iAttributeSW = 0; pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups;
      pMeshContainer->iAttributeSW++ )
     {
      DWORD cInfl = 0;

      for( DWORD iInfl = 0; iInfl < pMeshContainer->NumInfl; iInfl++ )
      {
       if( rgBoneCombinations[pMeshContainer->iAttributeSW].BoneId[iInfl] != UINT_MAX )
       {
        ++cInfl;
       }
      }

      if( cInfl > d3dCaps.MaxVertexBlendMatrices )
      {
       break;
      }
     }

     // if there is both HW and SW, add the Software Processing flag
     if( pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups )
     {
      LPD3DXMESH pMeshTmp;

      hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF( D3DXMESH_SOFTWAREPROCESSING |
       pMeshContainer->MeshData.pMesh->GetOptions(),
       pMeshContainer->MeshData.pMesh->GetFVF(),
       pd3dDevice, &pMeshTmp );
      if( FAILED( hr ) )
      {
       goto e_Exit;
      }

      pMeshContainer->MeshData.pMesh->Release();
      pMeshContainer->MeshData.pMesh = pMeshTmp;
      pMeshTmp = NULL;
     }

    e_Exit:
     return hr;
    }

    //class CAnimation
    class CAnimation
    {
    private:
     IDirect3DDevice9* m_pDevice;
     LPD3DXFRAME m_pFrameRoot;
     ID3DXAnimationController* m_pAnimController;
     D3DXVECTOR3 m_vObjectCenter;
     FLOAT m_fObjectRadius;
    private:
     HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase );
     HRESULT SetupBoneMatrixPointers(LPD3DXFRAME pFrame);
     void UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix );
     void DrawMeshContainer( IDirect3DDevice9* pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase );
     void DrawFrame( IDirect3DDevice9* pd3dDevice, LPD3DXFRAME pFrame );
    public:
     friend class CAllocateHierarchy;
     void Init(IDirect3DDevice9* pDevice, char* sFileName);
     void Logic(float fElapsedTime);
     void Render(float fElapsedTime);
    };
    void CAnimation::Init(IDirect3DDevice9* pDevice, char* sFileName)
    {
     m_pDevice = pDevice;
     CAllocateHierarchy Alloc;
     D3DXLoadMeshHierarchyFromXA( sFileName, D3DXMESH_MANAGED, m_pDevice,
      &Alloc, NULL, &m_pFrameRoot, &m_pAnimController );
     SetupBoneMatrixPointers( m_pFrameRoot );
     D3DXFrameCalculateBoundingSphere( m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius );
    }
    void CAnimation::Logic(float fElapsedTime)
    {
     m_pAnimController->AdvanceTime(fElapsedTime, 0);
     D3DXMATRIX matWorld;
     D3DXMatrixScaling(&matWorld, 0.01f, 0.01f, 0.01f);
     UpdateFrameMatrices(m_pFrameRoot, &matWorld);
    }
    void CAnimation::Render(float fElapsedTime)
    {
     DrawFrame(m_pDevice, m_pFrameRoot);
    }
    HRESULT CAnimation::SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase )
    {
     UINT iBone, cBones;
     D3DXFRAME_DERIVED* pFrame;

     D3DXMESHCONTAINER_DERIVED* pMeshContainer = ( D3DXMESHCONTAINER_DERIVED* )pMeshContainerBase;

     // if there is a skinmesh, then setup the bone matrices
     if( pMeshContainer->pSkinInfo != NULL )
     {
      cBones = pMeshContainer->pSkinInfo->GetNumBones();

      pMeshContainer->ppBoneMatrixPtrs = new D3DXMATRIX*[cBones];
      if( pMeshContainer->ppBoneMatrixPtrs == NULL )
       return E_OUTOFMEMORY;

      for( iBone = 0; iBone < cBones; iBone++ )
      {
       pFrame = ( D3DXFRAME_DERIVED* )D3DXFrameFind( m_pFrameRoot,
        pMeshContainer->pSkinInfo->GetBoneName( iBone ) );
       if( pFrame == NULL )
        return E_FAIL;

       pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix;
      }
     }

     return S_OK;
    }
    HRESULT CAnimation::SetupBoneMatrixPointers( LPD3DXFRAME pFrame )
    {
     HRESULT hr;

     if( pFrame->pMeshContainer != NULL )
     {
      hr = SetupBoneMatrixPointersOnMesh( pFrame->pMeshContainer );
      if( FAILED( hr ) )
       return hr;
     }

     if( pFrame->pFrameSibling != NULL )
     {
      hr = SetupBoneMatrixPointers( pFrame->pFrameSibling );
      if( FAILED( hr ) )
       return hr;
     }

     if( pFrame->pFrameFirstChild != NULL )
     {
      hr = SetupBoneMatrixPointers( pFrame->pFrameFirstChild );
      if( FAILED( hr ) )
       return hr;
     }

     return S_OK;
    }
    void CAnimation::UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix )
    {
     D3DXFRAME_DERIVED* pFrame = ( D3DXFRAME_DERIVED* )pFrameBase;

     if( pParentMatrix != NULL )
      D3DXMatrixMultiply( &pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix );
     else
      pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;

     if( pFrame->pFrameSibling != NULL )
     {
      UpdateFrameMatrices( pFrame->pFrameSibling, pParentMatrix );
     }

     if( pFrame->pFrameFirstChild != NULL )
     {
      UpdateFrameMatrices( pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix );
     }
    }
    void CAnimation::DrawMeshContainer( IDirect3DDevice9* pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase )
    {
     HRESULT hr;
     D3DXMESHCONTAINER_DERIVED* pMeshContainer = ( D3DXMESHCONTAINER_DERIVED* )pMeshContainerBase;
     D3DXFRAME_DERIVED* pFrame = ( D3DXFRAME_DERIVED* )pFrameBase;
     UINT iMaterial;
     UINT NumBlend;
     UINT iAttrib;
     DWORD AttribIdPrev;
     LPD3DXBONECOMBINATION pBoneComb;

     UINT iMatrixIndex;
     D3DXMATRIXA16 matTemp;
     D3DCAPS9 d3dCaps;
     pd3dDevice->GetDeviceCaps( &d3dCaps );

     // first check for skinning
     if( pMeshContainer->pSkinInfo != NULL )
     {
      AttribIdPrev = UNUSED32;
      pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>( pMeshContainer->pBoneCombinationBuf->GetBufferPointer
       () );

      // Draw using default vtx processing of the device (typically HW)
      for( iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++ )
      {
       NumBlend = 0;
       for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
       {
        if( pBoneComb[iAttrib].BoneId[i] != UINT_MAX )
        {
         NumBlend = i;
        }
       }

       if( d3dCaps.MaxVertexBlendMatrices >= NumBlend + 1 )
       {
        // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
        for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
        {
         iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
         if( iMatrixIndex != UINT_MAX )
         {
          D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex],
           pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
          V( pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp ) );
         }
        }

        V( pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, NumBlend ) );

        // lookup the material used for this subset of faces
        if( ( AttribIdPrev != pBoneComb[iAttrib].AttribId ) || ( AttribIdPrev == UNUSED32 ) )
        {
         V( pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D )
          );
         V( pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] ) );
         AttribIdPrev = pBoneComb[iAttrib].AttribId;
        }

        // draw the subset now that the correct material and matrices are loaded
        V( pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib ) );
       }
      }

      // If necessary, draw parts that HW could not handle using SW
      if( pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups )
      {
       AttribIdPrev = UNUSED32;
       V( pd3dDevice->SetSoftwareVertexProcessing( TRUE ) );
       for( iAttrib = pMeshContainer->iAttributeSW; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++ )
       {
        NumBlend = 0;
        for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
        {
         if( pBoneComb[iAttrib].BoneId[i] != UINT_MAX )
         {
          NumBlend = i;
         }
        }

        if( d3dCaps.MaxVertexBlendMatrices < NumBlend + 1 )
        {
         // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
         for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
         {
          iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
          if( iMatrixIndex != UINT_MAX )
          {
           D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex],
            pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
           V( pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp ) );
          }
         }

         V( pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, NumBlend ) );

         // lookup the material used for this subset of faces
         if( ( AttribIdPrev != pBoneComb[iAttrib].AttribId ) || ( AttribIdPrev == UNUSED32 ) )
         {
          V( pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D
           ) );
          V( pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] ) );
          AttribIdPrev = pBoneComb[iAttrib].AttribId;
         }

         // draw the subset now that the correct material and matrices are loaded
         V( pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib ) );
        }
       }
       V( pd3dDevice->SetSoftwareVertexProcessing( FALSE ) );
      }

      V( pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, 0 ) );
     }
     else  // standard mesh, just draw it after setting material properties
     {
      V( pd3dDevice->SetTransform( D3DTS_WORLD, &pFrame->CombinedTransformationMatrix ) );

      for( iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++ )
      {
       V( pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D ) );
       V( pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] ) );
       V( pMeshContainer->MeshData.pMesh->DrawSubset( iMaterial ) );
      }
     }
    }
    void CAnimation::DrawFrame( IDirect3DDevice9* pd3dDevice, LPD3DXFRAME pFrame )
    {
     LPD3DXMESHCONTAINER pMeshContainer;

     pMeshContainer = pFrame->pMeshContainer;
     while( pMeshContainer != NULL )
     {
      DrawMeshContainer( pd3dDevice, pMeshContainer, pFrame );

      pMeshContainer = pMeshContainer->pNextMeshContainer;
     }

     if( pFrame->pFrameSibling != NULL )
     {
      DrawFrame( pd3dDevice, pFrame->pFrameSibling );
     }

     if( pFrame->pFrameFirstChild != NULL )
     {
      DrawFrame( pd3dDevice, pFrame->pFrameFirstChild );
     }
    }

    #endif

    //使用方法
    //CAnimation Animation;
    //Animation.Init(g_pDevice, "sFileName"); -->添加到游戏的初始化中
    //Animation.Logic(fElaspedTime); -->添加到游戏的逻辑更新中
    //Animation.Render(fElapsedTime); -->添加到游戏的绘制中

    //对于其中Logic的具体实现可以更改

  • 相关阅读:
    迷宫
    小猫
    数位DP模板
    摘桃子
    [USACO10HOL]牛的政治Cow Politics
    ArcEngine中合并断开的线要素(根据几何判断)
    ArcEngine环境下合并断开的线要素(根据属性)
    Web Service和WCF的到底有什么区别
    OGC 的 WMS、WFS 及WCS服务(转)
    ArrayList的使用方法详解(转)
  • 原文地址:https://www.cnblogs.com/ketmales/p/2466250.html
Copyright © 2011-2022 走看看