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
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 );
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); // 更新子骨骼 }
动画.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; }