《精通DirectX 3D》 第二十一章 HLSL高级应用 07_HLSLSkinMesh

《精通DirectX 3D》 第二十一章 HLSL高级应用 07_HLSLSkinMesh



《精通DirectX 3D》 第二十一章 HLSL高级应用 07_HLSLSkinMesh_第1张图片

HLSLSkinMesh.fx

// =========================================================
//  Desc: 效果源代码
// =========================================================


// ---------------------------------------------------------
//  全局变量
// ---------------------------------------------------------
float4 lightDir  =  { 0.0f 0.0f - 1.0f 1.0f };
float4 lightDiffuse 
=  { 0.6f 0.6f 0.6f 1.0f }; 
float4 MaterialAmbient 
=  { 0.1f 0.1f 0.1f 1.0f };
float4 MaterialDiffuse 
=  { 0.8f 0.8f 0.8f 1.0f };

static   const   int  MAX_MATRICES  =   26 ;
float4x3    mWorldMatrixArray[MAX_MATRICES];  
// 骨骼调色板矩阵 
int          CurNumBones  =   2 ;     // 当前骨骼数量
float4x4    mProj;

// ----------------------------------------------------------
//  顶点渲染器输入和输出结构
// ----------------------------------------------------------
struct  VS_INPUT
{
    float4  Pos           : POSITION;
    float4  BlendWeights  : BLENDWEIGHT;
    float4  BlendIndices  : BLENDINDICES;
    float3  Normal        : NORMAL;
    float3  Tex0          : TEXCOORD0;
};

struct  VS_OUTPUT
{
    float4  Pos     : POSITION;
    float4  Diffuse : COLOR;
    float2  Tex0    : TEXCOORD0;
};


// ---------------------------------------------------------
//  子函数, 计算光照系数
// ---------------------------------------------------------
float3 Diffuse(float3 Normal)
{
    
float  CosTheta;
    CosTheta 
=  max( 0.0f , dot(Normal, lightDir.xyz));
    
return  (CosTheta);
}

// ---------------------------------------------------------
//  子函数, 完成顶点处理
// ---------------------------------------------------------
VS_OUTPUT VShade(VS_INPUT i, uniform  int  NumBones)
{
    VS_OUTPUT   o;
    float3      Pos 
=   0.0f ;
    float3      Normal 
=   0.0f ;
    
float        sumWeight   =   0.0f ;
    
float        LastWeight  =   0.0f ;
     
    
// 为Geforce3类型的显卡所做的补偿
    int4 IndexVector  =  D3DCOLORtoUBYTE4(i.BlendIndices);
    
    
// 将骨骼权重向量和骨骼索引向量变换至数组
     float  BlendWeightsArray[ 4 =  ( float [ 4 ])i.BlendWeights;
    
int    IndexArray[ 4 ]         =  ( int [ 4 ])IndexVector;

    
// 计算前NumBones-1个骨骼对于该顶点位置及法向量的影响
     for  ( int  iBone  =   0 ; iBone  <  NumBones - 1 ; iBone ++ )
    {
        sumWeight 
=  sumWeight  +  BlendWeightsArray[iBone];
        
        Pos 
+=  mul(i.Pos, mWorldMatrixArray[IndexArray[iBone]])  *  BlendWeightsArray[iBone];
        Normal 
+=  mul(i.Normal, mWorldMatrixArray[IndexArray[iBone]])  *  BlendWeightsArray[iBone];
    }
    LastWeight 
=   1.0f   -  sumWeight; 

    
// 计算最后一个骨骼对于顶点位置及法向量的影响
    Pos  +=  (mul(i.Pos, mWorldMatrixArray[IndexArray[NumBones - 1 ]])  *  LastWeight);
    Normal 
+=  (mul(i.Normal, mWorldMatrixArray[IndexArray[NumBones - 1 ]])  *  LastWeight); 
    
    o.Pos 
=  mul(float4(Pos.xyz,  1.0f ), mProj);
    Normal 
=  normalize(Normal);

    
// 计算光照
    o.Diffuse.xyz  =  MaterialAmbient.xyz  +  Diffuse(Normal)  *  MaterialDiffuse.xyz;
    o.Diffuse.w 
=   1.0f ;

    
// 输出纹理坐标
    o.Tex0   =  i.Tex0.xy;

    
return  o;
}


// ---------------------------------------------------------
//  顶点渲染器
// ---------------------------------------------------------
VertexShader vsArray[ 4 =  {
                            compile vs_1_1 VShade(
1 ), 
                            compile vs_1_1 VShade(
2 ),
                            compile vs_1_1 VShade(
3 ),
                            compile vs_1_1 VShade(
4 )
                          };


// ---------------------------------------------------------
//  技术与通道
// ---------------------------------------------------------
technique t0
{
    pass p0
    {
        VertexShader 
=  (vsArray[CurNumBones]);
    }
}






// =============================================================================
//  Desc: 主程序源文件
// =============================================================================
#include  " dxstdafx.h "
#include 
" resource.h "
#pragma warning(disable: 
4995 )

// -----------------------------------------------------------------------------
//  Desc: 继承自DXDXFRAME结构的结构
// -----------------------------------------------------------------------------
struct  D3DXFRAME_DERIVED:  public  D3DXFRAME
{
    D3DXMATRIXA16        CombinedTransformationMatrix;
};


// -----------------------------------------------------------------------------
//  Desc: 继承自D3DXMESHCONTAINER结构的结构
// -----------------------------------------------------------------------------
struct  D3DXMESHCONTAINER_DERIVED:  public  D3DXMESHCONTAINER
{
    LPDIRECT3DTEXTURE9
*   ppTextures;             // 纹理数组
    LPD3DXMESH           pOrigMesh;              // 原网格
    DWORD                NumAttributeGroups;     // 骨骼数量
    DWORD                NumInfl;                // 每个顶点最多可以影响多少骨骼
    LPD3DXBUFFER         pBoneCombinationBuf;    // 骨骼结合表
    D3DXMATRIX **          ppBoneMatrixPtrs;       // 存放骨骼的组合变换矩阵
    D3DXMATRIX *           pBoneOffsetMatrices;    // 存放骨骼的初始变换矩阵
    DWORD                NumPaletteEntries;      // 有多少骨骼可以使用(上限)
     bool                  UseSoftwareVP;          // 标识是否使用软件顶点处理
};


// -----------------------------------------------------------------------------
//  Desc: 该类用来从.X文件加载框架层次和网格模型数据
// -----------------------------------------------------------------------------
class  CAllocateHierarchy:  public  ID3DXAllocateHierarchy
{
private :
    HRESULT GenerateSkinnedMesh(IDirect3DDevice9 
* pd3dDevice, D3DXMESHCONTAINER_DERIVED  * pMeshContainer);
    HRESULT AllocateName( LPCSTR Name, LPSTR 
* pNewName );
    
void     RemovePathFromFileName(LPSTR fullPath, LPWSTR fileName);

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);

    CAllocateHierarchy() {}
};


