Crash when loading certain x-mesh files

Started by
9 comments, last by Juliean 9 years, 10 months ago

Hello,

I'm having a converter for x-meshes - I know, probably not the most modern format, but time to an assignemnt is due, and I don't want ot include and write another importer yet. The x-files serve their purpose under most circumstances - however, a few specific meshes seem to fail. I used all kinds of different meshes - some from the net, some convertes using 3ds-max, so it does not seem to be an issue with the files themselfs - some work, some don't its always the same, but it doesn't matter where they came from.

For example, this recent mesh I'm going to use for an assignment, always crashes after calling the "ID3DXAllocateHierarchy::CreateFrame"-mehod for the 66th time, after creating the final frame (I assume that its the final - its name is the same as the mesh, at least". The crash happens here:


		HRESULT STDMETHODCALLTYPE AllocMeshHierarchy::CreateFrame(LPCSTR Name, D3DXFRAME** ppNewFrame)
		{
			if(ppNewFrame)
			{
				D3DXFRAME* pFrame = new D3DXFRAME;
				ZeroMemory(pFrame, sizeof(D3DXFRAME));

				if(Name)
				{
					const size_t nameLength = strlen(Name)+1;
					pFrame->Name = new char[nameLength];
					strcpy_s(pFrame->Name, nameLength, Name);
				}
				else
				{
					pFrame->Name = new char[1];
					pFrame->Name[0] = '\0';
				}

				*ppNewFrame = pFrame;
			}
			
			return D3D_OK;
		}

The exact crash line is pointet to the "strcpy_s"-line, but it really happens once this function is done, and after I step out, I get the error. Setting a breakpoint at the beginning doesn't trigger before the crash, so I'm supposing it doesn't really happen here. Without posting the mesh here (I've got to check legals with the creator first), does anybody see something wrong here, or did somebody have an issue along those lines? Here is the full code that loads the mesh:


/****************************************
* Load mesh from file to graphic memory
****************************************/

AllocMeshHierarchy allocHierachy;
LoadUserData userData;
LPD3DXFRAME lpFrame = nullptr;
LPD3DXANIMATIONCONTROLLER lpController = nullptr;
// crash happens inside here
if(D3DXLoadMeshHierarchyFromX(stInName.c_str(), D3DXMESH_MANAGED, m_device.GetDevice(), &allocHierachy, &userData, &lpFrame, &lpController))
    throw resourceLoadException(stInName);

