• Advertisement
Sign in to follow this  

3D Model Loading Problems

This topic is 1235 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

Hello guys

 

I've written an obj loader that could load the 3dmax obj. I tried to draw a cube but all the things aren't what I've been expecting. There was something displayed but the cube looked  awkward and all the vertices are messed up. I don't think it's a cube anyway:(

 

I know there's something called vertex winding stuff. But I just can't fix this. I tried to load an obj file exported by blender. But it's still very messy.

 

I wonder if there's any software could export the exact same thing that is compatible with direct3d standard. It's very difficult to work with something wrong.

Share this post


Link to post
Share on other sites
Advertisement

Why don’t you show a picture of how it looks in your program and how it looks in Blender?

There is no Direct3D 11 standard format; you have to make everything yourself.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.

 

Cheers!

Share this post


Link to post
Share on other sites

Why don’t you show a picture of how it looks in your program and how it looks in Blender?

There is no Direct3D 11 standard format; you have to make everything yourself.

 

 

L. Spiro

I use 3dmax for this

iDoUAfs.jpg

 

Here's how it looks in my program

hTBgoiB.jpg

Share this post


Link to post
Share on other sites

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.

 

Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 

By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.

Share this post


Link to post
Share on other sites

 

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.

 

Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 

By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.

 

The 3D CAD tool 99 times out of 100 produces valid file(albit with there own tweak on some formats like DAE, wavefront object )

The problem most likely exists in your parser code, It is also posible that the CAD tool has produced a edge case with the file.

 

I would recomend that you use a tool like Assimp to do the heavy lifting for you and you just process the data from it.

It's what i do, And it saves me from the hassle of different 3D formats as it handles a nice variety of them.

 

Hope that helps smile.png

Share this post


Link to post
Share on other sites

kauna: "It is typical to see corrupted geometry when programming object importers / exporters.."

 

how could a professional 3d software give wrong indices or vertices?

 

Unlikely. I think kauna was referring to your importer. You should be checking the vertex/index array that you generate after you read in the obj file.

 

My guess at what was intended by kauna's comment is for you to check your data after reading in the obj file (which is the way to go at this point):

 

1. Do the triangles as indexed form a cube?

2. Assuming your app culls counter-clockwise, are the triangle vertices as indexed in clockwise winding order? I.e., when viewed from outside the cube, does each set of triangle vertices appear in clockwise order, relative to the center of each triangle?

3. If you're using a simple vertex array without indexing, does each set of 3 vertices in series in the vertex buffer form a triangle in clockwise winding order?

Edited by Buckeye

Share this post


Link to post
Share on other sites

The most likely problem is that you are not handling indices properly.

 

#1: Have you accounted for the fact that indices are 1-based and not 0-based?

#2: Have you accounted for the fact that there are 2 mapping modes for indices?  http://en.wikipedia.org/wiki/Wavefront_.obj_file#Relative_and_absolute_indices

 

 

L. Spiro

Share this post


Link to post
Share on other sites

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.
 
Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 
By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.
The 3D CAD tool 99 times out of 100 produces valid file(albit with there own tweak on some formats like DAE, wavefront object )
The problem most likely exists in your parser code, It is also posible that the CAD tool has produced a edge case with the file.
 
I would recomend that you use a tool like Assimp to do the heavy lifting for you and you just process the data from it.
It's what i do, And it saves me from the hassle of different 3D formats as it handles a nice variety of them.
 
Hope that helps :)
i don't know much about assimp.but i think i will have to go there some day. Is there any tutorial about assimp with d3d? If not , gl is fine

Share this post


Link to post
Share on other sites

The most likely problem is that you are not handling indices properly.
 
#1: Have you accounted for the fact that indices are 1-based and not 0-based?
#2: Have you accounted for the fact that there are 2 mapping modes for indices?  http://en.wikipedia.org/wiki/Wavefront_.obj_file#Relative_and_absolute_indices
 
 
L. Spiro

