ThresholdPosition

ThresholdPosition

#Overview

name: ThresholdPosition

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 38 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of ThresholdPosition is to determine when two vertex positions in a skeletal mesh are considered equal or overlapping. It is used in the mesh building and processing pipeline, particularly for skeletal meshes. Here are the key points about ThresholdPosition:

  1. It is part of the rendering system, specifically for skeletal mesh processing and optimization.

  2. The Unreal Engine subsystems that rely on this setting variable include the mesh building utilities, FBX import system, and skeletal mesh processing modules.

  3. The value of this variable is typically set during mesh import or when configuring skeletal mesh build settings. It can be adjusted in the Skeletal Mesh Editor and FBX import options.

  4. It interacts with other threshold variables like ThresholdTangentNormal, ThresholdUV, and MorphThresholdPosition, which are all part of the FOverlappingThresholds struct.

  5. Developers must be aware that this threshold affects mesh optimization and can impact the final geometry of imported skeletal meshes. Setting it too high might result in unintended vertex merging, while setting it too low might prevent necessary optimizations.

  6. Best practices when using this variable include:

    • Keep it at the default value (0.00002) unless there’s a specific reason to change it.
    • If changing it, test thoroughly to ensure the resulting mesh quality meets expectations.
    • Consider the scale of your meshes when adjusting this value, as it’s scale-dependent.
    • Use in conjunction with other threshold settings for consistent results.
  7. This variable is particularly important during FBX imports and when working with LODs (Levels of Detail) for skeletal meshes.

The ThresholdPosition is a crucial setting for maintaining the balance between mesh optimization and preserving mesh details in Unreal Engine’s skeletal mesh pipeline.

#Setting Variables

#References In INI files

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

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/Experimental/Mutable/Source/CustomizableObject/Private/MuCO/CustomizableObjectInstance.cpp:3264

Scope (from outer to inner):

file
function     void UCustomizableInstancePrivate::InitSkeletalMeshData

Source code excerpt:

			LODInfo.BuildSettings.bUseFullPrecisionUVs = true;
			LODInfo.BuildSettings.bUseBackwardsCompatibleF16TruncUVs = false;
			LODInfo.BuildSettings.ThresholdPosition = TNumericLimits<float>::Min();
			LODInfo.BuildSettings.ThresholdTangentNormal = TNumericLimits<float>::Min();
			LODInfo.BuildSettings.ThresholdUV = TNumericLimits<float>::Min();
			LODInfo.BuildSettings.MorphThresholdPosition = TNumericLimits<float>::Min();
			LODInfo.BuildSettings.BoneInfluenceLimit = 0;
#endif
			LODInfo.LODMaterialMap.SetNumZeroed(1);

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

Scope (from outer to inner):

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

Source code excerpt:


		GenericAssetPipeline->MeshPipeline->MorphThresholdPosition = SkeletalMeshImportData->MorphThresholdPosition;
		GenericAssetPipeline->MeshPipeline->ThresholdPosition = SkeletalMeshImportData->ThresholdPosition;
		GenericAssetPipeline->MeshPipeline->ThresholdTangentNormal = SkeletalMeshImportData->ThresholdTangentNormal;
		GenericAssetPipeline->MeshPipeline->ThresholdUV = SkeletalMeshImportData->ThresholdUV;

		if (SkeletalMeshImportData->VertexColorImportOption == EVertexColorImportOption::Ignore)
		{
			GenericAssetPipeline->CommonMeshesProperties->VertexColorImportOption = EInterchangeVertexColorImportOption::IVCIO_Ignore;

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

Scope (from outer to inner):

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

Source code excerpt:


				DestinationSkeletalMeshImportData->MorphThresholdPosition = GenericAssetPipeline->MeshPipeline->MorphThresholdPosition;
				DestinationSkeletalMeshImportData->ThresholdPosition = GenericAssetPipeline->MeshPipeline->ThresholdPosition;
				DestinationSkeletalMeshImportData->ThresholdTangentNormal = GenericAssetPipeline->MeshPipeline->ThresholdTangentNormal;
				DestinationSkeletalMeshImportData->ThresholdUV = GenericAssetPipeline->MeshPipeline->ThresholdUV;

				if (GenericAssetPipeline->CommonMeshesProperties->VertexColorImportOption == EInterchangeVertexColorImportOption::IVCIO_Ignore)
				{
					DestinationSkeletalMeshImportData->VertexColorImportOption = EVertexColorImportOption::Ignore;

#Loc: <Workspace>/Engine/Plugins/Interchange/Runtime/Source/FactoryNodes/Private/InterchangeSkeletalMeshFactoryNode.cpp:153

Scope (from outer to inner):

file
function     bool UInterchangeSkeletalMeshFactoryNode::FillCustomThresholdPositionFromAsset

Source code excerpt:

bool UInterchangeSkeletalMeshFactoryNode::FillCustomThresholdPositionFromAsset(UObject* Asset)
{
	IMPLEMENT_SKELETALMESH_BUILD_ASSET_TO_VALUE(ThresholdPosition, ThresholdPosition);
}

bool UInterchangeSkeletalMeshFactoryNode::GetCustomThresholdTangentNormal(float& AttributeValue) const
{
	IMPLEMENT_NODE_ATTRIBUTE_GETTER(ThresholdTangentNormal, float)
}

#Loc: <Workspace>/Engine/Plugins/Interchange/Runtime/Source/Pipelines/Private/InterchangeGenericAssetsPipeline.cpp:261

Scope (from outer to inner):

file
function     void UInterchangeGenericAssetsPipeline::FilterPropertiesFromTranslatedData

Source code excerpt:

				LocalHideProperty(CommonMeshesProperties, GET_MEMBER_NAME_CHECKED(UInterchangeGenericCommonMeshesProperties, VertexColorImportOption));
				LocalHideProperty(MeshPipeline, GET_MEMBER_NAME_CHECKED(UInterchangeGenericMeshPipeline, bImportMorphTargets));
				LocalHideProperty(MeshPipeline, GET_MEMBER_NAME_CHECKED(UInterchangeGenericMeshPipeline, ThresholdPosition));
				LocalHideProperty(MeshPipeline, GET_MEMBER_NAME_CHECKED(UInterchangeGenericMeshPipeline, ThresholdTangentNormal));
				LocalHideProperty(MeshPipeline, GET_MEMBER_NAME_CHECKED(UInterchangeGenericMeshPipeline, ThresholdUV));
				LocalHideProperty(MeshPipeline, GET_MEMBER_NAME_CHECKED(UInterchangeGenericMeshPipeline, MorphThresholdPosition));
			}
			else if (MeshPipeline->SkeletalMeshImportContentType == EInterchangeSkeletalMeshContentType::Geometry)
			{

#Loc: <Workspace>/Engine/Plugins/Interchange/Runtime/Source/Pipelines/Private/InterchangeGenericSkeletalMeshPipeline.cpp:493

Scope (from outer to inner):

file
function     UInterchangeSkeletalMeshFactoryNode* UInterchangeGenericMeshPipeline::CreateSkeletalMeshFactoryNode

Source code excerpt:

	//Skeletal meshes build options
	SkeletalMeshFactoryNode->SetCustomUseHighPrecisionSkinWeights(bUseHighPrecisionSkinWeights);
	SkeletalMeshFactoryNode->SetCustomThresholdPosition(ThresholdPosition);
	SkeletalMeshFactoryNode->SetCustomThresholdTangentNormal(ThresholdTangentNormal);
	SkeletalMeshFactoryNode->SetCustomThresholdUV(ThresholdUV);
	SkeletalMeshFactoryNode->SetCustomMorphThresholdPosition(MorphThresholdPosition);
	SkeletalMeshFactoryNode->SetCustomBoneInfluenceLimit(BoneInfluenceLimit);

	return SkeletalMeshFactoryNode;

#Loc: <Workspace>/Engine/Plugins/Interchange/Runtime/Source/Pipelines/Public/InterchangeGenericMeshPipeline.h:182

Scope (from outer to inner):

file
class        class UInterchangeGenericMeshPipeline : public UInterchangePipelineBase

Source code excerpt:

	/** Threshold value that is used to decide whether two vertex positions are equal. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skeletal Meshes", meta = (SubCategory = "Build"))
	float ThresholdPosition = 0.00002f;
	
	/** Threshold value that is used to decide whether two normals, tangents, or bi-normals are equal. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skeletal Meshes", meta = (SubCategory = "Build"))
	float ThresholdTangentNormal = 0.00002f;
	
	/** Threshold value that is used to decide whether two UVs are equal. */

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

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->bImportMorphTargets = TestPlan->ImportUI->SkeletalMeshImportData->bImportMorphTargets;
					ImportData->bImportVertexAttributes = TestPlan->ImportUI->SkeletalMeshImportData->bImportVertexAttributes;
					ImportData->ThresholdPosition = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdPosition;
					ImportData->ThresholdTangentNormal = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdTangentNormal;
					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;

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

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->bImportMorphTargets = TestPlan->ImportUI->SkeletalMeshImportData->bImportMorphTargets;
					ImportData->bImportVertexAttributes = TestPlan->ImportUI->SkeletalMeshImportData->bImportVertexAttributes;
					ImportData->ThresholdPosition = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdPosition;
					ImportData->ThresholdTangentNormal = TestPlan->ImportUI->SkeletalMeshImportData->ThresholdTangentNormal;
					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;

#Loc: <Workspace>/Engine/Source/Developer/MeshBuilder/Private/StaticMeshBuilder.cpp:989

Scope (from outer to inner):

file
namespace    UE::Private::StaticMeshBuilder
function     void BuildVertexBuffer

Source code excerpt:

		}
		FOverlappingThresholds OverlappingThresholds;
		OverlappingThresholds.ThresholdPosition = VertexComparisonThreshold;
		// Don't process degenerate triangles.
		if (PointsEqual(CornerPositions[0], CornerPositions[1], OverlappingThresholds)
			|| PointsEqual(CornerPositions[0], CornerPositions[2], OverlappingThresholds)
			|| PointsEqual(CornerPositions[1], CornerPositions[2], OverlappingThresholds))
		{
			WedgeIndex += 3;

#Loc: <Workspace>/Engine/Source/Developer/MeshUtilities/Private/MeshUtilities.cpp:4683

Scope (from outer to inner):

file
function     bool FMeshUtilities::BuildSkeletalMesh_Legacy

Source code excerpt:

			for (int32 j = i + 1; j < VertIndexAndZ.Num(); j++)
			{
				if (FMath::Abs(VertIndexAndZ[j].Z - VertIndexAndZ[i].Z) > OverlappingThresholds.ThresholdPosition)
				{
					// our list is sorted, so there can't be any more dupes
					break;
				}

				// check to see if the points are really overlapping

#Loc: <Workspace>/Engine/Source/Developer/MeshUtilities/Private/SkeletalMeshTools.cpp:95

Scope (from outer to inner):

file
namespace    SkeletalMeshTools
function     void BuildSkeletalMeshChunks

Source code excerpt:

				for(int32 j = i + 1; j < RawVertIndexAndZ.Num(); j++)
				{
					if(FMath::Abs(RawVertIndexAndZ[j].Z - RawVertIndexAndZ[i].Z) > OverlappingThresholds.ThresholdPosition)
					{
						// our list is sorted, so there can't be any more dupes
						break;
					}

					// check to see if the points are really overlapping

#Loc: <Workspace>/Engine/Source/Developer/MeshUtilities/Public/MeshUtilities.h:172

Scope (from outer to inner):

file
class        class IMeshUtilities : public IModuleInterface
function     void FillOptions

Source code excerpt:

		void FillOptions(const FSkeletalMeshBuildSettings& SkeletalMeshBuildSettings)
		{
			OverlappingThresholds.ThresholdPosition = SkeletalMeshBuildSettings.ThresholdPosition;
			OverlappingThresholds.ThresholdTangentNormal = SkeletalMeshBuildSettings.ThresholdTangentNormal;
			OverlappingThresholds.ThresholdUV = SkeletalMeshBuildSettings.ThresholdUV;
			OverlappingThresholds.MorphThresholdPosition = SkeletalMeshBuildSettings.MorphThresholdPosition;
			BoneInfluenceLimit = SkeletalMeshBuildSettings.BoneInfluenceLimit;
			bComputeNormals = SkeletalMeshBuildSettings.bRecomputeNormals;
			bComputeTangents = SkeletalMeshBuildSettings.bRecomputeTangents;

#Loc: <Workspace>/Engine/Source/Editor/Persona/Private/PersonaMeshDetails.cpp:1896

Scope (from outer to inner):

file
function     float FSkeletalMeshBuildSettingsLayout::GetThresholdPosition

Source code excerpt:

float FSkeletalMeshBuildSettingsLayout::GetThresholdPosition() const
{
	return BuildSettings.ThresholdPosition;
}

void FSkeletalMeshBuildSettingsLayout::SetThresholdPosition(float Value)
{
	if (BuildSettings.ThresholdPosition != Value)
	{
		FText TransactionText = FText::Format(LOCTEXT("PersonaSetThresholdPositionLOD", "LOD{0} build settings: threshold for position changed"), LODIndex);
		FScopedTransaction Transaction(TransactionText);
		ModifyMeshLODSettingsDelegate.ExecuteIfBound(LODIndex);

		BuildSettings.ThresholdPosition = Value;
	}
}

float FSkeletalMeshBuildSettingsLayout::GetThresholdTangentNormal() const
{
	return BuildSettings.ThresholdTangentNormal;

#Loc: <Workspace>/Engine/Source/Editor/Persona/Private/PersonaMeshDetails.cpp:4053

Scope (from outer to inner):

file
function     FReply FPersonaMeshDetails::ApplyLODChanges

Source code excerpt:

						}
						SKImportData->bComputeWeightedNormals = LODInfo->BuildSettings.bComputeWeightedNormals;
						SKImportData->ThresholdPosition = LODInfo->BuildSettings.ThresholdPosition;
						SKImportData->ThresholdTangentNormal = LODInfo->BuildSettings.ThresholdTangentNormal;
						SKImportData->ThresholdUV = LODInfo->BuildSettings.ThresholdUV;
						SKImportData->MorphThresholdPosition = LODInfo->BuildSettings.MorphThresholdPosition;
					}
				}
			}

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

Scope (from outer to inner):

file
class        class UFbxSceneImportOptionsSkeletalMesh : public UObject

Source code excerpt:

	/** Threshold to compare vertex position equality. */
	UPROPERTY(EditAnywhere, config, Category = "SkeletalMesh|Thresholds", meta = (NoSpinbox = "true", ClampMin = "0.0"))
	float ThresholdPosition;
	
	/** Threshold to compare normal, tangent or bi-normal equality. */
	UPROPERTY(EditAnywhere, config, Category = "SkeletalMesh|Thresholds", meta = (NoSpinbox = "true", ClampMin = "0.0", ClampMax = "1.0"))
	float ThresholdTangentNormal;
	
	/** Threshold to compare UV equality. */

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

Scope (from outer to inner):

file
class        class UFbxSkeletalMeshImportData : public UFbxMeshImportData

Source code excerpt:

	/** Threshold to compare vertex position equality. */
	UPROPERTY(EditAnywhere, config, Category="Mesh", meta = (ImportType = "SkeletalMesh|GeoOnly", SubCategory = "Thresholds", NoSpinbox = "true", ClampMin = "0.0"))
	float ThresholdPosition;
	
	/** Threshold to compare normal, tangent or bi-normal equality. */
	UPROPERTY(EditAnywhere, config, Category="Mesh", meta = (ImportType = "SkeletalMesh|GeoOnly", SubCategory = "Thresholds", NoSpinbox = "true", ClampMin = "0.0", ClampMax = "1.0"))
	float ThresholdTangentNormal;
	
	/** Threshold to compare UV equality. */

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

Scope (from outer to inner):

file
function     EReimportResult::Type UReimportFbxSkeletalMeshFactory::Reimport

Source code excerpt:

				LODInfo->BuildSettings.bRecomputeTangents = SKImportData->NormalImportMethod != EFBXNormalImportMethod::FBXNIM_ImportNormalsAndTangents;
				LODInfo->BuildSettings.bUseMikkTSpace = SKImportData->NormalGenerationMethod == EFBXNormalGenerationMethod::MikkTSpace;
				LODInfo->BuildSettings.ThresholdPosition = SKImportData->ThresholdPosition;
				LODInfo->BuildSettings.ThresholdTangentNormal = SKImportData->ThresholdTangentNormal;
				LODInfo->BuildSettings.ThresholdUV = SKImportData->ThresholdUV;
				LODInfo->BuildSettings.MorphThresholdPosition = SKImportData->MorphThresholdPosition;
			}
		}
	}

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

