bPreserveSmoothingGroups

bPreserveSmoothingGroups

#Overview

name: bPreserveSmoothingGroups

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 bPreserveSmoothingGroups is to control the preservation of smoothing groups during the import of 3D meshes, particularly skeletal meshes, into Unreal Engine 5. This setting is primarily used in the mesh import system, specifically for skeletal meshes.

bPreserveSmoothingGroups is primarily used in the FBX import system, which is part of the UnrealEd module. It’s also referenced in the Interchange Editor plugin, which is likely an alternative import system.

The value of this variable is typically set during the import process, either through user interface options or programmatically when importing assets. It’s often initialized in constructor functions (e.g., UFbxSceneImportOptionsSkeletalMesh) and can be modified through various import settings dialogs.

This variable interacts with other import settings, such as bKeepSectionsSeparate, bUpdateSkeletonReferencePose, and bUseT0AsRefPose. It’s part of a larger set of import options that collectively determine how a mesh is processed during import.

Developers should be aware that when bPreserveSmoothingGroups is set to true, it can affect the geometry of the imported mesh. It causes the importer to physically split triangles with non-matching smoothing groups, which can increase the number of vertices in the mesh.

Best practices when using this variable include:

  1. Consider the desired visual outcome: Preserving smoothing groups can maintain the original mesh’s intended shading, but may increase vertex count.
  2. Be consistent across related assets: Use the same setting for all meshes in a set to ensure consistent appearance.
  3. Test both options: The impact can vary depending on the source mesh, so it’s worth testing both true and false settings to see which gives better results for your specific asset.
  4. Consider performance: If vertex count is a concern, setting this to false might be preferable, especially for mobile or VR projects where performance is critical.
  5. Use in conjunction with other import settings: Adjust related settings like bKeepSectionsSeparate to achieve the desired import result.

#Setting Variables

#References In INI files

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

#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:380

Scope (from outer to inner):

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

Source code excerpt:

				DestinationSkeletalMeshImportData->bImportVertexAttributes = GenericAssetPipeline->MeshPipeline->bImportVertexAttributes;
				DestinationSkeletalMeshImportData->bKeepSectionsSeparate = GenericAssetPipeline->CommonMeshesProperties->bKeepSectionsSeparate;
				DestinationSkeletalMeshImportData->bPreserveSmoothingGroups = true;
				DestinationSkeletalMeshImportData->bUpdateSkeletonReferencePose = GenericAssetPipeline->MeshPipeline->bUpdateSkeletonReferencePose;
				DestinationSkeletalMeshImportData->bUseT0AsRefPose = GenericAssetPipeline->CommonSkeletalMeshesAndAnimationsProperties->bUseT0AsRefPose;
				if (GenericAssetPipeline->MeshPipeline->SkeletalMeshImportContentType == EInterchangeSkeletalMeshContentType::All)
				{
					DestinationSkeletalMeshImportData->ImportContentType = EFBXImportContentType::FBXICT_All;
				}

#Loc: <Workspace>/Engine/Plugins/Tests/EditorTests/Source/EditorTests/Private/UnrealEd/FbxAutomationTests.cpp:426

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->MorphThresholdPosition = TestPlan->ImportUI->SkeletalMeshImportData->MorphThresholdPosition;
					ImportData->ThresholdUV = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdUV;
					ImportData->bPreserveSmoothingGroups = TestPlan->ImportUI->SkeletalMeshImportData->bPreserveSmoothingGroups;
					ImportData->bKeepSectionsSeparate = TestPlan->ImportUI->SkeletalMeshImportData->bKeepSectionsSeparate;
					ImportData->bUpdateSkeletonReferencePose = TestPlan->ImportUI->SkeletalMeshImportData->bUpdateSkeletonReferencePose;
					ImportData->bUseT0AsRefPose = TestPlan->ImportUI->SkeletalMeshImportData->bUseT0AsRefPose;
					//Copy UFbxMeshImportData
					ImportData->bTransformVertexToAbsolute = TestPlan->ImportUI->SkeletalMeshImportData->bTransformVertexToAbsolute;
					ImportData->bBakePivotInVertex = TestPlan->ImportUI->SkeletalMeshImportData->bBakePivotInVertex;