// -----------------------------------------------------------------------------
//  全局变量
// -----------------------------------------------------------------------------
ID3DXFont *                  g_pFont  =  NULL;           // ID3DXFont字体对象
ID3DXSprite *                g_pTextSprite  =  NULL;     // ID3DXSprite文本精灵对象
bool                        g_bShowHelp  =   true ;       // 标识是否显示简单说明文本

CDXUTDialogResourceManager g_DialogResourceManager; 
// 对话框资源管理器
CD3DSettingsDlg            g_SettingsDlg;            // Direct3D设备设置对话框
CDXUTDialog                g_HUD;                    // 对话框
CDXUTDialog                g_SampleUI;               // 对话框

ID3DXEffect
*               g_pEffect  =  NULL;
LPD3DXFRAME               g_pFrameRoot 
=  NULL;
ID3DXAnimationController
*  g_pAnimController  =  NULL;
D3DXMATRIXA16
*             g_pBoneMatrices  =  NULL;
UINT                      g_NumBoneMatricesMax 
=   0 ;
D3DXMATRIXA16             g_matWorld;
D3DXMATRIXA16             g_matView;
D3DXMATRIXA16             g_matProj;


// -----------------------------------------------------------------------------
//  控件ID
// -----------------------------------------------------------------------------
#define  IDC_TOGGLEFULLSCREEN      1
#define  IDC_TOGGLEREF             2
#define  IDC_CHANGEDEVICE          3


// -----------------------------------------------------------------------------
//  Desc: 函数声明
// ------------------------------------------------------------------------------
bool     CALLBACK IsDeviceAcceptable( D3DCAPS9 *  pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,  bool  bWindowed,  void *  pUserContext );
bool     CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *  pDeviceSettings,  const  D3DCAPS9 *  pCaps,  void *  pUserContext );
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9
*  pd3dDevice,  const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext );
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9
*  pd3dDevice,  const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc,  void *  pUserContext );
void     CALLBACK OnFrameMove( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext );
void     CALLBACK OnFrameRender( IDirect3DDevice9 *  pd3dDevice,  double  fTime,  float  fElapsedTime,  void *  pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
bool *  pbNoFurtherProcessing,  void *  pUserContext );
void     CALLBACK KeyboardProc( UINT nChar,  bool  bKeyDown,  bool  bAltDown,  void *  pUserContext );
void     CALLBACK OnGUIEvent( UINT nEvent,  int  nControlID, CDXUTControl *  pControl,  void *  pUserContext );
void     CALLBACK OnLostDevice(  void *  pUserContext );
void     CALLBACK OnDestroyDevice(  void *  pUserContext );

void     InitApp();
void     RenderText();

void     DrawMeshContainer( IDirect3DDevice9  * pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase );
void     DrawFrame( IDirect3DDevice9  * pd3dDevice, LPD3DXFRAME pFrame );
HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainer );
HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrame );
void     UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix );


// -----------------------------------------------------------------------------
//  Desc: 
// -----------------------------------------------------------------------------
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;
}


