Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Texture UVs on FBX mesh are foo bared


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 12:09 PM

I ventured into loading FBX Meshes do to the ability for morph targets, skeletal mesh animation and other neat stuff that we all love. However, tutorials on FBX SDK are hard to come by like finding the last milk in a apocolypic future store. I grabbed some samples from others and somehow miracably able to create a mesh. However, the UV's aren't right.

 

As sceen in the attachment.  I looked at it closely and it appears to me that the UV's are using something other than the UV's. The code i have is:

for (int j = 0; j < meshArray.Size(); j++) {

			vCount = meshArray[j]->GetControlPointsCount();

			m_vertices = new myVertex[vCount];
			Face face;
			 polygonCount = meshArray[j]->GetPolygonVertexCount() / 3;
			numIndices = meshArray[j]->GetPolygonVertexCount();

			FbxVector4 *vert = meshArray[j]->GetControlPoints();
			int arrayIndex = 0;


			//memcpy(vert, meshArray[j]->GetControlPoints(), sizeof(FbxVector4)* vCount);


			for (int i = 0; i < polygonCount; i++) {
				for (unsigned int k = 0; k < 3; k++) {
					int index = 0;
					FbxVector4 fbxNorm(0, 0, 0, 0);
					FbxVector2 fbxUV(0, 0);
					FbxVector4 Vers(0, 0, 0, 0);

					FbxStringList UVStringNames;
					meshArray[j]->GetUVSetNames(UVStringNames);

					bool texCoordFound = false;
					face.indices[k] = index = meshArray[j]->GetPolygonVertex(i, k);
					Vers = vert[index];
					m_vertices[index].position = XMFLOAT4(Vers.mData[0],Vers.mData[2],Vers.mData[1],0.0f);
					
					meshArray[j]->GetPolygonVertexNormal(i, k, fbxNorm);
					m_vertices[index].normal = XMFLOAT3(fbxNorm.mData[0], fbxNorm.mData[2], fbxNorm.mData[1]);

					FbxLayerElementUV* fbxLayerUV = meshArray[j]->GetLayer(0)->GetUVs();
					if (fbxLayerUV) {
						int fbxUVIndex = 0;
						
						switch (fbxLayerUV->GetMappingMode())
						{
						case FbxLayerElement::eByControlPoint :
							fbxUVIndex = face.indices[k];
							break;
						case FbxLayerElement::eByPolygonVertex :
							fbxUVIndex = meshArray[j]->GetTextureUVIndex(i, k, FbxLayerElement::eTextureDiffuse);
							break;
						}
						fbxUV = fbxLayerUV->GetDirectArray().GetAt(fbxUVIndex);
					}
					m_vertices[index].texture = XMFLOAT2(fbxUV.mData[0], fbxUV.mData[1]);
	
				}
				Faces.push_back(face);

			}

		}

		int indexCount = Faces.size() * 3;
		indices = new unsigned long[indexCount];
		int indicie = 0;
		for (unsigned int i = 0; i < Faces.size(); ++i) {
			indices[indicie++] = Faces[i].indices[2];
			indices[indicie++] = Faces[i].indices[1];
			indices[indicie++] = Faces[i].indices[0];
		}
		Faces.clear();

Perhaps the indices aren't really well. I believe I switched the order of how the indices are drawn for some reason but can't remember why because I moved on to MD5 mesh and MD5 animation loading. However, unhappy with loading MD5 and want to continue looking into how I can correct the FBX mesh's texture coordiants.

 

I'll also look at the viewScene sample that came with the SDK as well in the meantime.

Attached Thumbnails

  • FBXMeshTextureCoordsNotRight.PNG

Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


Sponsor:

#2 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 12:16 PM

Also I provided some visual debugging for the UV Textures in the shader.  The incorrect one is the first one. The corrected UV are in my own model file format.

 

It appears to me I have the UV's reversed and the coloration in black is where the UV coords are messed up representing 0.0f perhaps?

Attached Thumbnails

  • InCoorectUVMappinginFBX.PNG
  • CorrectUVCoordsInSGMFOrmat.PNG

Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#3 cgrant   Members   -  Reputation: 1071

Like
2Likes
Like

Posted 06 May 2014 - 12:58 PM

Since you have access to the texture coordinate CPU side, break into the code or print the uv values while the model is being loaded to verify that they are on par with your loader. I've seen cases with 3DS Max, where the sign of the texture coordinate is flip due to wrapping...



#4 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 01:07 PM

