Loading FBX with Directx 11

Started by
14 comments, last by isu diss 6 years, 1 month ago

HRESULT FBXLoader::Open(HWND hWnd, char* Filename)
{
	HRESULT hr = S_OK;
	if (FBXM)
	{
		FBXIOS = FbxIOSettings::Create(FBXM, IOSROOT);
		FBXM->SetIOSettings(FBXIOS);

		FBXI = FbxImporter::Create(FBXM, "");

		if (!(FBXI->Initialize(Filename, -1, FBXIOS)))
			MessageBox(hWnd, (wchar_t*)FBXI->GetStatus().GetErrorString(), TEXT("ALM"), MB_OK);

		FBXS = FbxScene::Create(FBXM, "MCS"); 
		if (!FBXS)
			MessageBox(hWnd, TEXT("Failed to create the scene"), TEXT("ALM"), MB_OK);

		if (!(FBXI->Import(FBXS)))
			MessageBox(hWnd, TEXT("Failed to import fbx file content into the scene"), TEXT("ALM"), MB_OK);

		if (FBXI)
			FBXI->Destroy();

		FbxNode*	MainNode = FBXS->GetRootNode();
		int			NumKids = MainNode->GetChildCount();
		FbxNode*	ChildNode = NULL;

		for (int i=0; i<NumKids; i++)
		{
			ChildNode = MainNode->GetChild(i);
			FbxNodeAttribute* NodeAttribute = ChildNode->GetNodeAttribute();
			if (NodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
			{
				FbxMesh* Mesh = ChildNode->GetMesh();

				NumVertices = Mesh->GetControlPointsCount();//number of vertices
				MyV = new FBXVTX[NumVertices];

				for (DWORD j = 0; j < NumVertices; j++)
				{
					FbxVector4 Vertex = Mesh->GetControlPointAt(j);//Gets the control point at the specified index. 
					MyV[j].Position = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]);

				}

				NumIndices = Mesh->GetPolygonVertexCount();//number of indices; for cube 20
				MyI = new DWORD[NumIndices];
				MyI = (DWORD*)Mesh->GetPolygonVertices();//index array

				NumFaces = Mesh->GetPolygonCount();
				MyF = new FBXFACEX[NumFaces];
				for (int l=0;l<NumFaces;l++)
				{
					MyF[l].Vertices[0] = MyI[4*l];
					MyF[l].Vertices[1] = MyI[4*l+1];
					MyF[l].Vertices[2] = MyI[4*l+2];
					MyF[l].Vertices[3] = MyI[4*l+3];
				}

				UV = new XMFLOAT2[NumIndices];
				for (int i = 0; i < Mesh->GetPolygonCount(); i++)//polygon(=mostly rectangle) count
				{
				  FbxLayerElementArrayTemplate<FbxVector2>* uvVertices = NULL;

				  Mesh->GetTextureUV(&uvVertices);
				  for (int j = 0; j < Mesh->GetPolygonSize(i); j++)//retrieves number of vertices in a polygon
				  {
					 FbxVector2 uv = uvVertices->GetAt(Mesh->GetTextureUVIndex(i, j));
					 UV[4*i+j] = XMFLOAT2((float)uv.mData[0], (float)uv.mData[1]);
				  }
				}
			}
		}
	}
	else
		MessageBox(hWnd, TEXT("Failed to create the FBX Manager"), TEXT("ALM"), MB_OK);

	return hr;
}

I've been trying to load fbx files(cube.fbx) into my programme. but I get this. Can someone pls help me?

 

Untitled.jpg.cbebe4010d8c2538f3580ba44492eb08.jpg

Advertisement

Seems like your mesh is not triangulated so the indices are messed up. In Blender, you can triangulate with T button in edit mode. Or you can triangulate it yourself in the importing code.

Thank you very much


MyI = new DWORD[NumIndices];
MyI = (DWORD*)Mesh->GetPolygonVertices();//index array

Unrelated: the first line shouldn't be there, you're allocating an array and forgetting about it right after!

.:vinterberg:.


				//Loop through the polygons
				for (int p = 0; p < Mesh->GetPolygonCount(); p++)
				{
					//Loop through the three vertices within each polygon
					for(int v = 0; v < Mesh->GetPolygonSize(p); v++)
					{
						 FbxStringList UVSetNameList;
						 Mesh->GetUVSetNames( UVSetNameList );
						 

						FbxVector2 tex;
						bool isMapped;
						Mesh->GetPolygonVertexUV(p, v, UVSetNameList.GetStringAt(0), tex, isMapped);
						MyV[3*p+v].TexCoords = XMFLOAT2((float)tex.mData[0], (float)tex.mData[1]);

					}
		
				}

I'm having a problem loading UV coordinates from FBX. Is above code correct? what should I do?

Untitled.jpg

What happens if you change it to this?


MyV[3*p+v].TexCoords = XMFLOAT2((float)tex.mData[0], 1.0f - (float)tex.mData[1]);

 

.:vinterberg:.

Now I understand the problem but I don't know how to fix it. FBX stores UVs as per index. What I should do is load UV indices into Direct3D which I don't know. This should work if it's per vertex.


Vertices = new VTX[MyFBX->NumVertices];
for(DWORD i=0;i<MyFBX->NumVertices;i++)
{
	Vertices[i].Position = MyFBX->MyV[i];
	Vertices[i].TextureCoords = MyFBX->MyUV[i];
}

I understood that by loading simple plane.fbx. here are the screen shots.

 

Untitled.jpg

Untitled2.jpg

Untitled3.jpg

The problem is not only with texcoords but with any additional properties past the position.

If you take the example of a cube, you have 8 corner positions, 6 possible normals ( one per face ) and 4 texture coordinates possible if we consider a full wrap per face.

It means that a full vertex index is in fact a tuple of 3 index (pos idx, uv idx , normal idx). This is the kind of representation you can find in an OBJ file for example or in a FBX.

Because D3D only support a single index to fetch the complete vertex. It means you need to duplicate position/uv/normals into new vertices when appropriate. And to do so is easy, just create a dictionary like this std::map<std::tuple<int,int,int>,int> dico; and have an int nextVertexIdx. The key is your triplet, every time a triplet is not yet in the map, just insert it and allocate a vertex:  dico[triplet] = nextVertexIdx++;

Once you proceed with all the FBX indices and you have all the existing triplet, nextVertexIdx contains the number of vertices you need in your final vertex buffer. The dictionary also let you know what position/uv/normals to copy for each vertex ( if you invert it by swapping key/value in a second std::map ), And of course, generate the index buffer by looking from triplet to vertex index.

 

I can load all the position values and indices correctly. And I can render the model correctly via D3D DrawIndexed call. The only problem is loading UVs. I got your idea but my c++ knowledge is not so good. Can you give me a source code snippet?

10 hours ago, isu diss said:

I can load all the position values and indices correctly. And I can render the model correctly via D3D DrawIndexed call. The only problem is loading UVs. I got your idea but my c++ knowledge is not so good. Can you give me a source code snippet?

No, we are here to help, not to do the work for you. Or you would never learn, especially with something that basic.

 

Reread my answer, look at loading obj file tutorial, try and come ask help with your code if blocked.

This topic is closed to new replies.

Advertisement