need some fixes for my coding, thanks :)

Started by
8 comments, last by lucky6969b 12 years, 10 months ago
Hello, I have a faulty code needed to be fixed. Could anyone lend me a hand cos i've been struggling with it for a couple of days already.... thanks What i need is to display a skinned mesh in my scene
But I just can't do it...
Here is an extract of my code
AllocHierachy.h

#ifndef ALLOC_MESH_HIERARCHY_H
#define ALLOC_MESH_HIERARCHY_H

#include <d3dx9.h>

class AllocMeshHierarchy : public ID3DXAllocateHierarchy
{
public:
HRESULT STDMETHODCALLTYPE CreateFrame(THIS_ PCSTR Name, D3DXFRAME** ppNewFrame);

HRESULT STDMETHODCALLTYPE CreateMeshContainer(PCSTR Name, const D3DXMESHDATA* pMeshData,
const D3DXMATERIAL* pMaterials, const D3DXEFFECTINSTANCE* pEffectInstances, DWORD NumMaterials,
const DWORD *pAdjacency, ID3DXSkinInfo* pSkinInfo, D3DXMESHCONTAINER** ppNewMeshContainer);

HRESULT STDMETHODCALLTYPE DestroyFrame(THIS_ D3DXFRAME* pFrameToFree);
HRESULT STDMETHODCALLTYPE DestroyMeshContainer(THIS_ D3DXMESHCONTAINER* pMeshContainerBase);
};

#endif // ALLOC_MESH_HIERARCHY_H


AllocHierarchy.cpp

#include "stdafx.h"
#include "AllocMeshHierarchy.h"
#include "SkinnedMesh.h"

void CopyString(const char* input, char** output)
{
if( input )
{
UINT length = (UINT)::strlen(input) + 1; // add 1 for terminating null charater.
*output = new char[length];
::strcpy(*output, input);
}
else
{
*output = 0;
}
}

HRESULT AllocMeshHierarchy::CreateFrame(PCSTR Name, D3DXFRAME **ppNewFrame)
{
FrameEx *frameEx = new FrameEx();

if ( Name ) CopyString ( Name, &frameEx->Name );
else CopyString ("<no name>", &frameEx->Name );

frameEx->pMeshContainer = 0;
frameEx->pFrameSibling = 0;
frameEx->pFrameFirstChild = 0;
D3DXMatrixIdentity (&frameEx->TransformationMatrix);
D3DXMatrixIdentity (&frameEx->toRoot);

*ppNewFrame = frameEx;

return D3D_OK;
}

HRESULT AllocMeshHierarchy::CreateMeshContainer(PCTSTR Name,
const D3DXMESHDATA* pMeshData, const D3DXMATERIAL* pMaterials,
const D3DXEFFECTINSTANCE* pEffectInstances, DWORD NumMaterials,
const DWORD *pAdjacency, ID3DXSkinInfo* pSkinInfo,
D3DXMESHCONTAINER** ppNewMeshContainer)
{
*ppNewMeshContainer = 0;

MeshContainerEx *pMeshContainer = new MeshContainerEx();
ZeroMemory(pMeshContainer, sizeof(MeshContainerEx));

LPDIRECT3DDEVICE9 pDevice;
pMeshData->pMesh->GetDevice(&pDevice);

if ( Name != NULL )
{
CopyString( Name, &pMeshContainer->Name );
}
else
{
CopyString ("<no name>", &pMeshContainer->Name );
}

pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
// pMeshContainer->MeshData.pMesh = pMeshData->pMesh;

// pMeshData->pMesh->AddRef();


if (!(pMeshData->pMesh->GetFVF() & D3DFVF_NORMAL))
{
pMeshData->pMesh->CloneMeshFVF( pMeshData->pMesh->GetOptions(),
pMeshData->pMesh->GetFVF() | D3DFVF_NORMAL,
pDevice, &pMeshContainer->MeshData.pMesh);

D3DXComputeNormals( pMeshContainer->MeshData.pMesh, NULL );
}
else
{
pMeshContainer->MeshData.pMesh = pMeshData->pMesh;
pMeshContainer->MeshData.pMesh->AddRef();
}

DWORD dwNumFaces = pMeshData->pMesh->GetNumFaces();

pMeshContainer->NumMaterials = max (1, NumMaterials);
pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
pMeshContainer->pAdjacency = new DWORD[dwNumFaces * 3];

memcpy ( pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * dwNumFaces * 3);



if (NumMaterials > 0)
{
memcpy ( pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
D3DXMATERIAL *mtrls = pMeshContainer->pMaterials;
for (int i = 0; i < NumMaterials; i++)
{
D3DXMATERIAL mtrl = mtrls;
mtrl.MatD3D.Ambient = mtrl.MatD3D.Diffuse;
CopyString (mtrl.pTextureFilename, &mtrls.pTextureFilename);

pMeshContainer->mMaterials.push_back(mtrl.MatD3D);


if (mtrl.pTextureFilename != NULL)
{
LPDIRECT3DTEXTURE9 tex;
TCHAR texFilename[200];
_tcscpy (texFilename, "data\\");
_tcscat (texFilename, mtrl.pTextureFilename);
D3DXCreateTextureFromFile(pDevice, texFilename, &tex);
pMeshContainer->mTextures.push_back(tex);
}
}
}
else
{
pMeshContainer->mMaterials.clear();
pMeshContainer->mTextures.clear();
}

if ( pSkinInfo != NULL )
{
pMeshContainer->pSkinInfo = pSkinInfo;
pMeshContainer->pSkinInfo->AddRef();

pMeshContainer->m_pOrigMesh = pMeshData->pMesh;
pMeshContainer->m_pOrigMesh->AddRef();

DWORD dwNumBones = pSkinInfo->GetNumBones();
// pMeshContainer->m_pBoneOffsetMatrices = new D3DXMATRIX[dwNumBones];

for ( DWORD iBone = 0; iBone < dwNumBones; iBone++ )
{
pMeshContainer->m_pBoneOffsetMatrices.push_back(*(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone)));
}

}

*ppNewMeshContainer = pMeshContainer;
pMeshContainer = NULL;

pDevice->Release();
pDevice = NULL;



return D3D_OK;
}

