Problems with rmxfguid.h / LPD3DXFILEDATA-GetType()

Started by
2 comments, last by legalize 16 years, 6 months ago
Hi I know that DirectX specifies the GUIDS for data types within an x file in rmxfguid.h. My problem is that the values that my calls to LPD3DXFILEDATA->GetType() in my mesh parser sometimes return guids that are very similar but not exactly the same as those specified in rmxfguid.h. Heres an Example: Im loading a mesh with some frames specifed into my frame parser. The frame parser opens an enumerates the x file and loops through the enumeration picking out each data object of type TID_D3DRMFrame general X-File Parser

#ifndef _XFILEPARSER_H
#define _XFILEPARSER_H

#include "XFile.h"
class Base;


using namespace std;

class XFileParser
{

	public:
		XFileParser();
		virtual ~XFileParser();
		
		
		
		BOOL parse(LPCSTR fileName, void** Data = NULL);

		// Functions to help retrieve data object information
		char*	getObjectName(LPD3DXFILEDATA pDataObj);
		void* getObjectData(LPD3DXFILEDATA pDataObj,DWORD* size);

protected:

	// Functions called when parsing begins and ends.
	virtual BOOL BeginParse(void** Data){return TRUE;}
	virtual BOOL EndParse(void** Data){return TRUE;}

	// Function Called for every Data object found. 
	virtual BOOL parseObject(LPD3DXFILEDATA	pDataObj,
							 LPD3DXFILEDATA pParentDataObj,
							 DWORD Depth,
							 void** Data, BOOL Reference)
	{
		return parseChildObjects(pDataObj,Depth,Data,Reference);
	}
	
	// Function Called to Enumerate Child Objects.
	BOOL parseChildObjects(LPD3DXFILEDATA	pDataObj,
							DWORD Depth, void** Data, 
							BOOL ForceReference = FALSE);
	


	LPCSTR FileName;
	Base* base;
};



#endif

// CPP
#include "Base.h"
#include "XFileParser.h"


XFileParser::XFileParser()
{
	base = Base::Instance();
}

XFileParser::~XFileParser()
{
}


BOOL XFileParser::parse(LPCSTR fileName,void** Data)
{
	//Check if the file Exists
	if(! base->fileExists(fileName))
	{
		sprintf(base->buffer,"XFile: '%s' \nDoes not exist!",fileName);
		base->messageBox(base->hWnd,base->buffer,"File Not Found");
		return FALSE;
	}

	FileName = fileName;

	LPD3DXFILE			pDXFile = NULL;
	LPD3DXFILEENUMOBJECT pEnum	= NULL;
	LPD3DXFILEDATA		pData	= NULL;

	//Create an IDirectXFile interface for the XFile.
	
	if(FAILED(D3DXFileCreate(&pDXFile)))
	{
		base->messageBox(base->hWnd,"Failed to create DirectX XFile Interface!");
		pDXFile->Release();
		return FALSE;
	}

	//Register the Standard Templates
	if(FAILED(pDXFile->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES,D3DRM_XTEMPLATE_BYTES)))
	{
		base->messageBox(base->hWnd,"Failed to Register DirectX file Default Templates");
		pDXFile->Release();
		return FALSE;
	}

	//Create Enumeration Object
	if(FAILED(pDXFile->CreateEnumObject((LPVOID)fileName,DXFILELOAD_FROMFILE,&pEnum)))
	{
		base->messageBox(base->hWnd,"Failed to Create File Enumeration Object from XFile.");
		return FALSE;
	}

	// Call the begin parse function, continuing if allowed
	if(BeginParse(Data) == TRUE) {

		// Loop through all top-level objects, breaking on errors
		BOOL ParseResult;
		
		SIZE_T numChildren = 0;
		pEnum->GetChildren(&numChildren); // This is a new bit

		for(SIZE_T i=0; i < numChildren; i++)
		{
			if(SUCCEEDED(pEnum->GetChild(i,&pData)))
			{
				ParseResult = parseObject(pData, NULL, 0, Data, FALSE);
				SafeRelease(pData);
				if(ParseResult == FALSE)
					break;
			}
		}
	}

	// Call end parse function
	EndParse(Data);

	//Release COM Objects
	SafeRelease(pEnum);
	SafeRelease(pDXFile);

	return TRUE;
}