Since you have access to the texture coordinate CPU side, break into the code or print the uv values while the model is being loaded to verify that they are on par with your loader. I've seen cases with 3DS Max, where the sign of the texture coordinate is flip due to wrapping...

 Alright, I'm tweaking the code now to see if I see anything different. If not then I'll output to file.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#5 Scott Bruno   Members   -  Reputation: 199

Like
1Likes
Like

Posted 06 May 2014 - 02:03 PM

Are you converting the uv origin? Your 3D package probably thinks the origin is the lower-left corner, whereas DX puts the origin at the upper-left corner:

for( auto& vertex : mesh.vertex_buffer )
{
     // other xforms...

     if( gSettings.FlipTexV )
     {
          vertex.texcoord.y = 1.0f - vertex.texcoord.y;
     }
}

And here's how I extract the uv from FBX:

                        //---------------------------------------------------------
			// uv
			//---------------------------------------------------------
			FbxVector2 uv;
			FbxGeometryElementUV* leUV = mpMesh->GetElementUV( 0 );
			if( leUV == nullptr )
			{
				ERRPRINT( "No UV layers in mesh. Aborting." );
				return false;
			}
			else
			{
				switch( leUV->GetMappingMode() )
				{
					case FbxGeometryElement::eByControlPoint:
					{
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							uv = leUV->GetDirectArray().GetAt( cp_index );
							break;
							case FbxGeometryElement::eIndexToDirect:
							{
								int id = leUV->GetIndexArray().GetAt( cp_index );
								uv = leUV->GetDirectArray().GetAt( id );
							}
							break;
							default:
								break;
						}
					}
					break;

					case FbxGeometryElement::eByPolygonVertex:
					{
						int lTextureUVIndex = mpMesh->GetTextureUVIndex( i, j );
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							case FbxGeometryElement::eIndexToDirect:
							{
								uv = leUV->GetDirectArray().GetAt( lTextureUVIndex );
							}
							break;
							default:
								break;
						}
					}
					default:
						break;
				}
				vertex.texcoord = Vec2FromFbx( &uv );
			}


#6 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 04:51 PM

 

Are you converting the uv origin? Your 3D package probably thinks the origin is the lower-left corner, whereas DX puts the origin at the upper-left corner:

for( auto& vertex : mesh.vertex_buffer )
{
     // other xforms...

     if( gSettings.FlipTexV )
     {
          vertex.texcoord.y = 1.0f - vertex.texcoord.y;
     }
}

And here's how I extract the uv from FBX:

                        //---------------------------------------------------------
			// uv
			//---------------------------------------------------------
			FbxVector2 uv;
			FbxGeometryElementUV* leUV = mpMesh->GetElementUV( 0 );
			if( leUV == nullptr )
			{
				ERRPRINT( "No UV layers in mesh. Aborting." );
				return false;
			}
			else
			{
				switch( leUV->GetMappingMode() )
				{
					case FbxGeometryElement::eByControlPoint:
					{
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							uv = leUV->GetDirectArray().GetAt( cp_index );
							break;
							case FbxGeometryElement::eIndexToDirect:
							{
								int id = leUV->GetIndexArray().GetAt( cp_index );
								uv = leUV->GetDirectArray().GetAt( id );
							}
							break;
							default:
								break;
						}
					}
					break;

					case FbxGeometryElement::eByPolygonVertex:
					{
						int lTextureUVIndex = mpMesh->GetTextureUVIndex( i, j );
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							case FbxGeometryElement::eIndexToDirect:
							{
								uv = leUV->GetDirectArray().GetAt( lTextureUVIndex );
							}
							break;
							default:
								break;
						}
					}
					default:
						break;
				}
				vertex.texcoord = Vec2FromFbx( &uv );
			}

I'll give it a shot - as far as origion. I did flip the V to 1.0f - texcoord.mData[1]

 

I'll try out your code in a bit and I'll let you know what's up. Why are FBX so hard to work with or is the lack of tutorials?


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#7 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 04:53 PM

I have the Max 3DS SDK and I'm dying to know how to create export my own custom file format and put together what I desire. However, that's for another thread. I'll let you know what's going on and take more debug shots if needed, Scott.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#8 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 05:35 PM

Interestingly enough, I am able to write out the uV and I checked them with copy of the FBX as FBX ASCII file. Here's the UV in a text document the program wrote out:

0.709074,0.551956
0.709074,0.551956
0.709074,1
1,0.551956
0.418147,0.551956
0.418147,0.551956
0.418147,1
0.709074,0.551956

