蒙皮骨骼动画
一、蒙皮骨骼动画原理:蒙皮骨骼动画的思想来源于自然界,大多数动物都拥有一套骨骼,骨骼是身体的框架,身体的皮毛血肉都是依附于骨骼。当骨骼开始运动的时候,依附于对应骨骼的皮毛血肉都会随骨骼一起运动。而Mesh模型是由大量的三角形组成,三角形由定点组成。当我们运动时,有必要知道那些定点依附于那块骨骼,根据骨骼的移动来移动对应的顶点。
蒙皮骨骼动画的加载:和Mesh模型的加载一样,骨骼加载时也是基于本地空间,我们需要把骨骼一块一块的从基于本地空间转换到整个Mesh模型空间。对于一套骨骼,有一个根(root)骨骼,这个根骨骼位于模型的一个定点,如坐标原点,其他骨骼都是直接或者间接与之联系。每根骨骼都有相对于其父母骨骼的相对位置(包括位移,和绕关节进行的转动),这种转换由一个矩阵完成:LocalTransformMatrix,这只是完成了骨骼的定位,要实现动画还需要对骨骼进行各种变换,如你所料,这肯定也是利用矩阵完成:CombinedTransformMatrix。当上层骨骼运动时,下层骨骼并不会主动运动,而是被牵连着运动,所以上层的运动会传递到下层骨骼,这个原理表示为:(子骨骼)CombinedTransformMatrix = (子骨骼)LocalTransformMatrix * (父母骨骼的)CombinedTransformMatrix.当然这中传递是渲染之前计算好的。
关键结构体:Direct3d中一套骨骼是以树形结构存放的,有两个关键的结构体和一个接口。
1:typedef struct _D3DXFRAME
{
LPSTR Name;
D3DXMATRIX TransformationMatrix;
LPD3DXMESHCONTAINER pMeshContainer;
struct _D3DXFRAME *pFrameSibling;
struct _D3DXFRAME *pFrameFirstChild;
} D3DXFRAME, *LPD3DXFRAME;
这个结构体代表了一块骨骼,有一个标识的Name,变换矩阵TransformationMatrix对应于之前所说的LocalTransformMatrix,还有分别指向兄弟结点和第一个孩子结点的指针,最后是包含了一个指向D3DXMESHCONTAINER结构体的指针,这是第二个关键的结构体。
2:typedef struct _D3DXMESHCONTAINER
{
LPSTR Name;
D3DXMESHDATA MeshData;
LPD3DXMATERIAL pMaterials;
LPD3DXEFFECTINSTANCE pEffects;
DWORD NumMaterials;
DWORD *pAdjacency;
LPD3DXSKININFO pSkinInfo;
struct _D3DXMESHCONTAINER *pNextMeshContainer;
} D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER;
对于这个结构体还是比较了解的,所以略。
3:ID3DXAllocateHierarchy 接口,这个接口只包含四个纯虚函数,我们需要去重写他们,这些函数无需我们自己调用,在我们使用D3DXLoadMeshHierarchyFromX()接口加载SkineMesh数据是自动调用。
4:D3DXLoadMeshHierarchyFromX (
LPCWSTR Filename,
DWORD MeshOptions,
LPDIRECT3DDEVICE9 pD3DDevice,
LPD3DXALLOCATEHIERARCHY pAlloc,
LPD3DXLOADUSERDATA pUserDataLoader,
LPD3DXFRAME *ppFrameHierarchy,
LPD3DXANIMATIONCONTROLLER *ppAnimController
);
有几个关键的参数:pAlloc,这是一个指向3中所说的
ID3DXAllocateHierarchy 接口的指针;ppFrameHierarchy,骨骼层次,也就是一个代表骨骼的树,是一个返回值;ppAnimController,这是动画控制器,是一个返回值,利用这个动画控制器就可以对SkinMesh进行控制。
蒙皮骨骼动画的渲染:渲染这部分比较简单,递归渲染每个MeshContainer,这样说可能很奇怪,因为每个骨骼结构体(D3DXFRAME)都包含了一个指向MeshContainer的指针,而每次渲染每个MeshContainer都是整副骨骼进行设置纹理和材质,然后就有问题了?这不是重复渲染了?百度,google和经自己调试发现,网上并没有找到标准答案,就是大多时候一个骨骼的MeshContainer指针都是空的,我在调试时候只有骨骼Name为空字符串时MeshContainer不为空,所以只渲染了一次,哦,我的模型是tiny.x。最后我估计:一套骨骼中也许只有一个或几个不为空的MeshContainer指针,通常是一个如果没必要分割渲染的话,递归只是为了寻找这个不为空的pMeshContainer.
笔记到此先告一段落,由于理解只在十分基本的层面,没法就很多细节进行分析,故在此只记录十分表面的东西,以后补足。PS:笔记主要参考《Direct3D游戏开发技术详解》,MSDN
参考:Direct3D游戏开发技术详解 和 SDK simple 简单的加载了tiny.x动画,只实现了SOFTWARE处理方式和走路的动画。
- #include "CLD3D.h"
- #include <stdio.h>
-
-
- const wchar_t wndName[50] = L"蒙皮骨骼动画演示";
- const wchar_t wndTitle[100] = L"【Direct3D】——蒙皮骨骼动画演示-coderling";
- const wchar_t xFileName[20] = L"tiny.x";
- const unsigned int wndWidth = 800;
- const unsigned int wndHeight = 600;
-
-
- struct D3DXFRAME_EX: public D3DXFRAME
- {
- D3DXMATRIXA16 combinedTransformtionMatrix;
- };
-
-
- struct D3DXMESHCONTAINER_EX: public D3DXMESHCONTAINER
- {
- LPDIRECT3DTEXTURE9* ppTextures;
-
-
- LPD3DXMESH pOrigMesh;
- LPD3DXATTRIBUTERANGE pAttributeTable;
- DWORD numAttributeGroups;
- DWORD numInfl;
- LPD3DXBUFFER pBoneCombinatonBuf;
- D3DXMATRIX** ppBoneMatrixPtrs;
- D3DXMATRIX* pBoneOffsetMatrices;
- DWORD numPaletteEntries;
-
-
-
- };
-
- HRESULT GenerateSkinnedMesh( D3DXMESHCONTAINER_EX* );
-
-
- 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* pEffectInstance,
- DWORD numMaterials,
- CONST DWORD* pAdjacency,
- LPD3DXSKININFO pSkinInfo,
- LPD3DXMESHCONTAINER* ppNewMeshContainer );
- STDMETHOD(DestroyFrame)( THIS_ LPD3DXFRAME pFrameToFree );
- STDMETHOD(DestroyMeshContainer)( THIS_ LPD3DXMESHCONTAINER pMeshContainer );
-
- };
-
-
- HRESULT CAllocateHierarchy::CreateFrame( LPCSTR name, LPD3DXFRAME* ppNewFrame )
- {
- HRESULT hr = S_OK;
-
- D3DXFRAME_EX *pFrame;
-
- *ppNewFrame = NULL;
-
- pFrame = new D3DXFRAME_EX;
- if( pFrame == NULL )
- {
- hr = E_OUTOFMEMORY;
- return hr;
- }
-
- if( name )
- {
- unsigned int len = strlen( name ) + 1;
- pFrame->Name = new char[len];
- memcpy( pFrame->Name, name, sizeof(char)*len );
- }
-
-
- D3DXMatrixIdentity( &pFrame->TransformationMatrix );
- D3DXMatrixIdentity( &pFrame->combinedTransformtionMatrix );
-
- pFrame->pMeshContainer = NULL;
- pFrame->pFrameFirstChild = NULL;
- pFrame->pFrameSibling = NULL;
-
- *ppNewFrame = pFrame;
-
- pFrame = NULL;
-
- return hr;
- }
-
-
-
- HRESULT CAllocateHierarchy::CreateMeshContainer(
- LPCSTR name,
- CONST D3DXMESHDATA* pMeshData,
- CONST D3DXMATERIAL* pMaterials,
- CONST D3DXEFFECTINSTANCE* pEffectInstances,
- DWORD numMaterials,
- CONST DWORD* pAdjacency,
- LPD3DXSKININFO pSkinInfo,
- LPD3DXMESHCONTAINER* ppNewMeshContainer )
- {
- D3DXMESHCONTAINER_EX* pMeshContainer = NULL;
- unsigned int numFaces;
- unsigned int iMaterial;
- unsigned int iBone, 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_EX;
- if( pMeshContainer == NULL )
- return E_FAIL;
- memset( pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_EX) );
-
- if( name )
- {
- unsigned int len = strlen( name ) + 1;
- pMeshContainer->Name = new char[len];
- memcpy( pMeshContainer->Name, name, sizeof(char)*len );
- }
-
- pMesh->GetDevice( &pD3DDevice );
- numFaces = pMesh->GetNumFaces();
-
-
- if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) )
- {
- pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
-
- HRESULT hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL,
- pD3DDevice, &pMeshContainer->MeshData.pMesh );
- if( FAILED( hr ) )
- return E_FAIL;
-
- 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 ) )
- return E_FAIL;
-
- memcpy( pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * numFaces*3 );
- memset( pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials );
-
- if( numMaterials > 0 )
- {
- memcpy( pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * pMeshContainer->NumMaterials );
-
- for( iMaterial = 0; iMaterial < numMaterials; iMaterial++ )
- {
- if( pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL )
- {
- HRESULT hr = D3DXCreateTextureFromFileA( pD3DDevice,
- pMeshContainer->pMaterials[iMaterial].pTextureFilename,
- &pMeshContainer->ppTextures[iMaterial] );
- if( FAILED( hr ) )
- pMeshContainer->ppTextures[iMaterial] = NULL;
- }
- }
- }
- else
- {
- pMeshContainer->pMaterials[0].pTextureFilename = NULL;
- memset( &pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9) );
- pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
- pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
- pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
- pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
- }
-
- if( pSkinInfo != NULL )
- {
- pMeshContainer->pSkinInfo = pSkinInfo;
- pSkinInfo->AddRef();
-
- pMeshContainer->pOrigMesh = pMesh;
- pMesh->AddRef();
-
-
- cBones = pSkinInfo->GetNumBones();
- pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
- if( pMeshContainer->pBoneOffsetMatrices == NULL )
- return E_FAIL;
-
-
- for( iBone = 0; iBone < cBones; iBone++ )
- {
- pMeshContainer->pBoneOffsetMatrices[iBone] = *( pMeshContainer->pSkinInfo->GetBoneOffsetMatrix( iBone ) );
- }
-
- HRESULT hr = GenerateSkinnedMesh( pMeshContainer );
- if( FAILED( hr ) )
- return E_FAIL;
- }
-
- *ppNewMeshContainer = pMeshContainer;
-
-
-
-
-
-
- return S_OK;
- }
-
-
- HRESULT CAllocateHierarchy::DestroyFrame( LPD3DXFRAME pFrameToFree )
- {
- SAFE_DELETE_ARRAY( pFrameToFree->Name );
- SAFE_DELETE( pFrameToFree );
-
- return S_OK;
- }
-
-
- HRESULT CAllocateHierarchy::DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerBase )
- {
- unsigned int iMaterial;
- D3DXMESHCONTAINER_EX* pMeshContainer = (D3DXMESHCONTAINER_EX*)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->pBoneCombinatonBuf );
- SAFE_RELEASE( pMeshContainer->pSkinInfo );
- SAFE_RELEASE( pMeshContainer->pOrigMesh );
- SAFE_DELETE( pMeshContainer );
-
- return S_OK;
- }
-
-
-
-
-
- LPDIRECT3D9 g_pD3D = NULL;
- LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
- LPD3DXFONT g_pText = NULL;
- LPD3DXFRAME g_pFrameRoot = NULL;
- LPD3DXANIMATIONCONTROLLER g_pAnimController;
- double g_startTime = 0.0;
- wchar_t* g_pAdapter = NULL;
- unsigned int g_numBoneMatricesMax = 0;
- D3DXMATRIXA16* g_pBoneMatrices = NULL;
-
-
- LRESULT WINAPI MsgProc( HWND, UINT, WPARAM, LPARAM );
- HRESULT InitApp( HWND, HINSTANCE );
- HRESULT InitGeometry();
- VOID InitTranformMatrix();
- HRESULT InitText();
- VOID Render( HWND );
- VOID RenderText( HWND );
- VOID UpdateScene( HWND );
- VOID UpdateFrameMatrices( const LPD3DXFRAME, const LPD3DXMATRIX );
- VOID InitLight();
- VOID Cleanup();
- HRESULT SetupBoneMatrixPointers( LPD3DXFRAME );
- HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER );
- VOID DrawFrame( LPD3DXFRAME );
- VOID DrawMeshContainer( const LPD3DXMESHCONTAINER, const LPD3DXFRAME );
-
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE preInst, LPSTR lpCmdLine, int nCmdShow )
- {
-
- WNDCLASSEX wcEx = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
- GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
- wndName, NULL };
- RegisterClassEx( &wcEx );
-
-
- HWND hWnd = CreateWindow( wndName, wndTitle, WS_OVERLAPPEDWINDOW,
- 100, 100, wndWidth, wndHeight, GetDesktopWindow(),
- NULL, hInst, NULL );
-
- if( SUCCEEDED( InitApp( hWnd, hInst ) ) )
- {
- if( SUCCEEDED( InitGeometry() ) )
- {
-
- ShowWindow( hWnd, SW_SHOWDEFAULT );
- UpdateWindow( hWnd );
-
-
- MSG msg;
- SecureZeroMemory( &msg, sizeof(msg) );
- while( msg.message != WM_QUIT )
- {
- if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- else
- Render( hWnd );
- }
- }
- }
-
- UnregisterClass( wndName, wcEx.hInstance );
- return 0;
- }
-
- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_KEYDOWN:
- if( wParam == VK_ESCAPE )
- DestroyWindow( hWnd );
- break;
- case WM_DESTROY:
- Cleanup();
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc( hWnd, msg, wParam, lParam );
- }
- return S_OK;
- }
-
- HRESULT InitApp( HWND hWnd , HINSTANCE hInst )
- {
-
- if( FAILED( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) )
- return E_FAIL;
-
-
- D3DPRESENT_PARAMETERS d3dpp;
- SecureZeroMemory( &d3dpp, sizeof(d3dpp) );
- d3dpp.BackBufferWidth = wndWidth;
- d3dpp.BackBufferHeight = wndHeight;
- d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
- d3dpp.BackBufferCount = 1;
- d3dpp.hDeviceWindow = hWnd;
- d3dpp.Windowed = true;
- d3dpp.EnableAutoDepthStencil = true;
- d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.Flags = 0;
- d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
- d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
-
-
- D3DCAPS9 caps;
- g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps );
- int vp = 0;
- if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
- vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
- else
- vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
-
-
- if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- hWnd, vp, &d3dpp, &g_pD3DDevice ) ) )
- {
- return E_FAIL;
- }
-
- InitText();
-
- g_startTime = (double)timeGetTime();
-
- return S_OK;
- }
-
- HRESULT InitGeometry()
- {
- HRESULT hr;
- CAllocateHierarchy alloc;
-
- hr = D3DXLoadMeshHierarchyFromX( xFileName, D3DXMESH_MANAGED, g_pD3DDevice, &alloc, NULL, &g_pFrameRoot, &g_pAnimController );
- if( FAILED( hr ) )
- return E_FAIL;
-
-
- hr = SetupBoneMatrixPointers( g_pFrameRoot );
-
- InitLight();
-
- InitTranformMatrix();
- g_pD3DDevice->SetRenderState( D3DRS_NORMALIZENORMALS, true );
-
-
-
- wchar_t adapterTemp[200] = L"显卡型号:";
- D3DADAPTER_IDENTIFIER9 adapter;
- g_pAdapter = new wchar_t[200];
- g_pD3D->GetAdapterIdentifier( 0, 0, &adapter );
-
-
- int len = MultiByteToWideChar( CP_ACP, 0, adapter.Description, -1, NULL, 0 );
- MultiByteToWideChar( CP_ACP, 0, adapter.Description, -1, g_pAdapter, len );
- wcscat_s(adapterTemp,g_pAdapter );
- memcpy( g_pAdapter, adapterTemp, sizeof(adapterTemp) );
-
-
- return S_OK;
- }
-
- VOID InitTranformMatrix()
- {
- D3DXMATRIX matWorld;
- D3DXMatrixIdentity( &matWorld );
- g_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
-
-
- D3DXVECTOR3 pos(100.0f, 100.0f, -250.0f);
- D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
- D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
-
-
-
- D3DXMATRIX V;
-
- D3DXMatrixLookAtLH(
- &V,
- &pos,
- &target,
- &up);
- g_pD3DDevice->SetTransform(D3DTS_VIEW, &V);
-
-
- D3DXMATRIX proj;
- D3DXMatrixPerspectiveFovLH(
- &proj,
- D3DX_PI * 0.5f,
- (float)wndWidth/ (float)wndHeight,
- 1.0f,
- 1000.0f);
- g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &proj);
-
-
- D3DVIEWPORT9 vp;
- vp.X = 0;
- vp.Y = 0;
- vp.Width = wndWidth;
- vp.Height = wndHeight;
- vp.MinZ = 0;
- vp.MaxZ = 1;
- g_pD3DDevice->SetViewport( &vp );
- }
-
- HRESULT InitText()
- {
- HRESULT hr;
-
- hr = D3DXCreateFont( g_pD3DDevice, 25, 0, 1000, 0, false,
- DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
- DEFAULT_QUALITY, 0, L"微软雅黑", &g_pText );
-
- return hr;
- }
-
- VOID Render( HWND hWnd )
- {
- if( NULL == g_pD3DDevice )
- return ;
-
- g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
- D3DCOLOR_XRGB( 28, 154, 207 ), 1.0f, 0 );
-
- if( SUCCEEDED( g_pD3DDevice->BeginScene() ) )
- {
- UpdateScene( hWnd );
- DrawFrame( g_pFrameRoot );
-
- RenderText( hWnd );
- g_pD3DDevice->EndScene();
- }
-
- g_pD3DDevice->Present( NULL, NULL, NULL, NULL );
-
- }
-
-
- VOID DrawFrame( LPD3DXFRAME pFrame )
- {
- LPD3DXMESHCONTAINER pMeshContainer;
-
- pMeshContainer = pFrame->pMeshContainer;
- while( pMeshContainer != NULL )
- {
- DrawMeshContainer( pMeshContainer, pFrame );
- pMeshContainer = pMeshContainer->pNextMeshContainer;
- }
-
- if( pFrame->pFrameSibling != NULL )
- {
- DrawFrame( pFrame->pFrameSibling );
- }
-
- if( pFrame->pFrameFirstChild != NULL )
- {
- DrawFrame( pFrame->pFrameFirstChild );
- }
- }
-
-
- VOID DrawMeshContainer( const LPD3DXMESHCONTAINER pMeshContainerBase, const LPD3DXFRAME pFrameBase )
- {
- D3DXMESHCONTAINER_EX* pMeshContainer = (D3DXMESHCONTAINER_EX*)pMeshContainerBase;
- D3DXFRAME_EX* pFrame = (D3DXFRAME_EX*)pFrameBase;
- unsigned int iMaterial;
-
- unsigned int iAttrib;
-
-
-
-
-
- D3DXMATRIXA16 matTemp;
-
-
- if( pMeshContainer->pSkinInfo != NULL )
- {
-
-
- DWORD cBones = pMeshContainer->pSkinInfo->GetNumBones();
- DWORD iBone;
- PBYTE pbVerticesSrc;
- PBYTE pbVerticesDest;
-
-
- for( iBone = 0; iBone < cBones; ++iBone )
- {
- D3DXMatrixMultiply(
- &g_pBoneMatrices[iBone],
- &pMeshContainer->pBoneOffsetMatrices[iBone],
- pMeshContainer->ppBoneMatrixPtrs[iBone]
- );
- }
-
- pMeshContainer->pOrigMesh->LockVertexBuffer( D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc );
- pMeshContainer->MeshData.pMesh->LockVertexBuffer( 0, (LPVOID*)&pbVerticesDest );
-
- pMeshContainer->pSkinInfo->UpdateSkinnedMesh( g_pBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest );
-
-
-
-
- pMeshContainer->pOrigMesh->UnlockVertexBuffer();
- pMeshContainer->MeshData.pMesh->UnlockVertexBuffer();
-
- for( iAttrib = 0; iAttrib < pMeshContainer->numAttributeGroups; iAttrib++ )
- {
- g_pD3DDevice->SetMaterial( &( pMeshContainer->pMaterials[pMeshContainer->pAttributeTable[iAttrib].AttribId].MatD3D ) );
- g_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[pMeshContainer->pAttributeTable[iAttrib].AttribId]);
- pMeshContainer->MeshData.pMesh->DrawSubset( pMeshContainer->pAttributeTable[iAttrib].AttribId);
- }
- }
- else
- {
- for( iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++ )
- {
- g_pD3DDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D );
- g_pD3DDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] );
- pMeshContainer->MeshData.pMesh->DrawSubset( iMaterial );
- }
- }
- }
-
- VOID RenderText( HWND hWnd )
- {
- RECT clientRect;
- GetClientRect( hWnd, &clientRect );
-
-
- g_pText->DrawText( NULL, g_pAdapter, -1, &clientRect,
- DT_TOP | DT_LEFT, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ) );
-
-
- wchar_t strFPS[20];
- int len = swprintf_s(strFPS, 20, L"FPS:%.3f", GetFPS());
- g_pText->DrawText( NULL, strFPS, len, &clientRect, DT_TOP | DT_RIGHT,
- D3DXCOLOR( 0.0f, 1.0f, 0.0f, 1.0f ) );
-
- }
-
- VOID UpdateScene( HWND hWnd )
- {
- if( g_pAnimController != NULL )
- {
- double time = (double)timeGetTime();
- time = ( time - g_startTime ) * 0.001;
- g_startTime = (double)timeGetTime();
- g_pAnimController->AdvanceTime( time, NULL );
- }
-
- D3DXMATRIX matWorld;
-
- g_pD3DDevice->GetTransform( D3DTS_WORLD, &matWorld );
- UpdateFrameMatrices( g_pFrameRoot, &matWorld );
- }
-
-
-
- VOID UpdateFrameMatrices( const LPD3DXFRAME pFrameBase, const LPD3DXMATRIX pParentMatrix )
- {
- D3DXFRAME_EX* pFrame = (D3DXFRAME_EX*)pFrameBase;
-
- if( pParentMatrix != NULL )
- D3DXMatrixMultiply( &pFrame->combinedTransformtionMatrix, &pFrame->TransformationMatrix, pParentMatrix );
- else
- pFrame->combinedTransformtionMatrix = pFrame->TransformationMatrix;
-
- if( pFrame->pFrameSibling != NULL )
- {
- UpdateFrameMatrices( pFrame->pFrameSibling, pParentMatrix );
- }
-
- if( pFrame->pFrameFirstChild != NULL )
- {
- UpdateFrameMatrices( pFrame->pFrameFirstChild, &pFrame->combinedTransformtionMatrix );
- }
- }
-
- VOID InitLight()
- {
-
-
-
-
-
-
-
- D3DLIGHT9 pointLight;
- SecureZeroMemory( &pointLight, sizeof(pointLight) );
- D3DXCOLOR white = D3DCOLOR_RGBA( 255, 255, 255, 255 );
- D3DXCOLOR black = D3DCOLOR_RGBA( 0, 0, 0, 0 );
- pointLight.Type = D3DLIGHT_POINT;
- pointLight.Ambient = white*0.4f;
- pointLight.Diffuse = white;
- pointLight.Specular = white*0.6f;
- pointLight.Position = D3DXVECTOR3( 200.0f, 200.0f, 0.0f );
- pointLight.Range = 500.0f;
- pointLight.Attenuation0 = 1.0f;
- pointLight.Attenuation1 = 0.0f;
- pointLight.Attenuation2 = 0.0f;
-
- g_pD3DDevice->SetLight( 0, &pointLight );
- g_pD3DDevice->LightEnable( 0, true );
- }
-
- VOID Cleanup()
- {
- SAFE_DELETE( g_pAdapter );
- SAFE_RELEASE( g_pD3D );
- SAFE_RELEASE( g_pD3DDevice );
- SAFE_RELEASE( g_pText );
- SAFE_RELEASE( g_pAnimController );
-
-
- if( g_pFrameRoot != NULL )
- {
- CAllocateHierarchy alloc;
- D3DXFrameDestroy( g_pFrameRoot, &alloc );
- g_pFrameRoot = NULL;
- }
- }
-
-
- 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;
- }
-
- HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase )
- {
- unsigned int iBone;
- unsigned int cBones;
- D3DXFRAME_EX* pFrame;
-
- D3DXMESHCONTAINER_EX* pMeshContainer = ( D3DXMESHCONTAINER_EX* )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_EX*)D3DXFrameFind( g_pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName( iBone ) );
- if( pFrame == NULL )
- return E_FAIL;
-
- pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->combinedTransformtionMatrix;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- return S_OK;
- }
-
-
- HRESULT GenerateSkinnedMesh( D3DXMESHCONTAINER_EX* pMeshContainer )
- {
- HRESULT hr = S_OK;
-
- if( pMeshContainer->pSkinInfo == NULL )
- return hr;
- SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
- SAFE_RELEASE( pMeshContainer->pBoneCombinatonBuf );
-
- hr = pMeshContainer->pOrigMesh->CloneMeshFVF( D3DXMESH_MANAGED, pMeshContainer->pOrigMesh->GetFVF(),
- g_pD3DDevice, &pMeshContainer->MeshData.pMesh );
- if( FAILED(hr) )
- return hr;
-
- hr = pMeshContainer->MeshData.pMesh->GetAttributeTable( NULL, &pMeshContainer->numAttributeGroups );
- if( FAILED(hr) )
- return hr;
-
- delete[] pMeshContainer->pAttributeTable;
- pMeshContainer->pAttributeTable = new D3DXATTRIBUTERANGE[pMeshContainer->numAttributeGroups];
- if( pMeshContainer->pAttributeTable == NULL )
- return E_OUTOFMEMORY;
-
- hr = pMeshContainer->MeshData.pMesh->GetAttributeTable( pMeshContainer->pAttributeTable, NULL );
- if( FAILED(hr) )
- return hr;
-
- if( g_numBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones() )
- {
- g_numBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();
-
-
- g_pBoneMatrices = new D3DXMATRIXA16[g_numBoneMatricesMax];
- if( g_pBoneMatrices == NULL )
- return E_OUTOFMEMORY;
- }
-
- return hr;
- }
原文来自:http://blog.csdn.net/coderling/article/details/10168277