#Loc: <Workspace>/Engine/Plugins/Tests/EditorTests/Source/EditorTests/Private/UnrealEd/FbxAutomationTests.cpp:524

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->ThresholdUV = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdUV;
					ImportData->MorphThresholdPosition = TestPlan->ImportUI->SkeletalMeshImportData->MorphThresholdPosition;
					ImportData->bPreserveSmoothingGroups = TestPlan->ImportUI->SkeletalMeshImportData->bPreserveSmoothingGroups;
					ImportData->bKeepSectionsSeparate = TestPlan->ImportUI->SkeletalMeshImportData->bKeepSectionsSeparate;
					ImportData->bUpdateSkeletonReferencePose = TestPlan->ImportUI->SkeletalMeshImportData->bUpdateSkeletonReferencePose;
					ImportData->bUseT0AsRefPose = TestPlan->ImportUI->SkeletalMeshImportData->bUseT0AsRefPose;
					//Copy UFbxMeshImportData
					ImportData->bTransformVertexToAbsolute = TestPlan->ImportUI->SkeletalMeshImportData->bTransformVertexToAbsolute;
					ImportData->bBakePivotInVertex = TestPlan->ImportUI->SkeletalMeshImportData->bBakePivotInVertex;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxSceneImportOptionsSkeletalMesh.h:32

Scope (from outer to inner):

file
class        class UFbxSceneImportOptionsSkeletalMesh : public UObject

Source code excerpt:

	/** If checked, triangles with non-matching smoothing groups will be physically split. */
	UPROPERTY(EditAnywhere, config, Category = SkeletalMesh)
	uint32 bPreserveSmoothingGroups : 1;

	/** If checked, sections with matching materials are kept separate and will not get combined. */
	UPROPERTY(EditAnywhere, config, Category = SkeletalMesh)
	uint32 bKeepSectionsSeparate : 1;

	/** If checked, meshes nested in bone hierarchies will be imported instead of being converted to bones. */

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxSkeletalMeshImportData.h:74

Scope (from outer to inner):

file
class        class UFbxSkeletalMeshImportData : public UFbxMeshImportData

Source code excerpt:

	/** If checked, triangles with non-matching smoothing groups will be physically split. */
	UPROPERTY(EditAnywhere, AdvancedDisplay, config, Category=Mesh, meta=(ImportType="SkeletalMesh|GeoOnly"))
	uint32 bPreserveSmoothingGroups:1;

	/** If checked, sections with matching materials are kept separate and will not get combined. */
	UPROPERTY(EditAnywhere, AdvancedDisplay, config, Category=Mesh, meta=(ImportType="SkeletalMesh|GeoOnly"))
	uint32 bKeepSectionsSeparate:1;

	/** If checked, meshes nested in bone hierarchies will be imported instead of being converted to bones. */

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

Scope (from outer to inner):

file
namespace    UnFbx
function     void ApplyImportUIToImportOptions

Source code excerpt:

		InOutImportOptions.bImportRigidMesh				= ImportUI->OriginalImportType == FBXIT_StaticMesh && ImportUI->MeshTypeToImport == FBXIT_SkeletalMesh;
		InOutImportOptions.bUseT0AsRefPose				= ImportUI->SkeletalMeshImportData->bUseT0AsRefPose;
		InOutImportOptions.bPreserveSmoothingGroups		= ImportUI->SkeletalMeshImportData->bPreserveSmoothingGroups;
		InOutImportOptions.bKeepSectionsSeparate		= ImportUI->SkeletalMeshImportData->bKeepSectionsSeparate;
		InOutImportOptions.OverlappingThresholds.ThresholdPosition = ImportUI->SkeletalMeshImportData->ThresholdPosition;
		InOutImportOptions.OverlappingThresholds.ThresholdTangentNormal = ImportUI->SkeletalMeshImportData->ThresholdTangentNormal;
		InOutImportOptions.OverlappingThresholds.ThresholdUV = ImportUI->SkeletalMeshImportData->ThresholdUV;
		InOutImportOptions.OverlappingThresholds.MorphThresholdPosition = ImportUI->SkeletalMeshImportData->MorphThresholdPosition;
		InOutImportOptions.bImportMeshesInBoneHierarchy = ImportUI->SkeletalMeshImportData->bImportMeshesInBoneHierarchy;

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