BOOL XFileParser::parseChildObjects(LPD3DXFILEDATA pDataObj,          
									DWORD Depth, void **Data,            
									BOOL ForceReference)
{
	LPD3DXFILE				pSubObj  = NULL;
	LPD3DXFILEDATA          pSubData = NULL;
	LPVOID pDataRef = NULL;
	BOOL                       ParseResult = TRUE;

	// Scan for embedded templates
	//while(SUCCEEDED(pDataObj->GetNextObject(&pSubObj))) 
	//{
	// Scan for embedded templates
	SIZE_T numChildren = 0;
	pDataObj->GetChildren(&numChildren); // This is a new bit

	for(SIZE_T i=0; i < numChildren; i++)
	{
		if(SUCCEEDED(pDataObj->GetChild(i,&pSubData)))
		{
			
			// Process embedded references
			if(pDataObj->IsReference()) 
			{
			
				// Resolve the data object
				//if(SUCCEEDED(pDataRef->Resolve(&pSubData))) 
				{
					// Parse the object, remembering the return code
					ParseResult = parseObject(pSubData, pDataObj,Depth+1, Data, TRUE);
					SafeRelease(pSubData);
				}
				SafeDelete(pDataRef);

				// Return on parsing failure
				if(ParseResult == FALSE)
					return FALSE;
			
			// Process non-referenced embedded templates
			}else
			{
					// Parse the object, remembering the return code
					ParseResult = parseObject(pSubData, pDataObj,Depth+1, Data,ForceReference);
					SafeRelease(pSubData);
			}

			// Release the data object
			SafeRelease(pSubObj);

			// Return on parsing failure
			if(ParseResult == FALSE)
				return FALSE;
		}
	}

	return TRUE;
}


char* XFileParser::getObjectName(LPD3DXFILEDATA pDataObj)
{
	char  *Name = NULL;
	DWORD  Size = 0;

	// Error checking
	if(pDataObj == NULL)
		return NULL;

	// Get the template name (if any)
	if(FAILED(pDataObj->GetName(NULL, &Size)))
	{
		base->messageBox(base->hWnd,"Failed To Get Object Name!");
		return NULL;
	}
		

	// Allocate a name buffer and retrieve name
	if(Size > 1) 
	{
		if((Name = new char[Size]) != NULL)
			pDataObj->GetName(Name, &Size);
	}

	return Name;
}

void* XFileParser::getObjectData(LPD3DXFILEDATA pDataObj,
								 DWORD *size)
{
	void *TemplateData = NULL;
	DWORD TemplateSize = 0;

	// Error checking
	if(pDataObj == NULL)
		return NULL;

	// Get a data pointer to template
	if(SUCCEEDED(pDataObj->Lock(&TemplateSize,(LPCVOID*)&TemplateData)))
	{
		pDataObj->Unlock();
	}else
	{
		base->messageBox(base->hWnd,"Failed To Get Object Data");
	}

	//pDataObj->GetData(NULL,&TemplateSize,(PVOID*)&TemplateData);

	// Save size if needed
	if(size != NULL)
		*size = TemplateSize;

	return TemplateData;
}




Derived Frame Parser

#ifndef _FRAME_PARSER_H
#define _FRAME_PARSER_H

#include "XFileParser.h"
#include "XFile.h"
#include "Frame.h"
#include "D3DMESHCONTAINER_EX.h"

using namespace std;

struct FrameList
{
	Frame * pFrame;
	FrameList* pNext;

	FrameList()
	{
		pFrame = NULL;
		pNext = NULL;
	}

	~FrameList()
	{
//		SafeDelete(pFrame);
		SafeDelete(pNext);
	}
};

class FrameParser : public XFileParser
{

	public:

		FrameParser();											// Default No-args constructor.
		FrameParser(LPCSTR fileName);							//
		virtual ~FrameParser();

		void initialise(LPCSTR fileName);
		void cleanUp();
		
		UINT numFrames;
		FrameList* flatList;
		FrameList* flatListRoot;


		// the root frame of the heiarachy
		Frame* m_RootFrame;

	private:

		BOOL BeginParse(void** Data);

		BOOL parseObject(LPD3DXFILEDATA	pDataObj,
			LPD3DXFILEDATA pParentDataObj,
			DWORD Depth,
			void** Data, BOOL Reference);
		
		void appendToFlatList(Frame* pFrame);

};

#endif

// CPP

#include "Base.h"
#include "Frame.h"
#include "FrameParser.h"

FrameParser::FrameParser()
{
	m_RootFrame = NULL;
	flatList = NULL;
	flatListRoot = NULL;
}

FrameParser::FrameParser(LPCSTR fileName)
{
	m_RootFrame = NULL;
	flatList = NULL;
	flatListRoot = NULL;
    initialise(fileName);
}

FrameParser::~FrameParser()
{
	cleanUp();
}

void FrameParser::cleanUp()
{
   SafeDelete(m_RootFrame);
   SafeDelete(flatListRoot);

   numFrames = 0;
}

void FrameParser::initialise(LPCSTR fileName)
{

	parse(fileName);
}

BOOL FrameParser::BeginParse(void** Data)
{
	//Clear Hierarchy
	cleanUp();
	return TRUE;
}

