Skip to main content
GameDev.net gamedev.net
🔒 Locked

.X files animation loading

Started by Sagito Sep 1, 2005 at 10:02 AM 9 replies 3.3k views
Original Post
Sagito
Sagito
Hi everyone... Recently, I've learned how to program with DirectX interfaces in order to start the developmentof my own game engine (I'm using Visual C++ 6.0). I've already implemented sound, input and graphical support to my application, but I can't load animations from .X files. I'm trying to load animations with D3DXLoadMeshHierarchyFromX, and, in order to do that, I've created the following class: "class CAllocateHierarchy : public ID3DXAllocateHierarchy" and implemented the functions: CreateFrame, CreateMeshContainer, DestroyFrame and DestroyMeshContainer, according to the DirectX MultiAnimation sample. However, when I create a pointer to this interface ("CAllocateHierarchy * pAH"), it returns NULL or = to 0xcccccccc. Tried everything I could think of, but still can't load any animation... If that helps, I can post my code. Thanks everyone. =)
http://sagito.wordpress.com
Supernat02
Supernat02
Definitely posting the code will help. It could be anything. :)
Chris ByersMicrosoft DirectX MVP - 2005
Sagito
Sagito
This is the code I've got in my animation dedicated header file (don't mind the comments, they are all in portuguese... =P):

