X file meshes with more then 1 subset turning into polygon soup

Started by
8 comments, last by Negitivefrags 20 years ago
I have been trying to render X files loaded with D3DXCreateMeshFromX manualy without using DrawSubset, and my meathod works fine for meshes with only 1 subset, but for meshes with more then one, it doesnt seem to be indexing properly. Basicly I have been doing it like this: Loading: 1: Use D3DXCreateMeshFromX to load a mesh in the normal way. 2: Use OptimiseInPlace with the D3DXMESHOPT_ATTRSORT flag to create an attribute table 3: Store attribute table in my own data structure for latter use (My structure has Material and texture information bound with it making rendering more convieniant then keeping on using the attribute table) Rendering: 4: Arange all mesh subsets into the most efficent (least render state changes) way possibe. This is done with *all* meshes so that different meshes with the same texture can be rendered without a call to SetTexture in between. 5: Use DrawIndexedPrimitive with the appropriate information from my data structure to render each subset. But for some reason, the result always looks somthing like the mesh in the middle of this screenshot. (What it should look like is in the top right curtisy of the DX Mesh Viewer) Note that the tiger mesh that only has 1 subset renders fine. I have checked with the debugger, the calls made to Draw Indexed Primitive and all the numbers are the same as those given by the attribute table. I am really at a loss as to what could be causing the problem.
Advertisement
Post your mesh loading code and your render code so that we can see if there is anything out of the ordinary happening in there.

neneboricua
For what it''s worth, I''ve sometimes found that switching vertex buffers, or switching model views, is as expensive as switching textures.

Switching textures was expensive back when the cards had to suck textures in from main RAM. That''s not the case anymore, and hasn''t been for a while...

Switching SHADERS is expensive, though.
enum Bool { True, False, FileNotFound };
quote:Original post by hplus0603
For what it''s worth, I''ve sometimes found that switching vertex buffers, or switching model views, is as expensive as switching textures.

Switching textures was expensive back when the cards had to suck textures in from main RAM. That''s not the case anymore, and hasn''t been for a while...

Switching SHADERS is expensive, though.


so you''re implying that the d3dx effect rendering model is the worst possible way you can do things, if you''ve got multiple passes with different shaders in them?
die or be died...i think
attribute sorting rearranges your vertices, so you might want to make sure that you''re using the *new* set of indices, rather than the ones loaded from the .x file..
die or be died...i think
Okay, well I am getting the indices directly from the I3DXMESH object each frame, so the indices should be the optimised ones.

Here is the code to load the models:

bool Object3dMesh::CreateMesh(string MeshFilename, LPDIRECT3DDEVICE8& D3DDevice){	g_Log.Out(string("Loading mesh: ") + MeshFilename, LOG_TO_CONSOLE);	LPD3DXBUFFER pD3DXMtrlBuffer;	LPD3DXBUFFER pD3DXAdjBuffer;	DWORD NumMaterial = 0L;	if(FAILED(D3DXLoadMeshFromX((char*)MeshFilename.c_str(), D3DXMESH_MANAGED, D3DDevice, &pD3DXAdjBuffer, &pD3DXMtrlBuffer, &NumMaterial, &m_Mesh)))	{		g_Log.Out(string("Failed to load mesh: ") + MeshFilename);		pD3DXMtrlBuffer->Release();		pD3DXAdjBuffer->Release();		return false;	}	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();	for( DWORD i=0; i<NumMaterial; i++ )    {		D3DMATERIAL8 MaterialToCreate;        // Copy the material		MaterialToCreate = d3dxMaterials[i].MatD3D;		MaterialToCreate.Ambient = MaterialToCreate.Diffuse;		LPDIRECT3DTEXTURE8 TextureToCreate = NULL;		if(d3dxMaterials[i].pTextureFilename != NULL)		{			TextureToCreate = g_Engine->LoadTexture(d3dxMaterials[i].pTextureFilename);			if(!TextureToCreate)			{				g_Log.Out(string("Failed to Load Texture for Mesh: ") + MeshFilename);			}		}		//This creates the data structure to store a subset in		MeshSubset NewSubset;//This function registers the material of the mesh with the material system		NewSubset.m_Material = g_Engine->CreateMaterial(TextureToCreate, MaterialToCreate, m_Mesh->GetFVF());		m_Subsets.push_back(NewSubset);    }	//Optimise to create the attribute table	if(FAILED(m_Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL)))	{		g_Log.Out(string("Optimise failed for Mesh: ") + MeshFilename);		pD3DXMtrlBuffer->Release();		pD3DXAdjBuffer->Release();		return false;	}	//We have finished with the buffers	pD3DXMtrlBuffer->Release();	pD3DXAdjBuffer->Release();	//Now fill all the rendering information in the subset from the attribute table	DWORD NumberOfAttributes = 0;	m_Mesh->GetAttributeTable(NULL, &NumberOfAttributes);	D3DXATTRIBUTERANGE* AttributeTable = new D3DXATTRIBUTERANGE[NumberOfAttributes];	m_Mesh->GetAttributeTable(AttributeTable, &NumberOfAttributes);	D3DXATTRIBUTERANGE* It = AttributeTable;	vector<MeshSubset>::iterator ListIt = m_Subsets.begin();	for(int i = 0; i < (int)NumberOfAttributes; i++ )	{		(*ListIt).IndexCount = It->FaceCount;		(*ListIt).IndexStart = It->FaceStart;		(*ListIt).VertexCount = It->VertexCount;		(*ListIt).VertexStart = It->VertexStart;		It++; ListIt++;	}	delete[] AttributeTable;	g_Log.Out(string("Mesh Loaded: ") + MeshFilename, LOG_TO_CONSOLE);	return true;}


Okay, dont kill me becuase the code is probably crap.

And here is the rendering code. BTW it should be noted that the call to render somthing is stored in a structure called a RenderRequest which has the IndexBuffer pointer, the MeshSubset structure and position information in it

{	//Create a material to start with	MeshMaterial CurrentMaterial;	LPDIRECT3DVERTEXBUFFER8 CurrentVertexBuffer = NULL;	RenderRequest CurrentRequest;	multiset<RenderRequest>::iterator it;	for(it = m_RenderRequestManager->m_RenderRequests.begin(); it != m_RenderRequestManager->m_RenderRequests.end(); it++)	{		CurrentRequest = (*it);		//Check to see if the current material is the same as the fetched one		if(!(CurrentMaterial == (*(CurrentRequest.IndexSubset.m_Material))))		{			//If it is not, then change the texture and material settings			m_D3DDevice->SetTexture(0, CurrentRequest.IndexSubset.m_Material->m_Texture);			m_D3DDevice->SetMaterial( &(CurrentRequest.IndexSubset.m_Material->m_Material));			if(CurrentRequest.IndexSubset.m_Material->m_FVF != CurrentMaterial.m_FVF) m_D3DDevice->SetVertexShader( CurrentRequest.IndexSubset.m_Material->m_FVF);			CurrentMaterial = (*CurrentRequest.IndexSubset.m_Material);		}		//Set current position		m_D3DDevice->SetTransform(D3DTS_WORLDMATRIX(0), &(CurrentRequest.Position));		//Set the vertex Stream if different		if(CurrentVertexBuffer != CurrentRequest.Vertices)		{			//There are three posible different types of vertex stream			if( CurrentRequest.IndexSubset.m_Material->m_FVF == 258 ) m_D3DDevice->SetStreamSource(0, CurrentRequest.Vertices, sizeof(Vertex3dTextured)); else			if( CurrentRequest.IndexSubset.m_Material->m_FVF == 18 ) m_D3DDevice->SetStreamSource(0, CurrentRequest.Vertices, sizeof(Vertex3dNormal)); else			if( CurrentRequest.IndexSubset.m_Material->m_FVF == 274 ) m_D3DDevice->SetStreamSource(0, CurrentRequest.Vertices, sizeof(Vertex3dTexturedNormal)); else			{				m_D3DDevice->EndScene();				g_Log.Out("Error: Unknown FVF Encountered: Exiting");				return false;			}		}		m_D3DDevice->SetIndices(CurrentRequest.Indices, 0);		//Now render the actual object		m_D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, CurrentRequest.IndexSubset.VertexStart, CurrentRequest.IndexSubset.VertexCount, CurrentRequest.IndexSubset.IndexStart, CurrentRequest.IndexSubset.IndexCount);	}	m_RenderRequestManager->m_RenderRequests.clear();	return true;}


I know there is somthing really bad going with the seleting of the vertex format, but ah well. It also might be a bit confusing out of context.
Hi,
I have a very simmilar problem I am able to draw first subset without problems,but others are bad...
Have you ever solved it? Could You help me pls?
I think that problem could be in wrong DrawIndexedPrimitive parameters , but i'm not sure

[edited by - AlexanderCZ on March 25, 2004 8:09:42 AM]
I ran into a similar problem as well when I was working on my octree. My octree worked fine if the polygon soup used one skin but went bonkers when I used more than 1 skin. Finally I ended up breaking the surface into multiple ID3DXMesh(s) and everything has been working pretty well ever since.

-Richard ''vajuras'' Osborne
What primitive type are you specifying to DIP()? It needs to be triangle list, not triangle strip.

I like pie.
[sub]My spoon is too big.[/sub]
I already fixed it.it was in bad params of DIP()...
It seems that my english is bad,because when i was reading DX Documentation I didn''t noticed that MinIndex does mean StartVertex

This topic is closed to new replies.

Advertisement