what's mapping mode? For th first question i did thought about it

Share this post


Link to post
Share on other sites

I’ve posted a link where you can read all about it.

 

I’ve never loaded a .OBJ file, so I can’t advise you beyond what the link already explains.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

I’ve posted a link where you can read all about it.
 
I’ve never loaded a .OBJ file, so I can’t advise you beyond what the link already explains.
 
 
L. Spiro

what are you working with for 3d models?

Share this post


Link to post
Share on other sites

 

 

 

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.
 
Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 
By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.
The 3D CAD tool 99 times out of 100 produces valid file(albit with there own tweak on some formats like DAE, wavefront object )
The problem most likely exists in your parser code, It is also posible that the CAD tool has produced a edge case with the file.
 
I would recomend that you use a tool like Assimp to do the heavy lifting for you and you just process the data from it.
It's what i do, And it saves me from the hassle of different 3D formats as it handles a nice variety of them.
 
Hope that helps smile.png
i don't know much about assimp.but i think i will have to go there some day. Is there any tutorial about assimp with d3d? If not , gl is fine

 

This ought to get you started.

If you need more help just ask, Or if you want I could post the code I am currently using(but that will change after some time next month due to grabage output when using multiple objects but I am sure that has to do with how I am handling the vertices though... )

Share this post


Link to post
Share on other sites

 

I’ve posted a link where you can read all about it.
 
I’ve never loaded a .OBJ file, so I can’t advise you beyond what the link already explains.
 
 
L. Spiro

what are you working with for 3d models?

 

The FBX SDK.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

 

 

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.

 

Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 

By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.

 

The 3D CAD tool 99 times out of 100 produces valid file(albit with there own tweak on some formats like DAE, wavefront object )

The problem most likely exists in your parser code, It is also posible that the CAD tool has produced a edge case with the file.

 

I would recomend that you use a tool like Assimp to do the heavy lifting for you and you just process the data from it.

It's what i do, And it saves me from the hassle of different 3D formats as it handles a nice variety of them.

 

Hope that helps smile.png

 

 

aaaaaahhhhhhhhh!!!!!!!!!! I'm going crazy X(

I just don't know why it always doesn't give me the right result. though i use assimp for the data things,i'm still getting something like this

MIeoy16.jpg


bool LoadModel(const std::string &fileName, 
			   std::vector<XMFLOAT3> &positions,
			   std::vector<XMFLOAT3> &normals,
			   std::vector<XMFLOAT2> &texcoords,
			   std::vector<unsigned int> &posIndices,
			   std::vector<unsigned int> &norIndices,
			   std::vector<unsigned int> &uvIndices){
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(fileName,aiProcess_Triangulate|aiProcess_GenNormals);
	
	unsigned int numMeshes = scene->mNumMeshes;
	unsigned int numVertices = 0,numIndices = 0;
	for (unsigned int MeshIndex = 0; MeshIndex<numMeshes;MeshIndex++)
	{
		aiMesh *mesh = scene->mMeshes[MeshIndex];
	
		numIndices += mesh->mNumFaces*3;	
		for (unsigned int VertexIndex = 0;VertexIndex<mesh->mNumVertices;VertexIndex++)
		{
			XMFLOAT3 vertex,normal;
			XMFLOAT2 texcoord;

			vertex.x = mesh->mVertices[VertexIndex].x;
			vertex.y = mesh->mVertices[VertexIndex].y;
			vertex.z = mesh->mVertices[VertexIndex].z;
			
			normal.x = mesh->mNormals[VertexIndex].x;
			normal.y = mesh->mNormals[VertexIndex].y;
			normal.z = mesh->mNormals[VertexIndex].z;
// 
// 			char buffer[128];
// 			float tc = mesh->mTextureCoords[VertexIndex]->x;
// 			sprintf_s(buffer,"%f",tc);
// 			texcoord.x = mesh->mTextureCoords[VertexIndex]->x;
// 			texcoord.y = mesh->mTextureCoords[VertexIndex]->y;

			positions.push_back(vertex);
			normals.push_back(normal);
			texcoords.push_back(texcoord);
		}

		unsigned int loop_index = 0;
		for (unsigned int FaceIndex = 0;FaceIndex<mesh->mNumFaces;FaceIndex++)
		{
			const aiFace& face = mesh->mFaces[FaceIndex];
			posIndices.push_back(face.mIndices[0]);
			posIndices.push_back(face.mIndices[1]);
			posIndices.push_back(face.mIndices[2]);
		}
	}

	numIndices = posIndices.size();
	numVertices += positions.size();

// 	char vertexCount[128];
// 	sprintf_s(vertexCount,"%i",numVertices);
// 	MessageBoxA(0,vertexCount,0,0);
	return true;
}