HRESULT AllocMeshHierarchy::DestroyFrame(D3DXFRAME *pFrameToFree)
{
delete [] pFrameToFree->Name;
pFrameToFree->Name = NULL;

delete pFrameToFree;
pFrameToFree = NULL;

return S_OK;
}

HRESULT AllocMeshHierarchy::DestroyMeshContainer(D3DXMESHCONTAINER *pMeshContainerBase)
{
MeshContainerEx *meshContainer = (MeshContainerEx *) pMeshContainerBase;

delete [] meshContainer->Name;
delete [] meshContainer->pAdjacency;
delete [] meshContainer->pMaterials;



delete [] meshContainer->m_pAttributeTable;
//delete [] meshContainer->m_pBoneOffsetMatrices;

//delete [] meshContainer->m_pBoneMatrices;
//delete [] meshContainer->m_ppBoneMatrixPtrs;

ReleaseCOM(meshContainer->m_pBoneCombinationBuf);
ReleaseCOM(meshContainer->m_pOrigMesh);
ReleaseCOM(meshContainer->MeshData.pMesh);
ReleaseCOM(meshContainer->pSkinInfo);



delete meshContainer;

return D3D_OK;
}


skinnedmesh.h

#ifndef SKINNED_MESH_H
#define SKINNED_MESH_H

#include "d3dUtil.h"

#define ReleaseCOM(x) { if(x){ x->Release();x = 0; } }

struct FrameEx : public D3DXFRAME
{
D3DXMATRIX toRoot;
};

struct MeshContainerEx : public D3DXMESHCONTAINER
{
std::vector<D3DMATERIAL9> mMaterials;
std::vector<IDirect3DTexture9*> mTextures;
LPD3DXMESH m_pOrigMesh;
std::vector<D3DXMATRIX> m_pBoneOffsetMatrices;
std::vector<D3DXMATRIX*> m_ppBoneMatrixPtrs;

DWORD m_dwNumPaletteEntries;
DWORD m_dwNumInfl;
LPD3DXATTRIBUTERANGE m_pAttributeTable;
LPD3DXBUFFER m_pBoneCombinationBuf;
DWORD dwNumBones;

std::vector<D3DXMATRIX> m_pBoneMatrices;
DWORD dwNumPaletteEntries;//?
DWORD m_dwNumAttributeGroups;


};



class SkinnedMesh
{
public:
SkinnedMesh(std::string XFilename);
~SkinnedMesh();

UINT numBones();
const D3DXMATRIX* getFinalXFormArray();

protected:
D3DXFRAME* findNodeWithMesh (D3DXFRAME *frame);
bool hasNormals(ID3DXMesh *mesh);
bool GenerateSkinnedMesh(LPD3DXFRAME pFrame);
void MapFramesToBones(LPD3DXFRAME pCurFrame);
void UpdateFrames();

public:
LPD3DXFRAME GetFrameRoot() { return mRoot; }
LPD3DXANIMATIONCONTROLLER GetAnimController() { return mAnimCtrl; }

protected:

D3DXFRAME* mRoot;
ID3DXAnimationController *mAnimCtrl;

static const int MAX_NUM_BONES_SUPPORTED = 35;
};

#endif


SkinnedMesh.cpp

#include "stdafx.h"
#include "AllocMeshHierarchy.h"
#include "SkinnedMesh.h"

extern LPDIRECT3DDEVICE9 g_pDevice;