BOOL FrameParser::parseObject(LPD3DXFILEDATA	pDataObj,
						   LPD3DXFILEDATA pParentDataObj,
						   DWORD Depth,
						   void** Data, BOOL Reference)
{

	//Skip Reference Objects
	if(Reference == TRUE)
		return TRUE;

	GUID type;
	pDataObj->GetType( &type );

	//If the object type is a frame (non-referenced) 
	//then add it to the hierarchy
	if(type == TID_D3DRMFrame)
	{
		
		
		//char* Name = getObjectName(pDataObj);
		//base->messageBox(base->hWnd,Name,"Frame Object");
		//delete [] Name;
		
		
		//Alocate a frame container
		Frame* pFrame = new Frame();

		numFrames ++;

		//Get Frame Name (assign one if none found)
		if((pFrame->Name = getObjectName(pDataObj)) == NULL)
		{
			pFrame->Name = _strdup("No Name Frame");
		}

		//Link Frame Structure into list
		if(Data == NULL)
		{
			//Link as a sibling of root
			pFrame->pFrameSibling = m_RootFrame;
			m_RootFrame = pFrame;
			appendToFlatList(pFrame);
			pFrame = NULL;
			Data = (void**)&m_RootFrame;
		}
		else
		{
			//Link as a child of the supplied frame
			Frame* pFramePtr = (Frame*)*Data;
			pFrame->pFrameSibling = pFramePtr->pFrameFirstChild;
			pFramePtr->pFrameFirstChild = pFrame;

			appendToFlatList(pFrame);

			pFrame = NULL;
			Data = (void**)&pFramePtr->pFrameFirstChild;
		}

		SafeDelete(&type);

	}
	//Load Frame Transformation matrix
	if(type == TID_D3DRMFrameTransformMatrix)
	{
		Frame* pFrame = (Frame*)*Data;
		if(pFrame)
		{
			pFrame->TransformationMatrix = *(D3DXMATRIX*) getObjectData(pDataObj,NULL);
			pFrame->matOriginal = pFrame->TransformationMatrix;
		}

		SafeDelete(&type);
	}


	return parseChildObjects(pDataObj,Depth,Data,Reference);
}

void FrameParser::appendToFlatList(Frame* pFrame)
{
		if(!flatList)
		{
			flatList = new FrameList();
			flatListRoot = flatList;
			flatList->pFrame = pFrame;
			flatList->pNext = new FrameList();
		}else
		{
			flatList = flatList->pNext;
			flatList->pFrame = pFrame;
			flatList->pNext = new FrameList();
		}
}

The problem is here:

	GUID type;
	pDataObj->GetType( &type );

	//If the object type is a frame (non-referenced) 
	//then add it to the hierarchy
	if(type == TID_D3DRMFrame)
	{




The first frame found in each model works fine, the GUID defined in rmxfguid.h for TID_D3DRMFrame is the same as that in the GUID type found by pDataObj->GetType(&type), the parser then continues through other data but when it gets to the next frame, the GetType returns a very similar but not identical GUID. for example:

/* {3D82AB46-62DA-11cf-AB39-0020AF71E433} */
DEFINE_GUID(TID_D3DRMFrame,
0x3d82ab46, 0x62da, 0x11cf, 0xab, 0x39, 0x0, 0x20, 0xaf, 0x71, 0xe4, 0x33);



on the first frame found, type ={3D82AB46-62DA-11cf-AB39-0020AF71E433}, which is correct. However, on the second frame found, type = {3D82AB44-62DA-11cf-AB39-0020AF71E433} (NOTE THAT THE 8th NUMBER IN THE GUID IS DIFFERENT).As a result of that difference, the frame is not recognised as an TID_D3DRMFrame and is lost. Can anyone think of a reason why this is happening?
Advertisement
Have you validated that the data in the .x file is indeed correct?

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

Hi

Yes the XFile in question is Tiny.x from the SDK. This problem has only become prevelent since I changed from DirectX 9.0 to August 2007 (with the changes to the X File Interface Classes). It may be due to some other problem where I have tried to update my old code to the current interfaces. At present all models load perfectly but are all transformed to the identity matrix. So tiny.x loads but is squashed together at the origin.
Quote:Original post by treeway
Yes the XFile in question is Tiny.x from the SDK.


OK, so this is known good data, so that eliminates the bad data with good code scenario. Now we're left with the good data with bad code scenario.

I would compare what you are doing to load the mesh file to what the mesh viewer utility does to load the mesh file. The source to the mesh viewer is in the SDK.

I haven't updated Chapter 21. X Files to use the D3DX interfaces yet, but I have looked at the interfaces and updated my samples.

Try taking a look at my rt_XTreeView sample to see an example of using the D3DX interfaces for parsing .x files.

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

This topic is closed to new replies.

Advertisement