And here's the section where the UVS are in the mesh file:

LayerElementUV: 0 {
			Version: 101
			Name: "UVChannel_1"
			MappingInformationType: "ByPolygonVertex"
			ReferenceInformationType: "IndexToDirect"
			UV: *48 {
				a: 0.418147087097168,0,0.418147087097168,0.448043644428253,0,0.448043644428253,0,0,0.418147087097168,0.896087288856506,0,0.896087288856506,0,0.448043644428253,0.418147087097168,0.448043644428253,0.999999940395355,0,0.999999940395355,0.418147087097168,0.709073543548584,0.418147087097168,0.709073543548584,0,0.709073543548584,0.448043644428253,0.709073543548584,0.896087288856506,0.418147087097168,0.896087288856506,0.418147087097168,0.448043644428253,0.999999940395355,0.448043644428253,0.999999940395355,0.866190731525421,0.709073543548584,0.866190731525421,0.709073543548584,0.448043644428253,0.709073543548584,0,0.709073543548584,0.448043644428253,0.418147087097168,0.448043644428253,0.418147087097168,0
			} 
			UVIndex: *36 {
				a: 3,0,2,0,1,2,6,7,4,6,4,5,10,11,8,10,8,9,14,15,12,14,12,13,18,19,16,18,16,17,22,23,20,22,20,21
			} 
		}

Yeah, I have the V flipped. Maybe it's a index things?

 

I did what Scott said and checked the code to this: I'm confused on the whole cp_index though does he mean index what I have in my previous code?

FbxGeometryElementUV *uv = meshArray[j]->GetElementUV(0);
					if (uv == nullptr){
						//no texture uv detected.
						MessageBox(0, L"No UVs.", L"", 0);
						return false;
					}
					else {
						switch (uv->GetMappingMode())
						{
						case FbxGeometryElement::eByControlPoint:
						{
							switch (uv->GetReferenceMode())
							{
							case FbxGeometryElement::eDirect:
								fbxUV = uv->GetDirectArray().GetAt(index);
								
								break;
							case FbxGeometryElement::eIndexToDirect:{
								int id = uv->GetIndexArray().GetAt(index);
								fbxUV = uv->GetDirectArray().GetAt(id);

							}
								break;

							default:
								break;
							}
						}
							break;

						case FbxGeometryElement::eByPolygonVertex:
						{
							int lTextureUVIndex = meshArray[j]->GetTextureUVIndex(i, k);
							switch (uv->GetReferenceMode())
							{
							case FbxGeometryElement::eDirect:
								break;
							case FbxGeometryElement::eIndexToDirect: {
								fbxUV = uv->GetDirectArray().GetAt(lTextureUVIndex);

							} break;

							}

						}
						default:
							break;
						}
					}
					m_vertices[index].texture = XMFLOAT2(fbxUV.mData[0], 1.0f - fbxUV.mData[1]);

				}
				Faces.push_back(face);

			}

		}

		int indexCount = Faces.size() * 3;
		indices = new unsigned long[indexCount];
		int indicie = 0;
		for (unsigned int i = 0; i < Faces.size(); ++i) {
			indices[indicie++] = Faces[i].indices[2];
			indices[indicie++] = Faces[i].indices[1];
			indices[indicie++] = Faces[i].indices[0];
		}
		Faces.clear();

It's a possible indexing issue, yes?


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#9 Scott Bruno   Members   -  Reputation: 199

Like
1Likes
Like

Posted 06 May 2014 - 06:30 PM

Apologies; the cp_index is part of the overall loop of how I extract the data. I only posted the UV snippet above. Here's the whole thing for how I extract the vertex data and the subset of material properties I care about:

// This is where things start to get nasty...