SkinnedMesh::SkinnedMesh(std::string XFilename)
: mRoot(0), mAnimCtrl(0)
{
AllocMeshHierarchy allocMeshHierarchy;
HRESULT hr;


if (FAILED (hr=D3DXLoadMeshHierarchyFromX(XFilename.c_str(), NULL, g_pDevice,
&allocMeshHierarchy, NULL, (LPD3DXFRAME *)&mRoot, &mAnimCtrl)))


GenerateSkinnedMesh(mRoot);
MapFramesToBones(mRoot);


}

SkinnedMesh::~SkinnedMesh()
{
AllocMeshHierarchy alloc;
D3DXFrameDestroy(mRoot, &alloc);
ReleaseCOM(mAnimCtrl);
}

void SkinnedMesh::MapFramesToBones(LPD3DXFRAME pCurFrame)
{
UINT iBone, cBones;
FrameEx *pFrame = (FrameEx *)pCurFrame;

if (pCurFrame->pMeshContainer != NULL)
{
MeshContainerEx *pMeshContainer = (MeshContainerEx*) pCurFrame->pMeshContainer;

if (pMeshContainer->pSkinInfo != NULL)
{
cBones = pMeshContainer->pSkinInfo->GetNumBones();
//pMeshContainer->m_ppBoneMatrixPtrs = new D3DXMATRIX*[cBones];

for (iBone = 0; iBone < cBones; iBone++)
{
pFrame = (FrameEx *)D3DXFrameFind (mRoot, pMeshContainer->pSkinInfo->GetBoneName(iBone));
pMeshContainer->m_ppBoneMatrixPtrs.push_back(&pFrame->toRoot);
}
}
}

if (pCurFrame->pFrameFirstChild != NULL)
MapFramesToBones(pCurFrame->pFrameFirstChild);

if (pCurFrame->pFrameSibling != NULL)
MapFramesToBones(pCurFrame->pFrameSibling);

return;
}





bool SkinnedMesh::GenerateSkinnedMesh(LPD3DXFRAME pFrame)
{
if (pFrame == NULL)
return false;



MeshContainerEx *pCurMeshContainer = (MeshContainerEx *)pFrame->pMeshContainer;
while (pCurMeshContainer != NULL)
{
if (pCurMeshContainer->pSkinInfo != NULL)
{
pCurMeshContainer->MeshData.pMesh->Release();

if (FAILED (pCurMeshContainer->pSkinInfo->ConvertToBlendedMesh(
pCurMeshContainer->m_pOrigMesh,
D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
pCurMeshContainer->pAdjacency,
NULL, NULL, NULL,
&pCurMeshContainer->m_dwNumInfl,
&pCurMeshContainer->m_dwNumAttributeGroups,
&pCurMeshContainer->m_pBoneCombinationBuf,
&pCurMeshContainer->MeshData.pMesh
)))
return false;
}
pCurMeshContainer = (MeshContainerEx *)pCurMeshContainer->pNextMeshContainer;
}

if (pFrame->pFrameFirstChild != NULL)
if (!GenerateSkinnedMesh (pFrame->pFrameFirstChild))
return false;

if (pFrame->pFrameSibling != NULL)
if (!GenerateSkinnedMesh (pFrame->pFrameSibling))
return false;


return true;
}


Display portion of my code base




DWORD CDynamicObject::m_dwNumTriangle = 0;

CDynamicObject::CDynamicObject(void) :
m_vPos(0.0f, 0.0f, 0.0f),
m_vScale(1.0f, 1.0f, 1.0f),
m_vRot(0.0f, 0.0f, 0.0f),
m_vRotCenter(0.0f, 0.0f, 0.0f),
m_vScaleCenter(0.0f, 0.0f, 0.0f)
{
m_pDevice = NULL;
m_pAnimController = NULL;
m_pMesh = NULL;

D3DXMatrixIdentity(&m_matWorld);
m_pCombineFrameMatrix = NULL;
m_pCombineObjectMatrix = NULL;
D3DXQuaternionIdentity(&m_quatRot);

m_pTrackArray = NULL;
SetWalking(false);

mhTech = g_pEffect->GetTechniqueByName("VBlend2Tech");
mhWVP = g_pEffect->GetParameterByName(0, "gWVP");
mhWorldInvTrans = g_pEffect->GetParameterByName(0, "gWorldInvTrans");
mhFinalXForms = g_pEffect->GetParameterByName(0, "gFinalXForms");
mhMtrl = g_pEffect->GetParameterByName(0, "gMtrl");
mhLight = g_pEffect->GetParameterByName(0, "gLight");
mhEyePos = g_pEffect->GetParameterByName(0, "gEyePosW");
mhWorld = g_pEffect->GetParameterByName(0, "gWorld");
mhTex = g_pEffect->GetParameterByName(0, "gTex");

g_pEffect->SetTechnique(mhTech);
}

CDynamicObject::~CDynamicObject(void)
{
}