Share this post


Link to post
Share on other sites

Perhaps you should consider that it could be related to how to draw the object, not how you load it.

I would suggest posting the code for creating the vertex-buffer layout etc.

 

 

L. Spiro

Edited by L. Spiro

Share this post


Link to post
Share on other sites

 

 

 

It is typical to see corrupted geometry when programming object importers / exporters. Winding order is the simplest of the problems to solve. Typically invalid output is result of triangles indexing wrong vertices.

 

Cheers!

I know that. But how could a professional 3d software give wrong indices or vertices? 

By the way, vs2012 model view failed to load the obj exported by max. But it worked well with blender's.

 

The 3D CAD tool 99 times out of 100 produces valid file(albit with there own tweak on some formats like DAE, wavefront object )

The problem most likely exists in your parser code, It is also posible that the CAD tool has produced a edge case with the file.

 

I would recomend that you use a tool like Assimp to do the heavy lifting for you and you just process the data from it.

It's what i do, And it saves me from the hassle of different 3D formats as it handles a nice variety of them.

 

Hope that helps smile.png

 

 

aaaaaahhhhhhhhh!!!!!!!!!! I'm going crazy X(

I just don't know why it always doesn't give me the right result. though i use assimp for the data things,i'm still getting something like this

MIeoy16.jpg


bool LoadModel(const std::string &fileName, 
			   std::vector<XMFLOAT3> &positions,
			   std::vector<XMFLOAT3> &normals,
			   std::vector<XMFLOAT2> &texcoords,
			   std::vector<unsigned int> &posIndices,
			   std::vector<unsigned int> &norIndices,
			   std::vector<unsigned int> &uvIndices){
	Assimp::Importer importer;
	const aiScene* scene = importer.ReadFile(fileName,aiProcess_Triangulate|aiProcess_GenNormals);
	
	unsigned int numMeshes = scene->mNumMeshes;
	unsigned int numVertices = 0,numIndices = 0;
	for (unsigned int MeshIndex = 0; MeshIndex<numMeshes;MeshIndex++)
	{
		aiMesh *mesh = scene->mMeshes[MeshIndex];
	
		numIndices += mesh->mNumFaces*3;	
		for (unsigned int VertexIndex = 0;VertexIndex<mesh->mNumVertices;VertexIndex++)
		{
			XMFLOAT3 vertex,normal;
			XMFLOAT2 texcoord;

			vertex.x = mesh->mVertices[VertexIndex].x;
			vertex.y = mesh->mVertices[VertexIndex].y;
			vertex.z = mesh->mVertices[VertexIndex].z;
			
			normal.x = mesh->mNormals[VertexIndex].x;
			normal.y = mesh->mNormals[VertexIndex].y;
			normal.z = mesh->mNormals[VertexIndex].z;
// 
// 			char buffer[128];
// 			float tc = mesh->mTextureCoords[VertexIndex]->x;
// 			sprintf_s(buffer,"%f",tc);
// 			texcoord.x = mesh->mTextureCoords[VertexIndex]->x;
// 			texcoord.y = mesh->mTextureCoords[VertexIndex]->y;

			positions.push_back(vertex);
			normals.push_back(normal);
			texcoords.push_back(texcoord);
		}

		unsigned int loop_index = 0;
		for (unsigned int FaceIndex = 0;FaceIndex<mesh->mNumFaces;FaceIndex++)
		{
			const aiFace& face = mesh->mFaces[FaceIndex];
			posIndices.push_back(face.mIndices[0]);
			posIndices.push_back(face.mIndices[1]);
			posIndices.push_back(face.mIndices[2]);
		}
	}

	numIndices = posIndices.size();
	numVertices += positions.size();

// 	char vertexCount[128];
// 	sprintf_s(vertexCount,"%i",numVertices);
// 	MessageBoxA(0,vertexCount,0,0);
	return true;
}

