DX9动画加载

D3DUtil.h

//*****************************************************************************************
// Desc: D3DUtil.h头文件,用于公共辅助宏的定义

//*****************************************************************************************

#pragma once


#ifndef HR
#define HR(x)    { hr = x; if( FAILED(hr) ) { return hr; } }         //自定义一个HR宏,方便执行错误的返回
#endif

#ifndef SAFE_DELETE                    
#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }       //自定义一个SAFE_RELEASE()宏,便于指针资源的释放
#endif    

#ifndef SAFE_RELEASE            
#define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }     //自定义一个SAFE_RELEASE()宏,便于COM资源的释放
#endif

#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
#endif    
View Code

AllocateHierarchyClass.h

#pragma once

//=============================================================================
// Desc: CAllocateHierarchy.h
// 来自微软官方DirectX SDK Samples中的骨骼动画类
//=============================================================================

#include <d3d9.h>
#include <d3dx9.h>
#include "D3DUtil.h"


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


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


//-----------------------------------------------------------------------------
// Name: class CAllocateHierarchy
// Desc: 来自微软官方DirectX SDK Samples中的骨骼动画类,这个类用来从.X文件加载框架层次和网格模型数据
// 核心点:      #define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method 
//-----------------------------------------------------------------------------
class CAllocateHierarchy: public ID3DXAllocateHierarchy
{
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);
};




//-----------------------------------------------------------------------------
// Desc: 来自微软官方DirectX SDK Samples中的骨骼动画全局函数
//-----------------------------------------------------------------------------
void DrawFrame( IDirect3DDevice9* pd3dDevice, LPD3DXFRAME pFrame );
void DrawMeshContainer( IDirect3DDevice9* pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase );
HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrameBase, LPD3DXFRAME pFrameRoot );
void UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix );
View Code

AllocateHierarchyClass.cpp

//=============================================================================
// Desc: AllocateHierarchyClass.cpp
// 来自微软官方DirectX SDK Samples中的骨骼动画类
//=============================================================================

#include "AllocateHierarchyClass.h"