bool CDynamicObject::Create(LPDIRECT3DDEVICE9 pDevice, SkinnedMesh *pMesh, float fAnimSpeed)
{
if(pMesh == NULL)
return false;

m_pDevice = pDevice;
m_pMesh = pMesh;

if(m_pMesh->GetAnimController() != NULL)
{
DWORD dwNumAnimSet = m_pMesh->GetAnimController()->GetMaxNumAnimationSets();

// create a copy of the animation controller
LPD3DXANIMATIONCONTROLLER pAC = m_pMesh->GetAnimController();

pAC->CloneAnimationController( pAC->GetMaxNumAnimationOutputs(), // >GetMaxNumMatrices(),//>GetMaxNumAnimationOutputs(),
pAC->GetMaxNumAnimationSets(),
pAC->GetMaxNumTracks(),
pAC->GetMaxNumEvents(),
&m_pAnimController );



// fill up all tracks with animation sets
for(DWORD i = 0; i < dwNumAnimSet; i++)
{
LPD3DXANIMATIONSET pSet;
m_pAnimController->GetAnimationSet(i, &pSet);

// associate each animation set to tracks
m_pAnimController->SetTrackAnimationSet(i, pSet);
// set track's speed
SetTrackDesc(i, fAnimSpeed);

pSet->Release();
pSet = NULL;


}

// set default, ie activate first track
SetTrackDesc(0, fAnimSpeed, 1.0f);
m_dwDefaultTrack = m_dwLastTrack = m_dwCurrentTrack = 0;
}

return true;
}

void CDynamicObject::Update(float dt)
{
if(m_vRot.x != 0.0f || m_vRot.y != 0.0f || m_vRot.z != 0.0f)
{
D3DXQuaternionRotationYawPitchRoll(&m_quatRot, m_vRot.x, m_vRot.y, m_vRot.z);
D3DXMatrixTransformation(&m_matWorld, &m_vScaleCenter, NULL, &m_vScale,
&m_vRotCenter, &m_quatRot, &m_vPos);
}
else
D3DXMatrixTransformation(&m_matWorld, &m_vScaleCenter, NULL, &m_vScale,
NULL, NULL, &m_vPos);

// check if current object is attach to other object
if(m_pCombineFrameMatrix != NULL)
m_matWorld *= *m_pCombineFrameMatrix;

if(m_pAnimController != NULL)
{
m_pAnimController->AdvanceTime(dt, 0);
}


UpdateFrame(m_pMesh->GetFrameRoot(), &m_matWorld); // No need to do this???
}

void CDynamicObject::Render()
{
// render all frames
RenderFrame(m_pMesh->GetFrameRoot());
}

void CDynamicObject::UpdateFrame(LPD3DXFRAME pFrame, D3DXMATRIX *pMat)
{
FrameEx *pCurFrame = (FrameEx *) pFrame;

if (pMat != NULL)
D3DXMatrixMultiply (&pCurFrame->toRoot, &pCurFrame->TransformationMatrix, pMat);
else
pCurFrame->toRoot = pCurFrame->TransformationMatrix;

if (pCurFrame->pFrameFirstChild != NULL)
UpdateFrame(pCurFrame->pFrameFirstChild, &pCurFrame->toRoot);

if (pCurFrame->pFrameSibling != NULL)
UpdateFrame(pCurFrame->pFrameSibling, pMat);

// Adjust gEyePosW, same as global view matrix position
buildViewMtx();
}

void CDynamicObject::buildViewMtx()
{
D3DXMATRIX view = g_View;
D3DXVECTOR3 v(view._41, view._42, view._43);
g_pEffect->SetValue(mhEyePos, &v, sizeof(D3DXVECTOR3));

}

void CDynamicObject::RenderFrame(LPD3DXFRAME pFrame) // Stack overrun :(
{
FrameEx *bone = (FrameEx *) m_pMesh->GetFrameRoot();



if (bone->pMeshContainer != NULL)
{
MeshContainerEx *boneMesh = (MeshContainerEx *) bone->pMeshContainer;
g_pEffect->SetMatrixArray(mhFinalXForms, (D3DXMATRIX*) &boneMesh->m_pBoneMatrices[0], boneMesh->dwNumBones);

for (int i = 0; i < boneMesh->m_dwNumAttributeGroups; i++)
{
g_pEffect->SetValue(mhLight, &mLight, sizeof(DirLight));
g_pEffect->SetMatrix(mhWVP, &(m_matWorld*g_View*g_Proj));
D3DXMATRIX worldInvTrans;
D3DXMatrixInverse (&worldInvTrans, 0, &m_matWorld);
D3DXMatrixTranspose (&worldInvTrans, &worldInvTrans);
g_pEffect->SetMatrix(mhWorldInvTrans, &worldInvTrans);
g_pEffect->SetMatrix(mhWorld, &m_matWorld);
Mtrl m;
m.ambient = boneMesh->mMaterials.Ambient;
m.diffuse = boneMesh->mMaterials.Diffuse;
m.spec = boneMesh->mMaterials.Specular;
m.specPower = boneMesh->mMaterials.Power;
g_pEffect->SetValue (mhMtrl, &m, sizeof(Mtrl));
g_pEffect->SetTexture(mhTex, boneMesh->mTextures);

UINT numPasses = 0;
g_pEffect->Begin(&numPasses, 0);
g_pEffect->BeginPass(0);

boneMesh->MeshData.pMesh->DrawSubset(i);

g_pEffect->EndPass();
g_pEffect->End();
}
}

if (bone->pFrameSibling != NULL) RenderFrame ((FrameEx *)bone->pFrameSibling);
if (bone->pFrameFirstChild != NULL) RenderFrame ((FrameEx *)bone->pFrameFirstChild);

}