Have you tried a graphics debugger?

There are some options:

D3D SDK - PiX

nVidia - NSight

AMD - GPUPerfStudio

VS 2012/2013 (Pro+)

 

Perhaps you should consider that it could related to how to draw the object, not how you load it.

I would suggest posting the code for creating the vertex-buffer layout etc.

 

 

L. Spiro

Seconded.

 

HTH.

Share this post


Link to post
Share on other sites


Have you tried a graphics debugger?
There are some options:
D3D SDK - PiX
nVidia - NSight
AMD - GPUPerfStudio
VS 2012/2013 (Pro+)

 

I'm new to these things so I don't know anything about what you've mentioned above...

Basically there's nothing about how to debugger an application but just to implement them on most directx tutorial website.

Share this post


Link to post
Share on other sites
struct SimpleVertex
{
    XMFLOAT3 Pos;
    XMFLOAT3 Color;
};

So that's my SimpleVertex 

    // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"Model Loading.fx", "VS", "vs_4_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hr;
    }

	// Create the vertex shader
	hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
	if( FAILED( hr ) )
	{	
		pVSBlob->Release();
        return hr;
	}

    // Define the input layout
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
	hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
                                          pVSBlob->GetBufferSize(), &g_pVertexLayout );
	pVSBlob->Release();
	if( FAILED( hr ) )
        return hr;

    // Set the input layout
    g_pImmediateContext->IASetInputLayout( g_pVertexLayout );

	// Compile the pixel shader
	ID3DBlob* pPSBlob = NULL;
    hr = CompileShaderFromFile( L"Model Loading.fx", "PS", "ps_4_0", &pPSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hr;
    }

	// Create the pixel shader
	hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
	pPSBlob->Release();
    if( FAILED( hr ) )
        return hr;

	std::vector<XMFLOAT3> aiPos,aiNor;
	std::vector<XMFLOAT2> aiUV;
	std::vector<unsigned int> posIndices,norIndices,uvIndices;
	LoadModel("cube.obj",aiPos,aiNor,aiUV,posIndices,norIndices,uvIndices);
	g_numIndices = posIndices.size();
	for (unsigned int i = 0;i < aiPos.size();i++)
	{
		SimpleVertex vertex;
		vertex.Pos = aiPos[i];
		vertex.Color = aiPos[i];
		m_vertices.push_back(vertex);
	}
    D3D11_BUFFER_DESC bd;
	ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( SimpleVertex ) * m_vertices.size();
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
    D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = &m_vertices[0];
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
    if( FAILED( hr ) )
        return hr;

    // Set vertex buffer
    UINT stride = sizeof( SimpleVertex );
    UINT offset = 0;
    g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( unsigned int ) * posIndices.size();        // 36 vertices needed for 12 triangles in a triangle list
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	bd.CPUAccessFlags = 0;
    InitData.pSysMem = &posIndices[0];
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer );
    if( FAILED( hr ) )
        return hr;

I don't see anything wrong with those

Share this post


