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

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>
            亚洲视频一区二区免费在线观看| 久久av一区二区三区| 久久精品视频va| 欧美在线免费一级片| 欧美中文字幕在线| 久久综合九色综合网站 | 在线视频欧美精品| 亚洲午夜激情免费视频| 午夜伦欧美伦电影理论片| 久久精品一级爱片| 裸体歌舞表演一区二区| 亚洲精品护士| 最新亚洲激情| 午夜在线观看免费一区| 免费不卡亚洲欧美| 国产精品久久久爽爽爽麻豆色哟哟| 国产伦精品一区二区三区照片91 | 国产一区二区三区四区三区四| 在线日韩欧美| 性高湖久久久久久久久| 欧美www在线| 亚洲视频第一页| 久久女同精品一区二区| 欧美日韩一区综合| 在线成人欧美| 亚洲一区二区在线免费观看| 久久一区二区视频| 一区二区三区.www| 免费成人在线观看视频| 国产欧美一区二区三区久久| 亚洲精品日本| 另类天堂av| 亚洲欧美另类中文字幕| 欧美成人国产一区二区 | 一区二区三区波多野结衣在线观看| 性欧美1819性猛交| 亚洲人午夜精品| 久久免费高清视频| 国产欧美日韩综合一区在线播放 | 国产精品午夜视频| 洋洋av久久久久久久一区| 久久综合综合久久综合| 亚洲欧美另类久久久精品2019| 欧美人与性动交α欧美精品济南到| 激情一区二区| 久久国产精品一区二区| 美女成人午夜| 国产精品爱久久久久久久| 在线观看视频免费一区二区三区| 亚洲欧美久久久| 国模精品一区二区三区色天香| 亚洲男人av电影| 亚洲黄色高清| 欧美黄在线观看| 最新成人av网站| 欧美激情亚洲| 欧美国产在线电影| 日韩视频免费在线| 亚洲黄色在线| 欧美日韩一区二区视频在线 | 国产精品午夜av在线| 亚洲在线黄色| 一本综合久久| 国产精品视频免费观看www| 在线视频一区观看| 一区二区三区福利| 国产精品天天摸av网| 久久精品国产99精品国产亚洲性色| 亚洲免费在线观看视频| 国产亚洲精品自拍| 久久综合免费视频影院| 久久久久国产一区二区三区| 狠狠噜噜久久| 一区二区高清视频在线观看| 亚洲激情在线视频| 欧美日韩国产在线看| 亚洲一区精品视频| 小黄鸭精品aⅴ导航网站入口| 国产一区自拍视频| 亚洲国产成人在线| 欧美性开放视频| 久久久久女教师免费一区| 麻豆国产精品777777在线| 亚洲欧洲在线免费| 亚洲视频每日更新| 国产综合自拍| 亚洲精品男同| 国产欧亚日韩视频| 欧美福利视频在线观看| 欧美久色视频| 欧美一区免费视频| 免费成人性网站| 亚洲一区日韩| 久久全球大尺度高清视频| 一区二区激情视频| 欧美伊人影院| 一区二区日韩伦理片| 久久精品国产99精品国产亚洲性色 | 99www免费人成精品| 国产伦精品一区二区三| 一区二区不卡在线视频 午夜欧美不卡'| 亚洲开发第一视频在线播放| 国产日韩欧美视频在线| 欧美一区=区| 亚洲高清视频在线| 亚洲国产天堂久久国产91| 欧美日韩综合在线免费观看| 久久久国产成人精品| 欧美成人一二三| 久久精品夜色噜噜亚洲a∨| 欧美激情aⅴ一区二区三区| 久久久99爱| 国产精品xvideos88| 欧美插天视频在线播放| 国产精品久久久久久久免费软件| 欧美sm重口味系列视频在线观看| 国产精品人成在线观看免费| 亚洲区免费影片| 亚洲大片一区二区三区| 亚洲欧美激情诱惑| 亚洲尤物视频网| 欧美精品福利在线| 亚洲第一主播视频| 在线精品亚洲| 久久久噜噜噜久久| 久久精品99久久香蕉国产色戒| 欧美日韩国产高清视频| 亚洲国产精品久久久久秋霞蜜臀 | 亚洲一区二区精品| 免费欧美电影| 欧美成人国产一区二区| 激情综合久久| 久久精品一区二区三区不卡| 欧美在线一级视频| 国产日韩欧美综合精品| 亚洲综合清纯丝袜自拍| 亚洲欧美国产三级| 国产精品视频免费一区| 亚洲欧美日韩国产综合在线| 久久成人综合网| 国模套图日韩精品一区二区| 久久久久国产精品一区三寸| 欧美jizz19hd性欧美| 在线免费一区三区| 欧美成人一区二区三区在线观看| 亚洲国产高清aⅴ视频| 亚洲老板91色精品久久| 欧美精品不卡| 在线亚洲激情| 久久激情视频久久| 激情小说另类小说亚洲欧美| 另类天堂av| 亚洲伦伦在线| 欧美在线网站| 亚洲电影在线看| 欧美激情一二三区| 一本色道久久综合狠狠躁篇的优点 | 国产目拍亚洲精品99久久精品| 亚洲综合三区| 午夜视频在线观看一区二区| 午夜视频在线观看一区| 国产欧美一区二区精品性| 久久国产精品99国产精| 蜜桃精品一区二区三区| 亚洲每日在线| 国产精品一二| 老司机精品视频一区二区三区| 亚洲国产精品一区二区尤物区| 亚洲在线播放| 激情久久五月天| 欧美日韩免费高清| 久久精品国产91精品亚洲| 亚洲欧洲综合| 久久中文字幕一区二区三区| 一区二区免费在线播放| 国产综合香蕉五月婷在线| 欧美精品18| 欧美在线免费播放| 99re6这里只有精品| 久久综合中文字幕| 亚洲一区二区三区欧美| 揄拍成人国产精品视频| 国产精品国产三级国产专区53| 久久精品一区二区国产| 亚洲色图自拍| 亚洲国产精品热久久| 久久久99爱| 性做久久久久久| 亚洲免费成人av| 伊人久久大香线蕉综合热线| 国产精品免费网站| 欧美日韩国产精品一卡| 蜜桃视频一区| 久久久91精品国产| 亚洲欧美国产毛片在线| 一区二区三区欧美成人| 最新高清无码专区| 欧美成人dvd在线视频| 久久精品一区二区三区中文字幕| 亚洲天堂成人|