bOneConvexHullPerUCX

bOneConvexHullPerUCX

#Overview

name: bOneConvexHullPerUCX

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

#Summary

#Usage in the C++ source code

The purpose of bOneConvexHullPerUCX is to control the collision generation for static meshes during the import process in Unreal Engine. Specifically, it determines how convex hulls are created for UCX (Unreal Collision X) meshes.

This setting variable is primarily used by the static mesh import system, which is part of the Unreal Engine’s asset import pipeline. Based on the details in the Callsites section, it’s utilized in the following subsystems and modules:

  1. Interchange Editor Plugin
  2. Interchange Runtime Plugin
  3. UnrealEd (Unreal Editor)
  4. FBX import system

The value of this variable is typically set in the import options for static meshes. It can be configured through the FBX import UI, scene import options, or programmatically when setting up import data.

This variable interacts with other import-related variables, such as bImportCollision, bAutoGenerateCollision, and other static mesh import settings.

Developers should be aware of the following when using this variable:

  1. When set to true, each UCX collision mesh will be imported as a single convex hull.
  2. When set to false, a UCX mesh will be decomposed into separate pieces, and a convex hull will be generated for each piece.
  3. This setting only applies to meshes with names prefixed with “UCX” or “MCDCX”.

Best practices when using this variable include:

  1. Consider the complexity of your collision meshes. For simple shapes, setting this to true can be more efficient.
  2. For more complex collision requirements, setting this to false allows for more detailed collision representation at the cost of performance.
  3. Ensure that your UCX meshes are properly named and structured in your 3D modeling software before import.
  4. Test the collision behavior with both settings to determine which works best for your specific use case.
  5. Remember that this setting affects import-time behavior, so you may need to reimport assets if you change this setting.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEditorPerProjectUserSettings.ini:661, 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:153

Scope (from outer to inner):

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

Source code excerpt:

		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)
		{
			GenericAssetPipeline->CommonMeshesProperties->VertexColorImportOption = EInterchangeVertexColorImportOption::IVCIO_Ignore;

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

Scope (from outer to inner):

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

Source code excerpt:

				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)
				{
					DestinationStaticMeshImportData->VertexColorImportOption = EVertexColorImportOption::Ignore;

#Loc: <Workspace>/Engine/Plugins/Interchange/Runtime/Source/Import/Private/Mesh/InterchangeStaticMeshFactory.cpp:1527

Scope (from outer to inner):

file
function     bool UInterchangeStaticMeshFactory::ImportConvexCollision

Source code excerpt:

	TArray<FMeshPayload> MeshPayloads = GetMeshPayloads(Arguments, ConvexCollisionMeshUids);

	bool bOneConvexHullPerUCX;
	if (!LodDataNode->GetOneConvexHullPerUCX(bOneConvexHullPerUCX) || !bOneConvexHullPerUCX)
	{
		for (const FMeshPayload& MeshPayload : MeshPayloads)
		{
			const FTransform& Transform = FTransform::Identity;
			const TOptional<FMeshPayloadData>& PayloadData = MeshPayload.PayloadData.Get();

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

Scope (from outer to inner):

file
function     UInterchangeStaticMeshLodDataNode* UInterchangeGenericMeshPipeline::CreateStaticMeshLodDataNode

Source code excerpt:


	StaticMeshLodDataNode->InitializeNode(NodeUID, DisplayLabel, EInterchangeNodeContainerType::FactoryData);
	StaticMeshLodDataNode->SetOneConvexHullPerUCX(bOneConvexHullPerUCX);
	StaticMeshLodDataNode->SetImportCollision(bImportCollision);
	BaseNodeContainer->AddNode(StaticMeshLodDataNode);
	return StaticMeshLodDataNode;
}

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

Scope (from outer to inner):

file
class        class UInterchangeGenericMeshPipeline : public UInterchangePipelineBase

Source code excerpt:

	/** If enabled, each UCX collision mesh will be imported as a single convex hull. If disabled, a UCX mesh will be decomposed into its separate pieces and a convex hull generated for each. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Static Meshes", meta = (SubCategory = "Collision", editcondition = "bImportCollision && bImportCollisionAccordingToMeshName"))
	bool bOneConvexHullPerUCX = true;

	//////	Static Meshes Build settings Properties //////

	/** If enabled, imported meshes will be rendered by Nanite at runtime. Make sure your meshes and materials meet the requirements for Nanite. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Static Meshes", meta = (SubCategory = "Build"))
	bool bBuildNanite = false;

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

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->bBuildReversedIndexBuffer = TestPlan->ImportUI->StaticMeshImportData->bBuildReversedIndexBuffer;
					ImportData->bGenerateLightmapUVs = TestPlan->ImportUI->StaticMeshImportData->bGenerateLightmapUVs;
					ImportData->bOneConvexHullPerUCX = TestPlan->ImportUI->StaticMeshImportData->bOneConvexHullPerUCX;
					ImportData->bAutoGenerateCollision = TestPlan->ImportUI->StaticMeshImportData->bAutoGenerateCollision;
					//Copy UFbxMeshImportData
					ImportData->bTransformVertexToAbsolute = TestPlan->ImportUI->StaticMeshImportData->bTransformVertexToAbsolute;
					ImportData->bBakePivotInVertex = TestPlan->ImportUI->StaticMeshImportData->bBakePivotInVertex;
					ImportData->bImportMeshLODs = TestPlan->ImportUI->StaticMeshImportData->bImportMeshLODs;
					ImportData->NormalImportMethod = TestPlan->ImportUI->StaticMeshImportData->NormalImportMethod;

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

Scope (from outer to inner):

file
function     BEGIN_FUNCTION_BUILD_OPTIMIZATION bool F

Source code excerpt:

					ImportData->bBuildReversedIndexBuffer = TestPlan->ImportUI->StaticMeshImportData->bBuildReversedIndexBuffer;
					ImportData->bGenerateLightmapUVs = TestPlan->ImportUI->StaticMeshImportData->bGenerateLightmapUVs;
					ImportData->bOneConvexHullPerUCX = TestPlan->ImportUI->StaticMeshImportData->bOneConvexHullPerUCX;
					ImportData->bAutoGenerateCollision = TestPlan->ImportUI->StaticMeshImportData->bAutoGenerateCollision;
					//Copy UFbxMeshImportData
					ImportData->bTransformVertexToAbsolute = TestPlan->ImportUI->StaticMeshImportData->bTransformVertexToAbsolute;
					ImportData->bBakePivotInVertex = TestPlan->ImportUI->StaticMeshImportData->bBakePivotInVertex;
					ImportData->bImportMeshLODs = TestPlan->ImportUI->StaticMeshImportData->bImportMeshLODs;
					ImportData->NormalImportMethod = TestPlan->ImportUI->StaticMeshImportData->NormalImportMethod;

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Classes/Factories/FbxSceneImportOptionsStaticMesh.h:77

Scope (from outer to inner):

file
class        class UFbxSceneImportOptionsStaticMesh : public UObject

Source code excerpt:

	/** If checked, one convex hull per UCX_ prefixed collision mesh will be generated instead of decomposing into multiple hulls */
	UPROPERTY(EditAnywhere, config, Category = StaticMesh)
	uint32 bOneConvexHullPerUCX : 1;

	/** Enabling this option will read the tangents(tangent,binormal,normal) from FBX file instead of generating them automatically. */
	UPROPERTY(EditAnywhere, config, Category = StaticMesh)
	EFBXSceneNormalImportMethod NormalImportMethod;

	/** Use the MikkTSpace tangent space generator for generating normals and tangents on the mesh */

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

Scope (from outer to inner):

file
class        class UFbxStaticMeshImportData : public UFbxMeshImportData

Source code excerpt:

	/** If checked, one convex hull per UCX_ prefixed collision mesh will be generated instead of decomposing into multiple hulls */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, config, Category= Mesh, meta=(OBJRestrict="true", ImportType="StaticMesh"))
	uint32 bOneConvexHullPerUCX:1;

	/** If checked, collision will automatically be generated (ignored if custom collision is imported or used). */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, config, Category = Mesh, meta=(OBJRestrict="true", ImportType="StaticMesh", DisplayName="Generate Missing Collision"))
	uint32 bAutoGenerateCollision : 1;

	/** For static meshes, enabling this option will combine all meshes in the FBX into a single monolithic mesh in Unreal */

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