// -----------------------------------------------------------------------------
//  Desc: 从绝对路径中提取文件名
// -----------------------------------------------------------------------------
void  CAllocateHierarchy::RemovePathFromFileName(LPSTR fullPath, LPWSTR fileName)
{
    
// 先将fullPath的类型变换为LPWSTR
    WCHAR wszBuf[MAX_PATH];
    MultiByteToWideChar( CP_ACP, 
0 , fullPath,  - 1 , wszBuf, MAX_PATH );
    wszBuf[MAX_PATH
- 1 =  L ' \0 ' ;

    WCHAR
*  wszFullPath  =  wszBuf;

    
// 从绝对路径中提取文件名
    LPWSTR pch = wcsrchr(wszFullPath, ' \\ ' );
    
if  (pch)
        lstrcpy(fileName, 
++ pch);
    
else
        lstrcpy(fileName, wszFullPath);
}



// -----------------------------------------------------------------------------
//  Desc: 创建框架, 仅仅是分配内存和初始化,还没有对其成员赋予合适的值
// -----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME  * ppNewFrame )
{
    HRESULT hr 
=  S_OK;
    D3DXFRAME_DERIVED 
* pFrame;
    
    
* ppNewFrame  =  NULL;
    
    pFrame 
=   new  D3DXFRAME_DERIVED;   // 创建框架结构对象
     if  (pFrame  ==  NULL) 
    {
        
return  E_OUTOFMEMORY;
    }
    
    
// 为框架指定名称
    hr  =  AllocateName(Name, (LPSTR * ) & pFrame -> Name);
    
if  (FAILED(hr))
    {
        delete pFrame;
        
return  hr;
    }
    
    
// 初始化D3DXFRAME_DERIVED结构其它成员变量
    D3DXMatrixIdentity( & pFrame -> TransformationMatrix);
    D3DXMatrixIdentity(
& pFrame -> CombinedTransformationMatrix);
    
    pFrame
-> pMeshContainer  =  NULL;
    pFrame
-> pFrameSibling  =  NULL;
    pFrame
-> pFrameFirstChild  =  NULL;
    
    
* ppNewFrame  =  pFrame;
    pFrame 
=  NULL;

    
return  hr;
}


// -----------------------------------------------------------------------------
//  Desc: 在这里是调用了成员函数 GenerateSkinnedMesh(pMeshContainer);
//        是在这里加载了蒙皮信息
// -----------------------------------------------------------------------------
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 cBones;          // 当前网格模型骨骼总数
    LPDIRECT3DDEVICE9 pd3dDevice  =  NULL;
    LPD3DXMESH pMesh    
=  NULL;
    
* ppNewMeshContainer  =  NULL;

    
if  (pMeshData -> Type  !=  D3DXMESHTYPE_MESH)
    {
        
return  E_FAIL;
    }

    pMesh 
=  pMeshData -> pMesh;
    
    
if  (pMesh -> GetFVF()  ==   0 )
    {
        
return  E_FAIL;
    }

    
// 为网格容器分配内存
    pMeshContainer  =   new  D3DXMESHCONTAINER_DERIVED;
    
if  (pMeshContainer  ==  NULL)
    {
        
return  E_OUTOFMEMORY;
    }
    memset(pMeshContainer, 
0 sizeof (D3DXMESHCONTAINER_DERIVED));

    
// 填充网格容器结构D3DXMESHCONTAINER_DERIVED的成员

    
// 为网格指定名称
    hr  =  AllocateName(Name,  & pMeshContainer -> Name);
    
if  (FAILED(hr))
    {
        DestroyMeshContainer(pMeshContainer);
        
return  hr;
    }      
    
    pMesh
-> GetDevice( & pd3dDevice);
    NumFaces 
=  pMesh -> GetNumFaces();

    
// 确保网格顶点包含法线
     if  ( ! (pMesh -> GetFVF()  &  D3DFVF_NORMAL))
    {
        pMeshContainer
-> MeshData.Type  =  D3DXMESHTYPE_MESH;
        hr 
=  pMesh -> CloneMeshFVF( pMesh -> GetOptions(), 
                                  pMesh
-> GetFVF()  |  D3DFVF_NORMAL, 
                                  pd3dDevice, 
                                  
& pMeshContainer -> MeshData.pMesh );
        
if  (FAILED(hr))
        {
            SAFE_RELEASE(pd3dDevice);
            DestroyMeshContainer(pMeshContainer);
            
return  hr;
        }

        pMesh 
=  pMeshContainer -> MeshData.pMesh;
        D3DXComputeNormals( pMesh, NULL );
    }
    
else  
    {
        pMeshContainer
-> MeshData.pMesh  =  pMesh;
        pMeshContainer
-> MeshData.Type  =  D3DXMESHTYPE_MESH;
        pMesh
-> AddRef();
    }

    
// 为网格模型准备材质和纹理
    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)
        
