Jump to content
  • Advertisement
Sign in to follow this  
Fison

Loading Hierarchy problem

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was trying to use the class CAlllocateHierarchy copied from SDK Example to load tiny.x,but it failed.When i debug, i found that the numbones read from pSkinInfo->GetNumBones() == 0,but the SDK Example's == 35,anybody tell me why?THX~~ ps. pSkinInfo != NULL;

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
That interface is if for you to impliment ....
In the appropriate functions you need to create:
D3DXMeshContainer derived structures
and
D3DXFrame derived structures

It provide you all of the information to fill in the function arguments.


I'd suggest that you look at the implimentation in SDK samples.

Share this post


Link to post
Share on other sites
I know,I've already went over the example, can't find any difference between them, help...

Share this post


Link to post
Share on other sites
Here's the main part of the program,please check it out.

#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#include <d3d9.h>

#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

class CAllocHierarchy: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);

CAllocHierarchy() {}
};

struct D3DXFRAME_EX: public D3DXFRAME
{
D3DXMATRIXA16 CombinedTransformationMatrix;
};
struct D3DXMESHCONTAINER_EX:public D3DXMESHCONTAINER
{
LPDIRECT3DTEXTURE9* ppTextures; // array of textures, entries are NULL if no texture specified

// SkinMesh info
LPD3DXMESH pOrigMesh;
LPD3DXATTRIBUTERANGE pAttributeTable;
DWORD NumAttributeGroups;
DWORD NumInfl;
LPD3DXBUFFER pBoneCombinationBuf;
D3DXMATRIX** ppBoneMatrixPtrs;
D3DXMATRIX* pBoneOffsetMatrices;
DWORD NumPaletteEntries;
bool UseSW;
};
HRESULT AllocateName( LPCSTR Name, LPSTR *pNewName );
HRESULT GenerateSkinnedMesh( LPDIRECT3DDEVICE9 pDevice, D3DXMESHCONTAINER_EX *pMeshContainer);

HRESULT CAllocHierarchy::CreateFrame( THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame )
{
HRESULT hr = S_OK;
D3DXFRAME_EX *pFrame = new D3DXFRAME_EX;

*ppNewFrame = NULL;

if (pFrame == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}

hr = AllocateName(Name, &pFrame->Name);
if (FAILED(hr))
goto e_Exit;

// initialize other data members of the frame
D3DXMatrixIdentity(&pFrame->TransformationMatrix);
D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);

pFrame->pMeshContainer = NULL;
pFrame->pFrameSibling = NULL;
pFrame->pFrameFirstChild = NULL;

*ppNewFrame = pFrame;
pFrame = NULL;

e_Exit:
delete pFrame;
return hr;

}

HRESULT CAllocHierarchy::CreateMeshContainer( THIS_
LPCSTR Name,
const D3DXMESHDATA *pMeshData,
const D3DXMATERIAL *pMaterials,
const D3DXEFFECTINSTANCE *pEffectInstance,
DWORD NumMaterials,
const DWORD *pAdjacency,
LPD3DXSKININFO pSkinInfo,
LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
HRESULT hr;
D3DXMESHCONTAINER_EX *pMeshContainer = NULL;
UINT NumFaces;
UINT iMaterial;
UINT iBone, cBones;
LPDIRECT3DDEVICE9 pd3dDevice = 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_EX;
if (pMeshContainer == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}
memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_EX));

// 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];
if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}

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( D3DXCreateTextureFromFile( pd3dDevice, "tiger.bmp",
&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];
if (pMeshContainer->pBoneOffsetMatrices == NULL)
{
hr = E_OUTOFMEMORY;
goto e_Exit;
}

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

HRESULT CAllocHierarchy::DestroyFrame(THIS_ LPD3DXFRAME pFrameToFree)
{
SAFE_DELETE_ARRAY(pFrameToFree->Name);
SAFE_DELETE(pFrameToFree);
return S_OK;
}


HRESULT CAllocHierarchy::DestroyMeshContainer(THIS_ LPD3DXMESHCONTAINER pMeshContainerToFree)
{
UINT iMaterial;
D3DXMESHCONTAINER_EX *pMeshContainer = (D3DXMESHCONTAINER_EX*) pMeshContainerToFree;

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->pBoneCombinationBuf);
SAFE_RELEASE(pMeshContainer->pOrigMesh);
SAFE_RELEASE(pMeshContainer->pSkinInfo);
SAFE_RELEASE(pMeshContainer->MeshData.pMesh);
SAFE_DELETE(pMeshContainer);

return S_OK;
}
HRESULT GenerateSkinnedMesh( LPDIRECT3DDEVICE9 pDevice, D3DXMESHCONTAINER_EX *pMeshContainer)
{
HRESULT hr = S_OK;
D3DCAPS9 d3dCaps;
pDevice->GetDeviceCaps(&d3dCaps);

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

//UseSW = false;

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

DWORD NumMaxFaceInfl;
DWORD Flags = D3DXMESHOPT_VERTEXCACHE;

LPDIRECT3DINDEXBUFFER9 pIB = NULL;
hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB);
if(FAILED(hr))
return hr;

hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl);
pIB->Release();
if(FAILED(hr))
return hr;

NumMaxFaceInfl = min(NumMaxFaceInfl, 12);

if( d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl )
{
pMeshContainer->NumPaletteEntries = min( 256, pMeshContainer->pSkinInfo->GetNumBones());
pMeshContainer->UseSW = true;
Flags |= D3DXMESH_SYSTEMMEM;
}
else
{
pMeshContainer->NumPaletteEntries = min( ( d3dCaps.MaxVertexBlendMatrixIndex + 1 ) / 2,
pMeshContainer->pSkinInfo->GetNumBones());
pMeshContainer->UseSW = false;
Flags |= D3DXMESH_MANAGED;
}

hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh
(
pMeshContainer->pOrigMesh,
Flags,
pMeshContainer->NumPaletteEntries,
pMeshContainer->pAdjacency,
NULL, NULL, NULL,
&pMeshContainer->NumInfl,
&pMeshContainer->NumAttributeGroups,
&pMeshContainer->pBoneCombinationBuf,
&pMeshContainer->MeshData.pMesh);
return hr;

}
HRESULT AllocateName( LPCSTR Name, LPSTR *pNewName )
{
UINT cbLength;

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

return S_OK;
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Looks like you are not calling AddRef()
when true == (pMesh->GetFVF() & D3DFVF_NORMAL)
pMeshContainer->MeshData.pMesh = pMesh;

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!