//--------------------------------------------------------------------------------------
// Name: AllocateName()
// Desc: 为骨骼或网格名称的字符串分配内存
//--------------------------------------------------------------------------------------
HRESULT AllocateName( LPCSTR Name, LPSTR* pNewName )
{
    UINT cbLength;

    if( Name != NULL )
    {
        cbLength = ( UINT )strlen( Name ) + 1;
        *pNewName = new CHAR[cbLength];
        memcpy( *pNewName, Name, cbLength * sizeof( CHAR ) );
    }
    else
    {
        *pNewName = NULL;
    }

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Name: GenerateSkinnedMesh
// Desc: 生成蒙皮网格模型。该函数判断当前网格容器是否包含有蒙皮信息,如果当前网格模型
//       中不包含蒙皮信息,则直接退出该函数。接下来确定所需要的矩阵调色板容量。最后调
//       用ID3DXSkinInfo::ConvertToIndexedBlendedMesh()函数生成索引蒙皮网格模型
//--------------------------------------------------------------------------------------
HRESULT GenerateSkinnedMesh( IDirect3DDevice9* pd3dDevice, D3DXMESHCONTAINER_DERIVED* pMeshContainer )
{
    D3DCAPS9 d3dCaps;
    pd3dDevice->GetDeviceCaps( &d3dCaps );

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

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


    if (FAILED(pMeshContainer->pSkinInfo->ConvertToBlendedMesh(
        pMeshContainer->pOrigMesh, 
        D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
        pMeshContainer->pAdjacency,
        NULL, NULL, NULL,
        &pMeshContainer->NumInfl,
        &pMeshContainer->NumAttributeGroups,
        &pMeshContainer->pBoneCombinationBuf,
        &pMeshContainer->MeshData.pMesh)))
        return E_FAIL;
    return S_OK;
}



//--------------------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateFrame()
// Desc: 创建框架, 仅仅是分配内存和初始化,还没有对其成员赋予合适的值
//--------------------------------------------------------------------------------------
HRESULT CAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME* ppNewFrame )
{
    HRESULT hr = S_OK;
    D3DXFRAME_DERIVED *pFrame;

    *ppNewFrame = NULL;

    // 为框架指定名称
    pFrame = new D3DXFRAME_DERIVED;  // 创建框架结构对象
    if (FAILED(AllocateName(Name, (LPSTR*)&pFrame->Name)))
    {
        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;
}


//--------------------------------------------------------------------------------------
// Name: CAllocateHierarchy::CreateMeshContainer()
// Desc: 创建蒙皮网格容器,以加载蒙皮信息
//--------------------------------------------------------------------------------------
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;
    UINT NumFaces;
    UINT iMaterial;
    UINT iBone, cBones;
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;

    LPD3DXMESH pMesh = NULL;

    *ppNewMeshContainer = NULL;

    // this sample does not handle patch meshes, so fail when one is found
    if( pMeshData->Type != D3DXMESHTYPE_MESH )
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // get the pMesh interface pointer out of the mesh data structure
    pMesh = pMeshData->pMesh;

    // this sample does not FVF compatible meshes, so fail when one is found
    if( pMesh->GetFVF() == 0 )
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // allocate the overloaded structure to return as a D3DXMESHCONTAINER
    pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
    memset( pMeshContainer, 0, sizeof( D3DXMESHCONTAINER_DERIVED ) );

    // make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
    hr = AllocateName( Name, &pMeshContainer->Name );
    if( FAILED( hr ) )
        goto e_Exit;

    pMesh->GetDevice( &pd3dDevice );
    NumFaces = pMesh->GetNumFaces();

    // if no normals are in the mesh, add them
    if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) )
    {
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        // clone the mesh to make room for the normals
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL,
            pd3dDevice, &pMeshContainer->MeshData.pMesh );
        if( FAILED( hr ) )
            goto e_Exit;

        // get the new pMesh pointer back out of the mesh container to use
        // NOTE: we do not release pMesh because we do not have a reference to it yet
        pMesh = pMeshContainer->MeshData.pMesh;

        // now generate the normals for the pmesh
        D3DXComputeNormals( pMesh, NULL );
    }
    else  // if no normals, just add a reference to the mesh for the mesh container
    {
        pMeshContainer->MeshData.pMesh = pMesh;
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        pMesh->AddRef();
    }

    // allocate memory to contain the material information.  This sample uses
    //   the D3D9 materials and texture names instead of the EffectInstance style materials
    pMeshContainer->NumMaterials = max( 1, NumMaterials );
    pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
    pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
    pMeshContainer->pAdjacency = new DWORD[NumFaces*3];

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

    // if materials provided, copy them
    if( NumMaterials > 0 )
    {
        memcpy( pMeshContainer->pMaterials, pMaterials, sizeof( D3DXMATERIAL ) * NumMaterials );

        for( iMaterial = 0; iMaterial < NumMaterials; iMaterial++ )
        {
            if( pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL )
            {
                if( FAILED( D3DXCreateTextureFromFileA( pd3dDevice, pMeshContainer->pMaterials[iMaterial].pTextureFilename,
                    &pMeshContainer->ppTextures[iMaterial] ) ) )
                    pMeshContainer->ppTextures[iMaterial] = NULL;

                // don't remember a pointer into the dynamic memory, just forget the name after loading
                pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
            }
        }
    }
    else // if no materials provided, use a default one
    {
        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 there is skinning information, save off the required data and then setup for HW skinning
    if( pSkinInfo != NULL )
    {
        // first save off the SkinInfo and original mesh data
        pMeshContainer->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();

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

        // Will need an array of offset matrices to move the vertices from the figure space to the bone's space
        cBones = pSkinInfo->GetNumBones();
        pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];

        // get each of the bone offset matrices so that we don't need to get them later
        for( iBone = 0; iBone < cBones; iBone++ )
        {
            pMeshContainer->pBoneOffsetMatrices[iBone] = *( pMeshContainer->pSkinInfo->GetBoneOffsetMatrix( iBone ) );
        }

        // GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
        hr = GenerateSkinnedMesh( pd3dDevice, pMeshContainer );
        if( FAILED( hr ) )
            goto e_Exit;
    }

    *ppNewMeshContainer = pMeshContainer;
    pMeshContainer = NULL;

e_Exit:
    SAFE_RELEASE( pd3dDevice );

    // call Destroy function to properly clean up the memory allocated 
    if( pMeshContainer != NULL )
    {
        DestroyMeshContainer( pMeshContainer );
    }

    return hr;
}

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

//--------------------------------------------------------------------------------------
// Name: CAllocateHierarchy::DestroyMeshContainer()
// Desc: 释放网格容器
//--------------------------------------------------------------------------------------
HRESULT CAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerBase )
{
    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 );

    // release all the allocated textures
    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;
}