||  (pMeshContainer -> ppTextures  ==  NULL))
    {
        hr 
=  E_OUTOFMEMORY;
        SAFE_RELEASE(pd3dDevice);
        DestroyMeshContainer(pMeshContainer);
        
return  hr;
    }

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

    
if  (NumMaterials  >   0 )            
    {
        
// 复制材质属性, 设置材质环境光属性
        memcpy(pMeshContainer -> pMaterials, pMaterials,  sizeof (D3DXMATERIAL)  *  NumMaterials); 
        pMeshContainer
-> pMaterials -> MatD3D.Ambient  =  pMeshContainer -> pMaterials -> MatD3D.Diffuse;

        
for  (iMaterial  =   0 ; iMaterial  <  NumMaterials; iMaterial ++ )
        {
            
if  (pMeshContainer -> pMaterials[iMaterial].pTextureFilename  !=  NULL)
            {
                WCHAR strTexturePath[MAX_PATH];
                WCHAR wszBuf[MAX_PATH];
                
// 从纹理文件路径提取纹理文件名
                RemovePathFromFileName(pMeshContainer -> pMaterials[iMaterial].pTextureFilename, wszBuf);
                
// 根据纹理文件名从事先指定的路径查找纹理文件
                DXUTFindDXSDKMediaFileCch( strTexturePath, MAX_PATH, wszBuf );
                
if ( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexturePath,
                                                        
& pMeshContainer -> ppTextures[iMaterial] ) ) )
                    pMeshContainer
-> ppTextures[iMaterial]  =  NULL;

                pMeshContainer
-> pMaterials[iMaterial].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;
    }

     
// 如果当前网格包含蒙皮信息
     if  (pSkinInfo  !=  NULL)
    {
        
// 加载蒙皮网格信息
        pMeshContainer -> pSkinInfo  =  pSkinInfo; 
        pSkinInfo
-> AddRef();

        
// 保留原网格信息
        pMeshContainer -> pOrigMesh  =  pMesh;
        pMesh
-> AddRef();

        
// 获取骨骼数量
        cBones  =  pSkinInfo -> GetNumBones();

        
// 为每块骨骼分配保存初始变换矩阵的内存空间
        pMeshContainer -> pBoneOffsetMatrices  =   new  D3DXMATRIX[cBones];
        
if  (pMeshContainer -> pBoneOffsetMatrices  ==  NULL) 
        {
            hr 
=  E_OUTOFMEMORY;
            DestroyMeshContainer(pMeshContainer);
            
return  hr;
        }

        
// 保存每块骨骼的初始变换矩阵
         for  (UINT iBone  =   0 ; iBone  <  cBones; iBone ++ )
        {
            pMeshContainer
-> pBoneOffsetMatrices[iBone]  =   * (pMeshContainer -> pSkinInfo -> GetBoneOffsetMatrix(iBone));
        }

        
// 生成蒙皮网格模型
        hr  =  GenerateSkinnedMesh(pd3dDevice, pMeshContainer); 
        
if  (FAILED(hr))
        {
            DestroyMeshContainer(pMeshContainer);
            
return  hr;
        }
    }

    
* ppNewMeshContainer  =  pMeshContainer;
    pMeshContainer 
=  NULL;
    SAFE_RELEASE(pd3dDevice);
    
return  hr;
}


// -----------------------------------------------------------------------------
// Desc: 生成蒙皮网格模型(含有每个顶点的混合权重、索引和一个骨骼组合表)
// -----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::GenerateSkinnedMesh( IDirect3DDevice9  * pd3dDevice, 
                                                D3DXMESHCONTAINER_DERIVED 
* pMeshContainer )
{
    HRESULT hr 
=  S_OK;
    
if ( pMeshContainer -> pSkinInfo  ==  NULL )
        
return  hr;

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

    
// 获取当前设备的能力
    D3DCAPS9 d3dCaps;
    pd3dDevice
-> GetDeviceCaps(  & d3dCaps );

    pMeshContainer
-> NumPaletteEntries  =  min( 26 , pMeshContainer -> pSkinInfo -> GetNumBones());
    DWORD Flags 
=  D3DXMESHOPT_VERTEXCACHE;

    
if  (d3dCaps.VertexShaderVersion  >=  D3DVS_VERSION( 1 1 ))
    {
        pMeshContainer
-> UseSoftwareVP  =   false ;
        Flags 
|=  D3DXMESH_MANAGED;
    }
    
else
    {
        pMeshContainer
-> UseSoftwareVP  =   true ;
        Flags 
|=  D3DXMESH_SYSTEMMEM;
    }

    SAFE_RELEASE(pMeshContainer
-> MeshData.pMesh);

    hr 
=  pMeshContainer -> pSkinInfo -> ConvertToIndexedBlendedMesh 
                                                              ( pMeshContainer
-> pOrigMesh,
                                                                Flags, 
                                                                pMeshContainer
-> NumPaletteEntries, 
                                                                pMeshContainer
-> pAdjacency, 
                                                                NULL, NULL, NULL,             
                                                                
& pMeshContainer -> NumInfl,
                                                                
& pMeshContainer -> NumAttributeGroups, 
                                                                
& pMeshContainer -> pBoneCombinationBuf, 
                                                                
& pMeshContainer -> MeshData.pMesh);
    
if  (FAILED(hr))
        
return  hr;

    
//  FVF has to match our declarator. Vertex shaders are not as forgiving as FF pipeline
    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, pd3dDevice,  & 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))
        
return  hr;

    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))
        
return  hr;

    
//  allocate a buffer for bone matrices,
     if ( g_NumBoneMatricesMax  <  pMeshContainer -> pSkinInfo -> GetNumBones() )
    {
        g_NumBoneMatricesMax 
=  pMeshContainer -> pSkinInfo -> GetNumBones();

        
//  Allocate space for blend matrices
        delete[] g_pBoneMatrices; 
        g_pBoneMatrices  
=   new  D3DXMATRIXA16[g_NumBoneMatricesMax];
        
if ( g_pBoneMatrices  ==  NULL )
        {
            hr 
=  E_OUTOFMEMORY;
            
return  hr;
        }
    }

    