The shader part:

struct Mtrl
{
float4 ambient;
float4 diffuse;
float4 spec;
float specPower;
};

struct DirLight
{
float4 ambient;
float4 diffuse;
float4 spec;
float3 dirW;
};

uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInvTrans;
uniform extern float4x4 gWVP;
uniform extern float4x4 gFinalXForms[35];
uniform extern Mtrl gMtrl;
uniform extern DirLight gLight;
uniform extern float3 gEyePosW;
uniform extern texture gTex;

sampler TexS = sampler_state
{
Texture = <gTex>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};

struct OutputVS
{
float4 posH : POSITION0;
float3 normalW : TEXCOORD0;
float3 toEyeW : TEXCOORD1;
float2 tex0 : TEXCOORD2;
};

OutputVS VBlend2VS ( float3 posL : POSITION0,
float3 normalL : NORMAL0,
float2 tex0 : TEXCOORD0,
float weight0 : BLENDWEIGHT0,
int4 boneIndex : BLENDINDICES0 )
{
OutputVS outVS = (OutputVS) 0;

float weight1 = 1.0f - weight0;

float4 p = weight0 * mul(float4(posL, 1.0f), gFinalXForms[boneIndex[0]]);
p += weight1 * mul(float4(posL, 1.0f), gFinalXForms[boneIndex[1]]);
p.w = 1.0f;

// We can use the same matrix to transform normals since we are assuming
// no scaling (i.e., rigid-body).
float4 n = weight0 * mul(float4(normalL, 0.0f), gFinalXForms[boneIndex[0]]);
n += weight1 * mul(float4(normalL, 0.0f), gFinalXForms[boneIndex[1]]);
n.w = 0.0f;

// Transform vertex position to world space.
outVS.normalW = mul (n, gWorldInvTrans).xyz;

// Transform vertex position to world space.
float3 posW = mul (p, gWorld).xyz;

// Compute the vector from the vertex to the eye.
outVS.toEyeW = gEyePosW - posW;

// Transform to homogeneous clip space.
outVS.posH = mul (p, gWVP);



outVS.tex0 = tex0;

return outVS;
}

float4 VBlend2PS(float3 normalW : TEXCOORD0, float3 toEyeW : TEXCOORD1, float2 tex0 : TEXCOORD2) : COLOR
{
// Interpolated normals can become unnormal--so normalize.
normalW = normalize(normalW);
toEyeW = normalize(toEyeW);

// Light vector is opposite the direction of the light.
float3 lightVecW = -gLight.dirW;

// Compute the reflection vector.
float3 r = reflect(-lightVecW, normalW);

// Determine how much (if any) specular light makes it into the eye.
float t = pow(max(dot(r, toEyeW), 0.0f), gMtrl.specPower);

// Determine the diffuse light intensity that strikes the vertex.
float s = max(dot(lightVecW, normalW), 0.0f);

// Compute the ambient, diffuse and specular terms separatly.
float3 spec = t*(gMtrl.spec*gLight.spec).rgb;
float3 diffuse = s*(gMtrl.diffuse*gLight.diffuse).rgb;
float3 ambient = gMtrl.ambient*gLight.ambient;

// Get the texture color.
float4 texColor = tex2D(TexS, tex0);

// Combine the color from lighting with the texture color.
float3 color = (ambient + diffuse)*texColor.rgb + spec;

// Sum all the terms together and copy over the diffuse alpha.
return float4(color, gMtrl.diffuse.a*texColor.a);
}

technique VBlend2Tech
{
pass P0
{
// Specify the vertex and pixel shader associated with this pass.
vertexShader = compile vs_2_0 VBlend2VS();
pixelShader = compile ps_2_0 VBlend2PS();
}
}


Note that I have a stack overrun in the last method. But you can ignore it for the moment. I'll give that a fix later
So you get a general picture of the flow of my engine. Please leave comments where you feel appropriate.
Thanks in advance
Jack
Advertisement
Any thoughts? I need your help :) Thanks Jack
I have flipped another book, but I still have difficulties.
The code displays the original mesh that comes with the book fine. But can't display mine no matter how I tweak it.
Loading code .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(char fileName[]);
void Render(Bone *bone);
void RenderSkeleton(Bone* bone, Bone *parent, D3DXMATRIX world);