Scope (from outer to inner):

file
namespace    UnFbx
function     void ApplyImportUIToImportOptions

Source code excerpt:

		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;
	}
	
	// animation unshared options
	{

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

Scope (from outer to inner):

file
function     UnFbx::FBXImportOptions *JSONToFbxOption

Source code excerpt:

	OptionObj->TryGetBoolField(TEXT("bBuildReversedIndexBuffer"), Option->bBuildReversedIndexBuffer);
	OptionObj->TryGetBoolField(TEXT("bGenerateLightmapUVs"), Option->bGenerateLightmapUVs);
	OptionObj->TryGetBoolField(TEXT("bOneConvexHullPerUCX"), Option->bOneConvexHullPerUCX);
	OptionObj->TryGetBoolField(TEXT("bAutoGenerateCollision"), Option->bAutoGenerateCollision);
	FString LODGroup;
	if (OptionObj->TryGetStringField(TEXT("StaticMeshLODGroup"), LODGroup))
	{
		Option->StaticMeshLODGroup = FName(*LODGroup);
	}

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

Scope (from outer to inner):

file
function     FString FbxOptionToJSON

Source code excerpt:

		Option->bBuildReversedIndexBuffer ? 1 : 0,
		Option->bGenerateLightmapUVs ? 1 : 0,
		Option->bOneConvexHullPerUCX ? 1 : 0,
		Option->bAutoGenerateCollision ? 1 : 0,
		*(Option->StaticMeshLODGroup.ToString()),
		Option->bImportStaticMeshLODs ? 1 : 0
		);

	JsonString += FString::Printf(TEXT("\"bUpdateSkeletonReferencePose\" : \"%d\", \"bUseT0AsRefPose\" : \"%d\", \"bPreserveSmoothingGroups\" : \"%d\", \"bKeepSectionsSeparate\" : \"%d\", \"bImportMeshesInBoneHierarchy\" : \"%d\", \"bImportMorphTargets\" : \"%d\", , \"bImportVertexAttributes\" : \"%d\", \"OverlappingThresholds\" : {\"ThresholdPosition\" : \"%f\", \"ThresholdTangentNormal\" : \"%f\", \"ThresholdUV\" : \"%f\", \"MorphThresholdPosition\" : \"%f\"},"),

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

Scope (from outer to inner):

file
function     UFbxSceneImportOptionsStaticMesh::UFbxSceneImportOptionsStaticMesh

Source code excerpt:

	, bBuildReversedIndexBuffer(true)
	, bGenerateLightmapUVs(true)
	, bOneConvexHullPerUCX(true)
{
	VertexOverrideColor = FColor(255, 255, 255, 255);
	NormalImportMethod = EFBXSceneNormalImportMethod::FBXSceneNIM_ComputeNormals;
	NormalGenerationMethod = EFBXSceneNormalGenerationMethod::MikkTSpace;
}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxSceneImportOptionsStaticMesh.cpp:34

Scope (from outer to inner):

file
function     void UFbxSceneImportOptionsStaticMesh::FillStaticMeshInmportData

Source code excerpt:

	StaticMeshImportData->bBuildReversedIndexBuffer = bBuildReversedIndexBuffer;
	StaticMeshImportData->bGenerateLightmapUVs = bGenerateLightmapUVs;
	StaticMeshImportData->bOneConvexHullPerUCX = bOneConvexHullPerUCX;
	StaticMeshImportData->bRemoveDegenerates = bRemoveDegenerates;
	StaticMeshImportData->StaticMeshLODGroup = StaticMeshLODGroup;
	switch (VertexColorImportOption)
	{
	case EFbxSceneVertexColorImportOption::Ignore:
		StaticMeshImportData->VertexColorImportOption = EVertexColorImportOption::Ignore;

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

Scope (from outer to inner):

file
function     bool UnFbx::FFbxImporter::ImportCollisionModels

Source code excerpt:

		if ( ModelName.Find("UCX") != -1 || ModelName.Find("MCDCX") != -1 )
		{
			if( !ImportOptions->bOneConvexHullPerUCX )
			{
				if (StaticMeshImportUtils::DecomposeUCXMesh(CollisionVertices, CollisionFaceIdx, StaticMesh->GetBodySetup()))
				{
					bAtLeastOneCollisionMeshImported = true;
				}
				else

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxStaticMeshImportData.cpp:11

Scope (from outer to inner):

file
function     UFbxStaticMeshImportData::UFbxStaticMeshImportData

Source code excerpt:

	bBuildNanite = false;
	bGenerateLightmapUVs = true;
	bOneConvexHullPerUCX = true;
	bAutoGenerateCollision = true;
	bTransformVertexToAbsolute = true;
	bBakePivotInVertex = false;
	VertexOverrideColor = FColor(255, 255, 255, 255);
	DistanceFieldResolutionScale = 1.0f;
}

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

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopyStaticMeshOptionsToFbxOptions

Source code excerpt:

	ImportSettings->bBuildReversedIndexBuffer = StaticMeshOptions->bBuildReversedIndexBuffer;
	ImportSettings->bGenerateLightmapUVs = StaticMeshOptions->bGenerateLightmapUVs;
	ImportSettings->bOneConvexHullPerUCX = StaticMeshOptions->bOneConvexHullPerUCX;
	ImportSettings->bRemoveDegenerates = StaticMeshOptions->bRemoveDegenerates;
	ImportSettings->StaticMeshLODGroup = StaticMeshOptions->StaticMeshLODGroup;
	switch (StaticMeshOptions->VertexColorImportOption)
	{
	case EFbxSceneVertexColorImportOption::Replace:
		ImportSettings->VertexColorImportOption = EVertexColorImportOption::Type::Replace;

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

Scope (from outer to inner):

file
function     void SFbxSceneOptionWindow::CopyFbxOptionsToStaticMeshOptions

Source code excerpt:

	StaticMeshOptions->bBuildReversedIndexBuffer = ImportSettings->bBuildReversedIndexBuffer;
	StaticMeshOptions->bGenerateLightmapUVs = ImportSettings->bGenerateLightmapUVs;
	StaticMeshOptions->bOneConvexHullPerUCX = ImportSettings->bOneConvexHullPerUCX;
	StaticMeshOptions->bRemoveDegenerates = ImportSettings->bRemoveDegenerates;
	StaticMeshOptions->StaticMeshLODGroup = ImportSettings->StaticMeshLODGroup;
	switch (ImportSettings->VertexColorImportOption)
	{
	case EVertexColorImportOption::Type::Replace:
		StaticMeshOptions->VertexColorImportOption = EFbxSceneVertexColorImportOption::Replace;

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

Scope (from outer to inner):

file
namespace    UnFbx

Source code excerpt:

	bool bBuildNanite;
	bool bGenerateLightmapUVs;
	bool bOneConvexHullPerUCX;
	bool bAutoGenerateCollision;
	FName StaticMeshLODGroup;
	bool bImportStaticMeshLODs;
	bool bAutoComputeLodDistances;
	TArray<float> LodDistances;
	int32 MinimumLodNumber;