Scope (from outer to inner):

file
namespace    UnFbx
function     void ApplyImportUIToImportOptions

Source code excerpt:

		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:1666

Scope (from outer to inner):

file
namespace    UnFbx
function     bool FFbxImporter::ImportFromFile

Source code excerpt:

				  * @EventParam UpdateSkeletonReferencePose boolean Returns whether the importer should update the skeleton reference pose
				  * @EventParam UseT0AsRefPose boolean Returns whether the importer should use the the animation 0 time has the reference pose
				  * @EventParam ThresholdPosition float Returns the threshold delta to weld vertices
				  * @EventParam ThresholdTangentNormal float Returns the threshold delta to weld tangents and normals
				  * @EventParam ThresholdUV float Returns the threshold delta to weld UVs
				  * @EventParam MorphThresholdPosition float Returns the morph target threshold delta to compute deltas
				  * @EventParam AutoComputeLodDistances boolean Returns whether the importer should set the auto compute LOD distance
				  * @EventParam LodNumber integer Returns the LOD number we should have after the import
				  * @EventParam BuildReversedIndexBuffer boolean Returns whether the importer should fill the reverse index buffer when building the static mesh
				  * @EventParam GenerateLightmapUVs boolean Returns whether the importer should generate light map UVs
				  * @EventParam ImportStaticMeshLODs boolean Returns whether the importer should import the LODs
				  * @EventParam RemoveDegenerates boolean Returns whether the importer should remove the degenerated triangles when building the static mesh
				  * @EventParam MinimumLodNumber integer Returns the minimum LOD use by the rendering
				  * @EventParam StaticMeshLODGroup string Returns the LOD Group settings we use to build this imported static mesh
				  * @EventParam VertexColorImportOption string Returns how the importer should import the vertex color
				  * @EventParam VertexOverrideColor string Returns the color use if we need to override the vertex color
				  * @EventParam AnimationLengthImportType string Returns how we choose the animation time span
				  * @EventParam DeleteExistingMorphTargetCurves boolean Returns whether the importer should delete the existing morph target curves
				  * @EventParam AnimationRange string Returns the range of animation the importer should sample if the time span is custom
				  * @EventParam DoNotImportCurveWithZero boolean Returns whether the importer should import curves containing only zero value
				  * @EventParam ImportBoneTracks boolean Returns whether the importer should import the bone tracks
				  * @EventParam ImportCustomAttribute boolean Returns whether the importer should import the custom attribute curves
				  * @EventParam PreserveLocalTransform boolean Returns whether the importer should preserve the local transform when importing the animation
				  * @EventParam RemoveRedundantKeys boolean Returns whether the importer should remove all redundant key in an animation
				  * @EventParam Resample boolean Returns whether the importer should re-sample the animation
				  * @EventParam SetMaterialDriveParameterOnCustomAttribute boolean Returns whether the importer should hook all custom attribute curve to unreal material attribute
				  * @EventParam SetMaterialDriveParameterOnCustomAttribute boolean Returns whether the importer should hook some custom attribute (having the suffix) curve to unreal material attribute
				  * @EventParam ResampleRate float Returns the rate the exporter is suppose to re-sample any imported animations
				  * 
				  * @Owner Alexis.Matte
				*/
				FbxDocumentInfo* DocInfo = Scene->GetSceneInfo();
				if (DocInfo)
				{
					if( FEngineAnalytics::IsAvailable() )
					{
						const static UEnum* FBXImportTypeEnum = StaticEnum<EFBXImportType>();
						const static UEnum* FBXAnimationLengthImportTypeEnum = StaticEnum<EFBXAnimationLengthImportType>();
						const static UEnum* MaterialSearchLocationEnum = StaticEnum<EMaterialSearchLocation>();
						const static UEnum* FBXNormalGenerationMethodEnum = StaticEnum<EFBXNormalGenerationMethod::Type>();
						const static UEnum* FBXNormalImportMethodEnum = StaticEnum<EFBXNormalImportMethod>();
						const static UEnum* VertexColorImportOptionEnum = StaticEnum<EVertexColorImportOption::Type>();
						
						TArray<FAnalyticsEventAttribute> Attribs;

						FString LastSavedVendor(UTF8_TO_TCHAR(DocInfo->LastSaved_ApplicationVendor.Get().Buffer()));
						FString LastSavedAppName(UTF8_TO_TCHAR(DocInfo->LastSaved_ApplicationName.Get().Buffer()));
						FString LastSavedAppVersion(UTF8_TO_TCHAR(DocInfo->LastSaved_ApplicationVersion.Get().Buffer()));

						Attribs.Add(FAnalyticsEventAttribute(TEXT("LastSaved Application Vendor"), LastSavedVendor));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("LastSaved Application Name"), LastSavedAppName));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("LastSaved Application Version"), LastSavedAppVersion));

						Attribs.Add(FAnalyticsEventAttribute(TEXT("FBX Version"), FbxFileVersion));

						//////////////////////////////////////////////////////////////////////////
						//FBX import options
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportType"), FBXImportTypeEnum->GetNameStringByValue(ImportOptions->ImportType)));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ConvertScene"), ImportOptions->bConvertScene));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ConvertSceneUnit"), ImportOptions->bConvertSceneUnit));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ForceFrontXAxis"), ImportOptions->bForceFrontXAxis));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportMaterials"), ImportOptions->bImportMaterials));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportTextures"), ImportOptions->bImportTextures));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt InvertNormalMap"), ImportOptions->bInvertNormalMap));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt RemoveNameSpace"), ImportOptions->bRemoveNameSpace));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt UsedAsFullName"), ImportOptions->bUsedAsFullName));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportTranslation"), ImportOptions->ImportTranslation.ToString()));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportRotation"), ImportOptions->ImportRotation.ToString()));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ImportUniformScale"), ImportOptions->ImportUniformScale));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt MaterialBasePath"), ImportOptions->MaterialBasePath));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt MaterialSearchLocation"), MaterialSearchLocationEnum->GetNameStringByValue((uint64)(ImportOptions->MaterialSearchLocation))));
						Attribs.Add(FAnalyticsEventAttribute(TEXT("GenOpt ReorderMaterialToFbxOrder"), ImportOptions->bReorderMaterialToFbxOrder));

						//We cant capture a this member, so just assign the pointer here
						FBXImportOptions* CaptureImportOptions = ImportOptions;
						auto AddMeshAnalytic = [&Attribs, &CaptureImportOptions]()
						{

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

Scope (from outer to inner):

file
lambda-function

Source code excerpt:

							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));
							Attribs.Add(FAnalyticsEventAttribute(TEXT("SkeletalMeshOpt OverlappingThresholds.MorphThresholdPosition"), CaptureImportOptions->OverlappingThresholds.MorphThresholdPosition));
						};

						auto AddSMAnalytic = [&Attribs, &CaptureImportOptions]()

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