return  hr;
}


// -----------------------------------------------------------------------------
//  Desc: 释放框架
// -----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) 
{
    
if (pFrameToFree  !=  NULL)
    {
        SAFE_DELETE_ARRAY( pFrameToFree
-> Name );
        SAFE_DELETE( pFrameToFree );
    }
    
return  S_OK; 
}


// -----------------------------------------------------------------------------
//  Desc: 释放网格容器
// -----------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
    
if (pMeshContainerBase  ==  NULL)
        
return  S_OK;

    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 );
    
    
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;
}


// -----------------------------------------------------------------------------
//  Desc: 入口函数
// -----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR,  int  )
{
    
// 为Debug配置启用运行时内存检查功能
#if  defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF 
|  _CRTDBG_LEAK_CHECK_DF );
#endif

    
// 设置回调函数
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( KeyboardProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );

    
// 应用程序相关的初始化
    InitApp();

    
// 初始化DXUT, 创建窗口, 创建Direct3D设备对象
    DXUTInit(  true true true  );
    DXUTSetCursorSettings( 
true true  );
    DXUTCreateWindow( L
" HLSLSkinMesh "  );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, 
true 640 480
        IsDeviceAcceptable, ModifyDeviceSettings );

    
// 进入消息循环和场景渲染
    DXUTMainLoop();

    
// 在此进行应用程序相关的清除工作
    delete[] g_pBoneMatrices;

    
return  DXUTGetExitCode();
}


// -----------------------------------------------------------------------------
//  Desc: 应用程序相关初始化
// -----------------------------------------------------------------------------
void  InitApp()
{
    
// 初始化对话框
    g_SettingsDlg.Init(  & g_DialogResourceManager );
    g_HUD.Init( 
& g_DialogResourceManager );
    g_SampleUI.Init( 
& g_DialogResourceManager );

    
// 为g_HUD对话框设置消息处理函数,添加控件
    g_HUD.SetCallback( OnGUIEvent );  int  iY  =   10
    g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L
" Toggle full screen " 35 , iY,  125 22  );
    g_HUD.AddButton( IDC_TOGGLEREF, L
" Toggle REF (F3) " 35 , iY  +=   24 125 22  );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L
" Change device (F2) " 35 , iY  +=   24 125 22 , VK_F2 );
}


// -----------------------------------------------------------------------------
//  Desc: 设备能力检查
// -----------------------------------------------------------------------------
bool  CALLBACK IsDeviceAcceptable( D3DCAPS9 *  pCaps, D3DFORMAT AdapterFormat, 
                                  D3DFORMAT BackBufferFormat, 
bool  bWindowed, 
                                  
void *  pUserContext )
{
    
// 检查后台缓冲区格式是否支持Alpha混合等操作(post pixel blending operations)
    IDirect3D9 *  pD3D  =  DXUTGetD3DObject(); 
    
if ( FAILED( pD3D -> CheckDeviceFormat( pCaps -> AdapterOrdinal, pCaps -> DeviceType,
                    AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
                    D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        
return   false ;

    
// 检查当前设备支持顶点渲染器版本是否符合要求
     if ( pCaps -> VertexShaderVersion  <  D3DVS_VERSION( 1 , 1 ) )
        
return  FALSE;

    
return   true ;
}


// -----------------------------------------------------------------------------
//  Desc: 修改Direct3D渲染设备设置
// -----------------------------------------------------------------------------
bool  CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *  pDeviceSettings, 
                                    
const  D3DCAPS9 *  pCaps,  void *  pUserContext )
{
    
// 如果不支持硬件顶点处理则使用软件顶点处理
     if ( (pCaps -> DevCaps  &  D3DDEVCAPS_HWTRANSFORMANDLIGHT)  ==   0 )
    {
        pDeviceSettings
-> BehaviorFlags  =  D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }

    
// 如果使用纯硬件顶点处理模式则改为混合顶点处理模式
     if ( pDeviceSettings -> BehaviorFlags  &  D3DCREATE_HARDWARE_VERTEXPROCESSING )
        pDeviceSettings
-> BehaviorFlags  =  D3DCREATE_MIXED_VERTEXPROCESSING;
    
    
// 调试顶点渲染器需要参考设备或软件顶点处理
#ifdef DEBUG_VS
    
if ( pDeviceSettings -> DeviceType  !=  D3DDEVTYPE_REF )
    {
        pDeviceSettings
-> BehaviorFlags  &=   ~ D3DCREATE_HARDWARE_VERTEXPROCESSING;
        pDeviceSettings
-> BehaviorFlags  &=   ~ D3DCREATE_PUREDEVICE;
        pDeviceSettings
-> BehaviorFlags  |=  D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }
#endif

    
// 调试像素渲染器需要参考设备
#ifdef DEBUG_PS
    pDeviceSettings
-> DeviceType  =  D3DDEVTYPE_REF;
#endif

    
// 如果使用参考设备,则弹出警告对话框
     static   bool  s_bFirstTime  =   true ;
    
if ( s_bFirstTime )
    {
        s_bFirstTime 
=   false ;
        
if ( pDeviceSettings -> DeviceType  ==  D3DDEVTYPE_REF )
            DXUTDisplaySwitchingToREFWarning();
    }

    
return   true ;
}


// -----------------------------------------------------------------------------
//  Desc: 在此创建管理内存资源对象
// -----------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9 *  pd3dDevice, 
                                
const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc, 
                                
void *  pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnCreateDevice( pd3dDevice ) );
    V_RETURN( g_SettingsDlg.OnCreateDevice( pd3dDevice ) );
    
    
// 创建字体
    V_RETURN( D3DXCreateFont( pd3dDevice,  15 0 , FW_BOLD,  1 , FALSE, DEFAULT_CHARSET, 
                         OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH 
|  FF_DONTCARE, 
                         L
" Arial " & g_pFont ) );

    
// 创建效果
    DWORD dwShaderFlags  =  D3DXFX_NOT_CLONEABLE;
    #ifdef DEBUG_VS
        dwShaderFlags 
|=  D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
    
#endif
    #ifdef DEBUG_PS
        dwShaderFlags 
|=  D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
    
#endif
    V_RETURN(D3DXCreateEffectFromFile( pd3dDevice, L
" HLSLSkinMesh.fx " , NULL, NULL, 
                                       dwShaderFlags, NULL, 
& g_pEffect, NULL ));

    
// 创建网格模型
    CAllocateHierarchy Alloc;
    V_RETURN(D3DXLoadMeshHierarchyFromX( L
" tiny.x " , D3DXMESH_MANAGED, pd3dDevice,
                                         
& Alloc, NULL,  & g_pFrameRoot,  & g_pAnimController ));
    
    SetupBoneMatrixPointers( g_pFrameRoot );

    
return  S_OK;
}


