LODType

LODType

#Overview

name: LODType

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 LODType is to specify the Level of Detail (LOD) type for SpeedTree assets in Unreal Engine. It is primarily used in the rendering system to control how the SpeedTree model’s LOD transitions are handled.

This setting variable is mainly relied upon by the SpeedTree importer plugin and the rendering system within Unreal Engine. It’s used in the material expression system for SpeedTree materials and in the import process for SpeedTree assets.

The value of this variable is typically set during the import process of SpeedTree assets or when creating SpeedTree materials. It can be set programmatically or through the Unreal Engine editor interface.

LODType interacts with other variables such as GeometryType, WindType, and BillboardThreshold in the context of SpeedTree rendering and material setup.

Developers must be aware that:

  1. The LODType setting affects how the SpeedTree model transitions between different levels of detail.
  2. It’s not editable for billboard geometry types.
  3. Different LOD types may have different performance implications.

Best practices when using this variable include:

  1. Choose the appropriate LOD type based on the specific needs of your project and the characteristics of each SpeedTree asset.
  2. Consider performance implications when selecting LOD types, especially for projects targeting lower-end hardware.
  3. Ensure consistency in LOD type usage across similar SpeedTree assets in your project for uniform visual quality and performance.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEditorPerProjectUserSettings.ini:942, section: [/Script/SpeedTreeImporter.SpeedTreeImportData]

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Classes/SpeedTreeImportData.h:57

Scope (from outer to inner):

file
class        class USpeedTreeImportData : public UAssetImportData

Source code excerpt:

	/** Choose whether painted foliage or individual actor */
	UPROPERTY(EditAnywhere, config, Category=Mesh, meta = (DisplayName = "LOD Setup", SpeedTreeVersion = "8"))
	TEnumAsByte<enum EImportLODType> LODType;

	/**  */
	UPROPERTY(EditAnywhere, config, Category=Mesh, meta = (DisplayName = "Include Collision", SpeedTreeVersion = "8"))
	uint32 IncludeCollision : 1;

	/**  */

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportData.cpp:31

Scope (from outer to inner):

file
function     USpeedTreeImportData::USpeedTreeImportData

Source code excerpt:

	ImportGeometryType = IGT_3D;
	TreeScale = 30.48f;
	LODType = ILT_PaintedFoliage;
}

void USpeedTreeImportData::CopyFrom(USpeedTreeImportData* Other)
{
	TreeScale = Other->TreeScale;
	ImportGeometryType = Other->ImportGeometryType;
	LODType = Other->LODType;
	IncludeCollision = Other->IncludeCollision;
	MakeMaterialsCheck = Other->MakeMaterialsCheck;
	IncludeNormalMapCheck = Other->IncludeNormalMapCheck;
	IncludeDetailMapCheck = Other->IncludeDetailMapCheck;
	IncludeSpecularMapCheck = Other->IncludeSpecularMapCheck;
	IncludeBranchSeamSmoothing = Other->IncludeBranchSeamSmoothing;

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportFactory.cpp:901

Scope (from outer to inner):

file
function     UMaterialInterface* CreateSpeedTreeMaterial7

Source code excerpt:

		UMaterialExpressionSpeedTree* SpeedTreeExpression = NewObject<UMaterialExpressionSpeedTree>(UnrealMaterial);
	
		SpeedTreeExpression->LODType = (SpeedTreeImportData->IncludeSmoothLODCheck ? STLOD_Smooth : STLOD_Pop);
		SpeedTreeExpression->WindType = WindType;

		float BillboardThreshold = FMath::Clamp((float)(NumBillboards - 8) / 16.0f, 0.0f, 1.0f);
		SpeedTreeExpression->BillboardThreshold = 0.9f - BillboardThreshold * 0.8f;

		if (RenderState->m_bBranchesPresent)

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportFactory.cpp:1273

Scope (from outer to inner):

file
function     UMaterialInterface* CreateSpeedTreeMaterial8

Source code excerpt:

	{
		UMaterialExpressionSpeedTree* SpeedTreeExpression = NewObject<UMaterialExpressionSpeedTree>(UnrealMaterial);
		SpeedTreeExpression->LODType = (bCrossfadeLOD ? STLOD_Pop : STLOD_Smooth);
		SpeedTreeExpression->WindType = WindType;
		SpeedTreeExpression->BillboardThreshold = 1.0f; // billboards use crossfade technique now in v8
		SpeedTreeExpression->GeometryType = GeomType;
		UnrealMaterial->GetExpressionCollection().AddExpression(SpeedTreeExpression);
		UnrealMaterialEditorOnly->WorldPositionOffset.Expression = SpeedTreeExpression;
	}

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportFactory.cpp:2438

Scope (from outer to inner):

file
function     UObject* USpeedTreeImportFactory::FactoryCreateBinary7

Source code excerpt:


				// make better LOD info for SpeedTrees
				if (SpeedTreeImportData->LODType == EImportLODType::ILT_IndividualActors)
				{
					StaticMesh->bAutoComputeLODScreenSize = false;
				}
				StaticMesh->bRequiresLODDistanceConversion = false;
			}
		}

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportFactory.cpp:2564

Scope (from outer to inner):

file
function     UObject* USpeedTreeImportFactory::FactoryCreateBinary8

Source code excerpt:

				LODModel.BuildSettings.bGenerateLightmapUVs = false;

				if (SpeedTreeImportData->LODType == ILT_IndividualActors)
				{
					LODModel.ScreenSize = FMath::Lerp(1.0f, 0.1f, FMath::Square(LODIndex * Denominator));
				}
				else
				{
					LODModel.ScreenSize = FMath::Lerp(1.0f, 0.25f, LODIndex * Denominator);

#Loc: <Workspace>/Engine/Plugins/Editor/SpeedTreeImporter/Source/SpeedTreeImporter/Private/SpeedTreeImportFactory.cpp:2603

Scope (from outer to inner):

file
function     UObject* USpeedTreeImportFactory::FactoryCreateBinary8

Source code excerpt:

		StaticMesh->bAutoComputeLODScreenSize = false;
		StaticMesh->bRequiresLODDistanceConversion = false;
		bool bCrossfadeLOD = (SpeedTreeImportData->LODType == ILT_PaintedFoliage) ||
							((SpeedTree.Lods().Count() == 2) && SpeedTree.LastLodIsBillboard());

		// make geometry LODs
		for (uint32 LODIndex = 0; LODIndex < SpeedTree.Lods().Count(); ++LODIndex)
		{
			GameEngine8::CLod LOD = SpeedTree.Lods()[LODIndex];

#Loc: <Workspace>/Engine/Plugins/Experimental/Avalanche/Source/AvalancheModifiers/Private/Modifiers/AvaDynamicMeshConverterModifier.cpp:379

Scope (from outer to inner):

file
function     void UAvaDynamicMeshConverterModifier::ConvertComponents

Source code excerpt:

	static const FGeometryScriptCopyMeshFromAssetOptions FromMeshOptions;
	static FGeometryScriptMeshReadLOD FromMeshLOD;
	FromMeshLOD.LODType = EGeometryScriptLODType::SourceModel;
	TArray<AActor*> FilteredActors;
	GetFilteredActors(FilteredActors);
	if (HasFlag(EAvaDynamicMeshConverterModifierType::StaticMeshComponent))
	{
		TArray<UStaticMeshComponent*> Components;
		GetStaticMeshComponents(FilteredActors, Components);

#Loc: <Workspace>/Engine/Plugins/Experimental/ClonerEffector/Source/ClonerEffector/Private/Cloner/CEClonerComponent.cpp:819

Scope (from outer to inner):

file
function     void UCEClonerComponent::UpdateActorBakedDynamicMesh

Source code excerpt:

	{
		static FGeometryScriptMeshReadLOD SkeletalMeshLOD;
		SkeletalMeshLOD.LODType = EGeometryScriptLODType::SourceModel;

		TArray<USkeletalMeshComponent*> Components;
		InActor->GetComponents(Components, false);
		for (USkeletalMeshComponent* Component : Components)
		{
			USkeletalMesh* SkeletalMesh = Component->GetSkeletalMeshAsset();

#Loc: <Workspace>/Engine/Plugins/Experimental/ClonerEffector/Source/ClonerEffector/Private/Cloner/CEClonerComponent.cpp:986

Scope (from outer to inner):

file
function     void UCEClonerComponent::UpdateActorBakedDynamicMesh

Source code excerpt:

	{
		static FGeometryScriptMeshReadLOD StaticMeshLOD;
		StaticMeshLOD.LODType = EGeometryScriptLODType::RenderData;

		TArray<UStaticMeshComponent*> Components;
		InActor->GetComponents(Components, false);
		for (UStaticMeshComponent* Component : Components)
		{
			UStaticMesh* StaticMesh = Component->GetStaticMesh();

#Loc: <Workspace>/Engine/Plugins/Experimental/MeshModelingToolsetExp/Source/MeshModelingToolsExp/Private/ConvertMeshesTool.cpp:170

Scope (from outer to inner):

file
function     void UConvertMeshesTool::Shutdown

Source code excerpt:


			UE::Conversion::FToMeshOptions Options;
			Options.LODType = UE::Conversion::EMeshLODType::SourceModel;
			Options.LODIndex = 0;
			Options.bUseClosestLOD = true;
			if ((int32)TargetLOD <= (int32)EMeshLODIdentifier::LOD7)
			{
				Options.LODIndex = (int32)TargetLOD;
			}
			else if (TargetLOD == EMeshLODIdentifier::MaxQuality)
			{
				Options.LODType = UE::Conversion::EMeshLODType::MaxAvailable;
			}
			else if (TargetLOD == EMeshLODIdentifier::HiResSource)
			{
				Options.LODType = UE::Conversion::EMeshLODType::HiResSourceModel;
			}

			bool bSuccess = UE::Conversion::SceneComponentToDynamicMesh(InputComponent, Options, false, SourceMesh, SourceTransform, ErrorMessage, &ComponentMaterials, &AssetMaterials);
			if (!bSuccess)
			{
				UE_LOG(LogGeometry, Warning, TEXT("Convert Tool failed to convert %s: %s"), *InputComponent->GetName(), *ErrorMessage.ToString());

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:47

Scope (from outer to inner):

file
function     static UDynamicMesh* CopyMeshFromStaticMesh_SourceData

Source code excerpt:

)
{
	if (RequestedLOD.LODType != EGeometryScriptLODType::MaxAvailable && RequestedLOD.LODType != EGeometryScriptLODType::SourceModel && RequestedLOD.LODType != EGeometryScriptLODType::HiResSourceModel)
	{
		UE::Geometry::AppendError(Debug, EGeometryScriptErrorType::InvalidInputs, LOCTEXT("CopyMeshFromStaticMesh_LODNotAvailable", "CopyMeshFromStaticMesh: Requested LOD Type is not available"));
		return ToDynamicMesh;
	}

#if WITH_EDITOR
	if (RequestedLOD.LODType == EGeometryScriptLODType::HiResSourceModel && FromStaticMeshAsset->IsHiResMeshDescriptionValid() == false)
	{
		UE::Geometry::AppendError(Debug, EGeometryScriptErrorType::InvalidInputs, LOCTEXT("CopyMeshFromStaticMesh_HiResLODNotAvailable", "CopyMeshFromStaticMesh: HiResSourceModel LOD Type is not available"));
		return ToDynamicMesh;
	}

	const FMeshDescription* SourceMesh = nullptr;
	const FMeshBuildSettings* BuildSettings = nullptr;

	if ((RequestedLOD.LODType == EGeometryScriptLODType::HiResSourceModel) ||
		(RequestedLOD.LODType == EGeometryScriptLODType::MaxAvailable && FromStaticMeshAsset->IsHiResMeshDescriptionValid()))
	{
		SourceMesh = FromStaticMeshAsset->GetHiResMeshDescription();
		const FStaticMeshSourceModel& SourceModel = FromStaticMeshAsset->GetHiResSourceModel();
		BuildSettings = &SourceModel.BuildSettings;
	}
	else

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:155

Scope (from outer to inner):

file
function     static UDynamicMesh* CopyMeshFromStaticMesh_RenderData

Source code excerpt:

)
{
	if (RequestedLOD.LODType != EGeometryScriptLODType::MaxAvailable && RequestedLOD.LODType != EGeometryScriptLODType::RenderData)
	{
		UE::Geometry::AppendError(Debug, EGeometryScriptErrorType::InvalidInputs, LOCTEXT("CopyMeshFromStaticMesh_LODNotAvailable", "CopyMeshFromStaticMesh: Requested LOD Type is not available"));
		return ToDynamicMesh;
	}

#if !WITH_EDITOR

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:230

Scope (from outer to inner):

file
function     UDynamicMesh* UGeometryScriptLibrary_StaticMeshFunctions::CopyMeshFromStaticMesh

Source code excerpt:


#if WITH_EDITOR
	if (RequestedLOD.LODType == EGeometryScriptLODType::RenderData)
	{
		return CopyMeshFromStaticMesh_RenderData(FromStaticMeshAsset, ToDynamicMesh, AssetOptions, RequestedLOD, Outcome, Debug);
	}
	else
	{
		return CopyMeshFromStaticMesh_SourceData(FromStaticMeshAsset, ToDynamicMesh, AssetOptions, RequestedLOD, Outcome, Debug);

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:462

Scope (from outer to inner):

file
function     bool UGeometryScriptLibrary_StaticMeshFunctions::CheckStaticMeshHasAvailableLOD

Source code excerpt:

	}

	if (RequestedLOD.LODType == EGeometryScriptLODType::RenderData)
	{
		Outcome = (RequestedLOD.LODIndex >= 0 && RequestedLOD.LODIndex < FromStaticMeshAsset->GetNumLODs()) ?
			EGeometryScriptSearchOutcomePins::Found : EGeometryScriptSearchOutcomePins::NotFound;

#if !WITH_EDITOR
		if (FromStaticMeshAsset->bAllowCPUAccess == false)

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:479

Scope (from outer to inner):

file
function     bool UGeometryScriptLibrary_StaticMeshFunctions::CheckStaticMeshHasAvailableLOD

Source code excerpt:

#if WITH_EDITOR
	bool bResult = false;
	if (RequestedLOD.LODType == EGeometryScriptLODType::HiResSourceModel)
	{
		bResult = FromStaticMeshAsset->IsHiResMeshDescriptionValid();
	}
	else if (RequestedLOD.LODType == EGeometryScriptLODType::SourceModel)
	{
		bResult = RequestedLOD.LODIndex >= 0
			&& RequestedLOD.LODIndex < FromStaticMeshAsset->GetNumSourceModels()
			&& FromStaticMeshAsset->IsSourceModelValid(RequestedLOD.LODIndex);
	}
	else if (RequestedLOD.LODType == EGeometryScriptLODType::MaxAvailable)
	{
		bResult = (FromStaticMeshAsset->GetNumSourceModels() > 0);
	}
	Outcome = (bResult) ? EGeometryScriptSearchOutcomePins::Found : EGeometryScriptSearchOutcomePins::NotFound;
	return bResult;

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:506

Scope (from outer to inner):

file
function     int UGeometryScriptLibrary_StaticMeshFunctions::GetNumStaticMeshLODsOfType

Source code excerpt:

int UGeometryScriptLibrary_StaticMeshFunctions::GetNumStaticMeshLODsOfType(
	UStaticMesh* FromStaticMeshAsset,
	EGeometryScriptLODType LODType)
{
	if (FromStaticMeshAsset == nullptr) return 0;

#if WITH_EDITOR
	if (LODType == EGeometryScriptLODType::RenderData)
	{
		return FromStaticMeshAsset->GetNumLODs();
	}
	if (LODType == EGeometryScriptLODType::HiResSourceModel)
	{
		return FromStaticMeshAsset->IsHiResMeshDescriptionValid() ? 1 : 0;
	}
	if (LODType == EGeometryScriptLODType::SourceModel || LODType == EGeometryScriptLODType::MaxAvailable)
	{
		return FromStaticMeshAsset->GetNumSourceModels();
	}
#else
	if (LODType == EGeometryScriptLODType::RenderData && FromStaticMeshAsset->bAllowCPUAccess)
	{
		return FromStaticMeshAsset->GetNumLODs();
	}
#endif

	return 0;

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:553

Scope (from outer to inner):

file
function     void UGeometryScriptLibrary_StaticMeshFunctions::GetSectionMaterialListFromStaticMesh

Source code excerpt:


	// RenderData mesh sections directly reference a Material Index, which is set as the MaterialID in CopyMeshFromStaticMesh_RenderData
	if (RequestedLOD.LODType == EGeometryScriptLODType::RenderData)
	{
		MaterialList.Reset();
		MaterialIndex.Reset();
		MaterialSlotNames.Reset();
		const TArray<FStaticMaterial>& AssetMaterials = FromStaticMeshAsset->GetStaticMaterials();
		for (int32 k = 0; k < AssetMaterials.Num(); ++k)

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:572

Scope (from outer to inner):

file
function     void UGeometryScriptLibrary_StaticMeshFunctions::GetSectionMaterialListFromStaticMesh

Source code excerpt:

#if WITH_EDITOR

	if (RequestedLOD.LODType != EGeometryScriptLODType::MaxAvailable && RequestedLOD.LODType != EGeometryScriptLODType::SourceModel)
	{
		UE::Geometry::AppendError(Debug, EGeometryScriptErrorType::InvalidInputs, LOCTEXT("GetSectionMaterialListFromStaticMesh_LODNotAvailable", "GetSectionMaterialListFromStaticMesh: Requested LOD is not available"));
		return;
	}

	int32 UseLODIndex = FMath::Clamp(RequestedLOD.LODIndex, 0, FromStaticMeshAsset->GetNumSourceModels() - 1);

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/MeshAssetFunctions.cpp:617

Scope (from outer to inner):

file
function     UDynamicMesh* UGeometryScriptLibrary_StaticMeshFunctions::CopyMeshFromSkeletalMesh

Source code excerpt:

		return ToDynamicMesh;
	}
	if (RequestedLOD.LODType != EGeometryScriptLODType::MaxAvailable && RequestedLOD.LODType != EGeometryScriptLODType::SourceModel)
	{
		UE::Geometry::AppendError(Debug, EGeometryScriptErrorType::InvalidInputs, LOCTEXT("CopyMeshFromSkeletalMesh_LODNotAvailable", "CopyMeshFromSkeletalMesh: Requested LOD is not available"));
		return ToDynamicMesh;
	}

	// TODO: Consolidate this code with SkeletalMeshToolTarget::GetMeshDescription(..) 

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Private/SceneUtilityFunctions.cpp:70

Scope (from outer to inner):

file
function     UDynamicMesh* UGeometryScriptLibrary_SceneUtilityFunctions::CopyMeshFromComponent

Source code excerpt:

		return UE::Conversion::EMeshLODType::MaxAvailable;
	};
	ToMeshOptions.LODType = SafeConvertLODType(Options.RequestedLOD.LODType);
	ToMeshOptions.bWantNormals = Options.bWantNormals;
	ToMeshOptions.bWantTangents = Options.bWantTangents;
	ToMeshOptions.bWantInstanceColors = Options.bWantInstanceColors;
	UE::Geometry::FDynamicMesh3 NewMesh;
	FText ErrorMessage;
	bool bSuccess = UE::Conversion::SceneComponentToDynamicMesh(Component, ToMeshOptions, bTransformToWorld, NewMesh, LocalToWorld, ErrorMessage);

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Public/GeometryScript/GeometryScriptTypes.h:86

Scope: file

Source code excerpt:

public:
	UPROPERTY(BlueprintReadWrite, Category = LOD)
	EGeometryScriptLODType LODType = EGeometryScriptLODType::MaxAvailable;

	UPROPERTY(BlueprintReadWrite, Category = LOD)
	int32 LODIndex = 0;
};

#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryScripting/Source/GeometryScriptingCore/Public/GeometryScript/MeshAssetFunctions.h:117

Scope (from outer to inner):

file
function     class GEOMETRYSCRIPTINGCORE_API UGeometryScriptLibrary_StaticMeshFunctions : public UBlueprintFunctionLibrary { GENERATED_BODY

Source code excerpt:

	/** 
	* Check if a Static Mesh Asset has the RequestedLOD available, ie if CopyMeshFromStaticMesh will be able to
	* succeed for the given LODType and LODIndex. 
	*/
	UFUNCTION(BlueprintCallable, Category = "GeometryScript|StaticMesh", meta = (ExpandEnumAsExecs = "Outcome"))
	static bool
	CheckStaticMeshHasAvailableLOD(
		UStaticMesh* StaticMeshAsset, 
		FGeometryScriptMeshReadLOD RequestedLOD,
		EGeometryScriptSearchOutcomePins& Outcome,
		UGeometryScriptDebug* Debug = nullptr);

	/**
	 * Determine the number of available LODs of the requested LODType in a Static Mesh Asset
	 */
	UFUNCTION(BlueprintCallable, Category = "GeometryScript|StaticMesh")
	static int
	GetNumStaticMeshLODsOfType(
		UStaticMesh* StaticMeshAsset, 
		EGeometryScriptLODType LODType = EGeometryScriptLODType::SourceModel);

	/** 
	* Extracts a Dynamic Mesh from a Static Mesh Asset. 
	* 
	* Note that the LOD Index in RequestedLOD will be silently clamped to the available number of LODs (SourceModel or RenderData)
	*/

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:115

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh_SourceData

Source code excerpt:

		UStaticMesh* FromStaticMeshAsset,
		FStaticMeshConversionOptions AssetOptions,
		EMeshLODType LODType,
		int32 LODIndex,
		FDynamicMesh3& OutMesh,
		FText& OutErrorMessage
	)
	{
		using namespace ::UE::Geometry;

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:132

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh_SourceData

Source code excerpt:

		}

		if (LODType != EMeshLODType::MaxAvailable && LODType != EMeshLODType::SourceModel && LODType != EMeshLODType::HiResSourceModel)
		{
			OutErrorMessage = LOCTEXT("CopyMeshFromStaticMesh_LODNotAvailable", "Requested LOD Type is not available");
			return false;
		}

#if WITH_EDITOR
		if (LODType == EMeshLODType::HiResSourceModel && FromStaticMeshAsset->IsHiResMeshDescriptionValid() == false)
		{
			OutErrorMessage = LOCTEXT("CopyMeshFromStaticMesh_HiResLODNotAvailable", "HiResSourceModel LOD Type is not available");
			return false;
		}

		const FMeshDescription* SourceMesh = nullptr;
		const FMeshBuildSettings* BuildSettings = nullptr;

		if ((LODType == EMeshLODType::HiResSourceModel) ||
			(LODType == EMeshLODType::MaxAvailable && FromStaticMeshAsset->IsHiResMeshDescriptionValid()))
		{
			SourceMesh = FromStaticMeshAsset->GetHiResMeshDescription();
			const FStaticMeshSourceModel& SourceModel = FromStaticMeshAsset->GetHiResSourceModel();
			BuildSettings = &SourceModel.BuildSettings;
		}
		else

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:232

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh_RenderData

Source code excerpt:

		UStaticMeshComponent* StaticMeshComponent,
		FStaticMeshConversionOptions AssetOptions,
		EMeshLODType LODType,
		int32 LODIndex,
		FDynamicMesh3& OutMesh,
		FText& OutErrorMessage
	)
	{
		using namespace ::UE::Geometry;

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:242

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh_RenderData

Source code excerpt:

		OutMesh.Clear();

		if (LODType != EMeshLODType::MaxAvailable && LODType != EMeshLODType::RenderData)
		{
			OutErrorMessage = LOCTEXT("CopyMeshFromStaticMeshRender_LODNotAvailable", "Requested LOD Type is not available");
			return false;
		}

#if !WITH_EDITOR

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:311

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh

Source code excerpt:

		UStaticMeshComponent* StaticMeshComponent,
		FStaticMeshConversionOptions AssetOptions,
		EMeshLODType LODType,
		int32 LODIndex,
		bool bUseClosestLOD,
		FDynamicMesh3& OutMesh,
		FText& OutErrorMessage
	)
	{

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:327

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
namespace    Private::ConversionHelper
function     static bool CopyMeshFromStaticMesh

Source code excerpt:

		{
			// attempt to detect if an unavailable LOD was requested, and if so re-map to an available one
			if (LODType == EMeshLODType::MaxAvailable || LODType == EMeshLODType::HiResSourceModel)
			{
				LODIndex = 0;
			}
#if WITH_EDITOR
			if (LODType == EMeshLODType::MaxAvailable)
			{
				LODType = EMeshLODType::HiResSourceModel;
			}
			if (LODType == EMeshLODType::HiResSourceModel && !FromStaticMeshAsset->IsHiResMeshDescriptionValid())
			{
				LODType = EMeshLODType::SourceModel;
			}
			if (LODType == EMeshLODType::SourceModel)
			{
				LODIndex = FMath::Clamp(LODIndex, 0, FromStaticMeshAsset->GetNumSourceModels() - 1);
				if (!FromStaticMeshAsset->GetSourceModel(LODIndex).IsSourceModelInitialized())
				{
					LODType = EMeshLODType::RenderData;
				}
			}
			if (LODType == EMeshLODType::RenderData)
			{
				LODIndex = FMath::Clamp(LODIndex, 0, FromStaticMeshAsset->GetNumLODs() - 1);
			}
#else
			LODType = EMeshLODType::RenderData;
			LODIndex = FMath::Clamp(LODIndex, 0, FromStaticMeshAsset->GetNumLODs() - 1);
#endif
		}

		if (LODType == EMeshLODType::RenderData)
		{
			return CopyMeshFromStaticMesh_RenderData(FromStaticMeshAsset, StaticMeshComponent, AssetOptions, LODType, LODIndex, OutMesh, OutErrorMessage);
		}
		else
		{
			return CopyMeshFromStaticMesh_SourceData(FromStaticMeshAsset, AssetOptions, LODType, LODIndex, OutMesh, OutErrorMessage);
		}
	}
}


bool SceneComponentToDynamicMesh(USceneComponent* Component, const FToMeshOptions& Options, bool bTransformToWorld, 

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:411

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
function     bool SceneComponentToDynamicMesh

Source code excerpt:

	{
		const int32 NumLODs = SkinnedMeshComponent->GetNumLODs();
		int32 RequestedLOD = Options.LODType == EMeshLODType::MaxAvailable ? 0 : Options.LODIndex;
		if (Options.bUseClosestLOD)
		{
			RequestedLOD = FMath::Clamp(RequestedLOD, 0, NumLODs - 1);
		}
		if (RequestedLOD < 0 || RequestedLOD > NumLODs - 1)
		{

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:456

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
function     bool SceneComponentToDynamicMesh

Source code excerpt:

			AssetOptions.bRequestInstanceVertexColors = Options.bWantInstanceColors;
			bSuccess = Private::ConversionHelper::CopyMeshFromStaticMesh(
				StaticMesh, SplineMeshComponent, AssetOptions, Options.LODType, Options.LODIndex, Options.bUseClosestLOD, OutMesh, OutErrorMessage);

			// deform the dynamic mesh and its tangent space with the spline
			if (bSuccess)
			{
				const bool bUpdateTangentSpace = Options.bWantTangents;
				SplineDeformDynamicMesh(*SplineMeshComponent, OutMesh, bUpdateTangentSpace);

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/ConversionUtils/SceneComponentToDynamicMesh.cpp:490

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
function     bool SceneComponentToDynamicMesh

Source code excerpt:

			AssetOptions.bRequestInstanceVertexColors = Options.bWantInstanceColors;
			bSuccess = Private::ConversionHelper::CopyMeshFromStaticMesh(
				StaticMesh, StaticMeshComponent, AssetOptions, Options.LODType, Options.LODIndex, Options.bUseClosestLOD, OutMesh, OutErrorMessage);

			// if we have an ISMC, append instances
			if (UInstancedStaticMeshComponent* ISMComponent = Cast<UInstancedStaticMeshComponent>(StaticMeshComponent))
			{
				FDynamicMesh3 InstancedMesh = MoveTemp(OutMesh);
				OutMesh.Clear();

#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Public/ConversionUtils/SceneComponentToDynamicMesh.h:45

Scope (from outer to inner):

file
namespace    UE
namespace    Conversion
function     FToMeshOptions

Source code excerpt:

		// LOD index constructor -- requests specified source model LOD index
		FToMeshOptions(int32 LODIndex, bool bWantNormals = true, bool bWantTangents = true)
			: LODType(EMeshLODType::SourceModel), LODIndex(LODIndex), bWantNormals(bWantNormals), bWantTangents(bWantTangents)
		{}

		EMeshLODType LODType = EMeshLODType::MaxAvailable;
		// Which LOD to use. Ignored if the LODType is MaxAvailable or HiResSourceModel
		int32 LODIndex = 0;
		// Whether to fall back to the most similar LOD if the requested LOD is not available.
		bool bUseClosestLOD = true;

		bool bWantNormals = true;
		bool bWantTangents = true;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Materials/MaterialExpressionSpeedTree.h:61

Scope (from outer to inner):

file
class        class UMaterialExpressionSpeedTree : public UMaterialExpression

Source code excerpt:


	UPROPERTY(EditAnywhere, Category=MaterialExpressionSpeedTree, meta=(DisplayName = "LOD Type", ToolTip="The type of LOD to use"))
	TEnumAsByte<enum ESpeedTreeLODType> LODType;

	UPROPERTY(EditAnywhere, Category=MaterialExpressionSpeedTree, meta=(DisplayName = "Billboard Threshold", ToolTip="The threshold for triangles to be removed from the bilboard mesh when not facing the camera (0 = none pass, 1 = all pass).", ClampMin = "0.0", ClampMax = "1.0", UIMin = "0.0", UIMax = "1.0"))
	float BillboardThreshold;

	UPROPERTY(EditAnywhere, Category=MaterialExpressionSpeedTree, AdvancedDisplay, meta=(DisplayName = "Accurate Wind Velocities", ToolTip="Support accurate velocities from wind. This will incur extra cost per vertex."))
	bool bAccurateWindVelocities;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressionHLSL.cpp:1480

Scope (from outer to inner):

file
function     bool UMaterialExpressionSpeedTree::GenerateHLSLExpression

Source code excerpt:

	const FExpression* GeometryExpression = GeometryInput.AcquireHLSLExpressionOrConstant(Generator, Scope, int32(GeometryType));
	const FExpression* WindExpression = WindInput.AcquireHLSLExpressionOrConstant(Generator, Scope, int32(WindType));
	const FExpression* LODExpression = LODInput.AcquireHLSLExpressionOrConstant(Generator, Scope, int32(LODType));

	bool bExtraBend = (ExtraBendWS.GetTracedInput().Expression != nullptr);
	const FExpression* ExtraBendExpression = ExtraBendWS.AcquireHLSLExpressionOrConstant(Generator, Scope, FVector3f(0.f, 0.f, 0.f));

	OutExpression = Generator.GetTree().NewExpression<Material::FExpressionSpeedTree>(GeometryExpression, WindExpression, LODExpression, ExtraBendExpression, bExtraBend, bAccurateWindVelocities, BillboardThreshold, false);
	return true;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp:21696

Scope (from outer to inner):

file
function     UMaterialExpressionSpeedTree::UMaterialExpressionSpeedTree

Source code excerpt:

	GeometryType = STG_Branch;
	WindType = STW_None;
	LODType = STLOD_Pop;
	BillboardThreshold = 0.9f;
	bAccurateWindVelocities = false;

#if WITH_EDITORONLY_DATA
	MenuCategories.Add(ConstructorStatics.NAME_SpeedTree);
#endif

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp:21710

Scope (from outer to inner):

file
function     int32 UMaterialExpressionSpeedTree::Compile

Source code excerpt:

	int32 GeometryArg = (GeometryInput.GetTracedInput().Expression ? GeometryInput.Compile(Compiler) : Compiler->Constant(GeometryType));
	int32 WindArg = (WindInput.GetTracedInput().Expression ? WindInput.Compile(Compiler) : Compiler->Constant(WindType));
	int32 LODArg = (LODInput.GetTracedInput().Expression ? LODInput.Compile(Compiler) : Compiler->Constant(LODType));
	
	bool bExtraBend = (ExtraBendWS.GetTracedInput().Expression != nullptr);
	int32 ExtraBendArg = (ExtraBendWS.GetTracedInput().Expression ? ExtraBendWS.Compile(Compiler) : Compiler->Constant3(0.0f, 0.0f, 0.0f));
	 
	return Compiler->SpeedTree(GeometryArg, WindArg, LODArg, BillboardThreshold, bAccurateWindVelocities, bExtraBend, ExtraBendArg);
}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialExpressions.cpp:21756

Scope (from outer to inner):

file
function     bool UMaterialExpressionSpeedTree::CanEditChange

Source code excerpt:

	if (GeometryType == STG_Billboard)
	{
		if (InProperty->GetFName() == GET_MEMBER_NAME_STRING_CHECKED(ThisClass, LODType))
		{
			bIsEditable = false;
		}
	}
	else
	{