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:
- The LODType setting affects how the SpeedTree model transitions between different levels of detail.
- It’s not editable for billboard geometry types.
- Different LOD types may have different performance implications.
Best practices when using this variable include:
- Choose the appropriate LOD type based on the specific needs of your project and the characteristics of each SpeedTree asset.
- Consider performance implications when selecting LOD types, especially for projects targeting lower-end hardware.
- 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]
- INI Section:
/Script/SpeedTreeImporter.SpeedTreeImportData
- Raw value:
ILT_PaintedFoliage
- Is Array:
False
#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
{