private:
void UpdateMatrices(Bone* bone, D3DXMATRIX *parentMatrix);
void SetupBoneMatrixPointers(Bone *bone);

D3DXFRAME *m_pRootBone;
LPD3DXMESH m_pSphereMesh;
};

#endif


#include "skinnedMesh.h"
#include <fstream>

#pragma warning(disable:4996)

using namespace std;

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_ LPCTSTR 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 *g_pDevice = NULL;
pMeshData->pMesh->GetDevice(&g_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, 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
D3DXCreateTextureFromFile(g_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 = *(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 != NULL)
boneMesh->textures->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;
}

SkinnedMesh::~SkinnedMesh()
{
BoneHierarchyLoader boneHierarchy;
boneHierarchy.DestroyFrame(m_pRootBone);
}

void SkinnedMesh::Load(char fileName[])
{
BoneHierarchyLoader boneHierarchy;

D3DXLoadMeshHierarchyFromX(fileName, D3DXMESH_MANAGED,
g_pDevice, &boneHierarchy,
NULL, &m_pRootBone, NULL);

SetupBoneMatrixPointers((Bone*)m_pRootBone);

//Update all the bones
D3DXMATRIX i;
D3DXMatrixIdentity(&i);
UpdateMatrices((Bone*)m_pRootBone, &i);

//Create Sphere
D3DXCreateSphere(g_pDevice, 0.02f, 10, 10, &m_pSphereMesh, NULL);
}

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,
&boneMesh->boneOffsetMatrices,
boneMesh->boneMatrixPtrs);
}

//Set HW matrix palette
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.AttribId;
g_pDevice->SetMaterial(&(boneMesh->materials[mtrlIndex]));
g_pDevice->SetTexture(0, boneMesh->textures[mtrlIndex]);
g_pEffect->SetTexture("texDiffuse", boneMesh->textures[mtrlIndex]);
g_pEffect->SetMatrix("matW", &identity);

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++)
{
g_pDevice->SetMaterial(&boneMesh->materials);
g_pEffect->SetTexture("texDiffuse", boneMesh->textures);

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::RenderSkeleton(Bone* bone, Bone *parent, D3DXMATRIX world)
{
//Temporary function to render the bony hierarchy

if(world == NULL)return;
if(bone == NULL)bone = (Bone*)m_pRootBone;

//Draw line between bones
if(parent != NULL && bone->Name != NULL && parent->Name != NULL)
{
//Draw Sphere
g_pDevice->SetRenderState(D3DRS_LIGHTING, true);
g_pDevice->SetTransform(D3DTS_WORLD, &(bone->CombinedTransformationMatrix * world));
m_pSphereMesh->DrawSubset(0);

D3DXMATRIX w1 = bone->CombinedTransformationMatrix;
D3DXMATRIX w2 = parent->CombinedTransformationMatrix;

//Extract translation
D3DXVECTOR3 thisBone = D3DXVECTOR3(w1(3, 0), w1(3, 1), w1(3, 2));
D3DXVECTOR3 ParentBone = D3DXVECTOR3(w2(3, 0), w2(3, 1), w2(3, 2));

if(D3DXVec3Length(&(thisBone - ParentBone)) < 2.0f)
{
g_pDevice->SetTransform(D3DTS_WORLD, &world);
VERTEX vert[] = {VERTEX(ParentBone, 0xffff0000), VERTEX(thisBone, 0xff00ff00)};
g_pDevice->SetRenderState(D3DRS_LIGHTING, false);
g_pDevice->SetFVF(VERTEX::FVF);
g_pDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, 1, &vert[0], sizeof(VERTEX));
}
}

if(bone->pFrameSibling)RenderSkeleton((Bone*)bone->pFrameSibling, parent, world);
if(bone->pFrameFirstChild)RenderSkeleton((Bone*)bone->pFrameFirstChild, bone, world);
}

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 = &b->CombinedTransformationMatrix;
else boneMesh->boneMatrixPtrs = NULL;
}
}
}

if(bone->pFrameSibling != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameSibling);
if(bone->pFrameFirstChild != NULL)SetupBoneMatrixPointers((Bone*)bone->pFrameFirstChild);
}