// -----------------------------------------------------------------------------
//  Desc: 在此创建默认内存类型资源对象
// -----------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9 *  pd3dDevice, 
                                
const  D3DSURFACE_DESC *  pBackBufferSurfaceDesc, 
                                
void *  pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnResetDevice() );
    V_RETURN( g_SettingsDlg.OnResetDevice() );

    
// 设置对话框位置和尺寸
    g_HUD.SetLocation( pBackBufferSurfaceDesc -> Width - 170 0  );
    g_HUD.SetSize( 
170 170  );
    g_SampleUI.SetLocation( pBackBufferSurfaceDesc
-> Width - 170
                            pBackBufferSurfaceDesc
-> Height - 350  );
    g_SampleUI.SetSize( 
170 300  );

    
// 恢复字体
     if ( g_pFont )
        V_RETURN( g_pFont
-> OnResetDevice() );
   
    
// 创建ID3DXSprite接口对象
    V_RETURN( D3DXCreateSprite( pd3dDevice,  & g_pTextSprite ) );

    
// 恢复效果对象
     if ( g_pEffect )
        V_RETURN( g_pEffect
-> OnResetDevice() );

    
// 构造世界矩阵
    D3DXMatrixTranslation(  & g_matWorld,  0 30 - 100  );

    
// 构造观察矩阵
    D3DXVECTOR3 vEye(  0 0 - 1000  );
    D3DXVECTOR3 vAt( 
0 0 0  );
    D3DXVECTOR3 vUp( 
0 1 0  );
    D3DXMatrixLookAtLH( 
& g_matView,  & vEye,  & vAt,  & vUp);

    
// 构造投影矩阵
    D3DXMATRIXA16 matProj;
    
float  fAspectRatio  =  ( float )pBackBufferSurfaceDesc -> Width  /  pBackBufferSurfaceDesc -> Height;
    D3DXMatrixPerspectiveFovLH( 
& matProj, D3DX_PI / 4 , fAspectRatio,  1.0f 2000.0f  );;

    
// 为效果设置影矩阵
    V( g_pEffect -> SetMatrix(  " mProj " & matProj ) );

    
// 为效果设置灯光方向
    D3DXVECTOR4 vLightDir(  0.0f 1.0f - 1.0f 0.0f  );
    D3DXVec4Normalize( 
& vLightDir,  & vLightDir );
    V( g_pEffect
-> SetVector(  " lightDir " & vLightDir) );


    
return  S_OK;
}


// -----------------------------------------------------------------------------
//  Desc: 更新场景
// -----------------------------------------------------------------------------
void  CALLBACK OnFrameMove( IDirect3DDevice9 *  pd3dDevice,  double  fTime, 
                           
float  fElapsedTime,  void *  pUserContext )
{
}