struct D3DXFRAME_DERIV: public D3DXFRAME{	//D3DXMATRIX MatrizCombinada;};D3DXFRAME_DERIV* FrameBase;struct D3DXMESHCONTAINER_DERIV: public D3DXMESHCONTAINER{	LPDIRECT3DTEXTURE9* ppTexturas;	D3DMATERIAL9* pMateriais;	LPD3DXMESH pOrigMesh;	D3DXMATRIX* pBoneMatrices;	D3DXMATRIX* pBoneOffsets;	D3DXMATRIX* pFrameMatrices;};//Class destinada à gestão das funções CALLBACK presentes na class abstracta//ID3DXAllocateHierarchy.class CAllocateHierarchy: public ID3DXAllocateHierarchy{public:	STDMETHOD( CreateFrame )( THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame );        STDMETHOD( CreateMeshContainer )( THIS_ LPCSTR Name, 									  CONST D3DXMESHDATA * pMeshData,									  CONST D3DXMATERIAL * pMaterials,									  CONST D3DXEFFECTINSTANCE * pEffectInstances,									  DWORD NumMaterials,									  CONST DWORD * pAdjacency,									  LPD3DXSKININFO pSkinInfo,									  LPD3DXMESHCONTAINER * ppNewMeshContainer );    	STDMETHOD( DestroyFrame )( THIS_ LPD3DXFRAME pFrameToFree );    	STDMETHOD( DestroyMeshContainer )( THIS_ LPD3DXMESHCONTAINER pMeshContainerToFree );	CAllocateHierarchy(); //   STDMETHOD( SetMA )( THIS_ CMultiAnim *pMA );private:   // CMultiAnim *m_pMA;};CAllocateHierarchy::CAllocateHierarchy(){	MessageBox(0, "Constructor", "", MB_OK);};//Class destinada à gestão dos processos das animaçõesclass Anim{public:	bool Preparacao(void);};//Variável de gestão das funções de animação. Sendo declarada aqui, evita redefinições//posteriores, podendo ser usada sem problemas nos restantes ficheiros de nível superior.Anim Animacao;//////////////////////////////////////Funções////////////////////////////////////////////////////CHAR *CopiarNome( CHAR *sNome ){    DWORD dwLen = (DWORD) strlen( sNome );    CHAR * sNovoNome = new CHAR[ dwLen + 1 ];    strncpy( sNovoNome, sNome, dwLen );    sNovoNome[ dwLen ] = '\0';    return sNovoNome;}HRESULT CAllocateHierarchy::CreateFrame(LPCSTR Name, LPD3DXFRAME *ppNewFrame){	*ppNewFrame = NULL;          //Garantia para a minha sanidade mental	D3DXFRAME_DERIV *NovoFrame = new D3DXFRAME_DERIV;	ZeroMemory(NovoFrame, sizeof(D3DXFRAME_DERIV));	if(Name)		NovoFrame->Name = (CHAR*) CopiarNome( (CHAR*) Name );	else		NovoFrame->Name = (CHAR*) CopiarNome( "<sem nome>" );	D3DXMatrixIdentity(&NovoFrame->TransformationMatrix);//	D3DXMatrixIdentity(&NovoFrame->MatrizCombinada);	NovoFrame->pMeshContainer = NULL;	NovoFrame->pFrameSibling = NULL;    NovoFrame->pFrameFirstChild = NULL;	*ppNewFrame = NovoFrame;	return D3D_OK;}HRESULT CAllocateHierarchy::CreateMeshContainer(THIS_ LPCSTR Name, 							 CONST D3DXMESHDATA * pMeshData,							 CONST D3DXMATERIAL * pMaterials,							 CONST D3DXEFFECTINSTANCE * pEffectInstances,							 DWORD NumMaterials,							 CONST DWORD * pAdjacency,							 LPD3DXSKININFO pSkinInfo,							 LPD3DXMESHCONTAINER * ppNewMeshContainer){	D3DXMESHCONTAINER_DERIV *NovoMC = new D3DXMESHCONTAINER_DERIV;	ZeroMemory(NovoMC, sizeof(D3DXMESHCONTAINER_DERIV));	*ppNewMeshContainer = NULL;	if(Name)		NovoMC->Name = (CHAR*) CopiarNome( (CHAR*) Name );	else		NovoMC->Name = (CHAR*) CopiarNome( "<sem nome>" );			if(pMeshData->Type != D3DXMESHTYPE_MESH)	{		MessageBox(0, "O objecto existente não é do tipo D3DXMESHTYPE_MESH", "", MB_OK);		return D3DERR_INVALIDCALL; 				//Se esta função passar "false" não uso a função LoadMeshHierarchyFromX,		//mas apenas a LoadMeshFromX. Posso me ter enganado e ter tentado carregar uma		//animação de um edificio, por exemplo.	}	NovoMC->MeshData.Type = D3DXMESHTYPE_MESH;	//Carregar as adjacencias		DWORD nFaces = pMeshData->pMesh->GetNumFaces();	NovoMC->pAdjacency = new DWORD[nFaces * 3];	memcpy(NovoMC->pAdjacency, pAdjacency, sizeof(DWORD) * nFaces*3);	//Carregar o device do .x file	LPDIRECT3DDEVICE9 d3dDevice = NULL;//	pMeshData->pMesh->GetDevice(&d3dDevice);	d3dDevice = Device; //Quero que se lixe, eu uso o meu, não interessa o que esta definido!!!!	//Copiar os dados da mesh e coloca los no MeshContainer	pMeshData->pMesh->CloneMeshFVF(D3DXMESH_MANAGED, 								   pMeshData->pMesh->GetFVF(),								   d3dDevice,								   &NovoMC->MeshData.pMesh);	//Copiar texturas e materiais	NovoMC->NumMaterials = max(NumMaterials,1);	NovoMC->pMateriais = new D3DMATERIAL9[NovoMC->NumMaterials];	NovoMC->ppTexturas  = new LPDIRECT3DTEXTURE9[NovoMC->NumMaterials];	ZeroMemory(NovoMC->ppTexturas, 			   sizeof(LPDIRECT3DTEXTURE9) * NovoMC->NumMaterials);	if (NumMaterials > 0)	{		// Carregar texturas e copiar todos os materiais				for(DWORD i = 0; i < NumMaterials; ++i)		{			NovoMC->ppTexturas = NULL;				NovoMC->pMateriais = pMaterials.MatD3D;			if(pMaterials.pTextureFilename)			{				// Converter para UNICODE, para poder uilizar a função D3DXCreateTextureFromFileW				WCHAR wszTexName[MAX_PATH];				MultiByteToWideChar( CP_ACP, 0, pMaterials.pTextureFilename, -1, wszTexName, MAX_PATH );				if(FAILED(D3DXCreateTextureFromFile(d3dDevice, pMaterials.pTextureFilename, &NovoMC->ppTexturas)))				{					NovoMC->ppTexturas = NULL;				}			}		}	}	else    	// criar um material para o caso de não existir nenhum pre-definido no ficheiro    {		ZeroMemory(&NovoMC->pMateriais[0], sizeof( D3DMATERIAL9 ) );        NovoMC->pMateriais[0].Diffuse.r = 0.5f;        NovoMC->pMateriais[0].Diffuse.g = 0.5f;        NovoMC->pMateriais[0].Diffuse.b = 0.5f;        NovoMC->pMateriais[0].Specular = NovoMC->pMateriais[0].Diffuse;		NovoMC->ppTexturas[0] = NULL;    }	//Copiar os dados de skinning caso existam	if (pSkinInfo)	{	    NovoMC->pSkinInfo = pSkinInfo;	    pSkinInfo->AddRef();	    UINT numOssos = pSkinInfo->GetNumBones();	    NovoMC->pBoneOffsets = new D3DXMATRIX[numOssos];		NovoMC->pFrameMatrices = new D3DXMATRIX[numOssos];	    for (UINT i = 0; i < numOssos; i++)	        NovoMC->pBoneOffsets = *(NovoMC->pSkinInfo->GetBoneOffsetMatrix(i));        // Nota: Tenho que procurar implementar uma funcao GenerateSkinnedMesh aqui	}	else		{		NovoMC->pSkinInfo = NULL;		NovoMC->pBoneMatrices = NULL;		NovoMC->pBoneOffsets = NULL;		NovoMC->pOrigMesh = NULL;		NovoMC->pFrameMatrices = NULL;	}	d3dDevice->Release();	d3dDevice = NULL;	*ppNewMeshContainer = NovoMC;    	return D3D_OK;}HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) {	D3DXFRAME_DERIV *pFrame = (D3DXFRAME_DERIV*)pFrameToFree;	if(pFrame->Name)	delete[] pFrame->Name;	pFrame->Name = NULL;	if (pFrame)	delete pFrame;	pFrame = NULL;    return D3D_OK; }HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase){    D3DXMESHCONTAINER_DERIV* pMeshContainer = (D3DXMESHCONTAINER_DERIV*)pMeshContainerBase;		SAFE_DELETE_ARRAY(pMeshContainer->Name)	SAFE_DELETE_ARRAY(pMeshContainer->pMateriais)	if(pMeshContainer->ppTexturas)	{		for(UINT i = 0; i < pMeshContainer->NumMaterials; ++i)			SAFE_RELEASE(pMeshContainer->ppTexturas);	}	SAFE_DELETE_ARRAY(pMeshContainer->ppTexturas)	SAFE_DELETE_ARRAY(pMeshContainer->pAdjacency) 		SAFE_DELETE_ARRAY(pMeshContainer->pBoneOffsets)		SAFE_DELETE_ARRAY(pMeshContainer->pFrameMatrices)		SAFE_RELEASE(pMeshContainer->pOrigMesh)		SAFE_RELEASE(pMeshContainer->MeshData.pMesh)		SAFE_RELEASE(pMeshContainer->pSkinInfo)		SAFE_DELETE(pMeshContainer);    return D3D_OK;}bool Anim::Preparacao(){	CAllocateHierarchy* pAH;	hr = D3DXLoadMeshHierarchyFromX("tiny.x", D3DXMESH_MANAGED, Device, pAH, NULL, (LPD3DXFRAME *) &FrameBase, &AC);	if FAILED(hr)		return false;	return true;}


That's all, hope you can help me correcting what is wrong with it... =)

(And as you noticed, I'am from Portugal, so I'am sorry for any mistake in these posts)... =$

Thanks again...

[Edited by - Coder on September 1, 2005 1:08:01 PM]
http://sagito.wordpress.com
Saruman
Saruman
You created a pointer to the hierarchy allocation but I do not see anywhere that you assign it to an object of that type, so it is just a null pointer at the time it is used by the Load function.

This is not the best way of doing this as it has an unneeded allocation for each model loaded, but it should make it work:

bool Anim::Preparacao(){CAllocateHierarchy* pAH = new CAllocateHierarchy;hr = D3DXLoadMeshHierarchyFromX("tiny.x", D3DXMESH_MANAGED, Device, pAH, NULL, (LPD3DXFRAME *) &FrameBase, &AC);delete pAH;if FAILED(hr)return false;return true;}
Sagito
Sagito
Hi Saruman, thanks for posting... =)

I've also tried that solution before, but the code won't compile: "Cannot instantiate abstract class due to following members: -See declaration of CAllocationHierarchy;".

Any clue on how to avoid this error? I've tried to change CAllocationHierarchy in some points, but still no luck... =S

By the way, you said on your post this was not the best way to do it. How should I do it then? (Sorry for all these questions, but I'm a beginner in DirectX and I'm really lost in this hierarchy stuff). =P

Thanks... =D
http://sagito.wordpress.com
Saruman
Saruman
Quote:
Original post by Sagito
Hi Saruman, thanks for posting... =)

I've also tried that solution before, but the code won't compile: "Cannot instantiate abstract class due to following members: -See declaration of CAllocationHierarchy;".

Any clue on how to avoid this error? I've tried to change CAllocationHierarchy in some points, but still no luck... =S

By the way, you said on your post this was not the best way to do it. How should I do it then? (Sorry for all these questions, but I'm a beginner in DirectX and I'm really lost in this hierarchy stuff). =P

Thanks... =D

Those errors mean that you haven't implemented the full abstract class. There are four functions that you need to override and implement and you should make sure they are the same signature as the abstract base class. You left out the line from the debugger that tells which members the compiler is complaining about though so I am unsure where your error is and I'm at work so I don't have time to go through your full codebase there :)

Also when I said it isn't the best way to do it I didn't mean how you are loading the hierarchy, but I meant my example of creating the allocator each time you build a model. You may want to do this depending on your design, although you could also create this as a member somewhere and pass it in to the new model when you are creating it. That way you avoid instantiating it many times unnecessarily.
Sagito
Sagito
Er... Bad news is that this was the full quote from the compiler. It doesn't say which statement is wrong, or which function is not defined... =@ Just says: "Cannot instantiate abstract class due to following members: -See declaration of CAllocateHierarchy", nothing else comes afterwards.

I have defined all four functions of this class, but I'll re-check them for any errors (which would be easier if I knew what the compiler is complaining about). =P

Is there any other function besides D3DXLoadMeshHierarchyFromX that I can use to load an animation from .X files? =)

Thanks...
http://sagito.wordpress.com
Saruman
Saruman
Well that is the only function used for loading X files unless you want to write a manual parser, which I probably wouldn't suggest.

That error means that somewhere you have not implemented one of the base virtual functions. You might think that you have, but if the signatures differ in any way than you haven't, so you might want to really look at that.

Take a look here for some more help.

EDIT: Get rid of the CAllocateHierarchy constructor and try it.
Sagito
Sagito
Well, now I managed to figure out that the compiler was complaining about my CreateMeshContainer struct... =) But I tried to adapt that struct using that link you gave me (thanks for it, helped a lot... =D), but it still complains about it... However, now it says twice(?!) something like:

"CAllocateHierarchy: cannot instantiate abstract class due to following members:
See declaration of CAllocateHierarchy

warning C4259: 'long __stdcall ID3DXAllocateHierarchy::CreateMeshContainer(...)': pure virtual function call was nor defined"

I think that function is working now, because it is similar to the one in that link you posted and to the one which is written in DirectX SDK's MultiAnimation sample... Also, the functions signatures seem to be OK, still don't understand what's wrong with this... =S Lol, I'm getting desperate here... =P

Thanks, and sorry again for all the questions...
http://sagito.wordpress.com
Sagito
Sagito
PROBLEM SOLVED!!!!!!!! =D

Hehe, thanks a LOT for your help! =))))))
http://sagito.wordpress.com
Saruman
Saruman
No problem, glad you have it working :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.