• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            HLSL實現(xiàn)蒙皮動畫(1)

            Posted on 2008-12-02 16:26 Herbert 閱讀(1566) 評論(0)  編輯 收藏 引用 所屬分類: DirectX

               這兩天在做  3D蒙皮動畫時遇到些問題,折騰了一天半,嗨!很郁悶啊!我要大叫來發(fā)泄一下。
            本來打算用D3D設(shè)備直接設(shè)置世界坐標(biāo)矩陣來實現(xiàn)動畫的,但發(fā)現(xiàn)有一個問題,當(dāng)我不使用D3DXEFFECT來設(shè)置渲染效果的時候就可以正常顯示動畫;當(dāng)我使用它來設(shè)置渲染效果的時候,動畫就沒了。我想可能是用D3DXEFFECT來設(shè)置渲染效果的時候把D3D設(shè)備的 SetTransform功能屏蔽掉了(其實我不理解這個渲染過程^_^)。
               下面說一下加載和渲染蒙皮動畫的大概流程吧。
               首先繼承2個結(jié)構(gòu):D3DXFRAME、D3DMESHCONTAINER 和一個接口:ID3DXAllocateHierarchy。

            //------------------------------------------------------------
            //說明:框架
            //------------------------------------------------------------

            struct GFrame : public D3DXFRAME
            {
             D3DXMATRIXA16 CombinedTransformationMatrix; //最終變換矩陣
            };

             

             

            //------------------------------------------------------------
            //說明:網(wǎng)格容器
            //------------------------------------------------------------

            struct GMeshContainer : public D3DXMESHCONTAINER
            {
             LPDIRECT3DTEXTURE9 *  _ppTexs;  //紋理列表

             LPD3DXMESH     _pOrigMesh;  //原mesh

             DWORD      _dwNumAttrGroups; //屬性組個數(shù)
             DWORD      _dwMaxNumInfl;  //一個面最多受多少骨骼影響
             DWORD      _dwNumPaletteEntries; //樣色個數(shù)

             LPD3DXBUFFER    _pBoneCombBuf;  //鄰接矩陣列表
             D3DXMATRIX**    _ppBoneMatrixPtr; //骨骼矩陣列表
             D3DXMATRIX*     _pBoneOffsetMatrices; //骨骼矩陣引用

             DWORD      _iAttrSW; //用戶 GenerateSkinnedMesh
            };


            //------------------------------------------------------------
            //說明:封裝網(wǎng)格的創(chuàng)建類
            //------------------------------------------------------------

            class GAllocateHierarchy : public ID3DXAllocateHierarchy
            {
            public:

            // 下面4個方法是對父類的實現(xiàn)
                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);

            };

             

            //----------------------------------------------------
            // 創(chuàng)建框架
            //----------------------------------------------------
            HRESULT GAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME * ppNewFrame)
            {
             HRESULT hr;
             GFrame * pFrame;
             pFrame = new GFrame();

             *ppNewFrame = NULL;

             if( !pFrame)
             {
              hr = E_OUTOFMEMORY;
              goto e_Exit;
             }

             //復(fù)制框架名稱
             hr = HeapCopy( Name, &pFrame->Name);
             if( FAILED( hr) )
              goto e_Exit;

             //初始化其它屬性
             D3DXMatrixIdentity( &pFrame->TransformationMatrix);
             D3DXMatrixIdentity( &pFrame->CombinedTransformationMatrix);

             pFrame->pMeshContainer = NULL;
             pFrame->pFrameFirstChild = NULL;
             pFrame->pFrameSibling = NULL;

            //復(fù)制到新框架
             *ppNewFrame = pFrame;
             pFrame = NULL;

            e_Exit:
             delete pFrame;
             return hr;
            }

             

            //----------------------------------------------------
            // 創(chuàng)建Mesh
            //----------------------------------------------------
            HRESULT GAllocateHierarchy::CreateMeshContainer(
             LPCSTR Name,
             CONST D3DXMESHDATA * pMeshData,
             CONST D3DXMATERIAL * pMaterials,
             CONST D3DXEFFECTINSTANCE * pEffectInst,
             DWORD dwNumMaterials,
             CONST DWORD * pAdjacency,
             LPD3DXSKININFO pSkinInfo,
             LPD3DXMESHCONTAINER * ppNewMeshContainer)
            {
             HRESULT hr;
             GMeshContainer * pMeshContainer = NULL;
             UINT iNumFaces;
             LPDIRECT3DDEVICE9 pDev = NULL;

             LPD3DXMESH pMesh = NULL;

             *ppNewMeshContainer = NULL;

             //----------------------------
             //驗證異常
             if( pMeshData->Type != D3DXMESHTYPE_MESH)
             {
              hr = E_FAIL;
              goto e_Exit;
             }

             pMesh = pMeshData->pMesh;

             if( pMesh->GetFVF() == 0)
             {
              hr = E_FAIL;
              goto e_Exit;
             }

             pMeshContainer = new GMeshContainer();
             if( pMeshContainer == NULL)
             {
              hr = E_OUTOFMEMORY;
              goto e_Exit;
             }

             
             //-------------------------
             //初始化 pMeshContainer ,復(fù)制名字, 獲取pDev , 獲取面信息

             memset( pMeshContainer, 0, sizeof( GMeshContainer));

             hr = HeapCopy( Name, &pMeshContainer->Name);
             if( FAILED( hr))
              goto e_Exit;

             pMesh->GetDevice( & pDev);

             iNumFaces = pMesh->GetNumFaces();


             //--------------------------
             //判斷是否要處理法向量,并復(fù)制 Mesh

             if( !(pMesh->GetFVF() & D3DFVF_NORMAL) ) //如果沒有法向量,則添加法向量
             {
              pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

              hr = pMesh->CloneMeshFVF( pMesh->GetOptions(),
                    pMesh->GetFVF() | D3DFVF_NORMAL,
                    pDev,
                    &pMeshContainer->MeshData.pMesh);

              if( FAILED( hr))
               goto e_Exit;

              pMesh = pMeshContainer->MeshData.pMesh;

              D3DXComputeNormals( pMesh, NULL);
             }
             else //如果有法向量,則直接復(fù)制 Mesh
             {
              pMeshContainer->MeshData.pMesh = pMesh;
              pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
              pMesh->AddRef();
             }

             
             //----------------------------
             // 獲取材質(zhì)個數(shù),并初始化材質(zhì)、紋理、鄰接矩陣信息
             pMeshContainer->NumMaterials = max( 1, dwNumMaterials);
             pMeshContainer->pMaterials = new D3DXMATERIAL[ pMeshContainer->NumMaterials ];
             pMeshContainer->_ppTexs = new LPDIRECT3DTEXTURE9[ pMeshContainer->NumMaterials ];
             pMeshContainer->pAdjacency = new DWORD[ iNumFaces * 3];

             if( pMeshContainer->pMaterials == NULL || pMeshContainer->pAdjacency == NULL)
             {
              hr = E_OUTOFMEMORY;
              goto e_Exit;
             }

             memcpy( pMeshContainer->pAdjacency, pAdjacency, sizeof( DWORD) * iNumFaces * 3);
             memset( pMeshContainer->_ppTexs, 0, sizeof( LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);


             //--------------------------------
             // 復(fù)制材質(zhì),創(chuàng)建紋理
             if( dwNumMaterials > 0) //如果有材質(zhì),則復(fù)制材質(zhì)
             {
              memcpy( pMeshContainer->pMaterials, pMaterials, sizeof( D3DXMATERIAL) * dwNumMaterials);
              for( UINT i = 0; i < dwNumMaterials; ++i)
              {
               //如果有紋理則加載紋理
               if( pMeshContainer->pMaterials[ i ].pTextureFilename != NULL)
               {
                LPSTR pFileName = pMeshContainer->pMaterials[ i ].pTextureFilename;
                if( FAILED( D3DXCreateTextureFromFileA( pDev, pFileName, &pMeshContainer->_ppTexs[ i ])) )
                 pMeshContainer->_ppTexs[ i ] = NULL;

                //清除紋理文件名
                pMeshContainer->pMaterials[ i ].pTextureFilename = NULL;
               }
              }
             }
             else //如果沒有材質(zhì)則初始化默認(rèn)值
             {
              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;
             }


             //----------------------------
             //如果有 Skin 則創(chuàng)建 Skin,并創(chuàng)建拷貝它的骨骼矩陣信息
             if( pSkinInfo != NULL)
             {
              pMeshContainer->pSkinInfo = pSkinInfo;
              pSkinInfo->AddRef();

              pMeshContainer->_pOrigMesh = pMesh;
              pMesh->AddRef();

              UINT iTotalBones = pSkinInfo->GetNumBones();

              pMeshContainer->_pBoneOffsetMatrices = new D3DXMATRIX[ iTotalBones ];
              if( pMeshContainer->_pBoneOffsetMatrices == NULL)
              {
               hr = E_OUTOFMEMORY;
               goto e_Exit;
              }

              for( UINT i = 0; i < iTotalBones; ++i)
              {
               pMeshContainer->_pBoneOffsetMatrices[ i ] = *(pSkinInfo->GetBoneOffsetMatrix( i ));
              }

              hr = GenerateSkinnedMesh( pDev, pMeshContainer);
              if( FAILED( hr ) )
               goto e_Exit;
             }


             //--------------------------
             // 賦值 MeshContainer
             *ppNewMeshContainer = pMeshContainer;
             pMeshContainer = NULL;

            e_Exit:
             SAFE_RELEASE( pDev);

             if( pMeshContainer != NULL)
              DestroyMeshContainer( pMeshContainer);

             return hr;
            }

             

             


            //----------------------------------------------------
            // 銷毀 Frame
            //----------------------------------------------------
            HRESULT GAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree)
            {
             SAFE_DELETE_ARRAY( pFrameToFree->Name);
             SAFE_DELETE( pFrameToFree);
             return S_OK;
            }

             

            //----------------------------------------------------
            // 銷毀 MeshContainer
            //----------------------------------------------------
            HRESULT GAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerToFree)
            {
             GMeshContainer * pMeshContainer = ( GMeshContainer *) pMeshContainerToFree;

             SAFE_DELETE_ARRAY( pMeshContainer->Name);
             SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
             SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
             SAFE_DELETE_ARRAY( pMeshContainer->_pBoneOffsetMatrices);

             if( pMeshContainer->_ppTexs != NULL)
             {
              for( UINT i = 0; i < pMeshContainer->NumMaterials; ++i)
              {
               SAFE_RELEASE( pMeshContainer->_ppTexs[ i ]);
              }
             }

             SAFE_DELETE_ARRAY( pMeshContainer->_ppTexs );
             SAFE_DELETE_ARRAY( pMeshContainer->_ppBoneMatrixPtr);
             SAFE_RELEASE( pMeshContainer->_pBoneCombBuf);
             SAFE_RELEASE( pMeshContainer->MeshData.pMesh);
             SAFE_RELEASE( pMeshContainer->pSkinInfo );
             SAFE_RELEASE( pMeshContainer->_pOrigMesh);
             SAFE_DELETE( pMeshContainer );
             return S_OK;
            }

             

            //----------------------------------------------------
            // 為 MeshContainer生成紋理
            //----------------------------------------------------
            // pNumBoneMatrixMax 為最大受骨骼影響的數(shù)目
            HRESULT GAllocateHierarchy::GenerateSkinnedMesh( IDirect3DDevice9 * pDev, GMeshContainer * pMeshContainer)
            {
             HRESULT hr = S_OK;
             D3DCAPS9 caps;
             pDev->GetDeviceCaps( & caps);

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

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

             
              UINT iMaxMatrices = 26;

              pMeshContainer->_dwNumPaletteEntries = min( iMaxMatrices, pMeshContainer->pSkinInfo->GetNumBones());

              DWORD Flags = D3DXMESHOPT_VERTEXCACHE;
               Flags |= D3DXMESH_MANAGED;

              SAFE_RELEASE( pMeshContainer->MeshData.pMesh);

              hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(
               pMeshContainer->_pOrigMesh,
               Flags,
               pMeshContainer->_dwNumPaletteEntries,
               pMeshContainer->pAdjacency,
               NULL, NULL, NULL,
               & pMeshContainer->_dwMaxNumInfl,
               & pMeshContainer->_dwNumAttrGroups,
               & pMeshContainer->_pBoneCombBuf,
               & pMeshContainer->MeshData.pMesh );

              if( FAILED( hr ) )
               goto e_Exit;

              DWORD NewFVF = ( pMeshContainer->MeshData.pMesh->GetFVF() & D3DFVF_POSITION_MASK) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4;
              if( NewFVF != pMeshContainer->MeshData.pMesh->GetFVF() )
              {
               LPD3DXMESH pMesh;
               hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF( pMeshContainer->MeshData.pMesh->GetOptions(), NewFVF, pDev, &pMesh);
               if( ! FAILED( hr ) )
               {
                pMeshContainer->MeshData.pMesh->Release();
                pMeshContainer->MeshData.pMesh = pMesh;
                pMesh = NULL;
               }
              }

              D3DVERTEXELEMENT9 pDecl[ MAX_FVF_DECL_SIZE];
              LPD3DVERTEXELEMENT9 pDeclCur;
              hr = pMeshContainer->MeshData.pMesh->GetDeclaration( pDecl);
              if( FAILED( hr ) )
               goto e_Exit;

              pDeclCur = pDecl;
              while( pDeclCur->Stream != 0xff)
              {
               if( (pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES) && ( pDeclCur->UsageIndex == 0 ) )
                pDeclCur->Type = D3DDECLTYPE_D3DCOLOR;
               pDeclCur++;
              }

              hr = pMeshContainer->MeshData.pMesh->UpdateSemantics( pDecl);
              if( FAILED( hr ) )
               goto e_Exit;

              if( m_iNumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones() )
              {
               m_iNumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();

               SAFE_DELETE_ARRAY( m_pBoneMatrices);
               m_pBoneMatrices = new D3DXMATRIXA16[ m_iNumBoneMatricesMax ];
               if( *m_pBoneMatrices == NULL)
               {
                hr = E_OUTOFMEMORY;
                goto e_Exit;
               }
              }
                      
             //}

            e_Exit:
             return hr;
            }


               創(chuàng)建兩個全局指針:

            LPD3DXFRAME             g_pFrameRoot = NULL;      //根Frame
            ID3DXAnimationController* g_pAnimCtl = NULL; //動畫控制類

               接著在初始化的地方(如果使用DXUT,則可以在OnCreateDevice中)調(diào)用 D3DXLoadMeshHierarchyFromX 來加載x文件。

             GAllocateHierarchy ah;

            D3DXLoadMeshHierarchyFromX( strXFileName, D3DXMESH_MANAGED, pDev, 
                     & ah, NULL, & g_pFrameRoot, &g_pAnimCtl );

            SetupBoneMatrixPointers( g_pFrameRoot, g_pFrameRoot);  //建立矩陣指針
             D3DXFrameCalculateBoundingSphere( g_pFrameRoot, & g_vObjCenter,  g_fObjRadius );  //獲取模型邊界球

            SetupBoneMatrixPointers 實現(xiàn)如下:


            //------------------------------------------------------------
            //desc:為框架建立骨骼矩陣
            //param: pFrame 當(dāng)前框架
            //param: pFrameRoot 根框架
            //return: 操作是否成功
            //------------------------------------------------------------

            HRESULT XFileObjBuilder::SetupBoneMatrixPointers(LPD3DXFRAME pFrame, LPD3DXFRAME pFrameRoot)
            {
             HRESULT hr;

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

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

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

             return S_OK;
            }

             


            //------------------------------------------------------------
            //desc: 為網(wǎng)格容器創(chuàng)建骨骼矩陣
            //param: pMeshContainer 當(dāng)前容器
            //param: pFrameRoot 根框架
            //return: 操作是否成功
            //------------------------------------------------------------

            HRESULT XFileObjBuilder::SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameRoot)
            {
             GFrame * pFrame;

             GMeshContainer * pMeshContainer = (GMeshContainer *) pMeshContainerBase;

             
             if( pMeshContainer->pSkinInfo != NULL)
             {
              UINT iTotalBones = pMeshContainer->pSkinInfo->GetNumBones();

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

              for( UINT i = 0; i < iTotalBones; ++i)
              {
               pFrame = (GFrame *) D3DXFrameFind( pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName( i));

               if( NULL == pFrame)
                return E_FAIL;

               pMeshContainer->_ppBoneMatrixPtr[ i ] = & pFrame->CombinedTransformationMatrix;
              }
             }

             return S_OK;
            }


               接著在更新信息的地方(如果使用DXUT,則可以在OnFrameMove中添加)添加以下代碼:
             UpdateFrameMatrices( g_pFrameRoot, &matWorld); //更新骨骼矩陣(其中 matWorld 可以包含模型的平移、縮放、旋轉(zhuǎn)信息)

             if( g_pAnimCtl != NULL)
              g_pAnimCtl->AdvanceTime( fElapsedTime, NULL); //更新動畫信息就靠它了
            UpdateFrameMatrices 的實現(xiàn)如下:

            //------------------------------------------------------------
            //desc: 更新框架矩陣
            //param: pFrameBase 當(dāng)前框架
            //param: pParentMatrix 父框架矩陣
            //------------------------------------------------------------

            void G3DObjEntity::UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
            {
             assert( pFrameBase != NULL);
             assert( pParentMatrix != NULL);

             GFrame * pFrame = (GFrame *) 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);

            }

             


               最后在渲染的地方(如果使用DXUT,則在 OnFrameRender中)調(diào)用:
             DrawFrame( pDev, g_pFrameRoot); 

            DrawFrame 的實現(xiàn)如下:

            //------------------------------------------------------------
            //desc: 畫框架
            //param: matView 視口矩陣
            //param: pDev 設(shè)備
            //param: pFrame 框架
            //------------------------------------------------------------

            void G3DObjEntity::DrawFrame(IDirect3DDevice9 * pDev, LPD3DXFRAME  pFrame)
            {
             LPD3DXMESHCONTAINER pMeshContainer = pFrame->pMeshContainer;

             while( pMeshContainer != NULL)
             {
              DrawMeshContainer( pDev, pMeshContainer, pFrame);
              pMeshContainer = pMeshContainer->pNextMeshContainer;
             }

             if( pFrame->pFrameSibling != NULL)
              DrawFrame( pDev, pFrame->pFrameSibling);

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

             

             

            //------------------------------------------------------------
            //desc: 畫網(wǎng)格
            //param: matView 視口矩陣
            //param: pDev 設(shè)備
            //param: pMeshContainerBase 網(wǎng)格指針
            //param: pFrameBase 框架指針
            //------------------------------------------------------------

            void G3DObjEntity::DrawMeshContainer( IDirect3DDevice9 * pDev, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
            {
             HRESULT hr;
             GFrame * pFrame = ( GFrame *) pFrameBase;
             GMeshContainer * pMeshContainer = ( GMeshContainer *) pMeshContainerBase;

             UINT iMaterial;
             UINT iNumBlend;
             UINT iAttr;
             DWORD iAttrIdPrev;
             LPD3DXBONECOMBINATION pBoneComb;
             UINT iMatrixIndex;
             UINT iPaletteEntry;
             D3DXMATRIXA16 matTemp;

             LPD3DXEFFECT pEffect = NULL;
             if( m_pObjInfo != NULL && m_pObjInfo->GetEffectProxy() != NULL)
             {
              pEffect = m_pObjInfo->GetEffectProxy()->GetEffect();
             }

             D3DCAPS9 caps;
             pDev->GetDeviceCaps( & caps);

             if( pMeshContainer->pSkinInfo != NULL) //如果有蒙皮信息,則用HLSL處理蒙皮動畫
             {

              D3DXMATRIX matView = * GlobalState::GetInstance()->GetCamera()->GetViewMatrix(); //這里使用DXUT 提供的攝像機

               pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->_pBoneCombBuf->GetBufferPointer());
               for( iAttr = 0; iAttr < pMeshContainer->_dwNumAttrGroups; ++iAttr)
               {
                for( iPaletteEntry = 0; iPaletteEntry < pMeshContainer->_dwNumPaletteEntries; ++iPaletteEntry)
                {
                 iMatrixIndex = pBoneComb[ iAttr].BoneId[ iPaletteEntry];
                 if( iMatrixIndex != UINT_MAX )
                 {       
                  D3DXMatrixMultiply( & m_pObjInfo->m_pBoneMatrices[ iPaletteEntry], & pMeshContainer->_pBoneOffsetMatrices[ iMatrixIndex ], pMeshContainer->_ppBoneMatrixPtr[ iMatrixIndex ]);   
                 }
                }

               //把骨骼矩陣信息添加到 D3DXEFFECT 中
                V( pEffect->SetMatrixArray( "amPalette", m_pObjInfo->m_pBoneMatrices, pMeshContainer->_dwNumPaletteEntries) );
                
                D3DXCOLOR color1( pMeshContainer->pMaterials[ pBoneComb[iAttr].AttribId].MatD3D.Ambient);
                D3DXCOLOR color2(0.25, 0.25, 0.25, 1.0);
                D3DXCOLOR ambEmm;
                D3DXColorModulate( &ambEmm, &color1, &color2);
                ambEmm += D3DXCOLOR( pMeshContainer->pMaterials[ pBoneComb[iAttr].AttribId].MatD3D.Emissive);

                //把材質(zhì)信息添加到D3DXEFFECT中
            V( pEffect->SetVector("g_materialDiffuse", (D3DXVECTOR4*) &(pMeshContainer->pMaterials[pBoneComb[iAttr].AttribId].MatD3D.Diffuse)) );
                V( pEffect->SetVector("g_materialAmbient", (D3DXVECTOR4*) & ambEmm) );

                V( pDev->SetTexture( 0, pMeshContainer->_ppTexs[ pBoneComb[iAttr].AttribId] ) );

                V( pEffect->SetInt( "g_curNumBones", pMeshContainer->_dwMaxNumInfl - 1) );

                UINT numPasses;
                V( pEffect->Begin( &numPasses, D3DXFX_DONOTSAVESTATE) );
                for( UINT iPass = 0; iPass < numPasses; ++iPass)
                {
                 V( pEffect->BeginPass( iPass));
                 V( pMeshContainer->MeshData.pMesh->DrawSubset( iAttr));
                 V( pEffect->EndPass() );
                }

                V( pEffect->End() );
                
                V( pDev->SetVertexShader( NULL) );
               }

             }
             else //如果沒有skin ,則直接設(shè)置材質(zhì)
             {
              V( pDev->SetTransform( D3DTS_WORLD, &pFrame->CombinedTransformationMatrix ) );

              for( iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; ++iMaterial)
              {
               V( pDev->SetMaterial( &pMeshContainer->pMaterials[ iMaterial ].MatD3D) );
               V( pDev->SetTexture( 0, pMeshContainer->_ppTexs[ iMaterial ] ) );
               V( pMeshContainer->MeshData.pMesh->DrawSubset( iMaterial) );
              }
             }
            }


              到此為止就可以實現(xiàn)加載和渲染動畫了,這個實現(xiàn)的過程也有點復(fù)雜,一不小心搞錯了某個地方,可能折騰半天都找不出原因。
            精品国产热久久久福利| 一本一道久久精品综合| 久久97久久97精品免视看| 亚洲午夜精品久久久久久人妖| 青青青国产精品国产精品久久久久 | 久久国产乱子伦免费精品| 久久久噜噜噜久久中文福利| 秋霞久久国产精品电影院| 亚洲精品无码专区久久同性男| 久久久久久国产精品免费无码| 国产一区二区三精品久久久无广告| 欧美日韩精品久久久久| 国内精品久久久久久野外| 精品久久综合1区2区3区激情| 无码人妻久久一区二区三区免费| segui久久国产精品| 午夜精品久久久久久毛片| 大蕉久久伊人中文字幕| 久久精品aⅴ无码中文字字幕重口| 精品久久久久国产免费| 精品久久久久中文字幕日本| 久久久久18| 亚洲国产精品久久久久网站| 午夜不卡久久精品无码免费| 久久人人爽人爽人人爽av| 久久香蕉国产线看观看99| 97久久超碰国产精品2021| 亚洲va久久久噜噜噜久久天堂| 精品久久久久久国产免费了| 99久久中文字幕| 久久久久久亚洲Av无码精品专口| 亚洲中文字幕无码久久2017| 久久毛片一区二区| 亚洲欧洲久久av| 国产精品久久久久蜜芽| 亚洲精品无码久久久| 午夜视频久久久久一区| 亚洲精品无码久久不卡| 久久久久亚洲AV无码专区首JN| 久久国产精品无| 精品久久人人爽天天玩人人妻|