Here is the complete alloc-hierachy-class (though the othet three methods are never called before the crash, and so isn't the userData-loader):


		HRESULT STDMETHODCALLTYPE AllocMeshHierarchy::CreateFrame(LPCSTR Name, D3DXFRAME** ppNewFrame)
		{
			if(ppNewFrame)
			{
				D3DXFRAME* pFrame = new D3DXFRAME;
				ZeroMemory(pFrame, sizeof(D3DXFRAME));

				if(Name)
				{
					const size_t nameLength = strlen(Name)+1;
					pFrame->Name = new char[nameLength];
					strcpy_s(pFrame->Name, nameLength, Name);
				}
				else
				{
					pFrame->Name = new char[1];
					pFrame->Name[0] = '\0';
				}

				*ppNewFrame = pFrame;
			}
			
			return D3D_OK;
		}
			
		HRESULT STDMETHODCALLTYPE AllocMeshHierarchy::CreateMeshContainer(PCSTR Name,
			const D3DXMESHDATA* pMeshData,
			const D3DXMATERIAL* pMaterials,
			const D3DXEFFECTINSTANCE* pEffectInstances,
			DWORD NumMaterials,
			const DWORD *pAdjacency,
			ID3DXSkinInfo* pSkinInfo,
			D3DXMESHCONTAINER** ppNewMeshContainer)
		{
			if(pMeshData->Type != D3DXMESHTYPE_MESH)
				return E_FAIL;

			D3DXMESHCONTAINER* pMeshContainer = new D3DXMESHCONTAINER;
			ZeroMemory(pMeshContainer, sizeof(D3DXMESHCONTAINER));
			pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

			const size_t nameLength = strlen(Name)+1;
			pMeshContainer->Name = new char[nameLength];
			strcpy_s(pMeshContainer->Name, nameLength, Name);

			const size_t numVertices = pMeshData->pMesh->GetNumFaces()*3;
			pMeshContainer->pAdjacency = new DWORD[numVertices];
			memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD)*numVertices);

			pMeshContainer->MeshData.pMesh = pMeshData->pMesh;
			pMeshContainer->MeshData.pMesh->AddRef();

			pMeshContainer->NumMaterials = NumMaterials;
			pMeshContainer->pMaterials = new D3DXMATERIAL[NumMaterials];
			for(unsigned int i = 0; i < NumMaterials; i++)
			{
				pMeshContainer->pMaterials[i].MatD3D = pMaterials[i].MatD3D;

				if(pMaterials[i].pTextureFilename)
				{
					const size_t materialLength = strlen(pMaterials[i].pTextureFilename) + 1;
					pMeshContainer->pMaterials[i].pTextureFilename = new char[materialLength];
					strcpy_s(pMeshContainer->pMaterials[i].pTextureFilename, materialLength, pMaterials[i].pTextureFilename);
				}
				else
				{
					pMeshContainer->pMaterials[i].pTextureFilename = new char[1];
					pMeshContainer->pMaterials[i].pTextureFilename[0] = '\0';
				}
			}

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

				DWORD maxVertices, numCombination;
				LPD3DXBUFFER lpBuffer = nullptr;
				LPD3DXMESH pMesh = nullptr;
				pSkinInfo->ConvertToIndexedBlendedMesh(pMeshContainer->MeshData.pMesh,
					D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
					pSkinInfo->GetNumBones(),
					pMeshContainer->pAdjacency,
					nullptr,
					nullptr,
					nullptr,
					&maxVertices,
					&numCombination,
					&lpBuffer,
					&pMesh);

				pMeshContainer->MeshData.pMesh->Release();
				pMeshContainer->MeshData.pMesh = pMesh;
			}
			
			*ppNewMeshContainer = pMeshContainer;

			return D3D_OK;
		}

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

			return D3D_OK;
		}

		HRESULT STDMETHODCALLTYPE AllocMeshHierarchy::DestroyMeshContainer(THIS_ D3DXMESHCONTAINER* pMeshContainerBase)
		{
			pMeshContainerBase->pSkinInfo->Release();
			pMeshContainerBase->MeshData.pMesh->Release();

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

			for(unsigned int i = 0; i < pMeshContainerBase->NumMaterials; i++)
			{
				delete pMeshContainerBase->pMaterials[i].pTextureFilename;
			}

			delete pMeshContainerBase;

			return D3D_OK;
		}

Any ideas? tell me if you'd need the mesh for testing, I'll see what I can do. Thanks in advance!

EDIT: The exact crash message, roughly translated from german:


Exception (first chance) at 0x602A045F (D3DX9_43.dll) in Acclimate Editor.exe: 0xC0000005: Accessviolation reading position 0x00000002
Exception at 0x602A045F (D3DX9_43.dll) in Acclimate Editor.exe: 0xC0000005: Accessviolation reading position 0x00000002
Advertisement