Link to post
Share on other sites
bd.ByteWidth = sizeof( unsigned int ) * posIndices.size(); // 36 vertices needed for 12 triangles in a triangle list

That could be your problem, You should only hard code values for basic testing or when lazy.

Try changing that to three(assuming that there are only three vertices).

 

And what do you intend to do with: "posIndices", norIndices, uvIndices?

 

HTH

Share this post


Link to post
Share on other sites

bd.ByteWidth = sizeof( unsigned int ) * posIndices.size(); // 36 vertices needed for 12 triangles in a triangle list

That could be your problem, You should only hard code values for basic testing or when lazy.
Try changing that to three(assuming that there are only three vertices).

And what do you intend to do with: "posIndices", norIndices, uvIndices?

HTH
As you say it's just for testing.
I use drawIndexed() to draw my vertices. So you mean assimp doesn't export indices for me? If so, I would have to kill myself for struggling for that.................

Share this post


Link to post
Share on other sites

 

 

bd.ByteWidth = sizeof( unsigned int ) * posIndices.size(); // 36 vertices needed for 12 triangles in a triangle list

That could be your problem, You should only hard code values for basic testing or when lazy.
Try changing that to three(assuming that there are only three vertices).

And what do you intend to do with: "posIndices", norIndices, uvIndices?

HTH
As you say it's just for testing.
I use drawIndexed() to draw my vertices. So you mean assimp doesn't export indices for me? If so, I would have to kill myself for struggling for that.................

 

Assimp does provide/produce indices.

 

Can you set a breakpoint just after you imported/load the mesh and validate the indices and vertices?

Make sure that the cube has:

  • 36 indices
  • 24 vertices( if there are per vertex normals ) / 8 if there are no normals.

What GPU do you have?, You could then use the tool from the manufacturer to check out the data.

 

So if you still get invalid results after stepping through the code with the debugger (look at the indices and positions) I will upload the code I am currently using to get the data from Assimp and an explanation of how it is handled.

 

 

But it does seam strange that it is not working as the code looks right.

 

HTH.

Share this post


Link to post
Share on other sites

bd.ByteWidth = sizeof( unsigned int ) * posIndices.size(); // 36 vertices needed for 12 triangles in a triangle list

That could be your problem, You should only hard code values for basic testing or when lazy.
Try changing that to three(assuming that there are only three vertices).
And what do you intend to do with: "posIndices", norIndices, uvIndices?
HTH
As you say it's just for testing.
I use drawIndexed() to draw my vertices. So you mean assimp doesn't export indices for me? If so, I would have to kill myself for struggling for that.................
Assimp does provide/produce indices.
 
Can you set a breakpoint just after you imported/load the mesh and validate the indices and vertices?
Make sure that the cube has:
  • 36 indices
  • 24 vertices( if there are per vertex normals ) / 8 if there are no normals.
What GPU do you have?, You could then use the tool from the manufacturer to check out the data.
 
So if you still get invalid results after stepping through the code with the debugger (look at the indices and positions) I will upload the code I am currently using to get the data from Assimp and an explanation of how it is handled.
 
 
But it does seam strange that it is not working as the code looks right.
 
HTH.
I have already checked that. 36 vertices and 36 indices.

What's strange is there's only 8 groups of position info and shouldn't be 36. I think it copies the vertex info and form them as the indices order

My gpu is gt220.Nsight seeems to be a very complex tool for me to handle.

Share this post


Link to post
Share on other sites

It's a little late right not, But tomorow I will see if I can get a clean copy of my Assimp code up for posting here(Should not be a problem getting it together) smile.png

Share this post


Link to post
Share on other sites

It's a little late right not, But tomorow I will see if I can get a clean copy of my Assimp code up for posting here(Should not be a problem getting it together) :)

thank you :) but if it takes too much time for me then i might consider using a game engine like ogre or irrlicht. I've been working on the models for weeks like an idiot. :(

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement