bCombineMeshes

bCombineMeshes

#Overview

name: bCombineMeshes

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 16 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of bCombineMeshes is to control whether multiple static meshes in an FBX file should be combined into a single monolithic mesh when importing into Unreal Engine.

This setting variable is primarily used in the Unreal Engine’s FBX import system, specifically for static mesh imports. It’s part of the UFbxStaticMeshImportData class, which is used to configure various aspects of static mesh imports from FBX files.

The Unreal Engine subsystems that rely on this variable include:

  1. The FBX import system in the UnrealEd module
  2. The Interchange Editor plugin, which is a newer asset import framework

The value of this variable is typically set in the FBX import UI or through import settings. It can be modified programmatically or through the editor interface when importing FBX files.

This variable interacts with other import settings, particularly:

Developers should be aware that:

  1. When true, it combines all meshes in the FBX into a single static mesh.
  2. It may be overridden if LOD groups are detected in the FBX file.
  3. It affects how the import process handles multiple meshes and LOD groups.

Best practices when using this variable:

  1. Use it when you want to consolidate multiple mesh parts into a single static mesh asset.
  2. Be cautious when using it with files that contain LOD groups, as it may lead to unexpected results.
  3. Consider the performance implications of combining many meshes versus keeping them separate.
  4. Always test the result after import to ensure the combined mesh meets your requirements.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEditorPerProjectUserSettings.ini:663, section: [/Script/UnrealEd.FbxStaticMeshImportData]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/Interchange/Editor/Source/InterchangeEditor/Private/InterchangeFbxAssetImportDataConverter.cpp:151

Scope (from outer to inner):

file
namespace    UE::Interchange::Private
function     void FillInterchangeGenericAssetsPipelineFromFbxStaticMeshImportData

Source code excerpt:

		GenericAssetPipeline->MeshPipeline->bBuildNanite = StaticMeshImportData->bBuildNanite;
		GenericAssetPipeline->MeshPipeline->bBuildReversedIndexBuffer = StaticMeshImportData->bBuildReversedIndexBuffer;
		GenericAssetPipeline->MeshPipeline->bCombineStaticMeshes = StaticMeshImportData->bCombineMeshes;
		GenericAssetPipeline->MeshPipeline->bGenerateLightmapUVs = StaticMeshImportData->bGenerateLightmapUVs;
		GenericAssetPipeline->MeshPipeline->bOneConvexHullPerUCX = StaticMeshImportData->bOneConvexHullPerUCX;
		GenericAssetPipeline->CommonMeshesProperties->bRemoveDegenerates = StaticMeshImportData->bRemoveDegenerates;
		GenericAssetPipeline->MeshPipeline->DistanceFieldResolutionScale = StaticMeshImportData->DistanceFieldResolutionScale;
		GenericAssetPipeline->MeshPipeline->LodGroup = StaticMeshImportData->StaticMeshLODGroup;
		if (StaticMeshImportData->VertexColorImportOption == EVertexColorImportOption::Ignore)

#Loc: <Workspace>/Engine/Plugins/Interchange/Editor/Source/InterchangeEditor/Private/InterchangeFbxAssetImportDataConverter.cpp:316

Scope (from outer to inner):

file
namespace    UE::Interchange::Private
function     UAssetImportData* ConvertToLegacyFbx

Source code excerpt:

				DestinationStaticMeshImportData->bBuildNanite = GenericAssetPipeline->MeshPipeline->bBuildNanite;
				DestinationStaticMeshImportData->bBuildReversedIndexBuffer = GenericAssetPipeline->MeshPipeline->bBuildReversedIndexBuffer;
				DestinationStaticMeshImportData->bCombineMeshes = GenericAssetPipeline->MeshPipeline->bCombineStaticMeshes;
				DestinationStaticMeshImportData->bGenerateLightmapUVs = GenericAssetPipeline->MeshPipeline->bGenerateLightmapUVs;
				DestinationStaticMeshImportData->bOneConvexHullPerUCX = GenericAssetPipeline->MeshPipeline->bOneConvexHullPerUCX;
				DestinationStaticMeshImportData->bRemoveDegenerates = GenericAssetPipeline->CommonMeshesProperties->bRemoveDegenerates;
				DestinationStaticMeshImportData->DistanceFieldResolutionScale = GenericAssetPipeline->MeshPipeline->DistanceFieldResolutionScale;
				DestinationStaticMeshImportData->StaticMeshLODGroup = GenericAssetPipeline->MeshPipeline->LodGroup;
				if (GenericAssetPipeline->CommonMeshesProperties->VertexColorImportOption == EInterchangeVertexColorImportOption::IVCIO_Ignore)

