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

隨筆 - 505  文章 - 1034  trackbacks - 0
<2008年3月>
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345


子曾經曰過:編程無他,唯手熟爾!

常用鏈接

留言簿(94)

隨筆分類(649)

隨筆檔案(505)

相冊

BCB

Crytek

  • crymod
  • Crytek's Offical Modding Portal

Game Industry

OGRE

other

Programmers

Qt

WOW Stuff

搜索

  •  

積分與排名

  • 積分 - 921261
  • 排名 - 14

最新隨筆

最新評論

閱讀排行榜

評論排行榜






HLSLSkinMesh.fx

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


//---------------------------------------------------------
// 全局變量
//---------------------------------------------------------
float4 lightDir = {0.0f0.0f-1.0f1.0f};
float4 lightDiffuse 
= {0.6f0.6f0.6f1.0f}; 
float4 MaterialAmbient 
= {0.1f0.1f0.1f1.0f};
float4 MaterialDiffuse 
= {0.8f0.8f0.8f1.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, 
0sizeof(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, 0sizeof(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, 0sizeof(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(11))
    {
        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( truetruetrue );
    DXUTSetCursorSettings( 
truetrue );
    DXUTCreateWindow( L
"HLSLSkinMesh" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, 
true640480
        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, 12522 );
    g_HUD.AddButton( IDC_TOGGLEREF, L
"Toggle REF (F3)"35, iY += 2412522 );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L
"Change device (F2)"35, iY += 2412522, 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, 150, 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-1700 );
    g_HUD.SetSize( 
170170 );
    g_SampleUI.SetLocation( pBackBufferSurfaceDesc
->Width-170
                            pBackBufferSurfaceDesc
->Height-350 );
    g_SampleUI.SetSize( 
170300 );

    
//恢復字體
    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, 030-100 );

    
//構造觀察矩陣
    D3DXVECTOR3 vEye( 00-1000 );
    D3DXVECTOR3 vAt( 
000 );
    D3DXVECTOR3 vUp( 
010 );
    D3DXMatrixLookAtLH( 
&g_matView, &vEye, &vAt, &vUp);

    
//構造投影矩陣
    D3DXMATRIXA16 matProj;
    
float fAspectRatio = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
    D3DXMatrixPerspectiveFovLH( 
&matProj, D3DX_PI/4, fAspectRatio, 1.0f2000.0f );;

    
//為效果設置影矩陣
    V( g_pEffect->SetMatrix( "mProj"&matProj ) );

    
//為效果設置燈光方向
    D3DXVECTOR4 vLightDir( 0.0f1.0f-1.0f0.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.250.250.251.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(
04550170), 1.0f0) );

    
//渲染場景
    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( 
55 );
    txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f1.0f0.0f1.0f ) );
    txtHelper.DrawTextLine( DXUTGetFrameStats(
true) );
    txtHelper.DrawTextLine( DXUTGetDeviceStats() );

    
//顯示其他簡要信息
    txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f1.0f1.0f1.0f ) );
    txtHelper.DrawTextLine( L
"通過HLSL編程實現蒙皮骨骼動畫" );
    
    
//顯示簡單幫助文本
    const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
    
if( g_bShowHelp )
    {
        txtHelper.SetInsertionPos( 
10, pd3dsdBackBuffer->Height-15*6 );
        txtHelper.SetForegroundColor( D3DXCOLOR( 
1.0f0.75f0.0f1.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.0f1.0f1.0f1.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);
    }
}