//--------------------------------------------------------------------------------------
// Name: SetupBoneMatrixPointers()
// Desc: 设置好各级框架的组合变换矩阵。
//--------------------------------------------------------------------------------------
HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrameBase, LPD3DXFRAME pFrameRoot )
{
    if( pFrameBase->pMeshContainer != NULL )
    {
        D3DXFRAME_DERIVED* pFrame = NULL;
        D3DXMESHCONTAINER_DERIVED* pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pFrameBase->pMeshContainer;

        // if there is a skinmesh, then setup the bone matrices
        if (pMeshContainer->pSkinInfo != NULL)
        {
            UINT cBones = pMeshContainer->pSkinInfo->GetNumBones();
            pMeshContainer->ppBoneMatrixPtrs = new D3DXMATRIX*[cBones];
            for (UINT iBone = 0; iBone < cBones; iBone++)
            {
                pFrame = (D3DXFRAME_DERIVED*)D3DXFrameFind(pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName(iBone));
                if (pFrame == NULL) return E_FAIL;

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

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

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

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Name: DrawMeshContainer()
// Desc: 绘制蒙皮容器中的蒙皮网格
//--------------------------------------------------------------------------------------
void DrawMeshContainer( IDirect3DDevice9* pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase )
{
    D3DXMESHCONTAINER_DERIVED* pMeshContainer = ( D3DXMESHCONTAINER_DERIVED* )pMeshContainerBase;
    D3DXFRAME_DERIVED* pFrame = ( D3DXFRAME_DERIVED* )pFrameBase;
    UINT iMaterial;
    UINT NumBlend;
    UINT iAttrib;
    DWORD AttribIdPrev;
    LPD3DXBONECOMBINATION pBoneComb;

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

    // first check for skinning
    if( pMeshContainer->pSkinInfo != NULL )
    {
        AttribIdPrev = UNUSED32;
        pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>( pMeshContainer->pBoneCombinationBuf->GetBufferPointer() );

        // Draw using default vtx processing of the device (typically HW)
        for( iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++ )
        {
            NumBlend = 0;
            for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
            {
                if( pBoneComb[iAttrib].BoneId[i] != UINT_MAX )
                {
                    NumBlend = i;
                }
            }

            if( d3dCaps.MaxVertexBlendMatrices >= NumBlend + 1 )
            {
                // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
                for( DWORD i = 0; i < pMeshContainer->NumInfl; ++i )
                {
                    iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
                    if( iMatrixIndex != UINT_MAX )
                    {
                        D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex],
                            pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
                        pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
                    }
                }

                pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, NumBlend );

                // lookup the material used for this subset of faces
                if( ( AttribIdPrev != pBoneComb[iAttrib].AttribId ) || ( AttribIdPrev == UNUSED32 ) )
                {
                    pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                    pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
                    AttribIdPrev = pBoneComb[iAttrib].AttribId;
                }

                // draw the subset now that the correct material and matrices are loaded
                pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
            }
        }
        pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, 0 );
    }
    else  // standard mesh, just draw it after setting material properties
    {
        pd3dDevice->SetTransform( D3DTS_WORLD, &pFrame->CombinedTransformationMatrix );

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


//--------------------------------------------------------------------------------------
// Name: DrawFrame()
// Desc: 绘制骨骼
//--------------------------------------------------------------------------------------
void DrawFrame( IDirect3DDevice9* pd3dDevice, LPD3DXFRAME pFrame )
{
    if (pFrame == NULL) return;
    LPD3DXMESHCONTAINER pMeshContainer;
    pMeshContainer = pFrame->pMeshContainer;                    // 取得网格容器
    while( pMeshContainer != NULL )                      
    {
        DrawMeshContainer(pd3dDevice, pMeshContainer, pFrame);  // 绘制非空蒙皮网格
        pMeshContainer = pMeshContainer->pNextMeshContainer;    // 遍历所有网格容器
    }

    DrawFrame(pd3dDevice, pFrame->pFrameSibling);               // 绘制兄弟框架
    DrawFrame(pd3dDevice, pFrame->pFrameFirstChild);            // 绘制子框架
}

//--------------------------------------------------------------------------------------
// Name: UpdateFrameMatrics()
// Desc: 更新框架中的变换矩阵
//--------------------------------------------------------------------------------------
void UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix )
{
    if (pFrameBase == NULL || pParentMatrix == NULL) return;
    D3DXFRAME_DERIVED* pFrame = ( D3DXFRAME_DERIVED* )pFrameBase;

    // 将当前骨骼的相对于父骨骼的偏移矩阵作累积运算
    D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);

    UpdateFrameMatrices(pFrame->pFrameSibling, pParentMatrix);                              // 更新兄弟骨骼
    UpdateFrameMatrices(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);   // 更新子骨骼
}
View Code

动画.cpp

#include "d3dUtility.h"
#include <fstream>
#include <vector>

#include "AllocateHierarchyClass.h"

#pragma  comment(lib, "d3d9.lib")
#pragma  comment(lib, "d3dx9.lib")
#pragma  comment(lib, "winmm.lib")
IDirect3DDevice9* Device = 0; 

const int Width  = 640;
const int Height = 480;

//四个和骨骼动画相关的全局变量
LPD3DXFRAME                 g_pFrameRoot      = NULL;
D3DXMATRIX*                 g_pBoneMatrices   = NULL;
CAllocateHierarchy*         g_pAllocateHier   = NULL;
LPD3DXANIMATIONCONTROLLER   g_pAnimController = NULL;

bool Setup()
{
    g_pAllocateHier=new CAllocateHierarchy();
    D3DXLoadMeshHierarchyFromX(L"3.X", D3DXMESH_MANAGED, Device, 
                                g_pAllocateHier, NULL, &g_pFrameRoot, &g_pAnimController);
    SetupBoneMatrixPointers(g_pFrameRoot, g_pFrameRoot);


    D3DXVECTOR3 dir(1.0f, -1.0f, 1.0f);
    D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f);
    D3DLIGHT9 light = d3d::InitDirectionalLight(&dir, &col);

    Device->SetLight(0,&light);
    Device->LightEnable(0,true);
    Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
    Device->SetRenderState(D3DRS_SPECULARENABLE, true);
    
    D3DXVECTOR3 pos(4.0f, 4.f, -500.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

    D3DXMATRIX V;
    D3DXMatrixLookAtLH(
        &V,
        &pos,
        &target,
        &up);

    Device->SetTransform(D3DTS_VIEW, &V);

    //
    // Set projection matrix.
    //

    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
            &proj,
            D3DX_PI * 0.5f, // 90 - degree
            (float)Width / (float)Height,
            1.0f,
            1000.0f);
    Device->SetTransform(D3DTS_PROJECTION, &proj);
    return true;
}