u32 CPerfectSimView::Draw(float fElapsedTime)
{

try
{
//Create Matrices
D3DXMATRIX identity, view, proj, shadow;
D3DXMatrixIdentity(&identity);
D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(cos(90.1) * 3.0f, 1.5f, sin(90.1) * 3.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4.0f, (float)1000.0 / (float)1000.0, 1.0f, 1000.0f);
D3DXPLANE ground(0.0f, 1.0f, 0.0f, 0.0f);
D3DXVECTOR4 lightPos(-50.0f, 75.0f, -150.0f, 0.0f);
D3DXMatrixShadow(&shadow, &lightPos, &ground);

g_pDevice->SetTransform(D3DTS_WORLD, &identity);
g_pDevice->SetTransform(D3DTS_VIEW, &view);
g_pDevice->SetTransform(D3DTS_PROJECTION, &proj);

// Clear the viewport
g_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L);

// Begin the scene
if(SUCCEEDED(g_pDevice->BeginScene()))
{
//Render Drone
{
g_pEffect->SetMatrix("matW", &identity);
g_pEffect->SetMatrix("matVP", &(view * proj));
g_pEffect->SetVector("lightPos", &lightPos);

m_drone.Render(NULL);
}

// if(KeyDown(VK_SPACE))
// {
// g_pDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L);
// m_drone.RenderSkeleton(NULL, NULL, identity);
// }

RECT rc = {10, 10, 0, 0};
// g_pFont->DrawText(NULL, "Press Space to Toggle Skeleton", -1, &rc, DT_LEFT | DT_TOP | DT_NOCLIP, 0x66000000);

// End the scene.
g_pDevice->EndScene();
g_pDevice->Present(0, 0, 0, 0);
}
}
catch(...)
{
// g_debug << "Error in Application::Render() \n";
}
return 0;
}



The shader

//////////////////////////////////////////////////////////////////////////
// Character Animation with Direct3D //
// Author: C. Granberg //
// 2008 - 2009 //
//////////////////////////////////////////////////////////////////////////

//Transformation Matrices
matrix matW;
matrix matVP;

//World Light Position
float3 lightPos;

//Texture
texture texDiffuse;

//Sampler
sampler DiffuseSampler = sampler_state
{
Texture = (texDiffuse);
MinFilter = Linear; MagFilter = Linear; MipFilter = Linear;
AddressU = Wrap; AddressV = Wrap; AddressW = Wrap;
MaxAnisotropy = 16;
};

//Vertex Input
struct VS_INPUT
{
float4 position : POSITION0;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
};

//Vertex Output / Pixel Shader Input
struct VS_OUTPUT
{
float4 position : POSITION0;
float2 tex0 : TEXCOORD0;
float shade : TEXCOORD1;
};

//Vertex Shader
VS_OUTPUT vs_lighting(VS_INPUT IN)
{
VS_OUTPUT OUT = (VS_OUTPUT)0;

//getting the position of the vertex in the world
float4 posWorld = mul(IN.position, matW);
float4 normal = normalize(mul(IN.normal, matW));

//getting to position to object space
OUT.position = mul(posWorld, matVP);

//light the vertex
OUT.shade = max(dot(normal, normalize(lightPos - posWorld)), 0.2f);

//copy texture coordinates
OUT.tex0 = IN.tex0;

return OUT;
}

//Pixel Shader
float4 ps_lighting(VS_OUTPUT IN) : COLOR0
{
float4 color = tex2D(DiffuseSampler, IN.tex0);
return color * IN.shade;
}

//Lighting Technique
technique Lighting
{
pass P0
{
Lighting = false;

VertexShader = compile vs_2_0 vs_lighting();
PixelShader = compile ps_2_0 ps_lighting();
}
}

//Pixel Shader
float4 ps_shadow(VS_OUTPUT IN) : COLOR0
{
return float4(0.3f, 0.3f, 0.3f, 1.0f);
}

//Shadow Technique
technique Shadow
{
pass P0
{
Lighting = false;

VertexShader = compile vs_2_0 vs_lighting();
PixelShader = compile ps_2_0 ps_shadow();
}
}

////////////////////////////////////////////////////////////////////////////

extern float4x4 FinalTransforms[35];
extern int NumVertInfluences = 2; // <--- Normally set dynamically.

//Vertex Input
struct VS_INPUT_SKIN
{
float4 position : POSITION0;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
float4 weights : BLENDWEIGHT0;
int4 boneIndices : BLENDINDICES0;
};

VS_OUTPUT vs_Skinning(VS_INPUT_SKIN IN)
{
VS_OUTPUT OUT = (VS_OUTPUT)0;

float4 p = float4(0.0f, 0.0f, 0.0f, 1.0f);
float3 norm = float3(0.0f, 0.0f, 0.0f);
float lastWeight = 0.0f;
int n = NumVertInfluences-1;

IN.normal = normalize(IN.normal);

for(int i = 0; i < n; ++i)
{
lastWeight += IN.weights;
p += IN.weights * mul(IN.position, FinalTransforms[IN.boneIndices]);
norm += IN.weights * mul(IN.normal, FinalTransforms[IN.boneIndices]);
}
lastWeight = 1.0f - lastWeight;

p += lastWeight * mul(IN.position, FinalTransforms[IN.boneIndices[n]]);
norm += lastWeight * mul(IN.normal, FinalTransforms[IN.boneIndices[n]]);

p.w = 1.0f;
float4 posWorld = mul(p, matW);
OUT.position = mul(posWorld, matVP);
OUT.tex0 = IN.tex0;

//Calculate Lighting
norm = normalize(norm);
norm = mul(norm, matW);
OUT.shade = max(dot(norm, normalize(lightPos - posWorld)), 0.2f);

return OUT;
}