Scope (from outer to inner):

file
function     UnFbx::FBXImportOptions *JSONToFbxOption

Source code excerpt:

		if ((*DataObj)->TryGetNumberField(TEXT("ThresholdPosition"), Pos))
		{
			Option->OverlappingThresholds.ThresholdPosition = (float)Pos;
		}
		if ((*DataObj)->TryGetNumberField(TEXT("ThresholdTangentNormal"), NTB))
		{
			Option->OverlappingThresholds.ThresholdTangentNormal = (float)NTB;
		}
		if ((*DataObj)->TryGetNumberField(TEXT("ThresholdUV"), UV))

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

Scope (from outer to inner):

file
function     FString FbxOptionToJSON

Source code excerpt:

		Option->bImportMorph ? 1 : 0,
		Option->bImportVertexAttributes ? 1 : 0,
		Option->OverlappingThresholds.ThresholdPosition,
		Option->OverlappingThresholds.ThresholdTangentNormal,
		Option->OverlappingThresholds.ThresholdUV,
		Option->OverlappingThresholds.MorphThresholdPosition
		);

	JsonString += FString::Printf(TEXT("\"MaterialBasePath\" : \"%s\"}"), *(Option->MaterialBasePath.ToString()));

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

Scope (from outer to inner):

file
function     UFbxSceneImportOptionsSkeletalMesh::UFbxSceneImportOptionsSkeletalMesh

Source code excerpt:

	, bImportMorphTargets(false)
	, bImportVertexAttributes(false)
	, ThresholdPosition(THRESH_POINTS_ARE_SAME)
	, ThresholdTangentNormal(THRESH_NORMALS_ARE_SAME)
	, ThresholdUV(THRESH_UVS_ARE_SAME)
	, MorphThresholdPosition(THRESH_POINTS_ARE_NEAR)
	, bImportAnimations(true)
	, AnimationLength(EFBXAnimationLengthImportType::FBXALIT_AnimatedKey)
	, FrameImportRange(0, 0)

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

Scope (from outer to inner):

file
function     void UFbxSceneImportOptionsSkeletalMesh::FillSkeletalMeshInmportData

Source code excerpt:

	SkeletalMeshImportData->bImportVertexAttributes = bImportVertexAttributes;

	SkeletalMeshImportData->ThresholdPosition = ThresholdPosition;
	SkeletalMeshImportData->ThresholdTangentNormal = ThresholdTangentNormal;
	SkeletalMeshImportData->ThresholdUV = ThresholdUV;
	SkeletalMeshImportData->MorphThresholdPosition = MorphThresholdPosition;
	SkeletalMeshImportData->bPreserveSmoothingGroups = bPreserveSmoothingGroups;
	SkeletalMeshImportData->bKeepSectionsSeparate = bKeepSectionsSeparate;
	SkeletalMeshImportData->bUpdateSkeletonReferencePose = bUpdateSkeletonReferencePose;

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

Scope (from outer to inner):

file
function     USkeletalMesh* UnFbx::FFbxImporter::ImportSkeletalMesh

Source code excerpt:

	BuildOptions.bComputeWeightedNormals = ImportOptions->bComputeWeightedNormals;
	BuildOptions.bRemoveDegenerates = ImportOptions->bRemoveDegenerates;
	BuildOptions.ThresholdPosition = ImportOptions->OverlappingThresholds.ThresholdPosition;
	BuildOptions.ThresholdTangentNormal = ImportOptions->OverlappingThresholds.ThresholdTangentNormal;
	BuildOptions.ThresholdUV = ImportOptions->OverlappingThresholds.ThresholdUV;
	BuildOptions.MorphThresholdPosition = ImportOptions->OverlappingThresholds.MorphThresholdPosition;
	
	TSharedPtr<FExistingSkelMeshData> ExistSkelMeshDataPtr;
	if (ExistingSkelMesh)

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

Scope (from outer to inner):

file
function     USkeletalMesh* UnFbx::FFbxImporter::ReimportSkeletalMesh

Source code excerpt:

				LODInfo->BuildSettings.bRemoveDegenerates = true;
				LODInfo->BuildSettings.bUseMikkTSpace = SKImportData->NormalGenerationMethod == EFBXNormalGenerationMethod::MikkTSpace;
				LODInfo->BuildSettings.ThresholdPosition = SKImportData->ThresholdPosition;
				LODInfo->BuildSettings.ThresholdTangentNormal = SKImportData->ThresholdTangentNormal;
				LODInfo->BuildSettings.ThresholdUV = SKImportData->ThresholdUV;
				LODInfo->BuildSettings.MorphThresholdPosition = SKImportData->MorphThresholdPosition;
			}
		}
	}

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

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopySkeletalMeshOptionsToFbxOptions

Source code excerpt:

	ImportSettings->bImportMorph = SkeletalMeshOptions->bImportMorphTargets;
	ImportSettings->bImportVertexAttributes = SkeletalMeshOptions->bImportVertexAttributes;
	ImportSettings->OverlappingThresholds.ThresholdPosition = SkeletalMeshOptions->ThresholdPosition;
	ImportSettings->OverlappingThresholds.ThresholdTangentNormal = SkeletalMeshOptions->ThresholdTangentNormal;
	ImportSettings->OverlappingThresholds.ThresholdUV = SkeletalMeshOptions->ThresholdUV;
	ImportSettings->OverlappingThresholds.MorphThresholdPosition = SkeletalMeshOptions->MorphThresholdPosition;
	ImportSettings->bPreserveSmoothingGroups = SkeletalMeshOptions->bPreserveSmoothingGroups;
	ImportSettings->bKeepSectionsSeparate = SkeletalMeshOptions->bKeepSectionsSeparate;
	ImportSettings->bUpdateSkeletonReferencePose = SkeletalMeshOptions->bUpdateSkeletonReferencePose;

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

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopyFbxOptionsToSkeletalMeshOptions

Source code excerpt:

	SkeletalMeshOptions->bImportMorphTargets = ImportSettings->bImportMorph;
	SkeletalMeshOptions->bImportVertexAttributes = ImportSettings->bImportVertexAttributes;
	SkeletalMeshOptions->ThresholdPosition = ImportSettings->OverlappingThresholds.ThresholdPosition;
	SkeletalMeshOptions->ThresholdTangentNormal = ImportSettings->OverlappingThresholds.ThresholdTangentNormal;
	SkeletalMeshOptions->ThresholdUV = ImportSettings->OverlappingThresholds.ThresholdUV;
	SkeletalMeshOptions->MorphThresholdPosition = ImportSettings->OverlappingThresholds.MorphThresholdPosition;
	SkeletalMeshOptions->bPreserveSmoothingGroups = ImportSettings->bPreserveSmoothingGroups;
	SkeletalMeshOptions->bKeepSectionsSeparate = ImportSettings->bKeepSectionsSeparate;
	SkeletalMeshOptions->bUpdateSkeletonReferencePose = ImportSettings->bUpdateSkeletonReferencePose;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/FbxMeshUtils.cpp:655

Scope (from outer to inner):

file
namespace    FbxMeshUtils
function     bool ImportSkeletalMeshLOD

Source code excerpt:

					LODInfo->BuildSettings.bComputeWeightedNormals = ImportOptions->bComputeWeightedNormals;
					LODInfo->BuildSettings.bRemoveDegenerates = ImportOptions->bRemoveDegenerates;
					LODInfo->BuildSettings.ThresholdPosition = ImportOptions->OverlappingThresholds.ThresholdPosition;
					LODInfo->BuildSettings.ThresholdTangentNormal = ImportOptions->OverlappingThresholds.ThresholdTangentNormal;
					LODInfo->BuildSettings.ThresholdUV = ImportOptions->OverlappingThresholds.ThresholdUV;
					LODInfo->BuildSettings.MorphThresholdPosition = ImportOptions->OverlappingThresholds.MorphThresholdPosition;
				}
			}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SkinWeightsUtilities.cpp:284

Scope (from outer to inner):

file
function     bool FSkinWeightsUtilities::ImportAlternateSkinWeight

Source code excerpt:

				IMeshUtilities::MeshBuildOptions BuildOptions;
				//Use the Lod info build settings
				BuildOptions.OverlappingThresholds.ThresholdPosition = LODInfo->BuildSettings.ThresholdPosition;
				BuildOptions.OverlappingThresholds.ThresholdTangentNormal = LODInfo->BuildSettings.ThresholdTangentNormal;
				BuildOptions.OverlappingThresholds.ThresholdUV = LODInfo->BuildSettings.ThresholdUV;
				BuildOptions.OverlappingThresholds.MorphThresholdPosition = LODInfo->BuildSettings.MorphThresholdPosition;
				BuildOptions.bComputeNormals = LODInfo->BuildSettings.bRecomputeNormals;
				BuildOptions.bComputeTangents = LODInfo->BuildSettings.bRecomputeTangents;
				BuildOptions.bUseMikkTSpace = LODInfo->BuildSettings.bUseMikkTSpace;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SkinWeightsUtilities.cpp:398

Scope (from outer to inner):

file
function     bool FSkinWeightsUtilities::RemoveSkinnedWeightProfileData

Source code excerpt:

	if (FSkeletalMeshLODInfo* LODInfo = SkeletalMesh->GetLODInfo(LODIndex))
	{
		BuildOptions.OverlappingThresholds.ThresholdPosition = LODInfo->BuildSettings.ThresholdPosition;
		BuildOptions.OverlappingThresholds.ThresholdTangentNormal = LODInfo->BuildSettings.ThresholdTangentNormal;
		BuildOptions.OverlappingThresholds.ThresholdUV = LODInfo->BuildSettings.ThresholdUV;
		BuildOptions.OverlappingThresholds.MorphThresholdPosition = LODInfo->BuildSettings.MorphThresholdPosition;
		BuildOptions.bComputeNormals = LODInfo->BuildSettings.bRecomputeNormals;
		BuildOptions.bComputeTangents = LODInfo->BuildSettings.bRecomputeTangents;
		BuildOptions.bUseMikkTSpace = LODInfo->BuildSettings.bUseMikkTSpace;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/EngineTypes.h:2784

Scope: file

Source code excerpt:

	/** Threshold use to decide if two vertex position are equal. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BuildSettings)
	float ThresholdPosition;

	/** Threshold use to decide if two normal, tangents or bi-normals are equal. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BuildSettings)
	float ThresholdTangentNormal;

	/** Threshold use to decide if two UVs are equal. */

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/EngineTypes.h:2819

Scope (from outer to inner):

file
function     FSkeletalMeshBuildSettings

Source code excerpt:

		, bUseFullPrecisionUVs(false)
		, bUseBackwardsCompatibleF16TruncUVs(false)
		, ThresholdPosition(0.00002f)
		, ThresholdTangentNormal(0.00002f)
		, ThresholdUV(0.0009765625f)
		, MorphThresholdPosition(0.015f)
		, BoneInfluenceLimit(0)
	{}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/EngineTypes.h:2838

Scope (from outer to inner):

file
function     bool operator==

Source code excerpt:

			&& bUseFullPrecisionUVs == Other.bUseFullPrecisionUVs
			&& bUseBackwardsCompatibleF16TruncUVs == Other.bUseBackwardsCompatibleF16TruncUVs
			&& ThresholdPosition == Other.ThresholdPosition
			&& ThresholdTangentNormal == Other.ThresholdTangentNormal
			&& ThresholdUV == Other.ThresholdUV
			&& MorphThresholdPosition == Other.MorphThresholdPosition
			&& BoneInfluenceLimit == Other.BoneInfluenceLimit;
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SkinnedAssetCommon.cpp:72

Scope (from outer to inner):

file
function     static void SerializeBuildSettingsForDDC

Source code excerpt:

	FArchive_Serialize_BitfieldBool(Ar, BuildSettings.bUseHighPrecisionTangentBasis);
	FArchive_Serialize_BitfieldBool(Ar, BuildSettings.bUseHighPrecisionSkinWeights);
	Ar << BuildSettings.ThresholdPosition;
	Ar << BuildSettings.ThresholdTangentNormal;
	Ar << BuildSettings.ThresholdUV;
	Ar << BuildSettings.MorphThresholdPosition;
	Ar << BuildSettings.BoneInfluenceLimit;
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/MeshBuild.h:14

Scope (from outer to inner):

file
function     FOverlappingThresholds

Source code excerpt:

public:
	FOverlappingThresholds()
		: ThresholdPosition(UE_THRESH_POINTS_ARE_SAME)
		, ThresholdTangentNormal(UE_THRESH_NORMALS_ARE_SAME)
		, ThresholdUV(UE_THRESH_UVS_ARE_SAME)
		, MorphThresholdPosition(UE_THRESH_POINTS_ARE_NEAR)
	{}

	/** Threshold use to decide if two vertex position are equal. */
	float ThresholdPosition;
	
	/** Threshold use to decide if two normal, tangents or bi-normals are equal. */
	float ThresholdTangentNormal;
	
	/** Threshold use to decide if two UVs are equal. */
	float ThresholdUV;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/MeshBuild.h:45

Scope (from outer to inner):

file
function     inline bool PointsEqual

Source code excerpt:

inline bool PointsEqual(const FVector3f& V1, const FVector3f& V2, const FOverlappingThresholds& OverlappingThreshold)
{
	const float Epsilon = OverlappingThreshold.ThresholdPosition;
	return FMath::Abs(V1.X - V2.X) <= Epsilon && FMath::Abs(V1.Y - V2.Y) <= Epsilon && FMath::Abs(V1.Z - V2.Z) <= Epsilon;
}

/**
 * Returns true if the specified normal vectors are about equal
 */