// ------------------------------------------------------------------------------
//  Desc: 渲染网格模型
// ------------------------------------------------------------------------------
void  DrawMeshContainer( IDirect3DDevice9  * pd3dDevice, 
                       LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase )
{
    HRESULT hr;
    D3DXMESHCONTAINER_DERIVED 
* pMeshContainer  =  (D3DXMESHCONTAINER_DERIVED * )pMeshContainerBase;
    D3DXFRAME_DERIVED 
* pFrame  =  (D3DXFRAME_DERIVED * )pFrameBase;
    UINT iMaterial;
    UINT iAttrib;
    LPD3DXBONECOMBINATION pBoneComb;

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

    
// 检查是否是蒙皮网格模型
     if  (pMeshContainer -> pSkinInfo  !=  NULL)
    {
            
if  (pMeshContainer -> UseSoftwareVP)
            {
                V( pd3dDevice
-> SetSoftwareVertexProcessing(TRUE) );
            }

            pBoneComb 
=  reinterpret_cast < LPD3DXBONECOMBINATION > (pMeshContainer -> pBoneCombinationBuf -> GetBufferPointer());
            
for  (iAttrib  =   0 ; iAttrib  <  pMeshContainer -> NumAttributeGroups; iAttrib ++ )
            { 
                
for  (iPaletteEntry  =   0 ; iPaletteEntry  <  pMeshContainer -> NumPaletteEntries;  ++ iPaletteEntry)
                {
                    iMatrixIndex 
=  pBoneComb[iAttrib].BoneId[iPaletteEntry];
                    
if  (iMatrixIndex  !=  UINT_MAX)
                    {
                        D3DXMatrixMultiply(
& matTemp,  & pMeshContainer -> pBoneOffsetMatrices[iMatrixIndex], pMeshContainer -> ppBoneMatrixPtrs[iMatrixIndex]);
                        D3DXMatrixMultiply(
& g_pBoneMatrices[iPaletteEntry],  & matTemp,  & g_matView);
                    }
                }
                V( g_pEffect
-> SetMatrixArray(  " mWorldMatrixArray " , g_pBoneMatrices, pMeshContainer -> NumPaletteEntries) );

                D3DXCOLOR color1(pMeshContainer
-> pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient);
                D3DXCOLOR color2(
0.25 0.25 0.25 1.0 );
                D3DXCOLOR ambEmm;
                D3DXColorModulate(
& ambEmm,  & color1,  & color2);
                ambEmm 
+=  D3DXCOLOR(pMeshContainer -> pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Emissive);

                
// 设置材质属性
                V( g_pEffect -> SetVector( " MaterialDiffuse " , (D3DXVECTOR4 * ) & (pMeshContainer -> pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Diffuse)) );
                V( g_pEffect
-> SetVector( " MaterialAmbient " , (D3DXVECTOR4 * ) & ambEmm) );

                
/// 设置纹理
                V( pd3dDevice -> SetTexture(  0 , pMeshContainer -> ppTextures[pBoneComb[iAttrib].AttribId] ) );

                
// 设置当前骨骼数量
                V( g_pEffect -> SetInt(  " CurNumBones " , pMeshContainer -> NumInfl  - 1 ) );

                
// 使用效果渲染网格
                UINT numPasses;
                V( g_pEffect
-> Begin(  & numPasses, D3DXFX_DONOTSAVESTATE ) );
                
for ( UINT iPass  =   0 ; iPass  <  numPasses; iPass ++  )
                {
                    V( g_pEffect
-> BeginPass( iPass ) );
                    V( pMeshContainer
-> MeshData.pMesh -> DrawSubset( iAttrib ) );
                    V( g_pEffect
-> EndPass() );
                }
                V( g_pEffect
-> End() );

                V( pd3dDevice
-> SetVertexShader(NULL) );
            }
            
if  (pMeshContainer -> UseSoftwareVP)
            {
                V( pd3dDevice
-> SetSoftwareVertexProcessing(FALSE) );
            }
       

    }
    
else
    {
        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  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 );
    }
}


// -----------------------------------------------------------------------------
//  Desc: 渲染场景
// -----------------------------------------------------------------------------
void  CALLBACK OnFrameRender( IDirect3DDevice9 *  pd3dDevice,  double  fTime, 
                            
float  fElapsedTime,  void *  pUserContext )
{
    HRESULT hr;
  
    
// 如果正在利用Direct3D设备设置对话框进行设置, 则不渲染场景
     if ( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.OnRender( fElapsedTime );
        
return ;
    }

    
// 清除后台颜色缓冲区和深度缓冲区
    V( pd3dDevice -> Clear( 0 , NULL, D3DCLEAR_TARGET  |  D3DCLEAR_ZBUFFER, 
                         D3DCOLOR_ARGB(
0 45 50 170 ),  1.0f 0 ) );

    
// 渲染场景
     if ( SUCCEEDED( pd3dDevice -> BeginScene() ) )
    {
        
// 渲染网格模型
         if ( g_pAnimController  !=  NULL )
            g_pAnimController
-> AdvanceTime( fElapsedTime, NULL );
        UpdateFrameMatrices( g_pFrameRoot, 
& g_matWorld );
        DrawFrame( pd3dDevice, g_pFrameRoot );

        
// 渲染文本和控件
        DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L " HUD / Stats "  ); 
        RenderText();
        V( g_HUD.OnRender( fElapsedTime ) );
        V( g_SampleUI.OnRender( fElapsedTime ) );
        DXUT_EndPerfEvent();

        V( pd3dDevice
-> EndScene() );
    }
}


// -----------------------------------------------------------------------------
//  Desc: 渲染文本
// -----------------------------------------------------------------------------
void  RenderText()
{
    CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 
15  );

    
// 显示当前Direct3D设备状态和渲染帧速率
    txtHelper.Begin();
    txtHelper.SetInsertionPos( 
5 5  );
    txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 1.0f 0.0f 1.0f  ) );
    txtHelper.DrawTextLine( DXUTGetFrameStats(
true ) );
    txtHelper.DrawTextLine( DXUTGetDeviceStats() );

    
