Jump to content
  • Advertisement
isu diss

DX11 Loading FBX with Directx 11

Recommended Posts

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

Share this post


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

Share this post


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

Share this post


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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

 

Share this post


Link to post
Share on other sites

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?

Share this post


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

Edited by galop1n

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!