I followed a book actually and plug it into a QT project
Do you find anything unusual?
D3DX: MEMORY LEAKS DETECTED: 159 allocations unfreed (3312 bytes)
D3DX: Set HKLM\Software\Microsoft\Direct3D\D3DXBreakOnAllocId=0x2fd0 to debug
myDX9Widget.h
#pragma once
#include "dxwidget.h"
class myDX9Widget :
public DXWidget
{
public:
#ifdef QWIDGET_H
myDX9Widget( QWidget *parent = 0, Qt::WFlags flags = 0 )
: DXWidget( parent, flags ), m_pD3D(0), m_pDevice(0)
{
}
#else
myDX9Widget()
: m_pD3D(0), m_pDevice(0)
{
}
#endif
virtual ~myDX9Widget()
{
uninitialize();
}
virtual void initCamera()
{
m_camera[0].Load(m_pDevice, "Data\\Others\\Demo1.cam");
m_camera[1].Load(m_pDevice, "Data\\Others\\Demo2.cam");
m_camera[2].Load(m_pDevice, "Data\\Others\\Demo3.cam");
}
virtual void initModels()
{
mOperatorMesh.Load(L"Data\\operator.x");
}
//-----------------------------------------------------------------------------
// Name: initialize()
// Desc: This function will only be called once during the application's
// initialization phase. Therefore, it can't contain any resources that
// need to be restored every time the Direct3D device is lost or the
// window is resized.
//-----------------------------------------------------------------------------
HRESULT initialize()
{
HRESULT hr = S_OK;
m_pD3D = 0;
m_pDevice = 0;
m_pVB = NULL;
m_pIB = NULL;
m_pVertexShader = NULL;
m_pConstantTable = NULL;
m_pVertexDeclaration = NULL;
m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); //Standard
D3DCAPS9 Caps;
m_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps );
DWORD BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW
// then switch to SWVP.
if( ( Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ||
Caps.VertexShaderVersion < D3DVS_VERSION( 2, 0 ) )
{
BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
ZeroMemory( &m_d3dpp, sizeof(m_d3dpp) );
m_d3dpp.Windowed = TRUE;
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
m_d3dpp.MultiSampleQuality = 0;
m_d3dpp.EnableAutoDepthStencil = TRUE;
m_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
for( int m=0; m<=(int)D3DMULTISAMPLE_4_SAMPLES; m+=2 )
{
DWORD QualityBackBuffer = 0;
hr = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
m_d3dpp.BackBufferFormat,
m_d3dpp.Windowed,
(D3DMULTISAMPLE_TYPE)m,
&QualityBackBuffer );
if( FAILED(hr) ) break;
if( QualityBackBuffer>0 )
{
m_d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)m;
m_d3dpp.MultiSampleQuality = QualityBackBuffer-1;
}
}
// Hardware Device
hr = m_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winId(),
BehaviorFlags, &m_d3dpp, &m_pDevice );
if( FAILED(hr) )
{
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
m_d3dpp.MultiSampleQuality = 0;
// Reference Rasterizer
hr = m_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, winId(),
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_d3dpp, &m_pDevice );
}
g_pDevice = m_pDevice;
if (SUCCEEDED(hr))
{
hr = restoreDeviceObjects();
}
initCamera();
initModels();
return hr;
}
//-----------------------------------------------------------------------------
// Name: uninitialize()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
void uninitialize()
{
invalidateDeviceObjects();
SAFE_RELEASE(m_pDevice);
SAFE_RELEASE(m_pD3D);
}
//-----------------------------------------------------------------------------
// Name: restoreDeviceObjects()
// Desc: You are encouraged to develop applications with a single code path to
// respond to device loss. This code path is likely to be similar, if not
// identical, to the code path taken to initialize the device at startup.
//-----------------------------------------------------------------------------
HRESULT restoreDeviceObjects()
{
if( !m_pDevice ) return E_FAIL;
HRESULT hr = S_OK;
DWORD VERTS_PER_EDGE = 64;
DWORD dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
DWORD dwNumIndices = 6 * ( VERTS_PER_EDGE - 1 ) * ( VERTS_PER_EDGE - 1 );
// Create and initialize index buffer
WORD* pIndices;
V_RETURN( m_pDevice->CreateIndexBuffer( dwNumIndices * sizeof( WORD ),
0, D3DFMT_INDEX16,
D3DPOOL_DEFAULT, &m_pIB, NULL ) );
V_RETURN( m_pIB->Lock( 0, 0, ( void** )&pIndices, 0 ) );
DWORD y;
for( y = 1; y < VERTS_PER_EDGE; y++ )
{
for( DWORD x = 1; x < VERTS_PER_EDGE; x++ )
{
*pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 1 ) );
*pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 1 ) );
*pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 0 ) );
*pIndices++ = ( WORD )( ( y - 1 ) * VERTS_PER_EDGE + ( x - 0 ) );
*pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 1 ) );
*pIndices++ = ( WORD )( ( y - 0 ) * VERTS_PER_EDGE + ( x - 0 ) );
}
}
V_RETURN( m_pIB->Unlock() );
// Create and initialize vertex buffer
V_RETURN( m_pDevice->CreateVertexBuffer( dwNumVertices * sizeof( D3DXVECTOR2 ), 0, 0,
D3DPOOL_DEFAULT, &m_pVB, NULL ) );
D3DXVECTOR2* pVertices;
V_RETURN( m_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) );
for( y = 0; y < VERTS_PER_EDGE; y++ )
{
for( DWORD x = 0; x < VERTS_PER_EDGE; x++ )
{
*pVertices++ = D3DXVECTOR2( ( ( float )x / ( float )( VERTS_PER_EDGE - 1 ) - 0.5f ) * D3DX_PI,
( ( float )y / ( float )( VERTS_PER_EDGE - 1 ) - 0.5f ) * D3DX_PI );
}
}
V_RETURN( hr = m_pVB->Unlock() );
LPD3DXBUFFER pCode;
D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
D3DDECL_END()
};
V_RETURN( m_pDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ) );
DWORD dwShaderFlags = 0;
#ifdef DEBUG_VS
dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif
V_RETURN( D3DXCompileShaderFromFile( L"HLSLwithoutFX.vsh", NULL, NULL, "Ripple",
"vs_2_0", dwShaderFlags, &pCode,
NULL, &m_pConstantTable ) );
hr = m_pDevice->CreateVertexShader( ( DWORD* )pCode->GetBufferPointer(), &m_pVertexShader );
pCode->Release();
if( FAILED( hr ) )
return hr;
m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
m_pDevice->SetRenderState( D3DRS_MULTISAMPLEANTIALIAS, TRUE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: invalidateDeviceObjects()
// Desc: If the lost device can be restored, the application prepares the
// device by destroying all video-memory resources and any
// swap chains. This is typically accomplished by using the SAFE_RELEASE
// macro.
//-----------------------------------------------------------------------------
HRESULT invalidateDeviceObjects()
{
if( !m_pDevice ) return E_FAIL;
SAFE_RELEASE( m_pVertexShader );
SAFE_RELEASE( m_pConstantTable );
SAFE_RELEASE( m_pVertexDeclaration );
SAFE_RELEASE( m_pIB );
SAFE_RELEASE( m_pVB );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
virtual HRESULT render()
{
if( !m_pDevice ) return E_FAIL;
HRESULT hr = S_OK;
clearScene( D3DXCOLOR( 0.0f, 0.25f, 0.25f, 0.55f ), 1.0f, 0 );
DWORD VERTS_PER_EDGE = 64;
DWORD dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
DWORD dwNumIndices = 6 * ( VERTS_PER_EDGE - 1 ) * ( VERTS_PER_EDGE - 1 );
if( SUCCEEDED(beginScene()) )
{
D3DXMATRIXA16 mWorldViewProj = D3DXMATRIXA16((float*)&ViewMatrix()) * D3DXMATRIXA16((float*)&ProjMatrix());
// DX10 spec only guarantees Sincos function from -100 * Pi to 100 * Pi
float fBoundedTime = (float) m_fTime - (floor( (float) m_fTime / (2.0f * D3DX_PI)) * 2.0f * D3DX_PI);
m_pConstantTable->SetMatrix( m_pDevice, "mWorldViewProj", &mWorldViewProj );
m_pConstantTable->SetFloat( m_pDevice, "fTime", fBoundedTime );
m_pDevice->SetVertexDeclaration( m_pVertexDeclaration );
m_pDevice->SetVertexShader( m_pVertexShader );
m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof( D3DXVECTOR2 ) );
m_pDevice->SetIndices( m_pIB );
m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, dwNumVertices, 0, dwNumIndices / 3 );
endScene();
}
hr = present();
m_lastRendered = m_fTime;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: clearScene()
// Desc: Clear the render target and depth stencil
//-----------------------------------------------------------------------------
void clearScene( D3DXCOLOR ClearColor, float Z, DWORD Stencil )
{
m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, (DWORD)ClearColor, Z, Stencil );
}
//-----------------------------------------------------------------------------
// Name: clearRenderTarget()
// Desc: Clear the render target
//-----------------------------------------------------------------------------
void clearRenderTarget( D3DXCOLOR ClearColor )
{
m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET,(DWORD)ClearColor, 1.0f, 0 );
}
//-----------------------------------------------------------------------------
// Name: clearScene()
// Desc: Clear the render target
//-----------------------------------------------------------------------------
void clearDepthStencil( float Z, DWORD Stencil )
{
m_pDevice->Clear( 0, 0, D3DCLEAR_TARGET, 0, Z, Stencil );
}
//-----------------------------------------------------------------------------
// Name: beginScene()
// Desc: Begin the scene
//-----------------------------------------------------------------------------
HRESULT beginScene()
{
return m_pDevice->BeginScene();
}
//-----------------------------------------------------------------------------
// Name: endScene()
// Desc: End the scene
//-----------------------------------------------------------------------------
HRESULT endScene()
{
return m_pDevice->EndScene();
}
//-----------------------------------------------------------------------------
// Name: present()
// Desc: Present the backbuffer contents to the display
//-----------------------------------------------------------------------------
HRESULT present()
{
HRESULT hr;
hr = m_pDevice->Present( 0, 0, 0, 0 );
// The following code refer to "Direct3D (DirectX 9.0) Code Samples Page6: Lost Device Recovery".
// URL: http://www.codesampler.com/dx9src.htm
//
// If Present fails with D3DERR_DEVICELOST the application needs to be
// notified so it cleanup resources and reset the device.
//
if( D3DERR_DEVICELOST == hr )
{
// Yield some CPU time to other processes
Sleep( 100 ); // 100 milliseconds
//
// Test the cooperative level to see if it's okay to render.
// The application can determine what to do on encountering a lost
// device by querying the return value of the TestCooperativeLevel
// method.
//
if( FAILED( hr = m_pDevice->TestCooperativeLevel() ) )
{
// The device has been lost but cannot be reset at this time.
// Therefore, rendering is not possible and we'll have to return
// and try again at a later time.
if( hr == D3DERR_DEVICELOST )
return hr;
// The device has been lost but it can be reset at this time.
if( hr == D3DERR_DEVICENOTRESET )
{
//
// If the device can be restored, the application prepares the
// device by destroying all video-memory resources and any
// swap chains.
//
invalidateDeviceObjects();
//
// Then, the application calls the Reset method.
//
// Reset is the only method that has an effect when a device
// is lost, and is the only method by which an application can
// change the device from a lost to an operational state.
// Reset will fail unless the application releases all
// resources that are allocated in D3DPOOL_DEFAULT, including
// those created by the IDirect3DDevice9::CreateRenderTarget
// and IDirect3DDevice9::CreateDepthStencilSurface methods.
//
hr = m_pDevice->Reset( &m_d3dpp );
if( FAILED( hr ) )
return hr;
//
// Finally, a lost device must re-create resources (including
// video memory resources) after it has been reset.
//
restoreDeviceObjects();
}
}
}
return hr;
}
virtual void paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
render();
}
void onResize( UINT nWidth, UINT nHeight )
{
HRESULT hr = S_OK;
if( !m_pDevice ) return;
m_d3dpp.BackBufferWidth = nWidth;
m_d3dpp.BackBufferHeight = nHeight;
invalidateDeviceObjects();
hr = m_pDevice->Reset(&m_d3dpp);
restoreDeviceObjects();
// Camera ---------------------------------------------------
setAspect( width() / (float)height() );
render();
}
private:
//! Used to create the D3DDevice
IDirect3D9* m_pD3D;
//! Our rendering device
IDirect3DDevice9* m_pDevice;
//! D3D Device Parameterss
D3DPRESENT_PARAMETERS m_d3dpp;
LPDIRECT3DVERTEXBUFFER9 m_pVB;
LPDIRECT3DINDEXBUFFER9 m_pIB;
LPDIRECT3DVERTEXSHADER9 m_pVertexShader;
LPD3DXCONSTANTTABLE m_pConstantTable;
LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration;
SkinnedMesh mOperatorMesh;
};
skinnedmesh.h
//////////////////////////////////////////////////////////////////////////
// Character Animation with Direct3D //
// Author: C. Granberg //
// 2008 - 2009 //
//////////////////////////////////////////////////////////////////////////
#ifndef SKINNED_MESH
#define SKINNED_MESH
#include <windows.h>
#include <d3dx9.h>
#include <string>
#include <vector>
using namespace std;
struct Bone: public D3DXFRAME
{
D3DXMATRIX CombinedTransformationMatrix;
};
struct BoneMesh: public D3DXMESHCONTAINER
{
ID3DXMesh* OriginalMesh;
vector<D3DMATERIAL9> materials;
vector<IDirect3DTexture9*> textures;
DWORD NumAttributeGroups;
D3DXATTRIBUTERANGE* attributeTable;
D3DXMATRIX** boneMatrixPtrs;
D3DXMATRIX* boneOffsetMatrices;
D3DXMATRIX* currentBoneMatrices;
};
class SkinnedMesh
{
public:
SkinnedMesh();
~SkinnedMesh();
void Load(const std::wstring& fileName);
void Render(Bone *bone);
void SetPose(D3DXMATRIX world);
void GetAnimations(vector<string> &animations);
ID3DXAnimationController* GetController();
private:
void UpdateMatrices(Bone* bone, D3DXMATRIX *parentMatrix);
void SetupBoneMatrixPointers(Bone *bone);
D3DXFRAME *m_pRootBone;
ID3DXAnimationController *m_pAnimControl;
};
#endif
skinnedMesh.cpp
#include "skinnedMesh.h"
#include <fstream>
#pragma warning(disable:4996)
extern IDirect3DDevice9 *g_pDevice;
//extern ID3DXEffect *g_pEffect;
extern ofstream g_debug;
class BoneHierarchyLoader: 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);
};
HRESULT BoneHierarchyLoader::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
{
Bone *newBone = new Bone;
memset(newBone, 0, sizeof(Bone));
//Copy name
if(Name != NULL)
{
newBone->Name = new char[strlen(Name)+1];
strcpy(newBone->Name, Name);
}
//Set the transformation matrices
D3DXMatrixIdentity(&newBone->TransformationMatrix);
D3DXMatrixIdentity(&newBone->CombinedTransformationMatrix);
//Return the new bone...
*ppNewFrame = (D3DXFRAME*)newBone;
return S_OK;
}
HRESULT BoneHierarchyLoader::CreateMeshContainer(LPCSTR Name,
CONST D3DXMESHDATA *pMeshData,
CONST D3DXMATERIAL *pMaterials,
CONST D3DXEFFECTINSTANCE *pEffectInstances,
DWORD NumMaterials,
CONST DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
//Create new Bone Mesh
BoneMesh *boneMesh = new BoneMesh;
memset(boneMesh, 0, sizeof(BoneMesh));
//Get mesh data
boneMesh->OriginalMesh = pMeshData->pMesh;
boneMesh->MeshData.pMesh = pMeshData->pMesh;
boneMesh->MeshData.Type = pMeshData->Type;
pMeshData->pMesh->AddRef(); //Add Reference so that the mesh isnt deallocated
IDirect3DDevice9 *pDevice = NULL;
pMeshData->pMesh->GetDevice(&pDevice); //Get g_pDevice ptr from mesh
//Copy materials and load textures (just like with a static mesh)
for(int i=0;i<(int)NumMaterials;i++)
{
D3DXMATERIAL mtrl;
memcpy(&mtrl, &pMaterials[i], sizeof(D3DXMATERIAL));
boneMesh->materials.push_back(mtrl.MatD3D);
IDirect3DTexture9* newTexture = NULL;
if(mtrl.pTextureFilename != NULL)
{
char textureFname[200];
strcpy(textureFname, "resources/meshes/");
strcat(textureFname, mtrl.pTextureFilename);
//Load texture
D3DXCreateTextureFromFileA(pDevice, textureFname, &newTexture);
}
boneMesh->textures.push_back(newTexture);
}
if(pSkinInfo != NULL)
{
//Get Skin Info
boneMesh->pSkinInfo = pSkinInfo;
pSkinInfo->AddRef(); //Add reference so that the SkinInfo isnt deallocated
DWORD maxVertInfluences = 0;
DWORD numBoneComboEntries = 0;
ID3DXBuffer* boneComboTable = 0;
pSkinInfo->ConvertToIndexedBlendedMesh(pMeshData->pMesh,
D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
30,
0, // ignore adjacency in
0, // ignore adjacency out
0, // ignore face remap
0, // ignore vertex remap
&maxVertInfluences,
&numBoneComboEntries,
&boneComboTable,
&boneMesh->MeshData.pMesh);
if(boneComboTable != NULL)
boneComboTable->Release();
//Get Attribute Table
boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);
boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];
boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);
//Create bone offset and current matrices
int NumBones = pSkinInfo->GetNumBones();
boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];
boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];
//Get bone offset matrices
for(int i=0;i < NumBones;i++)
boneMesh->boneOffsetMatrices[i] = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));
}
//Set ppNewMeshContainer to the newly created boneMesh container
*ppNewMeshContainer = boneMesh;
return S_OK;
}
HRESULT BoneHierarchyLoader::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
if(pFrameToFree)
{
//Free name
if(pFrameToFree->Name != NULL)
delete [] pFrameToFree->Name;
//Free bone
delete pFrameToFree;
}
pFrameToFree = NULL;
return S_OK;
}
HRESULT BoneHierarchyLoader::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
BoneMesh *boneMesh = (BoneMesh*)pMeshContainerBase;
//Release textures
int numTextures = (int)boneMesh->textures.size();
for(int i=0;i < numTextures;i++)
if(boneMesh->textures[i] != NULL)
boneMesh->textures[i]->Release();
//Release mesh data
if(boneMesh->MeshData.pMesh)boneMesh->MeshData.pMesh->Release();
if(boneMesh->pSkinInfo)boneMesh->pSkinInfo->Release();
if(boneMesh->OriginalMesh)boneMesh->OriginalMesh->Release();
delete boneMesh;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// SKINNED MESH //
//////////////////////////////////////////////////////////////////////////////////////////////////
struct VERTEX{
VERTEX();
VERTEX(D3DXVECTOR3 pos, D3DCOLOR col){position = pos; color = col;}
D3DXVECTOR3 position;
D3DCOLOR color;
static const DWORD FVF;
};
const DWORD VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
SkinnedMesh::SkinnedMesh()
{
m_pRootBone = NULL;
m_pAnimControl = NULL;
}
SkinnedMesh::~SkinnedMesh()
{
//BoneHierarchyLoader boneHierarchy;
///boneHierarchy.DestroyFrame(m_pRootBone);
BoneHierarchyLoader alloc;
D3DXFrameDestroy(m_pRootBone, &alloc);
if(m_pAnimControl)m_pAnimControl->Release();
}
void SkinnedMesh::Load(const std::wstring& fileName)
{
BoneHierarchyLoader boneHierarchy;
D3DXLoadMeshHierarchyFromX(fileName.c_str(), D3DXMESH_MANAGED,
g_pDevice, &boneHierarchy,
NULL, &m_pRootBone, &m_pAnimControl);
SetupBoneMatrixPointers((Bone*)m_pRootBone);
//Update all the bones
D3DXMATRIX i;
D3DXMatrixIdentity(&i);
UpdateMatrices((Bone*)m_pRootBone, &i);
}
void SkinnedMesh::UpdateMatrices(Bone* bone, D3DXMATRIX *parentMatrix)
{
if(bone == NULL)return;
D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
&bone->TransformationMatrix,
parentMatrix);
if(bone->pFrameSibling)UpdateMatrices((Bone*)bone->pFrameSibling, parentMatrix);
if(bone->pFrameFirstChild)UpdateMatrices((Bone*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
}
void SkinnedMesh::Render(Bone *bone)
{
/*
if(bone == NULL)bone = (Bone*)m_pRootBone;
//If there is a mesh to render...
if(bone->pMeshContainer != NULL)
{
BoneMesh *boneMesh = (BoneMesh*)bone->pMeshContainer;
if (boneMesh->pSkinInfo != NULL)
{
// set up bone transforms
int numBones = boneMesh->pSkinInfo->GetNumBones();
for(int i=0;i < numBones;i++)
{
D3DXMatrixMultiply(&boneMesh->currentBoneMatrices[i],
&boneMesh->boneOffsetMatrices[i],
boneMesh->boneMatrixPtrs[i]);
}
D3DXMATRIX view, proj, identity;
g_pEffect->SetMatrixArray("FinalTransforms", boneMesh->currentBoneMatrices, boneMesh->pSkinInfo->GetNumBones());
D3DXMatrixIdentity(&identity);
//Render the mesh
for(int i=0;i < (int)boneMesh->NumAttributeGroups;i++)
{
int mtrlIndex = boneMesh->attributeTable[i].AttribId;
m_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
m_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
g_pEffect->SetMatrix("matW", &identity);
g_pEffect->SetTexture("texDiffuse", boneMesh->textures[mtrlIndex]);
D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("Skinning");
g_pEffect->SetTechnique(hTech);
g_pEffect->Begin(NULL, NULL);
g_pEffect->BeginPass(0);
boneMesh->MeshData.pMesh->DrawSubset(mtrlIndex);
g_pEffect->EndPass();
g_pEffect->End();
}
}
else
{
//Normal Static Mesh
g_pEffect->SetMatrix("matW", &bone->CombinedTransformationMatrix);
D3DXHANDLE hTech = g_pEffect->GetTechniqueByName("Lighting");
g_pEffect->SetTechnique(hTech);
//Render the mesh
int numMaterials = (int)boneMesh->materials.size();
for(int i=0;i < numMaterials;i++)
{
m_pDevice->SetMaterial(&boneMesh->materials[i]);
g_pEffect->SetTexture("texDiffuse", boneMesh->textures[i]);
g_pEffect->Begin(NULL, NULL);
g_pEffect->BeginPass(0);
boneMesh->OriginalMesh->DrawSubset(i);
g_pEffect->EndPass();
g_pEffect->End();
}
}
}
*/
if(bone->pFrameSibling != NULL)Render((Bone*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)Render((Bone*)bone->pFrameFirstChild);
}
void SkinnedMesh::SetupBoneMatrixPointers(Bone *bone)
{
if(bone->pMeshContainer != NULL)
{
BoneMesh *boneMesh = (BoneMesh*)bone->pMeshContainer;
if(boneMesh->pSkinInfo != NULL)
{
int NumBones = boneMesh->pSkinInfo->GetNumBones();
boneMesh->boneMatrixPtrs = new D3DXMATRIX*[NumBones];
for(int i=0;i < NumBones;i++)
{
Bone *b = (Bone*)D3DXFrameFind(m_pRootBone, boneMesh->pSkinInfo->GetBoneName(i));
if(b != NULL)boneMesh->boneMatrixPtrs[i] = &b->CombinedTransformationMatrix;
else boneMesh->boneMatrixPtrs[i] = NULL;
}
}
}
if(bone->pFrameSibling != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameFirstChild);
}
void SkinnedMesh::SetPose(D3DXMATRIX world)
{
UpdateMatrices((Bone*)m_pRootBone, &world);
}
void SkinnedMesh::GetAnimations(vector<string> &animations)
{
ID3DXAnimationSet *anim = NULL;
for(int i=0;i<(int)m_pAnimControl->GetMaxNumAnimationSets();i++)
{
anim = NULL;
m_pAnimControl->GetAnimationSet(i, &anim);
if(anim != NULL)
{
animations.push_back(anim->GetName());
anim->Release();
}
}
}
ID3DXAnimationController* SkinnedMesh::GetController()
{
ID3DXAnimationController* newAnimController = NULL;
if(m_pAnimControl != NULL)
{
m_pAnimControl->CloneAnimationController(m_pAnimControl->GetMaxNumAnimationOutputs(),
m_pAnimControl->GetMaxNumAnimationSets(),
m_pAnimControl->GetMaxNumTracks(),
m_pAnimControl->GetMaxNumEvents(),
&newAnimController);
}
return newAnimController;
}