technique Skinning
{
pass P0
{
Lighting = false;

VertexShader = compile vs_2_0 vs_Skinning();
PixelShader = compile ps_2_0 ps_lighting();
}
}



the mesh loads ok (S_OK), but just no display for my own mesh
How can I check it is the world transformation problem or the camera's problem
I just assume there aren't any one-method-to-fit-all ways to do it
thanks
Jack
The code displays the original mesh that comes with the book fine. But can't display mine no matter how I tweak it.[/quote]

I think it comes from D3DXFRAME::Name.

In your ::CreateFrame() function, set Name parameter to NULL first, then do whatever you want:


HRESULT BoneHierarchyLoader::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame)
{
Bone *newBone = new Bone;
memset(newBone, 0, sizeof(Bone));

newBone->Name = NULL; // <---- I've added this line!

//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;
}

hth.
-R
There's no "hard", and "the impossible" takes just a little time.
Hi programci_84,

Thanks for your response. I am sorry to tell that it doesn't work as expected. Maybe some more advices for me :)
Just tried to contact the author for a week with no replies.... so i am totally despair
Thanks a lot
Jack
You've surrounded the draw() with a try ... catch block that silently swallows exceptions. Have you put in logging or tried removing this block? You could also look into adding additional error handling or logging in some places, for instance adding an "else" block to "if(SUCCEEDED(g_pDevice->BeginScene())".

I also see some function have no error checking, e.g. there is a call to D3DXCreateTextureFromFile that lacks error checking.
Sorry, I have changed my mind again. This time I converted my code back to the fixed pipeline (displaying the skinned mesh) and a shader displaying the static mesh
I wonder this approach would cause any strange results. Also, I have hardcoded the skinned mesh part. Letting it not have textures and having a predefined materials.
I have used another model which was proved to be correct in another application. I have cross-checked the matrix values against the program that is properly working.
Avoiding all the peculiar matrix values.... and finally I still can't see the skinned mesh. What other things do I have to take care of in my case?
Any comments are welcome!
BTW, thanks rip-off and other guys who are helping along.
I can send the program thru to the person who wishes to help too.... it isn't that big virtually (~30MB including data on VS2008)
Thanks
Jack
Things got lots easier than it seems now. Finally I got meshes displayed owing to projection/view matrices unset.
But i run into another problem. Is the mesh never animates..
I have update the animation controller with a running clock and I have updated the frame hierarchy
The mesh has the animationset ready. I can see the animationset returns 1
I have set the track descriptor as well plus SetTrackAnimationSet
What elses am I missing?
Thanks
Jack
Seems like advancetime has no effect on the transformationMatrix variable
I have cloned the animationcontroller, but the animation is not starting
I tried to use the original animation controller (not cloned) from mesh loading object, it animates.
Why CloneAnimationController won't work at all?


bool CDynamicObject::Create(LPDIRECT3DDEVICE9 pDevice, SkinnedMesh *pMesh, float fAnimSpeed)
{
if(pMesh == NULL)
return false;

m_pDevice = pDevice;
m_pMesh = pMesh;

if(m_pMesh->GetAnimController() != NULL)
{
DWORD dwNumAnimSet = m_pMesh->GetAnimController()->GetMaxNumAnimationSets();

LPD3DXANIMATIONCONTROLLER pAC = m_pMesh->GetAnimController();

HRESULT hr = pAC->CloneAnimationController( pAC->GetMaxNumAnimationOutputs(), // >GetMaxNumMatrices(),//>GetMaxNumAnimationOutputs(),
pAC->GetMaxNumAnimationSets(),
pAC->GetMaxNumTracks(),
pAC->GetMaxNumEvents(),
&m_pAnimController );


// fill up all tracks with animation sets
for(DWORD i = 0; i < dwNumAnimSet; i++)
{
LPD3DXANIMATIONSET pSet;
m_pAnimController->GetAnimationSet(i, &pSet);

m_pAnimController->SetTrackAnimationSet(i, pSet);
SetTrackDesc(i, fAnimSpeed, 1.0f);

pSet->Release();
pSet = NULL;


}

// set default, ie activate first track
SetTrackDesc(0, fAnimSpeed, 1.0f);
m_dwDefaultTrack = m_dwLastTrack = m_dwCurrentTrack = 0;
}

return true;
}


Sign!
Thanks
Jack
Seems like the master copy is working, when i clone it and distribute it to different objects. All the animation becomes stagnant. Any thoughts why this would happen..... Sorry for bumping this, cos this is quite urgent
What really annoying is CloneAnimationController actually works and returns with some ok value...
Thanks Jack

This topic is closed to new replies.

Advertisement