Archived

This topic is now archived and is closed to further replies.

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

This topic is 5006 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 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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..

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites