Exemple #1
0
FbxVector4 FBXScene::GetTangent(FbxMesh* pFBXMesh, int nLayerIndex, int nPolygonIndex, int nPolygonVertexIndex, int nVertexIndex)
{
	FbxVector4 vTangent(0,0,0,0);
	int nLayerCount = pFBXMesh->GetLayerCount();
	if( nLayerIndex < nLayerCount )//for( int i = 0; i < nLayerCount; ++i )
	{
		FbxLayer* pFBXLayer = pFBXMesh->GetLayer(nLayerIndex);

		if( pFBXLayer )
		{
			FbxLayerElementTangent* pTangents = pFBXLayer->GetTangents();

			if( pTangents )
			{
				const FbxLayerElementArrayTemplate<FbxVector4>& pTangentArray = pTangents->GetDirectArray();

				if( nVertexIndex < pTangentArray.GetCount() )
				{
					
					vTangent = pTangentArray.GetAt(nVertexIndex);
					vTangent.Normalize();
				}
			}
		}

	}
	return vTangent;
}
Exemple #2
0
void Model::processMeshTextCoords(FbxMesh *mesh, Vertex *verts, int numVerts)
{
	int matCount = mesh->GetElementMaterialCount();
	FbxLayerElementMaterial *matElem = NULL;
	if (matCount) //only supporting 1 material layer max
		matElem = mesh->GetElementMaterial(0);
	int polCount = mesh->GetPolygonCount();
	for (int polInd = 0; polInd < polCount; polInd++)
	{
		int textureId = 0;
		if (matElem)
		{
			textureId = matElem->GetIndexArray().GetAt(polInd);
		}
		for (unsigned polVert = 0; polVert < 3; polVert++)
		{
			int cornerIndex = mesh->GetPolygonVertex(polInd, polVert);
			FbxVector2 UV = FbxVector2(0, 0);
			FbxLayer *layer = mesh->GetLayer(0);
			FbxLayerElementUV *layerUV = layer->GetUVs();
			FbxLayerElementTexture *layerTexture = layer->GetTextures(FbxLayerElement::eTextureDiffuse);
			if (layerUV)
			{
				int UVindex = 0;
				switch (layerUV->GetMappingMode())
				{
				case FbxLayerElement::eByControlPoint:
					UVindex = cornerIndex;
					break;
				case FbxLayerElement::eByPolygonVertex:
					UVindex = mesh->GetTextureUVIndex(polInd, polVert, FbxLayerElement::eTextureDiffuse);
					break;
				case FbxLayerElement::eByPolygon:
					UVindex = polInd;
					break;
				}

				UV = layerUV->GetDirectArray().GetAt(UVindex);
				verts[cornerIndex].color.x = textureId;
				verts[cornerIndex].texture.x = UV[0];
				verts[cornerIndex].texture.y = 1.f - UV[1];
			}
		}
	}
}
Exemple #3
0
FbxVector4 FBXScene::GetNormal(FbxMesh* pFBXMesh, int nLayerIndex, int nPolygonIndex, int nPolygonVertexIndex, int nVertexIndex)
{
	FbxVector4 vNormal(0, 0, 0, 0);
	int nLayerCount = pFBXMesh->GetLayerCount();
	if( nLayerIndex < nLayerCount )//for( int i = 0; i < nLayerCount; ++i )
	{
		FbxLayer* pFBXLayer = pFBXMesh->GetLayer(nLayerIndex);

		if( pFBXLayer )
		{
			FbxLayerElementNormal* pNormals = pFBXLayer->GetNormals();
		
			if( pNormals )
			{
				int nIdx = 0;
				if( pNormals->GetReferenceMode( ) == FbxLayerElement::EReferenceMode::eDirect )
				{
					nIdx = nVertexIndex;
				}

				if( pNormals->GetReferenceMode( ) == FbxLayerElement::EReferenceMode::eIndexToDirect )
				{
					nIdx = pNormals->GetIndexArray( ).GetAt( nVertexIndex );
				}

				const FbxLayerElementArrayTemplate<FbxVector4>& pNormalArray = pNormals->GetDirectArray();
				if( nIdx < pNormalArray.GetCount() )
				{					
					vNormal = pNormalArray.GetAt(nIdx);
					vNormal.Normalize();
				}
			}
		}

	}
	return vNormal;
}
Exemple #4
0
BTHFBX_VEC2 FBXScene::GetTexCoord(FbxMesh* pFBXMesh, int nLayerIndex, int nPolygonIndex, int nPolygonVertexIndex, int nVertexIndex)
{
	int nLayerCount = pFBXMesh->GetLayerCount();
	if( nLayerIndex < nLayerCount )//for( int i = 0; i < nLayerCount; ++i )
	{
		FbxLayer* pFBXLayer = pFBXMesh->GetLayer(nLayerIndex);

		if( pFBXLayer )
		{
			FbxLayerElementUV* pUVs = pFBXLayer->GetUVs(FbxLayerElement::EType::eTextureDiffuse);
			if( pUVs )
			{
				FbxLayerElement::EMappingMode mappingMode = pUVs->GetMappingMode();
				FbxLayerElement::EReferenceMode referenceMode = pUVs->GetReferenceMode();

				const FbxLayerElementArrayTemplate<FbxVector2>& pUVArray = pUVs->GetDirectArray();
				const FbxLayerElementArrayTemplate<int>& pUVIndexArray = pUVs->GetIndexArray();

				switch(mappingMode)
				{
					case FbxLayerElement::eByControlPoint:
					{
						int nMappingIndex = nVertexIndex;
						switch(referenceMode)
						{
							case FbxLayerElement::eDirect:
								if( nMappingIndex < pUVArray.GetCount() )
								{
									return FBXTexCoordToD3DTexCoord( KFbxVector2ToBTHFBX_VEC2( pUVArray.GetAt(nMappingIndex) ) );
								}
							break;
							case FbxLayerElement::eIndexToDirect:
								if( nMappingIndex < pUVIndexArray.GetCount() )
								{
									int nIndex = pUVIndexArray.GetAt(nMappingIndex);
									if( nIndex < pUVArray.GetCount() )
									{
										return FBXTexCoordToD3DTexCoord( KFbxVector2ToBTHFBX_VEC2( pUVArray.GetAt(nIndex) ) );
									}
								}
							break;
						};
					}
					break;

					case FbxLayerElement::eByPolygonVertex:
					{
						int nMappingIndex = pFBXMesh->GetTextureUVIndex(nPolygonIndex, nPolygonVertexIndex, FbxLayerElement::eTextureDiffuse);
						switch(referenceMode)
						{
						case FbxLayerElement::EReferenceMode::eDirect:
						case FbxLayerElement::EReferenceMode::eIndexToDirect: //I have no idea why the index array is not used in this case.
							if( nMappingIndex < pUVArray.GetCount() )
							{
								return FBXTexCoordToD3DTexCoord( KFbxVector2ToBTHFBX_VEC2( pUVArray.GetAt(nMappingIndex) ) );
							}
						break;
						};
					}
					break;
				};
			}
		}
	}
	return BTHFBX_VEC2();
}
/**
 * Adds an Fbx Mesh to the FBX scene based on the data in the given FStaticLODModel
 */
FbxNode* FFbxExporter::CreateMesh(const USkeletalMesh* SkelMesh, const TCHAR* MeshName)
{
	const FSkeletalMeshResource* SkelMeshResource = SkelMesh->GetImportedResource();
	const FStaticLODModel& SourceModel = SkelMeshResource->LODModels[0];
	const int32 VertexCount = SourceModel.NumVertices;

	// Verify the integrity of the mesh.
	if (VertexCount == 0) return NULL;

	// Copy all the vertex data from the various chunks to a single buffer.
	// Makes the rest of the code in this function cleaner and easier to maintain.  
	TArray<FSoftSkinVertex> Vertices;
	SourceModel.GetVertices(Vertices);
	if (Vertices.Num() != VertexCount) return NULL;

	FbxMesh* Mesh = FbxMesh::Create(Scene, TCHAR_TO_UTF8(MeshName));

	// Create and fill in the vertex position data source.
	Mesh->InitControlPoints(VertexCount);
	FbxVector4* ControlPoints = Mesh->GetControlPoints();
	for (int32 VertIndex = 0; VertIndex < VertexCount; ++VertIndex)
	{
		FVector Position			= Vertices[VertIndex].Position;
		ControlPoints[VertIndex]	= Converter.ConvertToFbxPos(Position);
	}

	// Create Layer 0 to hold the normals
	FbxLayer* LayerZero = Mesh->GetLayer(0);
	if (LayerZero == NULL)
	{
		Mesh->CreateLayer();
		LayerZero = Mesh->GetLayer(0);
	}

	// Create and fill in the per-face-vertex normal data source.
	// We extract the Z-tangent and drop the X/Y-tangents which are also stored in the render mesh.
	FbxLayerElementNormal* LayerElementNormal= FbxLayerElementNormal::Create(Mesh, "");

	LayerElementNormal->SetMappingMode(FbxLayerElement::eByControlPoint);
	// Set the normal values for every control point.
	LayerElementNormal->SetReferenceMode(FbxLayerElement::eDirect);

	for (int32 VertIndex = 0; VertIndex < VertexCount; ++VertIndex)
	{
		FVector Normal			= Vertices[VertIndex].TangentZ;
		FbxVector4 FbxNormal	= Converter.ConvertToFbxPos(Normal);

		LayerElementNormal->GetDirectArray().Add(FbxNormal);
	}

	LayerZero->SetNormals(LayerElementNormal);


	// Create and fill in the per-face-vertex texture coordinate data source(s).
	// Create UV for Diffuse channel.
	const int32 TexCoordSourceCount = SourceModel.NumTexCoords;
	TCHAR UVChannelName[32];
	for (int32 TexCoordSourceIndex = 0; TexCoordSourceIndex < TexCoordSourceCount; ++TexCoordSourceIndex)
	{
		FbxLayer* Layer = Mesh->GetLayer(TexCoordSourceIndex);
		if (Layer == NULL)
		{
			Mesh->CreateLayer();
			Layer = Mesh->GetLayer(TexCoordSourceIndex);
		}

		if (TexCoordSourceIndex == 1)
		{
			FCString::Sprintf(UVChannelName, TEXT("LightMapUV"));
		}
		else
		{
			FCString::Sprintf(UVChannelName, TEXT("DiffuseUV"));
		}

		FbxLayerElementUV* UVDiffuseLayer = FbxLayerElementUV::Create(Mesh, TCHAR_TO_UTF8(UVChannelName));
		UVDiffuseLayer->SetMappingMode(FbxLayerElement::eByControlPoint);
		UVDiffuseLayer->SetReferenceMode(FbxLayerElement::eDirect);

		// Create the texture coordinate data source.
		for (int32 TexCoordIndex = 0; TexCoordIndex < VertexCount; ++TexCoordIndex)
		{
			const FVector2D& TexCoord = Vertices[TexCoordIndex].UVs[TexCoordSourceIndex];
			UVDiffuseLayer->GetDirectArray().Add(FbxVector2(TexCoord.X, -TexCoord.Y + 1.0));
		}

		Layer->SetUVs(UVDiffuseLayer, FbxLayerElement::eTextureDiffuse);
	}

	FbxLayerElementMaterial* MatLayer = FbxLayerElementMaterial::Create(Mesh, "");
	MatLayer->SetMappingMode(FbxLayerElement::eByPolygon);
	MatLayer->SetReferenceMode(FbxLayerElement::eIndexToDirect);
	LayerZero->SetMaterials(MatLayer);


	// Create the per-material polygons sets.
	TArray<uint32> Indices;
	SourceModel.MultiSizeIndexContainer.GetIndexBuffer(Indices);

	int32 SectionCount = SourceModel.Sections.Num();
	for (int32 SectionIndex = 0; SectionIndex < SectionCount; ++SectionIndex)
	{
		const FSkelMeshSection& Section = SourceModel.Sections[SectionIndex];

		int32 MatIndex = Section.MaterialIndex;

		// Static meshes contain one triangle list per element.
		int32 TriangleCount = Section.NumTriangles;

		// Copy over the index buffer into the FBX polygons set.
		for (int32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
		{
			Mesh->BeginPolygon(MatIndex);
			for (int32 PointIndex = 0; PointIndex < 3; PointIndex++)
			{
				Mesh->AddPolygon(Indices[Section.BaseIndex + ((TriangleIndex * 3) + PointIndex)]);
			}
			Mesh->EndPolygon();
		}
	}

	// Create and fill in the vertex color data source.
	FbxLayerElementVertexColor* VertexColor = FbxLayerElementVertexColor::Create(Mesh, "");
	VertexColor->SetMappingMode(FbxLayerElement::eByControlPoint);
	VertexColor->SetReferenceMode(FbxLayerElement::eDirect);
	FbxLayerElementArrayTemplate<FbxColor>& VertexColorArray = VertexColor->GetDirectArray();
	LayerZero->SetVertexColors(VertexColor);

	for (int32 VertIndex = 0; VertIndex < VertexCount; ++VertIndex)
	{
		FLinearColor VertColor = Vertices[VertIndex].Color.ReinterpretAsLinear();
		VertexColorArray.Add( FbxColor(VertColor.R, VertColor.G, VertColor.B, VertColor.A ));
	}

	FbxNode* MeshNode = FbxNode::Create(Scene, TCHAR_TO_UTF8(MeshName));
	MeshNode->SetNodeAttribute(Mesh);



	// Add the materials for the mesh
	int32 MaterialCount = SkelMesh->Materials.Num();

	for(int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex)
	{
		UMaterialInterface* MatInterface = SkelMesh->Materials[MaterialIndex].MaterialInterface;

		FbxSurfaceMaterial* FbxMaterial = NULL;
		if(MatInterface && !FbxMaterials.Find(MatInterface))
		{
			FbxMaterial = ExportMaterial(MatInterface);
		}
		else
		{
			// Note: The vertex data relies on there being a set number of Materials.  
			// If you try to add the same material again it will not be added, so create a 
			// default material with a unique name to ensure the proper number of materials

			TCHAR NewMaterialName[MAX_SPRINTF]=TEXT("");
			FCString::Sprintf( NewMaterialName, TEXT("Fbx Default Material %i"), MaterialIndex );

			FbxMaterial = FbxSurfaceLambert::Create(Scene, TCHAR_TO_UTF8(NewMaterialName));
			((FbxSurfaceLambert*)FbxMaterial)->Diffuse.Set(FbxDouble3(0.72, 0.72, 0.72));
		}

		MeshNode->AddMaterial(FbxMaterial);
	}

	int32 SavedMaterialCount = MeshNode->GetMaterialCount();
	check(SavedMaterialCount == MaterialCount);

	return MeshNode;
}
Exemple #6
0
/**
 * メッシュ情報を読み込む
 *
 * @param mesh メッシュ情報
 */
void FbxFileLoader::load_mesh( FbxMesh* mesh )
{
	if ( ! mesh )
	{
		return;
	}

	if ( ! get_model()->get_mesh() )
	{
		get_model()->set_mesh( create_mesh() );
	}

	VertexIndexMap vertex_index_map;
	VertexList vertex_list;

	Mesh::PositionList position_list;
	Mesh::VertexWeightList vertex_weight_list;

	// load_mesh_vertex()
	for ( int n = 0; n < mesh->GetControlPointsCount(); n++ )
	{
		FbxVector4 v = mesh->GetControlPointAt( n );

		position_list.push_back(
			Mesh::Position(
				static_cast< float >( v[ 0 ] ),
				static_cast< float >( v[ 1 ] ),
				static_cast< float >( v[ 2 ] ) ) );
	}

	// load_mesh_vertex_weight()
	{
		int skin_count = mesh->GetDeformerCount( FbxDeformer::eSkin );

		if ( skin_count > 0 )
		{
			assert( skin_count == 1 );

			vertex_weight_list.resize( position_list.size() );

			FbxSkin* skin = FbxCast< FbxSkin >( mesh->GetDeformer( 0, FbxDeformer::eSkin ) );

			load_mesh_vertex_weight( skin, vertex_weight_list );
		}
	}

	FbxLayerElementSmoothing* smoothing = 0;

	// load_mesh_smoothing_info()
	{
		FbxLayer* layer = mesh->GetLayer( 0 );
		smoothing = layer->GetSmoothing();
	}

	if ( ! smoothing )
	{
		COMMON_THROW_EXCEPTION_MESSAGE( "this FBX format is not supported. ( no smoothing info )" );
	}

	// load_mesh_plygon()
	FbxLayerElementArrayTemplate< int >* material_indices;
	mesh->GetMaterialIndices( & material_indices );

	for ( int n = 0; n < mesh->GetPolygonCount(); n++ )
	{
		Mesh::VertexGroup* vertex_group = get_model()->get_mesh()->get_vertex_group_at( material_indices->GetAt( n ) );

		bool is_smooth = smoothing->GetDirectArray().GetAt( n ) != 0;
		FbxVector4 polygon_normal( 0.f, 0.f, 0.f );

		if ( ! is_smooth )
		{
			// ポリゴンの法線を計算する
			Mesh::Position p1( position_list.at( mesh->GetPolygonVertex( n, 0 ) ) );
			Mesh::Position p2( position_list.at( mesh->GetPolygonVertex( n, 1 ) ) );
			Mesh::Position p3( position_list.at( mesh->GetPolygonVertex( n, 2 ) ) );

			FbxVector4 a = FbxVector4( p1.x(), p1.y(), p1.z() );
			FbxVector4 b = FbxVector4( p2.x(), p2.y(), p2.z() );
			FbxVector4 c = FbxVector4( p3.x(), p3.y(), p3.z() );

			FbxVector4 ab( b - a );
			FbxVector4 bc( c - b );

			polygon_normal = ab.CrossProduct( bc );
			polygon_normal.Normalize();
		}

		for ( int m = 0; m < mesh->GetPolygonSize( n ); m++ )
		{
			int position_index = mesh->GetPolygonVertex( n, m );

			Mesh::Vertex v;
			v.Position = Mesh::Position( position_list.at( position_index ) );

			FbxVector2 uv_vector;
			bool unmapped;
			
			if ( mesh->GetPolygonVertexUV( n, m, "UVMap", uv_vector, unmapped) )
			{
				v.TexCoord = Mesh::TexCoord(
					static_cast< float >( uv_vector[ 0 ] ),
					1.f - static_cast< float >( uv_vector[ 1 ] ) );
			}

			if ( is_smooth )
			{
				FbxVector4 normal_vector;

				// 頂点の法線
				if ( mesh->GetPolygonVertexNormal( n, m, normal_vector ) )
				{
					v.Normal = Mesh::Normal(
						static_cast< float >( normal_vector[ 0 ] ),
						static_cast< float >( normal_vector[ 1 ] ),
						static_cast< float >( normal_vector[ 2 ] ) );
				}
			}
			else
			{
				// ポリゴンの法線
				v.Normal = Mesh::Normal(
					static_cast< float >( polygon_normal[ 0 ] ),
					static_cast< float >( polygon_normal[ 1 ] ),
					static_cast< float >( polygon_normal[ 2 ] ) );
			}
			
			// 頂点の一覧に追加
			{
				VertexIndexMap::iterator i = vertex_index_map.find( v );

				if ( i != vertex_index_map.end() )
				{
					vertex_group->add_index( i->second );
				}
				else
				{
					Mesh::Index vertex_index = static_cast< Mesh::Index >( get_model()->get_mesh()->get_vertex_count() );

					get_model()->get_mesh()->add_vertex( v );

					if ( ! vertex_weight_list.empty() )
					{
						get_model()->get_mesh()->add_vertex_weight( vertex_weight_list.at( position_index ) );
					}

					vertex_group->add_index( vertex_index );

					vertex_index_map[ v ] = vertex_index;
				}
			}
		}
	}
}
Exemple #7
0
	void FbxLoader::LoadAttribute(FbxNodeAttribute* pAttribute)
	{
		if (pAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
		{
			FbxMesh* pMesh = (FbxMesh*)pAttribute;

			FbxVector4* IControlPoints = pMesh->GetControlPoints();
			m_vertexCount = pMesh->GetControlPointsCount();
			m_vertexBuffer = new float[m_vertexCount * 4];
			for (int i = 0; i < m_vertexCount * 4; i+=4)
			{
				m_vertexBuffer[i]     = (float)IControlPoints[i / 4].mData[0];
				m_vertexBuffer[i + 1] = (float)IControlPoints[i / 4].mData[1];
				m_vertexBuffer[i + 2] = (float)IControlPoints[i / 4].mData[2];
				m_vertexBuffer[i + 3] = 1.0f;// IControlPoints[i / 4].mData[3];
			}

			int* pIndices = pMesh->GetPolygonVertices();
			m_indexCount = pMesh->GetPolygonVertexCount();
			m_indexBuffer = new uint32[m_indexCount];
			for (int i = 0; i < m_indexCount; ++i)
			{
				m_indexBuffer[i] = pIndices[i];
			}

			FbxLayer* pLayer = pMesh->GetLayer(0);
			if (pLayer != NULL)
			{
				FbxLayerElementNormal* pNormal = pLayer->GetNormals();
				m_normalCount = pNormal->mDirectArray->GetCount();
				m_normalBuffer = new float[m_normalCount * 3];
				for (int i = 0; i < m_normalCount * 3; i+=3)
				{
					m_normalBuffer[i]     = (float)(*pNormal->mDirectArray)[i / 3][0];
					m_normalBuffer[i + 1] = (float)(*pNormal->mDirectArray)[i / 3][1];
					m_normalBuffer[i + 2] = (float)(*pNormal->mDirectArray)[i / 3][2];
					//m_normalBuffer[i + 3] = (*pNormal->mDirectArray)[i / 4][3];
				}

				FbxLayerElementUV* pUV = pLayer->GetUVs();
				if (pUV->GetMappingMode() == FbxLayerElement::eByPolygonVertex)
				{
					if (pUV->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						m_uvCount = pUV->mIndexArray->GetCount();
						m_uvBuffer = new float[m_uvCount * 2];
						for (int i = 0; i < m_uvCount * 2; i+=2)
						{
							m_uvBuffer[i] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][0];
							m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][1];
						}
					}
					else
					{
						m_uvCount = pUV->mDirectArray->GetCount();
						m_uvBuffer = new float[m_uvCount * 2];
						for (int i = 0; i < m_uvCount * 2; i += 2)
						{
							m_uvBuffer[i] = (float)(*pUV->mDirectArray)[i / 2][0];
							m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[i / 2][1];
						}
					}
				}
				else
				{
					if (pUV->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						m_uvCount = pUV->mIndexArray->GetCount();
						m_uvBuffer = new float[m_uvCount * 2];
						for (int i = 0; i < m_uvCount * 2; i+=2)
						{
							m_uvBuffer[i] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][0];
							m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[(*pUV->mIndexArray)[i / 2]][1];
						}
					}
					else
					{
						m_uvCount = pUV->mDirectArray->GetCount();
						m_uvBuffer = new float[m_uvCount * 2];
						for (int i = 0; i < m_uvCount * 2; i+=2)
						{
							m_uvBuffer[i] = (float)(*pUV->mDirectArray)[i / 2][0];
							m_uvBuffer[i + 1] = (float)(*pUV->mDirectArray)[i / 2][1];
						}
					}
				}
			}
		}
	}