void Cleanup()
{

}

bool Display(float timeDelta)
{if( Device )
{
    // 重新 设置骨骼动画的矩阵
    D3DXMATRIX matFinal , matScal, matRot,matTran;
    D3DXMatrixIdentity(&matFinal);
    D3DXMatrixScaling(&matScal, 8.0f, 8.0f,8.0f);
    D3DXMatrixRotationX(&matRot,0.0*(2.0f*D3DX_PI)/360.f);
    D3DXMatrixTranslation(&matTran,0,-4.0f,0);
    matFinal = matScal *matFinal*matRot*matTran;
    Device->SetTransform(D3DTS_WORLD, &matFinal);
    //更新骨骼动画
    g_pAnimController->AdvanceTime(timeDelta, NULL);  //设置骨骼动画的时间
    UpdateFrameMatrices(g_pFrameRoot, &matFinal);   //更新框架中的变换矩阵
    Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
    Device->BeginScene();
        
    DrawFrame(Device, g_pFrameRoot);


    Device->EndScene();
    Device->Present(0, 0, 0, 0);
}
return true;
}

//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {
    case WM_DESTROY:
        ::PostQuitMessage(0);
        break;

    case WM_KEYDOWN:
        if( wParam == VK_ESCAPE )
            ::DestroyWindow(hwnd);
        break;
    }
    return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
    HINSTANCE prevInstance, 
    PSTR cmdLine,
    int showCmd)
{
    if(!d3d::InitD3D(hinstance,
        Width, Height, true, D3DDEVTYPE_HAL, &Device))
    {
        ::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
        return 0;
    }

    if(!Setup())
    {
        ::MessageBox(0, L"Setup() - FAILED", 0, 0);
        return 0;
    }

    d3d::EnterMsgLoop( Display );

    Cleanup();

    Device->Release();

    return 0;
}
View Code

 

posted @ 2022-05-05 11:30  szmtjs10  阅读(265)  评论(0编辑  收藏  举报