// 显示其他简要信息
    txtHelper.SetForegroundColor( D3DXCOLOR(  1.0f 1.0f 1.0f 1.0f  ) );
    txtHelper.DrawTextLine( L
" 通过HLSL编程实现蒙皮骨骼动画 "  );
    
    
// 显示简单帮助文本
     const  D3DSURFACE_DESC *  pd3dsdBackBuffer  =  DXUTGetBackBufferSurfaceDesc();
    
if ( g_bShowHelp )
    {
        txtHelper.SetInsertionPos( 
10 , pd3dsdBackBuffer -> Height - 15 * 6  );
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 0.75f 0.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Controls (F1 to hide): "  );

        txtHelper.SetInsertionPos( 
40 , pd3dsdBackBuffer -> Height - 15 * 5  );
        txtHelper.DrawTextLine( L
" Quit: ESC "  );
    }
    
else
    {
        txtHelper.SetInsertionPos( 
10 , pd3dsdBackBuffer -> Height - 15 * 2  );
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f 1.0f 1.0f 1.0f  ) );
        txtHelper.DrawTextLine( L
" Press F1 for help "  );
    }
    txtHelper.End();
}


// -----------------------------------------------------------------------------
//  Desc: 消息处理
// -----------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
                         
bool *  pbNoFurtherProcessing,  void *  pUserContext )
{
    
* pbNoFurtherProcessing  =  g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;

    
if ( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        
return   0 ;
    }

    
* pbNoFurtherProcessing  =  g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;
   
    
* pbNoFurtherProcessing  =  g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    
if * pbNoFurtherProcessing )
        
return   0 ;

    
return   0 ;
}


// -----------------------------------------------------------------------------
//  Desc: 键盘消息处理
// -----------------------------------------------------------------------------
void  CALLBACK KeyboardProc( UINT nChar,  bool  bKeyDown,  bool  bAltDown,  void *  pUserContext )
{
    
if ( bKeyDown )
    {
        
switch ( nChar )
        {
            
case  VK_F1: g_bShowHelp  =   ! g_bShowHelp;  break ;
        }
    }
}


// -----------------------------------------------------------------------------
//  Desc: 处理各种控件消息
// -----------------------------------------------------------------------------
void  CALLBACK OnGUIEvent( UINT nEvent,  int  nControlID, CDXUTControl *  pControl, 
                         
void *  pUserContext )
{
    
switch ( nControlID )
    {
        
case  IDC_TOGGLEFULLSCREEN:
            DXUTToggleFullScreen(); 
            
break ;

        
case  IDC_TOGGLEREF:
            DXUTToggleREF(); 
            
break ;

        
case  IDC_CHANGEDEVICE:
            g_SettingsDlg.SetActive( 
! g_SettingsDlg.IsActive() ); 
            
break ;
    }
}


// -----------------------------------------------------------------------------
//  Desc: 释放在OnResetDevice()中创建的资源
// -----------------------------------------------------------------------------
void  CALLBACK OnLostDevice(  void *  pUserContext )
{
    g_DialogResourceManager.OnLostDevice();
    g_SettingsDlg.OnLostDevice();
    
if ( g_pFont )
        g_pFont
-> OnLostDevice();
    SAFE_RELEASE( g_pTextSprite );

    
if ( g_pEffect )
        g_pEffect
-> OnLostDevice();
}


// ------------------------------------------------------------------------------
//  Desc: 释放在OnCreateDevice()中创建的资源
// ------------------------------------------------------------------------------
void  CALLBACK OnDestroyDevice(  void *  pUserContext )
{
    g_DialogResourceManager.OnDestroyDevice();
    g_SettingsDlg.OnDestroyDevice();
    SAFE_RELEASE( g_pFont );

    SAFE_RELEASE( g_pEffect );
    CAllocateHierarchy Alloc;
    D3DXFrameDestroy( g_pFrameRoot, 
& Alloc );
    SAFE_RELEASE( g_pAnimController );
}



// --------------------------------------------------------------------------------------
//  Desc: 设置骨骼矩阵
// --------------------------------------------------------------------------------------
HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase )
{
    UINT iBone, cBones;
    D3DXFRAME_DERIVED 
* pFrame;

    D3DXMESHCONTAINER_DERIVED 
* pMeshContainer  =  (D3DXMESHCONTAINER_DERIVED * )pMeshContainerBase;

    
// 设置骨骼矩阵
     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( g_pFrameRoot, 
                                             pMeshContainer
-> pSkinInfo -> GetBoneName(iBone) );
            
if  (pFrame  ==  NULL)
                
return  E_FAIL;

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

    
return  S_OK;
}


// --------------------------------------------------------------------------------------
//  Desc: 设置骨骼矩阵指针
// --------------------------------------------------------------------------------------
HRESULT 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;
}




// --------------------------------------------------------------------------------------
//  update the frame matrices
// --------------------------------------------------------------------------------------
void  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);
    }
}















你可能感兴趣的:(《精通DirectX 3D》 第二十一章 HLSL高级应用 07_HLSLSkinMesh)