posted on 2008-04-16 11:01 七星重劍 閱讀(1321) 評論(0)  編輯 收藏 引用 所屬分類: Game Graphics
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲性人人天天夜夜摸| 欧美不卡视频一区发布| 久久精品首页| 亚洲欧美另类国产| 亚洲欧美综合v| 亚洲欧美成人在线| 久久精品九九| 看片网站欧美日韩| 亚洲国产天堂网精品网站| 欧美在线视频在线播放完整版免费观看| 亚洲免费在线播放| 久久久一二三| 欧美大片在线看| 亚洲激情午夜| 亚洲午夜黄色| 国产精品区一区二区三| 亚洲天堂av电影| 亚洲免费av电影| 在线视频精品一区| 久久成人久久爱| 免费成人在线视频网站| 男人的天堂亚洲在线| 亚洲精品乱码久久久久久按摩观| 亚洲日韩成人| 一区二区三区视频在线观看| 欧美在线免费视频| 欧美电影在线观看完整版| 国产精品vip| 影音先锋中文字幕一区二区| 亚洲免费高清| 久久精品国产久精国产思思| 亚洲欧洲美洲综合色网| 亚洲尤物精选| 欧美激情一二三区| 国产亚洲亚洲| 中文精品99久久国产香蕉| 久久精品av麻豆的观看方式 | 久久精品综合一区| 亚洲精品中文在线| 久久av一区二区| 欧美午夜视频网站| 亚洲国产天堂久久国产91| 新狼窝色av性久久久久久| 亚洲国产一区二区三区在线播| 午夜精品久久久久久久久久久| 久热精品视频在线观看一区| 国产精品亚洲美女av网站| 日韩午夜三级在线| 亚洲高清中文字幕| 久久精品女人| 黄色亚洲网站| 久久精品国产亚洲一区二区三区| 亚洲国产视频直播| 美女爽到呻吟久久久久| 国产亚洲一区二区三区在线播放 | 国产精品香蕉在线观看| 在线亚洲精品福利网址导航| 欧美激情乱人伦| 欧美专区在线| 精品51国产黑色丝袜高跟鞋| 欧美伊人久久| 午夜免费日韩视频| 国产视频自拍一区| 欧美诱惑福利视频| 亚洲男人av电影| 国产欧美日韩精品一区| 亚洲欧美文学| 亚洲欧美视频一区| 国产九九精品视频| 久久国产一区二区| 亚洲免费视频中文字幕| 国产精品美女诱惑| 久久成人av少妇免费| 亚洲欧美精品| 在线播放日韩| 亚洲国产毛片完整版 | 一区二区激情| 一区二区三区精品| 国产精品亚洲аv天堂网| 欧美在线不卡| 久久高清免费观看| 在线免费观看成人网| 久久电影一区| 欧美丰满少妇xxxbbb| 中文久久精品| 亚洲欧美一区二区在线观看| 国产午夜精品在线| 欧美成人免费视频| 欧美日韩另类一区| 久久精品国产一区二区三| 久久久五月婷婷| 亚洲视频 欧洲视频| 亚洲综合第一页| 亚洲日本成人女熟在线观看| 国产精品一香蕉国产线看观看| 久久久久久国产精品一区| 欧美国产高清| 欧美呦呦网站| 欧美日韩成人在线观看| 欧美在线视频一区二区| 久久青草久久| 亚洲摸下面视频| 噜噜爱69成人精品| 亚洲欧美一区二区三区在线| 久久精品中文| 亚洲女人av| 免费成人在线观看视频| 亚洲综合日韩中文字幕v在线| 久久久欧美精品| 在线一区免费观看| 久久一区视频| 久久精品国产视频| 欧美日韩亚洲一区二区三区四区| 久久蜜桃精品| 国产精品日韩欧美一区二区三区| 免费观看日韩| 国产综合色在线| 一区二区三区av| 一区二区免费在线播放| 久久国产精品99国产| 亚洲综合999| 欧美成人精品高清在线播放| 欧美在线视频二区| 欧美午夜久久| 亚洲最新视频在线播放| 亚洲国产小视频在线观看| 午夜精品久久久久久久久久久久 | 欧美.www| 尤物99国产成人精品视频| 亚洲欧美日韩一区二区三区在线观看 | 欧美国产精品v| 国产一区二区剧情av在线| 99re热这里只有精品免费视频| 亚洲国产高清在线| 欧美一区二区三区免费看| 香蕉久久国产| 欧美日韩免费看| 99国产精品久久| 亚洲视频欧美视频| 欧美视频手机在线| 日韩一级成人av| 中国亚洲黄色| 欧美无乱码久久久免费午夜一区| 亚洲国产岛国毛片在线| 91久久国产综合久久| 女同性一区二区三区人了人一| 久久美女性网| 狠狠色综合网| 久久久青草婷婷精品综合日韩| 老司机aⅴ在线精品导航| 影音国产精品| 欧美极品一区| 日韩亚洲视频在线| 亚洲欧美另类国产| 国产一区日韩一区| 久久亚洲综合色一区二区三区| 久久亚洲精品欧美| 亚洲国产一区二区三区a毛片| 久久黄金**| 在线精品视频一区二区| 你懂的网址国产 欧美| 亚洲国产精品黑人久久久| 99国产精品99久久久久久| 欧美性色综合| 久久久久久久久久久一区| 亚洲国产91| 亚洲免费一级电影| 一区二区三区亚洲| 欧美精品在线一区二区三区| 亚洲一区www| 久久久久久噜噜噜久久久精品| 樱桃成人精品视频在线播放| 欧美黑人多人双交| 亚洲已满18点击进入久久 | 日韩视频在线免费观看| 亚洲午夜久久久久久久久电影院| 国产精品免费一区二区三区观看| 久久高清一区| 一区二区三区日韩精品| 老司机精品视频一区二区三区| 亚洲日本精品国产第一区| 国产精品黄视频| 看欧美日韩国产| 亚洲欧美成人一区二区三区| 欧美国产精品人人做人人爱| 欧美一级网站| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 欧美日韩hd| 久久久天天操| 午夜精品剧场| 99精品欧美一区二区三区| 久久欧美中文字幕| 小黄鸭视频精品导航| 亚洲精品久久久久久下一站 | 欧美理论在线| 久久久久国色av免费观看性色| 一区二区三区高清在线| 亚洲一区bb| 蜜桃av一区二区三区| 午夜精品免费在线|