bool Import_FBX::ExtractGeometry()
{
	// control points
	uint32 countCP = mpMesh->GetControlPointsCount();
	control_points.reserve( countCP );
	FbxVector4* ControlPoints = mpMesh->GetControlPoints();

	for( uint32 i = 0; i < countCP; i++ )
	{
		control_points.push_back( Vec3FromFbx( &ControlPoints[i] ) );
	}

	// polygons
	uint32 countPolys = mpMesh->GetPolygonCount();
	polygons.reserve( countPolys );

	int vertexID = 0;
	for( uint32 i = 0; i < countPolys; i++ )
	{
		xPolygon polygon;

		uint32 countPolyVerts = mpMesh->GetPolygonSize( i );
		if( countPolyVerts < 3 || countPolyVerts > 4 ) // only tris and quads for now
		{
			ERRPRINT("Found poly (index %d) with unsupported vertex count: %d", i, countPolyVerts);
			return false;
		}
		for( uint32 j = 0; j < countPolyVerts; j++ )
		{
			vertex_type vertex;

			//---------------------------------------------------------
			// position
			//---------------------------------------------------------
			int cp_index = mpMesh->GetPolygonVertex( i, j );
			FbxVector4 cp = ControlPoints[cp_index];
			vertex.position = Vec3FromFbx( &cp );


			//---------------------------------------------------------
			// normal
			//---------------------------------------------------------
			FbxVector4 fbxNormal;
			FbxGeometryElementNormal* leNormal = mpMesh->GetElementNormal( 0 );
			if( leNormal == nullptr )
			{
//				ERRPRINT("No normals in mesh");
			}
			else
			{
				FbxLayerElement::EMappingMode normals_MapMode = leNormal->GetMappingMode();
				if( normals_MapMode == FbxGeometryElement::eByPolygonVertex )
				{
					switch( leNormal->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxNormal = leNormal->GetDirectArray().GetAt( vertexID );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leNormal->GetIndexArray().GetAt( vertexID );
						fbxNormal = leNormal->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				else if( normals_MapMode == FbxGeometryElement::eByControlPoint )
				{
					switch( leNormal->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxNormal = leNormal->GetDirectArray().GetAt( cp_index );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leNormal->GetIndexArray().GetAt( cp_index );
						fbxNormal = leNormal->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				vertex.normal = Vec3FromFbx( &fbxNormal );
			}

			//---------------------------------------------------------
			// tangent
			//---------------------------------------------------------
			FbxVector4 fbxTangent;
			FbxGeometryElementTangent* leTangent = mpMesh->GetElementTangent( 0 );
			if( leTangent == nullptr )
			{
//				ERRPRINT("No tangents in mesh");
			}
			else
			{
				FbxLayerElement::EMappingMode tangent_MapMode = leTangent->GetMappingMode();
				if( tangent_MapMode == FbxGeometryElement::eByPolygonVertex )
				{
					switch( leTangent->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxTangent = leTangent->GetDirectArray().GetAt( vertexID );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leTangent->GetIndexArray().GetAt( vertexID );
						fbxTangent = leTangent->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				else if( tangent_MapMode == FbxGeometryElement::eByControlPoint )
				{
					switch( leTangent->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxTangent = leTangent->GetDirectArray().GetAt( cp_index );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leTangent->GetIndexArray().GetAt( cp_index );
						fbxTangent = leTangent->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				vertex.tangent = Vec3FromFbx( &fbxTangent );
			}



			//---------------------------------------------------------
			// binormal
			//---------------------------------------------------------
			FbxVector4 fbxBinormal;
			FbxGeometryElementBinormal* leBinormal = mpMesh->GetElementBinormal( 0 );
			if( leBinormal == nullptr )
			{
//				ERRPRINT( "No binormals in mesh" );
			}
			else
			{
				FbxLayerElement::EMappingMode binormal_MapMode = leTangent->GetMappingMode();
				if( binormal_MapMode == FbxGeometryElement::eByPolygonVertex )
				{
					switch( leBinormal->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxBinormal = leBinormal->GetDirectArray().GetAt( vertexID );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leBinormal->GetIndexArray().GetAt( vertexID );
						fbxBinormal = leBinormal->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				else if( binormal_MapMode == FbxGeometryElement::eByControlPoint )
				{
					switch( leBinormal->GetReferenceMode() )
					{
					case FbxGeometryElement::eDirect:
						fbxBinormal = leBinormal->GetDirectArray().GetAt( cp_index );
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leBinormal->GetIndexArray().GetAt( cp_index );
						fbxBinormal = leBinormal->GetDirectArray().GetAt( id );
					}
						break;
					default:
						break;
					}
				}
				vertex.binormal = Vec3FromFbx( &fbxBinormal );
			}



			//---------------------------------------------------------
			// uv
			//---------------------------------------------------------
			FbxVector2 uv;
			FbxGeometryElementUV* leUV = mpMesh->GetElementUV( 0 );
			if( leUV == nullptr )
			{
				ERRPRINT( "No UV layers in mesh. Aborting." );
				return false;
			}
			else
			{
				switch( leUV->GetMappingMode() )
				{
					case FbxGeometryElement::eByControlPoint:
					{
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							uv = leUV->GetDirectArray().GetAt( cp_index );
							break;
							case FbxGeometryElement::eIndexToDirect:
							{
								int id = leUV->GetIndexArray().GetAt( cp_index );
								uv = leUV->GetDirectArray().GetAt( id );
							}
							break;
							default:
								break;
						}
					}
					break;

					case FbxGeometryElement::eByPolygonVertex:
					{
						int lTextureUVIndex = mpMesh->GetTextureUVIndex( i, j );
						switch( leUV->GetReferenceMode() )
						{
							case FbxGeometryElement::eDirect:
							case FbxGeometryElement::eIndexToDirect:
							{
								uv = leUV->GetDirectArray().GetAt( lTextureUVIndex );
							}
							break;
							default:
								break; 
						}
					}
					default:
						break;
				}
				vertex.texcoord = Vec2FromFbx( &uv );
			}
			polygon.vertices.push_back( vertex );
			++vertexID;
		}

		polygon.vertex_count = polygon.vertices.size();
		polygons.push_back( polygon );
	}
	return true;
}

bool Import_FBX::ExtractMaterials()
{
	//------------------------------------------------------------
	// Initialize material list and get material index per polygon
	//------------------------------------------------------------
	int lMtrlCount = mpNode->GetMaterialCount();
	for( int i = 0; i < lMtrlCount; i++ )
	{
		SerializedMaterial m;
		m.id = i;
		materials.push_back( m );
	}
	for( int l = 0; l < mpMesh->GetElementMaterialCount(); l++ )
	{
		FbxGeometryElementMaterial* leMat = mpMesh->GetElementMaterial( l );
		if( leMat != nullptr )
		{
			if( leMat->GetReferenceMode() == FbxGeometryElement::eIndex || leMat->GetReferenceMode() == FbxGeometryElement::eIndexToDirect )
			{
				int lIndexArrayCount = leMat->GetIndexArray().GetCount();
				for( int i = 0; i < lIndexArrayCount; i++ )
				{
					polygons[i].material_id = leMat->GetIndexArray().GetAt( i );
				}
			}
		}
	}

	//----------------------------------------------------------------
	// From each material extract the diffuse texture and uv repeat
	// The rest of the maps and properties will be set in our own tool
	//----------------------------------------------------------------
	int lMaterialIndex;
    FbxProperty lProperty;
	int lNbMat = mpNode->GetSrcObjectCount<FbxSurfaceMaterial>();
	for( lMaterialIndex = 0; lMaterialIndex < lNbMat; lMaterialIndex++ )
	{
		FbxSurfaceMaterial *lMaterial = mpNode->GetSrcObject<FbxSurfaceMaterial>( lMaterialIndex );
		if( lMaterial != nullptr )
		{
			SerializedMaterial& material = materials[lMaterialIndex];
			strcpy( material.tex_0, "default.dds" );
			material.texture_flags |= tex_Diffuse;

			lProperty = lMaterial->FindProperty( FbxLayerElement::sTextureChannelNames[0] );
			cstring propertyName = lProperty.GetNameAsCStr();
			propertyName.makeLower();
			if( propertyName == "diffusecolor" )
			{
				FbxTexture* lTexture = lProperty.GetSrcObject<FbxTexture>( 0 );
				if( lTexture )
				{
					FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>( lTexture );
					if( lFileTexture != nullptr )
					{
						//TODO: Revisit when archives are reworked
						cstring texname1 = lFileTexture->GetRelativeFileName();
						cstring texname2 = lFileTexture->GetFileName();

						strcpy( material.tex_0, texname1.c_str() );
						material.map_scales.x = static_cast<float>( lFileTexture->GetScaleU() );
						material.map_scales.y = static_cast<float>( lFileTexture->GetScaleV() );
					}
				}
			}
		}
	}
}

xPolygon is just a simple struct that contains the vertex array for that poly and some helper functions for calculating tangents, centroid; stuff like that. Basically I extract the FBX into my own list of polys, do whatever processing I want on them, and then create the per-material submeshes I'll write out to the model format, from that list of polys.


Edited by Scott Bruno, 06 May 2014 - 07:10 PM.


#10 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 06 May 2014 - 09:13 PM

I'll have to check out your code. Of what I've understand is that you get the control points which are the vertices inside the mesh. You get the total, reserve a vector or some type of stl container then stuff the control points inside that container. When down to the nitty gritty of getting the polygon count size whether the mesh is quad or triangulated. The local variable index or cp_index which is where the index of the vertice's (control points) are...Responsible of getting the normals, bitangents, texture uv's. So, polygon is indices in FBX terms, right? so for instance myMesh->GetPolygonSize() would return the number of indices or would it be more myMesh->GetPolygonVertexCount() to receive indice count or the number of polygons inside the mesh?

 

I think control points and polygons are tripping me a bit because to me loading a simple box FBX mesh isn't like loading a OBJ file. I understand it's composed of vertices, normals, tangents, bitangents and uv maps as in every model format kind of similar does. Tangents and bitangents have to be calculated when loading OBJ files.

 

Anyways, I'm going to have a look at your code - my brain has to cool down from storing a lot new information.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#11 L. Spiro   Crossbones+   -  Reputation: 20761

Like
2Likes
Like

Posted 07 May 2014 - 03:58 AM

Of what I've understand is that you get the control points which are the vertices inside the mesh.

Yes. Control points = vertices.

So, polygon is indices in FBX terms, right?

No, they are faces (see below).

When down to the nitty gritty of getting the polygon count size whether the mesh is quad or triangulated.

Meshes are always stored as an array of faces and these faces are stored as triangle fans. These need to be triangulated, stored, and reduced (eliminate duplicates) manually.
For each face you have 1 triangle fan with any number of triangles in it. Converting a triangle fan into a triangle list is trivial.



GetPolygonCount() returns the number of faces.
Here is a sample from my book that shows how to loop over each face in the mesh and get the start and total of each.

We now have something to use with an std::map to sort faces and their vertices on a per-material basis. Next, inside of CMesh::LoadMesh(), we declare the map as a local and begin to go over the faces of the mesh. Each face represents a triangle fan, but if we kept them in this format we would have to issue one draw call for each face, with each draw call rendering only a few triangles. We want to pack as many triangles into each draw call as we can, so we convert each face into a triangle list so that many faces can be packed into a single vertex buffer and drawn at once. The Autodesk® FBX® SDK refers to faces as polygons (which is not uncommon) and each polygon/face has a starting index (into a pool of polygon/face indices stored by the mesh) and number of consecutive indices that belong to that polygon/face. The skeleton of our loop over the faces is added to the end of CMesh::LoadMesh().
Listing 15-17 FCMesh.cpp

    // #include <map> added to the header.
    std::map<FC_MATERIAL_KEY, FC_FACE_VERTEX_PAIR> mBuckets;
    std::vector<FC_FACE::FC_FACE_VERTEX> vVertexPool;
    u32 ui32FaceCount = m_pfmMesh->GetPolygonCount();	
    for ( u32 I = 0; I < ui32FaceCount; ++I ) {
        u32 ui32PolyTotal = m_pfmMesh->GetPolygonSize( I );
        u32 ui32PolyStart = m_pfmMesh->GetPolygonVertexIndex( I );
    }	



The only hard part is how you have to index into the pools of normals, UV’s, colors, etc., as there are 2 possible indices you can use (the index of the control point directly or the result of indexing the control point index into another array) and once you have that index you use it to either directly index into the pool or once again get an intermediate pool index.

In Scott Bruno’s code, the if checks (“normals_MapMode == FbxGeometryElement::eByPolygonVertex” and “normals_MapMode == FbxGeometryElement::eByControlPoint”) determine which index you are supposed to use (notice the use of vertexID in one case and cp_index in the other) and then the switch cases on leNormal->GetReferenceMode() determine how to use that index (directly into the pool or into a pool of indices and then into the pool).



These are basically the most confusing points in the FBX SDK, until you get to animation blend weights and indices and building a proper local matrix for all the meshes.
Point of advice: Don’t just export only the meshes but the whole hierarchy. This has nothing to do with the FBX® SDK, but any 3D file format you make period. It is the only way to ensure animations run both properly and efficiently. Ignore “unwanted” data such as group nodes at your own risk.


L. Spiro

#12 SIC Games   Members   -  Reputation: 771

Like
0Likes
Like

Posted 07 May 2014 - 08:32 AM

Thanks again everyone. I'll let everyone know how it goes.Meantime, I'll be looking up the samples inside the FBX SDK. I'll be interested in your book L. Spiro when will it be released or has it been released already?


Game Engine's WIP Videos - http://www.youtube.com/sicgames88

SIC Games @ GitHub - https://github.com/SICGames?tab=repositories

Simple D2D1 Font Wrapper for D3D11 - https://github.com/SICGames/D2DFontX


#13 L. Spiro   Crossbones+   -  Reputation: 20761

Like
0Likes
Like

Posted 07 May 2014 - 08:32 AM

Should be later this year.


L. Spiro




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS