青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

HLSL實現蒙皮動畫(1)

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

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

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

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

 

 

//------------------------------------------------------------
//說明:網格容器
//------------------------------------------------------------

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

 LPD3DXMESH     _pOrigMesh;  //原mesh

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

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

 DWORD      _iAttrSW; //用戶 GenerateSkinnedMesh
};


//------------------------------------------------------------
//說明:封裝網格的創建類
//------------------------------------------------------------

class GAllocateHierarchy : public ID3DXAllocateHierarchy
{
public:

// 下面4個方法是對父類的實現
    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 GAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME * ppNewFrame)
{
 HRESULT hr;
 GFrame * pFrame;
 pFrame = new GFrame();

 *ppNewFrame = NULL;

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

 //復制框架名稱
 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;

//復制到新框架
 *ppNewFrame = pFrame;
 pFrame = NULL;

e_Exit:
 delete pFrame;
 return hr;
}

 

//----------------------------------------------------
// 創建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 ,復制名字, 獲取pDev , 獲取面信息

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

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

 pMesh->GetDevice( & pDev);

 iNumFaces = pMesh->GetNumFaces();


 //--------------------------
 //判斷是否要處理法向量,并復制 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 //如果有法向量,則直接復制 Mesh
 {
  pMeshContainer->MeshData.pMesh = pMesh;
  pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  pMesh->AddRef();
 }

 
 //----------------------------
 // 獲取材質個數,并初始化材質、紋理、鄰接矩陣信息
 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);


 //--------------------------------
 // 復制材質,創建紋理
 if( dwNumMaterials > 0) //如果有材質,則復制材質
 {
  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 //如果沒有材質則初始化默認值
 {
  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 則創建 Skin,并創建拷貝它的骨骼矩陣信息
 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 為最大受骨骼影響的數目
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;
}


   創建兩個全局指針:

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

   接著在初始化的地方(如果使用DXUT,則可以在OnCreateDevice中)調用 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 實現如下:


//------------------------------------------------------------
//desc:為框架建立骨骼矩陣
//param: pFrame 當前框架
//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: 為網格容器創建骨骼矩陣
//param: pMeshContainer 當前容器
//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 可以包含模型的平移、縮放、旋轉信息)

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

//------------------------------------------------------------
//desc: 更新框架矩陣
//param: pFrameBase 當前框架
//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中)調用:
 DrawFrame( pDev, g_pFrameRoot); 

DrawFrame 的實現如下:

//------------------------------------------------------------
//desc: 畫框架
//param: matView 視口矩陣
//param: pDev 設備
//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: 畫網格
//param: matView 視口矩陣
//param: pDev 設備
//param: pMeshContainerBase 網格指針
//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);

    //把材質信息添加到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 ,則直接設置材質
 {
  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) );
  }
 }
}


  到此為止就可以實現加載和渲染動畫了,這個實現的過程也有點復雜,一不小心搞錯了某個地方,可能折騰半天都找不出原因。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美va亚洲va香蕉在线| 艳女tv在线观看国产一区| 欧美一区二区三区免费观看视频| 国产精品久久久久久久午夜片| 亚洲欧美国产三级| 欧美一级播放| 亚洲欧洲日韩在线| 99视频超级精品| 国产精品日韩欧美一区| 国产精品毛片| 伊人男人综合视频网| 欧美不卡一卡二卡免费版| 欧美不卡一卡二卡免费版| 洋洋av久久久久久久一区| 亚洲午夜成aⅴ人片| 国产一区视频观看| 亚洲国产精品激情在线观看| 欧美日韩国产色综合一二三四| 亚洲欧美日本国产有色| 久久精品国产2020观看福利| 亚洲精品中文字幕在线| 午夜精品成人在线| 亚洲乱码国产乱码精品精可以看| 亚洲图片欧洲图片av| 亚洲第一区中文99精品| 亚洲图片在区色| 亚洲激情视频网| 午夜在线精品| 中文一区二区在线观看| 久久久精品欧美丰满| 亚洲私拍自拍| 欧美风情在线| 久久久九九九九| 国产精品高潮呻吟久久| 欧美高清在线精品一区| 国产午夜精品美女毛片视频| 最新国产拍偷乱拍精品| 伊人激情综合| 欧美一区2区视频在线观看| 亚洲视频精品| 欧美激情1区2区3区| 老司机午夜精品| 国产美女精品人人做人人爽| 亚洲精品日韩久久| 亚洲激情婷婷| 老司机免费视频一区二区| 欧美一级夜夜爽| 国产精品都在这里| 99国产精品99久久久久久| 亚洲人午夜精品免费| 久久久久久午夜| 久久久久久999| 国产欧美婷婷中文| 亚洲主播在线观看| 亚洲在线第一页| 欧美午夜电影在线| 一本色道久久综合亚洲91| 99精品热视频| 欧美精品一二三| 亚洲人成欧美中文字幕| 91久久黄色| 欧美激情按摩| 亚洲精品美女久久7777777| 亚洲欧洲日韩女同| 欧美激情第1页| 99精品视频一区二区三区| 亚洲日本视频| 欧美日产国产成人免费图片| 亚洲人成欧美中文字幕| 在线视频你懂得一区| 欧美美女日韩| 国产精品99久久久久久宅男| 亚洲综合色网站| 国产午夜精品理论片a级大结局| 欧美亚洲网站| 毛片精品免费在线观看| 激情视频一区二区三区| 亚洲国产日韩美| 免费一级欧美在线大片| 亚洲激情国产精品| 亚洲人成网站色ww在线| 欧美日韩国产美| 亚洲男人的天堂在线aⅴ视频| 久久久99精品免费观看不卡| 娇妻被交换粗又大又硬视频欧美| 久久婷婷丁香| 日韩亚洲在线观看| 久久成人精品无人区| 亚洲国产91| 欧美日韩专区在线| 久久精品成人一区二区三区| 欧美国产欧美亚州国产日韩mv天天看完整| 亚洲高清视频中文字幕| 欧美午夜欧美| 蜜桃av噜噜一区二区三区| 艳女tv在线观看国产一区| 久久全国免费视频| 亚洲精品一区二区三区福利| 欧美网站在线| 久久网站免费| 亚洲午夜未删减在线观看| 久久在线视频在线| 亚洲在线视频观看| 亚洲福利视频一区| 国产精品免费一区二区三区在线观看| 久久成人18免费网站| 亚洲剧情一区二区| 久久久青草婷婷精品综合日韩| 99热这里只有成人精品国产| 国产欧美日韩免费| 欧美日韩另类丝袜其他| 久久精品国产精品亚洲| 亚洲一级一区| 亚洲精品日韩在线观看| 美腿丝袜亚洲色图| 欧美一区二区三区四区在线观看| 亚洲精品中文在线| 亚洲电影在线| 国产一本一道久久香蕉| 国产精品成人一区二区网站软件 | 国产午夜精品一区二区三区欧美 | 久久久久中文| 欧美在线一二三区| 亚洲欧美日韩一区二区三区在线观看 | 妖精视频成人观看www| 影音先锋欧美精品| 国产精品资源| 国产精品久久久对白| 欧美日韩国产成人在线91| 蜜桃久久av一区| 久久免费99精品久久久久久| 小辣椒精品导航| 亚洲自拍电影| 亚洲一区二区三区中文字幕在线 | 亚洲国产精品福利| 老鸭窝91久久精品色噜噜导演| 销魂美女一区二区三区视频在线| 一区二区三区国产在线观看| 亚洲区欧美区| 亚洲人成绝费网站色www| 在线观看一区二区视频| 一区二区三区无毛| 极品尤物av久久免费看| 黄色小说综合网站| 在线成人www免费观看视频| 国产综合在线视频| 狠狠色丁香婷综合久久| 国内精品一区二区三区| 一区二区在线视频| 亚洲电影天堂av| 亚洲免费激情| 亚洲欧美一区二区精品久久久| 亚洲性图久久| 欧美在线精品免播放器视频| 久久国产视频网站| 裸体素人女欧美日韩| 亚洲二区精品| 亚洲免费成人av电影| 在线视频你懂得一区二区三区| 在线一区亚洲| 久久精品国产欧美激情| 欧美1区2区| 欧美丝袜一区二区| 国内精品免费在线观看| 在线看日韩av| 亚洲一区影音先锋| 久久免费99精品久久久久久| 欧美高清一区| 亚洲一区二区三区中文字幕| 欧美一级午夜免费电影| 欧美成人免费全部| 国产精品久久久久久久久免费 | 欧美一区1区三区3区公司| 美女任你摸久久| 日韩视频亚洲视频| 久久精品国产一区二区三| 欧美激情精品久久久久久| 国产精品你懂的在线| 亚洲第一页中文字幕| 午夜久久资源| 亚洲国产日韩欧美| 性欧美办公室18xxxxhd| 欧美+亚洲+精品+三区| 国产精品一级久久久| 亚洲娇小video精品| 亚洲男女毛片无遮挡| 欧美成人国产va精品日本一级| 夜夜嗨av色一区二区不卡| 久久久精品免费视频| 国产精品每日更新| 亚洲精品三级| 欧美va亚洲va香蕉在线| 亚洲一区亚洲二区| 欧美精品久久久久久久久久| 国产亚洲一区二区三区| 在线亚洲精品| 亚洲激情在线观看| 久久婷婷蜜乳一本欲蜜臀| 国产精品人人做人人爽| 中国成人黄色视屏|