Scope (from outer to inner):

file
lambda-function

Source code excerpt:

							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt ImportMorph"), CaptureImportOptions->bImportMorph));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt ImportSkeletalMeshLODs"), CaptureImportOptions->bImportSkeletalMeshLODs));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt PreserveSmoothingGroups"), CaptureImportOptions->bPreserveSmoothingGroups));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt KeepSectionsSeparate"), CaptureImportOptions->bKeepSectionsSeparate));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt UpdateSkeletonReferencePose"), CaptureImportOptions->bUpdateSkeletonReferencePose));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt UseT0AsRefPose"), CaptureImportOptions->bUseT0AsRefPose));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt OverlappingThresholds.ThresholdPosition"), CaptureImportOptions->OverlappingThresholds.ThresholdPosition));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt OverlappingThresholds.ThresholdTangentNormal"), CaptureImportOptions->OverlappingThresholds.ThresholdTangentNormal));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt OverlappingThresholds.ThresholdUV"), CaptureImportOptions->OverlappingThresholds.ThresholdUV));

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportData.cpp:118

Scope (from outer to inner):

file
function     UnFbx::FBXImportOptions *JSONToFbxOption

Source code excerpt:

	//OptionObj->TryGetBoolField(TEXT("bUseT0AsRefPose"), Option->bUseT0AsRefPose);
	Option->bUseT0AsRefPose = false;
	OptionObj->TryGetBoolField(TEXT("bPreserveSmoothingGroups"), Option->bPreserveSmoothingGroups);
	OptionObj->TryGetBoolField(TEXT("bKeepSectionsSeparate"), Option->bKeepSectionsSeparate);
	OptionObj->TryGetBoolField(TEXT("bImportMeshesInBoneHierarchy"), Option->bImportMeshesInBoneHierarchy);
	OptionObj->TryGetBoolField(TEXT("bImportMorphTargets"), Option->bImportMorph);
	OptionObj->TryGetBoolField(TEXT("bImportVertexAttributes"), Option->bImportVertexAttributes);
	
	if (OptionObj->TryGetObjectField(TEXT("OverlappingThresholds"), DataObj))

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportData.cpp:208

Scope (from outer to inner):

file
function     FString FbxOptionToJSON

Source code excerpt:

		Option->bUpdateSkeletonReferencePose ? 1 : 0,
		Option->bUseT0AsRefPose ? 1 : 0,
		Option->bPreserveSmoothingGroups ? 1 : 0,
		Option->bKeepSectionsSeparate ? 1 : 0,
		Option->bImportMeshesInBoneHierarchy ? 1 : 0,
		Option->bImportMorph ? 1 : 0,
		Option->bImportVertexAttributes ? 1 : 0,
		Option->OverlappingThresholds.ThresholdPosition,
		Option->OverlappingThresholds.ThresholdTangentNormal,

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportOptionsSkeletalMesh.cpp:15

Scope (from outer to inner):

file
function     UFbxSceneImportOptionsSkeletalMesh::UFbxSceneImportOptionsSkeletalMesh

Source code excerpt:

	, bCreatePhysicsAsset(false)
	, bUseT0AsRefPose(false)
	, bPreserveSmoothingGroups(false)
	, bKeepSectionsSeparate(false)
	, bImportMeshesInBoneHierarchy(true)
	, bImportMorphTargets(false)
	, bImportVertexAttributes(false)
	, ThresholdPosition(THRESH_POINTS_ARE_SAME)
	, ThresholdTangentNormal(THRESH_NORMALS_ARE_SAME)

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportOptionsSkeletalMesh.cpp:48

Scope (from outer to inner):

file
function     void UFbxSceneImportOptionsSkeletalMesh::FillSkeletalMeshInmportData

Source code excerpt:

	SkeletalMeshImportData->ThresholdUV = ThresholdUV;
	SkeletalMeshImportData->MorphThresholdPosition = MorphThresholdPosition;
	SkeletalMeshImportData->bPreserveSmoothingGroups = bPreserveSmoothingGroups;
	SkeletalMeshImportData->bKeepSectionsSeparate = bKeepSectionsSeparate;
	SkeletalMeshImportData->bUpdateSkeletonReferencePose = bUpdateSkeletonReferencePose;
	SkeletalMeshImportData->bUseT0AsRefPose = bUseT0AsRefPose;

	SkeletalMeshImportData->bImportMeshLODs = SceneImportOptions->bImportSkeletalMeshLODs;
	SkeletalMeshImportData->ImportTranslation = SceneImportOptions->ImportTranslation;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSkeletalMeshImport.cpp:1451

Scope (from outer to inner):

file
function     bool UnFbx::FFbxImporter::FillSkeletalMeshImportData

Source code excerpt:

	}

	if (ImportOptions->bPreserveSmoothingGroups)
	{
		bool bDuplicateUnSmoothWedges = false; //We deprecate legacy build
		DoUnSmoothVerts(*SkelMeshImportDataPtr, bDuplicateUnSmoothWedges);
	}
	else
	{

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSkeletalMeshImport.cpp:3271

Scope (from outer to inner):

file
function     bool UnFbx::FFbxImporter::FillSkelMeshImporterFromFbx

Source code excerpt:

	}

	if( LayerCount > 0 && ImportOptions->bPreserveSmoothingGroups )
	{
		// Check and see if the smooothing data is valid.  If not generate it from the normals
		BaseLayer = Mesh->GetLayer(0);
		if( BaseLayer )
		{
			const FbxLayerElementSmoothing* SmoothingLayer = BaseLayer->GetSmoothing();

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/SFbxSceneOptionWindow.cpp:1501

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopySkeletalMeshOptionsToFbxOptions

Source code excerpt:

	ImportSettings->OverlappingThresholds.ThresholdUV = SkeletalMeshOptions->ThresholdUV;
	ImportSettings->OverlappingThresholds.MorphThresholdPosition = SkeletalMeshOptions->MorphThresholdPosition;
	ImportSettings->bPreserveSmoothingGroups = SkeletalMeshOptions->bPreserveSmoothingGroups;
	ImportSettings->bKeepSectionsSeparate = SkeletalMeshOptions->bKeepSectionsSeparate;
	ImportSettings->bUpdateSkeletonReferencePose = SkeletalMeshOptions->bUpdateSkeletonReferencePose;
	ImportSettings->bUseT0AsRefPose = SkeletalMeshOptions->bUseT0AsRefPose;

	ImportSettings->bImportAnimations = SkeletalMeshOptions->bImportAnimations;
	ImportSettings->AnimationLengthImportType = SkeletalMeshOptions->AnimationLength;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/SFbxSceneOptionWindow.cpp:1530

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopyFbxOptionsToSkeletalMeshOptions

Source code excerpt:

	SkeletalMeshOptions->ThresholdUV = ImportSettings->OverlappingThresholds.ThresholdUV;
	SkeletalMeshOptions->MorphThresholdPosition = ImportSettings->OverlappingThresholds.MorphThresholdPosition;
	SkeletalMeshOptions->bPreserveSmoothingGroups = ImportSettings->bPreserveSmoothingGroups;
	SkeletalMeshOptions->bKeepSectionsSeparate = ImportSettings->bKeepSectionsSeparate;
	SkeletalMeshOptions->bUpdateSkeletonReferencePose = ImportSettings->bUpdateSkeletonReferencePose;
	SkeletalMeshOptions->bUseT0AsRefPose = ImportSettings->bUseT0AsRefPose;

	SkeletalMeshOptions->bImportAnimations = ImportSettings->bImportAnimations;
	SkeletalMeshOptions->AnimationLength = ImportSettings->AnimationLengthImportType;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Public/FbxImporter.h:183

Scope (from outer to inner):

file
namespace    UnFbx

Source code excerpt:

	bool bImportRigidMesh;
	bool bUseT0AsRefPose;
	bool bPreserveSmoothingGroups;
	bool bKeepSectionsSeparate;
	FOverlappingThresholds OverlappingThresholds;
	bool bImportMeshesInBoneHierarchy;
	bool bCreatePhysicsAsset;
	UPhysicsAsset *PhysicsAsset;
	bool bImportSkeletalMeshLODs;