#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/FbxImportUIDetails.cpp:291

Scope (from outer to inner):

file
function     void FFbxImportUIDetails::CustomizeDetails
lambda-function

Source code excerpt:

				Property->GetFName() == GET_MEMBER_NAME_CHECKED(UFbxImportUI, bImportRigidMesh) ||
				Property->GetFName() == GET_MEMBER_NAME_CHECKED(UFbxSkeletalMeshImportData, bImportMeshesInBoneHierarchy) ||
				Property->GetFName() == GET_MEMBER_NAME_CHECKED(UFbxStaticMeshImportData, bCombineMeshes)
				)
			{
				AddRefreshCustomDetailEvent(Handle);
			}
		}
	};

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxStaticMeshImportData.h:54

Scope (from outer to inner):

file
class        class UFbxStaticMeshImportData : public UFbxMeshImportData

Source code excerpt:

	/** For static meshes, enabling this option will combine all meshes in the FBX into a single monolithic mesh in Unreal */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, config, Category = Mesh, meta = (ToolTip = "If enabled, combines all meshes into a single mesh", ImportType = "StaticMesh"))
	uint32 bCombineMeshes : 1;

	/**
	 * Scale to apply to the mesh when allocating the distance field volume texture.
	 * The default scale is 1, which is assuming that the mesh will be placed unscaled in the world.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, config, Category= Mesh, meta=(ImportType="StaticMesh"))

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Factories/EditorFactories.cpp:6112

Scope (from outer to inner):

file
function     EReimportResult::Type UReimportFbxStaticMeshFactory::Reimport

Source code excerpt:


	ReimportUI->MeshTypeToImport = FBXIT_StaticMesh;
	ReimportUI->StaticMeshImportData->bCombineMeshes = true;

	if (!ImportUI)
	{
		ImportUI = NewObject<UFbxImportUI>(this, NAME_None, RF_Public);
	}
	//Prevent any UI for automation, unattended and commandlet

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:432

Scope (from outer to inner):

file
function     UObject* UFbxFactory::FactoryCreateFile

Source code excerpt:


			bool bImportStaticMeshLODs = ImportUI->StaticMeshImportData->bImportMeshLODs;
			bool bCombineMeshes = ImportUI->StaticMeshImportData->bCombineMeshes;
			bool bCombineMeshesLOD = false;

			const bool bCanImportStaticMesh = FbxImporter->CanImportClass(UStaticMesh::StaticClass());
			//We can import skeletal mesh only if we can import skeleton or a skeleton was specified in the import options
			const bool bCanImportSkeletalMesh = FbxImporter->CanImportClass(USkeletalMesh::StaticClass()) && (ImportOptions->SkeletonForAnimation || FbxImporter->CanImportClass(USkeleton::StaticClass()));
			const bool bCanImportAnimSequence = FbxImporter->CanImportClass(UAnimSequence::StaticClass());

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:449

Scope (from outer to inner):

file
function     UObject* UFbxFactory::FactoryCreateFile

Source code excerpt:

				FbxImporter->ApplyTransformSettingsToFbxNode(RootNodeToImport, ImportUI->StaticMeshImportData);

				if( bCombineMeshes && !bImportStaticMeshLODs )
				{
					// If Combine meshes and dont import mesh LODs, the interesting node count should be 1 so all the meshes are grouped together into one static mesh
					InterestingNodeCount = 1;
				}
				else
				{
					// count meshes in lod groups if we dont care about importing LODs
					bool bCountLODGroupMeshes = !bImportStaticMeshLODs && bCombineMeshes;
					int32 NumLODGroups = 0;
					InterestingNodeCount = FbxImporter->GetFbxMeshCount(RootNodeToImport,bCountLODGroupMeshes,NumLODGroups);

					// if there were LODs in the file, do not combine meshes even if requested
					if( bImportStaticMeshLODs && bCombineMeshes && NumLODGroups > 0)
					{
						bCombineMeshes = false;
						//Combine all the LOD together and export one mesh with LODs
						bCombineMeshesLOD = true;
					}
				}
				//Find all collision models, even the one contain under a LOD Group
				FbxImporter->FillFbxCollisionMeshArray(RootNodeToImport);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:489

Scope (from outer to inner):

file
function     UObject* UFbxFactory::FactoryCreateFile

Source code excerpt:

				{
					UStaticMesh* NewStaticMesh = NULL;
					if (bCombineMeshes)
					{
						TArray<FbxNode*> FbxMeshArray;
						FbxImporter->FillFbxMeshArray(RootNodeToImport, FbxMeshArray, FbxImporter);
						if (FbxMeshArray.Num() > 0)
						{
							NewStaticMesh = FbxImporter->ImportStaticMeshAsSingle(InParent, FbxMeshArray, Name, Flags, ImportUI->StaticMeshImportData, NULL, 0, nullptr);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:601

Scope (from outer to inner):

file
function     UObject* UFbxFactory::FactoryCreateFile

Source code excerpt:

						}
					}
					else // !bCombineMeshes && !bCombineMeshesLOD
					{
						FFormatNamedArguments Args;
						Args.Add(TEXT("NodeIndex"), 1);
						Args.Add(TEXT("ArrayLength"), InterestingNodeCount);
						FScopedSlowTask ImportNodeSlowTask(InterestingNodeCount, GetImportTaskText(FText::Format(NSLOCTEXT("UnrealEd", "Importingf", "Importing ({NodeIndex} of {ArrayLength})"), Args)));
						ImportNodeSlowTask.MakeDialog(true);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:1597

Scope (from outer to inner):

file
namespace    ImportCompareHelper
function     void FillStaticMeshCompareData

Source code excerpt:

		TArray<FbxNode*> FbxMeshArray;
		bool bImportStaticMeshLODs = ImportUI->StaticMeshImportData->bImportMeshLODs;
		bool bCombineMeshes = ImportUI->StaticMeshImportData->bCombineMeshes;
		bool bCombineMeshesLOD = false;
		TArray<TArray<FbxNode*>> FbxMeshesLod;
		FbxNode* Node = nullptr;
		
		if (bCombineMeshes && !bImportStaticMeshLODs)
		{
			FFbxImporter->FillFbxMeshArray(FFbxImporter->Scene->GetRootNode(), FbxMeshArray, FFbxImporter);
		}
		else
		{
			// count meshes in lod groups if we dont care about importing LODs
			bool bCountLODGroupMeshes = !bImportStaticMeshLODs && bCombineMeshes;
			int32 NumLODGroups = 0;
			FFbxImporter->GetFbxMeshCount(FFbxImporter->Scene->GetRootNode(), bCountLODGroupMeshes, NumLODGroups);
			// if there were LODs in the file, do not combine meshes even if requested
			if (bImportStaticMeshLODs && bCombineMeshes && NumLODGroups > 0)
			{
				TArray<FbxNode*> FbxLodGroups;
				FFbxImporter->FillFbxMeshAndLODGroupArray(FFbxImporter->Scene->GetRootNode(), FbxLodGroups, FbxMeshArray);
				FbxMeshesLod.Add(FbxMeshArray);
				for (FbxNode* LODGroup : FbxLodGroups)
				{

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:1645

Scope (from outer to inner):

file
namespace    ImportCompareHelper
function     void FillStaticMeshCompareData

Source code excerpt:

				}
				bCombineMeshesLOD = true;
				bCombineMeshes = false;
				//Set the first LOD
				FbxMeshArray = FbxMeshesLod[0];
			}
			else
			{
				FFbxImporter->FillFbxMeshArray(FFbxImporter->Scene->GetRootNode(), FbxMeshArray, FFbxImporter);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxFactory.cpp:1661

Scope (from outer to inner):

file
namespace    ImportCompareHelper
function     void FillStaticMeshCompareData

Source code excerpt:

			Node = FbxMeshArray[0];
		}
		else if (!bCombineMeshes && !bCombineMeshesLOD)
		{
			Node = FFbxImporter->GetMeshNodesFromName(StaticMesh->GetName(), FbxMeshArray);
		}

		// If there is no match it may be because an LOD group was imported where
		// the mesh name does not match the file name. This is actually the common case.

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxMainImport.cpp:487

Scope (from outer to inner):

file
namespace    UnFbx
function     void ApplyImportUIToImportOptions

Source code excerpt:

	//Static mesh unshared options
	{
		InOutImportOptions.bCombineToSingle				= ImportUI->StaticMeshImportData->bCombineMeshes;
		InOutImportOptions.bRemoveDegenerates			= ImportUI->StaticMeshImportData->bRemoveDegenerates;
		InOutImportOptions.bBuildReversedIndexBuffer	= ImportUI->StaticMeshImportData->bBuildReversedIndexBuffer;
		InOutImportOptions.bGenerateLightmapUVs			= ImportUI->StaticMeshImportData->bGenerateLightmapUVs;
		InOutImportOptions.bOneConvexHullPerUCX			= ImportUI->StaticMeshImportData->bOneConvexHullPerUCX;
		InOutImportOptions.bAutoGenerateCollision		= ImportUI->StaticMeshImportData->bAutoGenerateCollision;
		InOutImportOptions.StaticMeshLODGroup			= ImportUI->StaticMeshImportData->StaticMeshLODGroup;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxStaticMeshImport.cpp:1436

Scope (from outer to inner):

file
function     UStaticMesh* UnFbx::FFbxImporter::ReimportStaticMesh

Source code excerpt:

	// get meshes in Fbx file
	bool bImportStaticMeshLODs = ImportOptions->bImportStaticMeshLODs;
	bool bCombineMeshes = ImportOptions->bCombineToSingle;
	bool bCombineMeshesLOD = false;
	TArray<TArray<FbxNode*>> FbxMeshesLod;

	if (bCombineMeshes && !bImportStaticMeshLODs)
	{
		//the function also fill the collision models, so we can update collision models correctly
		FillFbxMeshArray(Scene->GetRootNode(), FbxMeshArray, this);
	}
	else
	{
		// count meshes in lod groups if we dont care about importing LODs
		bool bCountLODGroupMeshes = !bImportStaticMeshLODs && bCombineMeshes;
		int32 NumLODGroups = 0;
		GetFbxMeshCount(Scene->GetRootNode(), bCountLODGroupMeshes, NumLODGroups);
		// if there were LODs in the file, do not combine meshes even if requested
		if (bImportStaticMeshLODs && bCombineMeshes && NumLODGroups > 0)
		{
			TArray<FbxNode*> FbxLodGroups;
			
			FillFbxMeshAndLODGroupArray(Scene->GetRootNode(), FbxLodGroups, FbxMeshArray);
			FbxMeshesLod.Add(FbxMeshArray);
			for (FbxNode* LODGroup : FbxLodGroups)

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxStaticMeshImport.cpp:1492

Scope (from outer to inner):

file
function     UStaticMesh* UnFbx::FFbxImporter::ReimportStaticMesh

Source code excerpt:

			}
			bCombineMeshesLOD = true;
			bCombineMeshes = false;
			//Set the first LOD
			FbxMeshArray = FbxMeshesLod[0];
		}
		else
		{
			FillFbxMeshArray(Scene->GetRootNode(), FbxMeshArray, this);

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxStaticMeshImport.cpp:1508

Scope (from outer to inner):

file
function     UStaticMesh* UnFbx::FFbxImporter::ReimportStaticMesh

Source code excerpt:

		Node = FbxMeshArray[0];
	}
	else if(!bCombineMeshes && !bCombineMeshesLOD)
	{
		Node = GetMeshNodesFromName(Mesh->GetName(), FbxMeshArray);
	}

	// If there is no match it may be because an LOD group was imported where
	// the mesh name does not match the file name. This is actually the common case.