after creating the final frame (I assume that its the final - its name is the same as the mesh, at least"

Frames can be in any order.

As you know the line where it fails, what are the values for pFrame, Name, namelength, etc.? Is everything valid? Does Name point to a valid string?

If you're using Visual Studio, for debugging purposes, you can add something like:


if(Name && strlen(Name) > 0) // Name is a pointer. The string itself may be empty.
{
    OutputDebugString(Name);
    OutputDebugString("\n");
}


Also, does the x-file load into a viewer correctly?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


As you know the line where it fails, what are the values for pFrame, Name, namelength, etc.? Is everything valid? Does Name point to a valid string?

Actually, the values are all garbage, but thats the even stranger thing - sometimes "name" is even a nullptr, which means the condition couldn't even have been met. With application verifier activated, it jumps me into some completely different function somewhere from my gui/my main engine in the visual-studio callstack. As I said, the function isn't event really called, since no breakpoint and/or conditons are met, output won't be executed too, I supsect there is some memory-corruption that leads to a function-ptr being called from some invalid memory region, don't know.


Also, does the x-file load into a viewer correctly?

I haven't tested yet, but I also don't have any x-file-viewer on my pc, hasn't microsoft removed those from the SDK? Or do you have any link to a x-file-viewer?

I've never used a custom user data loader (never needed it), but maybe you're not implementing it correctly. Have you set breakpoints in your code for that to see if that may be the problem? Most x-files don't need user data loading, but post the code for your implementation. EDIT: You do have implementation code for it, correct? If not, that may very well be your problem. See the docs for ID3DXLoadUserData. That interface is "implemented by the application.." <-- that means you.

Re: mesh viewer - if you don't have an old SDK, you could google for "directx mesh viewer download." You may run across an old MView zip file, or DxViewer zip file or something. Seems I remember a forum somewhere in which somebody posted a link to something useful.

Is the x-file in text format? If so, I'd recommend you add the debugging info I suggested above and look at the frame names that get loaded. Then open the x-file in an ASCII reader (notepad, etc.) and, starting at the next-to-last or last frame which seems to get loaded, see if the file looks corrupt.

In the meantime, message me and make arrangements to get me the x-file, and I'll take a look at it.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


I've never used a custom user data loader (never needed it), but maybe you're not implementing it correctly. Have you set breakpoints in your code for that to see if that may be the problem? Most x-files don't need user data loading, but post the code for your implementation. EDIT: You do have implementation code for it, correct? If not, that may very well be your problem. See the docs for ID3DXLoadUserData. That interface is "implemented by the application.." <-- that means you.

Actually, I only implemented this to make sure passing a nullptr for ID3DXLoadUserData was not part of the issue. Non of them methods are being called eigther, so thats completely unrelated.


Re: mesh viewer - if you don't have an old SDK, you could google for "directx mesh viewer download." You may run across an old MView zip file, or DxViewer zip file or something. Seems I remember a forum somewhere in which somebody posted a link to something useful.

Yeah sure, should have have really though about simply using google before, silly me... so I tried it out and quess what, its crashing even with the mesh viewer. Wtf? I now tested it with another mesh, exported from the same application with all the same settings (its even been made by the same person), and it worked. That is very strange, if I could send you the mesh-file for you to take a look at it I would be very gratefull. The last loaded frame is "Akai", but I didn't see any obvious corruption there (I didn't know where to look at, too)... thanks so far!

For general info, Juliean and I messaged; I looked at the file and it contains an FVFData section in the mesh. It's not clear that that's causing the problem but both MView and DxViewer crash with loading it. I'm not familiar with the implementation of that particular template, so couldn't help further.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

From my experience, here's some things to look for:
- are the subframes/ hierarchy exported correctly?
- are there corrupt materials?
- can you open it in "EffectEdit" use some simple shader
(I know it's old, but it works)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

You can get the DX viewer here

http://www.gamefront.com/files/17257131/DxViewer.zip/

:)
I'm probably a bit late, but since I discovered this only yesterday...

There's an alternative way to load X files using ID3DXFile. Looks like it's supposed to handle custom data (so-called templates). Disadvantage being all the nice stuff the mesh/hierarchy loader doing automatically one now has to do manually (similar to traversing a XML-tree).

There's a rudimentary D3D9 sample in the June 2010 SDK (StateManager) using it to define a scene through an x-file. Also, there's a skeleton parser in source code(Common\XParser) from the book Advanced Animation with DirectX.

Hope this helps.

This is a great book to learn from if yout working with .x animated meshs

http://www.cjgraphic.com/?page=character-book

:)

This topic is closed to new replies.

Advertisement