MaxEdgeLength
MaxEdgeLength
#Overview
name: MaxEdgeLength
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 54
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of MaxEdgeLength is to control the maximum length of edges in a mesh during tessellation or remeshing operations. It is primarily used in the rendering system and geometry processing modules of Unreal Engine 5.
Key points about MaxEdgeLength:
-
It is used in various Unreal Engine subsystems and modules, including:
- Datasmith CAD Importer
- Geometry Processing
- Mesh Modeling Toolset
- Nanite rendering system
-
The value of MaxEdgeLength is typically set as part of tessellation or remeshing parameters. It’s often initialized with a default value (e.g., 0.0 or 1.33) and can be modified based on specific requirements.
-
MaxEdgeLength often interacts with MinEdgeLength. Together, they define a range for acceptable edge lengths in a mesh.
-
In many cases, MaxEdgeLength is used in comparisons to determine if an edge should be split during mesh operations. For example:
if (EdgeLengthSqr > MaxEdgeLength * MaxEdgeLength) { // Split the edge }
-
Developers should be aware that setting MaxEdgeLength too low can result in over-tessellation, leading to performance issues and increased memory usage. Conversely, setting it too high might result in insufficient detail in the mesh.
-
Best practices when using MaxEdgeLength include:
- Adjusting it based on the scale and detail requirements of your specific model or scene.
- Considering the trade-off between mesh quality and performance.
- Using it in conjunction with other tessellation parameters for optimal results.
- Testing different values to find the right balance for your specific use case.
-
In some cases, MaxEdgeLength is used as part of more complex calculations, such as determining “free” areas in a mesh or calculating edge length statistics.
-
When working with imported CAD models or other precise geometry, careful tuning of MaxEdgeLength can help maintain model accuracy while optimizing for performance.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Plugins/Enterprise/DatasmithImporter/Config/BaseDatasmithImporter.ini:7, section: [FileProducerTessellationOptions]
- INI Section:
FileProducerTessellationOptions
- Raw value:
0.0
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADInterfaces/Private/TechSoftUtils.cpp:174
Scope (from outer to inner):
file
namespace CADLibrary
namespace TechSoftUtils
function bool FillBodyMesh
Source code excerpt:
TessellationParameters->m_dAngleToleranceDeg = ImportParameters.GetMaxNormalAngle();
TessellationParameters->m_dMaximalTriangleEdgeLength = 0; //ImportParameters.MaxEdgeLength;
TessellationParameters->m_bAccurateTessellation = A3D_FALSE; // A3D_FALSE' indicates the tessellation is set for visualization
TessellationParameters->m_bAccurateTessellationWithGrid = A3D_FALSE; // Enable accurate tessellation with faces inner points on a grid.
TessellationParameters->m_dAccurateTessellationWithGridMaximumStitchLength = 0; // Maximal grid stitch length. Disabled if value is 0. Be careful, a too small value can generate a huge tessellation.
TessellationParameters->m_bKeepUVPoints = A3D_TRUE; // Keep parametric points as texture points.
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADKernelSurface/Private/CADKernelSurfaceExtension.cpp:37
Scope (from outer to inner):
file
function bool UCADKernelParametricSurfaceData::Tessellate
Source code excerpt:
CADLibrary::FImportParameters ImportParameters;
ImportParameters.SetModelCoordinateSystem((FDatasmithUtils::EModelCoordSystem) SceneParameters.ModelCoordSys);
ImportParameters.SetTesselationParameters(RetessellateOptions.ChordTolerance, RetessellateOptions.MaxEdgeLength, RetessellateOptions.NormalTolerance, (CADLibrary::EStitchingTechnique) RetessellateOptions.StitchingTechnique);
CADLibrary::FMeshParameters CadMeshParameters;
CadMeshParameters.bNeedSwapOrientation = MeshParameters.bNeedSwapOrientation;
CadMeshParameters.bIsSymmetric = MeshParameters.bIsSymmetric;
CadMeshParameters.SymmetricNormal = (FVector3f) MeshParameters.SymmetricNormal;
CadMeshParameters.SymmetricOrigin = (FVector3f) MeshParameters.SymmetricOrigin;
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADKernelSurface/Public/CADModelToCADKernelConverterBase.h:71
Scope (from outer to inner):
file
class class FCADModelToCADKernelConverterBase : public CADLibrary::ICADModelConverter
function virtual void SetImportParameters
Source code excerpt:
}
virtual void SetImportParameters(double ChordTolerance, double MaxEdgeLength, double NormalTolerance, CADLibrary::EStitchingTechnique StitchingTechnique) override
{
ImportParameters.SetTesselationParameters(ChordTolerance, MaxEdgeLength, NormalTolerance, StitchingTechnique);
}
virtual bool IsSessionValid() override
{
return true;
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Private/CADOption.cpp:161
Scope (from outer to inner):
file
namespace CADLibrary
function uint32 GetTypeHash
Source code excerpt:
uint32 ParametersHash = ::GetTypeHash(ImportParameters.bGDisableCADKernelTessellation);
ParametersHash = HashCombine(ParametersHash, ::GetTypeHash(ImportParameters.ChordTolerance));
ParametersHash = HashCombine(ParametersHash, ::GetTypeHash(ImportParameters.MaxEdgeLength));
ParametersHash = HashCombine(ParametersHash, ::GetTypeHash(ImportParameters.MaxNormalAngle));
ParametersHash = HashCombine(ParametersHash, ::GetTypeHash(ImportParameters.StitchingTechnique));
return ParametersHash;
}
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:50
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
Source code excerpt:
private:
double ChordTolerance;
double MaxEdgeLength;
double MaxNormalAngle;
EStitchingTechnique StitchingTechnique;
EMesher Mesher;
FDatasmithUtils::EModelCoordSystem ModelCoordSys;
public:
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:78
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function FImportParameters
Source code excerpt:
FImportParameters(FDatasmithUtils::EModelCoordSystem NewCoordinateSystem = FDatasmithUtils::EModelCoordSystem::ZUp_RightHanded)
: ChordTolerance(0.2)
, MaxEdgeLength(0.0)
, MaxNormalAngle(20.0)
, StitchingTechnique(EStitchingTechnique::StitchingNone)
, Mesher(EMesher::TechSoft)
, ModelCoordSys(NewCoordinateSystem)
{
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:88
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function FImportParameters
Source code excerpt:
FImportParameters(const FImportParameters& InParamneters, EMesher InMesher)
: ChordTolerance(InParamneters.ChordTolerance)
, MaxEdgeLength(InParamneters.MaxEdgeLength)
, MaxNormalAngle(InParamneters.MaxNormalAngle)
, StitchingTechnique(InParamneters.StitchingTechnique)
, Mesher(InMesher)
, ModelCoordSys(InParamneters.ModelCoordSys)
{
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:99
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function void SetTesselationParameters
Source code excerpt:
{
ChordTolerance = InChordTolerance * GMeshingParameterFactor;
MaxEdgeLength = InMaxEdgeLength * GMeshingParameterFactor;
MaxNormalAngle = InMaxNormalAngle;
StitchingTechnique = InStitchingTechnique;
Mesher = FImportParameters::bGDisableCADKernelTessellation ? EMesher::TechSoft : EMesher::CADKernel;
}
void SetTesselationParameters(double InChordTolerance, double InMaxEdgeLength, double InMaxNormalAngle, EStitchingTechnique InStitchingTechnique, EMesher InMesher)
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:114
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function uint32 GetHash
Source code excerpt:
{
uint32 Hash = 0;
for (double Param : {ChordTolerance, MaxEdgeLength, MaxNormalAngle, (double) GStitchingForceFactor})
{
Hash = HashCombine(Hash, ::GetTypeHash(Param));
}
for (uint32 Param : {uint32(StitchingTechnique), uint32(Mesher), uint32(ModelCoordSys)})
{
Hash = HashCombine(Hash, ::GetTypeHash(Param));
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:132
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function FArchive& operator<<
Source code excerpt:
{
Ar << ImportParameters.ChordTolerance;
Ar << ImportParameters.MaxEdgeLength;
Ar << ImportParameters.MaxNormalAngle;
Ar << (uint32&) ImportParameters.StitchingTechnique;
Ar << (uint8&) ImportParameters.Mesher;
Ar << (uint8&) ImportParameters.ModelCoordSys;
// these static variables have to be serialized to be transmitted to CADWorkers
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/CADTools/Public/CADOptions.h:173
Scope (from outer to inner):
file
namespace CADLibrary
class class FImportParameters
function double GetMaxEdgeLength
Source code excerpt:
double GetMaxEdgeLength() const
{
return MaxEdgeLength;
}
EStitchingTechnique GetStitchingTechnique() const
{
return StitchingTechnique;
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithCADTranslator/Private/DatasmithCADTranslator.cpp:176
Scope (from outer to inner):
file
function bool FDatasmithCADTranslator::LoadScene
Source code excerpt:
ImportParameters.SetTesselationParameters(CheckParameterValue(TesselationOptions.ChordTolerance, UE::DatasmithTessellation::MinTessellationChord, TEXT("Chord tolerance")),
FMath::IsNearlyZero(TesselationOptions.MaxEdgeLength) ? 0. : CheckParameterValue(TesselationOptions.MaxEdgeLength, UE::DatasmithTessellation::MinTessellationEdgeLength, TEXT("Max Edge Length")),
CheckParameterValue(TesselationOptions.NormalTolerance, UE::DatasmithTessellation::MinTessellationAngle, TEXT("Max Angle")),
(EStitchingTechnique)TesselationOptions.StitchingTechnique);
ImportParameters.SetModelCoordinateSystem(FDatasmithUtils::EModelCoordSystem::ZUp_RightHanded);
UE_LOG(LogCADTranslator, Display, TEXT(" - Import parameters:"));
UE_LOG(LogCADTranslator, Display, TEXT(" - ChordTolerance: %lf"), ImportParameters.GetChordTolerance());
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithOpenNurbsTranslator/Private/DatasmithOpenNurbsImportOptions.cpp:29
Scope (from outer to inner):
file
function bool UDatasmithOpenNurbsImportOptions::CanEditChange
Source code excerpt:
}
else if (PropertyFName == GET_MEMBER_NAME_CHECKED(FDatasmithOpenNurbsOptions, ChordTolerance)
|| PropertyFName == GET_MEMBER_NAME_CHECKED(FDatasmithOpenNurbsOptions, MaxEdgeLength)
|| PropertyFName == GET_MEMBER_NAME_CHECKED(FDatasmithOpenNurbsOptions, NormalTolerance)
|| PropertyFName == GET_MEMBER_NAME_CHECKED(FDatasmithOpenNurbsOptions, StitchingTechnique)
)
{
// Enable tessellation options only when using CAD library to tessellate
return Options.Geometry == EDatasmithOpenNurbsBrepTessellatedSource::UseUnrealNurbsTessellation;
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithOpenNurbsTranslator/Private/DatasmithOpenNurbsTranslator.cpp:2979
Scope (from outer to inner):
file
function bool FOpenNurbsTranslatorImpl::TranslateBRep
Source code excerpt:
{
// Ref. visitBRep
CADModelConverter->SetImportParameters(OpenNurbsOptions.ChordTolerance, OpenNurbsOptions.MaxEdgeLength, OpenNurbsOptions.NormalTolerance, (CADLibrary::EStitchingTechnique)OpenNurbsOptions.StitchingTechnique);
CADModelConverter->InitializeProcess();
OpenNurbsBRepConverter->AddBRep(*Brep, Offset);
CADModelConverter->RepairTopology();
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithPLMXMLTranslator/Private/DatasmithPlmXmlImporter.cpp:251
Scope (from outer to inner):
file
namespace PlmXml
class class FPlmXmlMeshLoaderWithDatasmithDispatcher
function FPlmXmlMeshLoaderWithDatasmithDispatcher
Source code excerpt:
// Setup of import parameters for DatasmithDispatcher copied from FDatasmithCADTranslator's setup
ImportParameters.SetTesselationParameters(TessellationOptions.ChordTolerance, TessellationOptions.MaxEdgeLength, TessellationOptions.NormalTolerance, (CADLibrary::EStitchingTechnique) TessellationOptions.StitchingTechnique);
DatasmithDispatcher = MakeUnique<DatasmithDispatcher::FDatasmithDispatcher>(ImportParameters, CacheDir, CADFileToUEFileMap, CADFileToUEGeomMap);
}
// Adds geom file to load and returns Id to use in InstantiateMesh later(after all is loaded)
int32 AddMeshToLoad(const FString& FullPath)
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithPLMXMLTranslator/Private/DatasmithPlmXmlTranslator.cpp:85
Scope (from outer to inner):
file
function bool FDatasmithPlmXmlTranslator::LoadScene
Source code excerpt:
CommonTessellationOptions.ChordTolerance = CheckParameterValue(CommonTessellationOptions.ChordTolerance, UE::DatasmithTessellation::MinTessellationChord, TEXT("Chord tolerance"));
CommonTessellationOptions.MaxEdgeLength = FMath::IsNearlyZero(CommonTessellationOptions.MaxEdgeLength) ? 0. : CheckParameterValue(CommonTessellationOptions.MaxEdgeLength, UE::DatasmithTessellation::MinTessellationEdgeLength, TEXT("Max Edge Length"));
CommonTessellationOptions.NormalTolerance = CheckParameterValue(CommonTessellationOptions.NormalTolerance, UE::DatasmithTessellation::MinTessellationAngle, TEXT("Max Angle"));
UE_LOG(LogDatasmithXMLPLMTranslator, Display, TEXT(" - Import parameters:"));
UE_LOG(LogDatasmithXMLPLMTranslator, Display, TEXT(" - ChordTolerance: %f"), CommonTessellationOptions.ChordTolerance);
UE_LOG(LogDatasmithXMLPLMTranslator, Display, TEXT(" - MaxEdgeLength: %f"), CommonTessellationOptions.MaxEdgeLength);
UE_LOG(LogDatasmithXMLPLMTranslator, Display, TEXT(" - MaxNormalAngle: %f"), CommonTessellationOptions.NormalTolerance);
FString StitchingTechnique;
switch ((EStitchingTechnique)CommonTessellationOptions.StitchingTechnique)
{
case EStitchingTechnique::StitchingHeal:
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithWireTranslator/Private/DatasmithWireTranslator.cpp:480
Scope (from outer to inner):
file
namespace UE_DATASMITHWIRETRANSLATOR_NAMESPACE
function void FWireTranslatorImpl::SetTessellationOptions
Source code excerpt:
{
TessellationOptions = Options;
CADModelConverter->SetImportParameters(Options.ChordTolerance, Options.MaxEdgeLength, Options.NormalTolerance, (CADLibrary::EStitchingTechnique)Options.StitchingTechnique);
SceneFileHash = HashCombine(Options.GetHash(), GetSceneFileHash(SceneFullPath, SceneName));
}
bool FWireTranslatorImpl::Read()
{
// Initialize Alias.
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/DatasmithWireTranslator/Private/DatasmithWireTranslator.cpp:2435
Scope (from outer to inner):
file
namespace UE_DATASMITHWIRETRANSLATOR_NAMESPACE
function bool FDatasmithWireTranslator::LoadScene
Source code excerpt:
const FDatasmithTessellationOptions& TessellationOptions = GetCommonTessellationOptions();
UE_LOG(LogDatasmithWireTranslator, Display, TEXT(" - ChordTolerance: %lf"), TessellationOptions.ChordTolerance);
UE_LOG(LogDatasmithWireTranslator, Display, TEXT(" - MaxEdgeLength: %lf"), TessellationOptions.MaxEdgeLength);
UE_LOG(LogDatasmithWireTranslator, Display, TEXT(" - MaxNormalAngle: %lf"), TessellationOptions.NormalTolerance);
FString StitchingTechnique;
switch (TessellationOptions.StitchingTechnique)
{
case EDatasmithCADStitchingTechnique::StitchingHeal:
StitchingTechnique = TEXT("Heal");
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurface/Private/TechSoft/TechSoftParametricSurface.cpp:36
Scope (from outer to inner):
file
function bool UTechSoftParametricSurfaceData::Tessellate
Source code excerpt:
{
CADLibrary::FImportParameters ImportParameters((FDatasmithUtils::EModelCoordSystem)SceneParameters.ModelCoordSys);
ImportParameters.SetTesselationParameters(RetessellateOptions.ChordTolerance, RetessellateOptions.MaxEdgeLength, RetessellateOptions.NormalTolerance, (CADLibrary::EStitchingTechnique)RetessellateOptions.StitchingTechnique);
FMeshConversionContext Context(ImportParameters, MeshParameters);
CADLibrary::FTechSoftInterface& TechSoftInterface = CADLibrary::FTechSoftInterface::Get();
bSuccessfulTessellation = TechSoftInterface.InitializeKernel(*FPaths::EnginePluginsDir());
if (bSuccessfulTessellation)
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurface/Public/CADModelConverter.h:47
Scope (from outer to inner):
file
namespace CADLibrary
class class ICADModelConverter
Source code excerpt:
* Tack care to set scale factor before because import parameters will be scale according to scale factor
* @param ChordTolerance : SAG
* @param MaxEdgeLength : max length of element's edge
* @param NormalTolerance : Angle between two adjacent triangles
* @param StitchingTechnique : CAD topology correction technique
* @param bScaleUVMap : Scale the UV map to a world unit.
*/
virtual void SetImportParameters(double ChordTolerance, double MaxEdgeLength, double NormalTolerance, CADLibrary::EStitchingTechnique StitchingTechnique) = 0;
virtual bool IsSessionValid() = 0;
virtual void AddSurfaceDataForMesh(const TCHAR* InFilePath, const FMeshParameters& InMeshParameters, const FDatasmithTessellationOptions& InTessellationOptions, FDatasmithMeshElementPayload& OutMeshPayload) const = 0;
};
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurface/Public/CADModelToTechSoftConverterBase.h:37
Scope (from outer to inner):
file
class class FCADModelToTechSoftConverterBase : public CADLibrary::ICADModelConverter
function virtual void SetImportParameters
Source code excerpt:
virtual bool Tessellate(const CADLibrary::FMeshParameters& InMeshParameters, FMeshDescription& OutMeshDescription) override;
virtual void SetImportParameters(double ChordTolerance, double MaxEdgeLength, double NormalTolerance, CADLibrary::EStitchingTechnique StitchingTechnique) override
{
ImportParameters.SetTesselationParameters(ChordTolerance, MaxEdgeLength, NormalTolerance, StitchingTechnique);
}
virtual bool IsSessionValid() override
{
return true;
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurfaceExtension/Private/DataprepTessellationOperation.cpp:27
Scope (from outer to inner):
file
function void UDataprepTessellationOperation::PostLoad
Source code excerpt:
{
ChordTolerance = TessellationSettings_DEPRECATED.ChordTolerance;
MaxEdgeLength = TessellationSettings_DEPRECATED.MaxEdgeLength;
NormalTolerance = TessellationSettings_DEPRECATED.NormalTolerance;
// Mark TessellationSettings_DEPRECATED as non usable
TessellationSettings_DEPRECATED.ChordTolerance = -MAX_FLT;
}
Super::PostLoad();
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurfaceExtension/Private/DataprepTessellationOperation.h:25
Scope (from outer to inner):
file
class class UDataprepTessellationOperation : public UDataprepOperation
function UDataprepTessellationOperation
Source code excerpt:
UDataprepTessellationOperation()
: ChordTolerance(0.2f)
, MaxEdgeLength(0.0f)
, NormalTolerance(20.0f)
// Mark TessellationSettings_DEPRECATED as non usable
, TessellationSettings_DEPRECATED(-MAX_FLT)
{
}
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/ParametricSurfaceExtension/Private/DataprepTessellationOperation.h:53
Scope (from outer to inner):
file
class class UDataprepTessellationOperation : public UDataprepOperation
Source code excerpt:
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Tessellation Options", meta = (Units = cm, DisplayName = "Max Edge Length", ToolTip = "Maximum length of any edge in the generated triangles. Smaller values make more triangles.", ClampMin = "0.0"))
float MaxEdgeLength;
/**
* Maximum angle between the normal of two triangles generated by the tessellation process.
* The angle is expressed in degree. The smaller the more triangles are generated.
* Default value is 20 degrees.
*/
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithContent/Source/DatasmithContent/Public/DatasmithImportOptions.h:225
Scope (from outer to inner):
file
function FDatasmithTessellationOptions
Source code excerpt:
FDatasmithTessellationOptions(float InChordTolerance = 0.2f, float InMaxEdgeLength = 0.0f, float InNormalTolerance = 20.0f, EDatasmithCADStitchingTechnique InStitchingTechnique = EDatasmithCADStitchingTechnique::StitchingSew)
: ChordTolerance(InChordTolerance)
, MaxEdgeLength(InMaxEdgeLength)
, NormalTolerance(InNormalTolerance)
, StitchingTechnique(InStitchingTechnique)
{
}
/**
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithContent/Source/DatasmithContent/Public/DatasmithImportOptions.h:246
Scope: file
Source code excerpt:
*/
UPROPERTY(config, EditAnywhere, BlueprintReadWrite, AdvancedDisplay, Category = "Geometry & Tessellation Options", meta = (Units = cm, DisplayName = "Max Edge Length", ToolTip = "Maximum length of any edge in the generated triangles. Smaller values make more triangles.", ClampMin = "0.0"))
float MaxEdgeLength;
/**
* Maximum angle between the normal of two triangles generated by the tessellation process.
* The angle is expressed in degree. The smaller the more triangles are generated.
* Default value is 20 degrees, min value is 5 degrees.
*/
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithContent/Source/DatasmithContent/Public/DatasmithImportOptions.h:274
Scope (from outer to inner):
file
function bool operator ==
Source code excerpt:
{
return FMath::IsNearlyEqual(ChordTolerance, Other.ChordTolerance)
&& FMath::IsNearlyEqual(MaxEdgeLength, Other.MaxEdgeLength)
&& FMath::IsNearlyEqual(NormalTolerance, Other.NormalTolerance)
&& StitchingTechnique == Other.StitchingTechnique;
}
uint32 GetHash() const
{
uint32 Hash = uint32(StitchingTechnique);
for (float Param : {ChordTolerance, MaxEdgeLength, NormalTolerance})
{
Hash = HashCombine(Hash, GetTypeHash(Param));
}
return Hash;
}
};
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithContent/Source/DatasmithContent/Public/DatasmithImportOptions.h:308
Scope (from outer to inner):
file
function void operator =
Source code excerpt:
{
ChordTolerance = Other.ChordTolerance;
MaxEdgeLength = Other.MaxEdgeLength;
NormalTolerance = Other.NormalTolerance;
StitchingTechnique = Other.StitchingTechnique;
}
};
/**
#Loc: <Workspace>/Engine/Plugins/Enterprise/DatasmithImporter/Source/DatasmithImporter/Private/DatasmithFileProducer.cpp:1928
Scope (from outer to inner):
file
function void UDatasmithFileProducer::LoadDefaultSettings
Source code excerpt:
GConfig->GetFloat( TessellationSectionName, TEXT("ChordTolerance"), DefaultTessellationOptions.ChordTolerance, DatasmithImporterIni);
GConfig->GetFloat( TessellationSectionName, TEXT("MaxEdgeLength"), DefaultTessellationOptions.MaxEdgeLength, DatasmithImporterIni);
GConfig->GetFloat( TessellationSectionName, TEXT("NormalTolerance"), DefaultTessellationOptions.NormalTolerance, DatasmithImporterIni);
FString StitchingTechnique = GConfig->GetStr( TessellationSectionName, TEXT("StitchingTechnique"), DatasmithImporterIni);
if(StitchingTechnique == TEXT("StitchingHeal"))
{
DefaultTessellationOptions.StitchingTechnique = EDatasmithCADStitchingTechnique::StitchingHeal;
#Loc: <Workspace>/Engine/Plugins/Experimental/MeshModelingToolsetExp/Source/MeshModelingToolsExp/Private/DynamicMeshSculptTool.cpp:1844
Scope (from outer to inner):
file
function void UDynamicMeshSculptTool::ConfigureRemesher
Source code excerpt:
{
// this is the case where we don't want remeshing in smoothing
Remesher.MaxEdgeLength = 3 * InitialEdgeLength;
Remesher.MinEdgeLength = InitialEdgeLength * 0.05;
}
else
{
if (RemeshProperties->PreserveDetail > 0)
{
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/NormalFlowRemesher.cpp:161
Scope (from outer to inner):
file
function void FNormalFlowRemesher::TrackedFaceProjectionPass
Source code excerpt:
}
const double MaxStepDistance = (bIsTuningIteration) ? (0.25 * MaxEdgeLength) : (0.5 * MaxEdgeLength); // kind of arbitrary...
const double SmoothAreaDistance = FillAreaDistanceMultiplier * MaxEdgeLength;
const TFunction<FVector3d(const FDynamicMesh3&, int, double)> UseSmoothFunc = GetSmoothFunction();
// For each triangle, rotate it such that it aligns with closest normal on the target surface.
// Each vertex is then assigned a weighted combination of its corresponding triangle corner positions. The weighting
// is chosen to favor triangles that don't rotate much (i.e. are already aligned with the target surface.)
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/NormalFlowRemesher.cpp:350
Scope (from outer to inner):
file
function void FNormalFlowRemesher::TrackedFaceProjectionPass
lambda-function
Source code excerpt:
const FIndex2i& EdgeVertices = Mesh->GetEdgeV(EdgeID);
const double NewEdgeLength = Distance(TempPosBuffer[EdgeVertices[0]], TempPosBuffer[EdgeVertices[1]]);
if (NewEdgeLength < MinEdgeLength || NewEdgeLength > MaxEdgeLength)
{
EdgeShouldBeQueuedBuffer[EdgeID] = true;
}
});
for (int EdgeID : Mesh->EdgeIndicesItr())
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/NormalFlowRemesher.cpp:399
Scope (from outer to inner):
file
function void FNormalFlowRemesher::TrackedFaceProjectionPass_Serial
Source code excerpt:
InitializeVertexBufferForFacePass();
double MaxStepDistance = (bIsTuningIteration) ? (0.25*MaxEdgeLength) : (0.5*MaxEdgeLength); // kind of arbitrary...
double SmoothAreaDistance = FillAreaDistanceMultiplier * MaxEdgeLength;
TFunction<FVector3d(const FDynamicMesh3&, int, double)> UseSmoothFunc = GetSmoothFunction();
// this function computes rotated position of triangle, such that it
// aligns with face normal on target surface. We accumulate weighted-average
// of vertex positions, which we will then use further down where possible.
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/NormalFlowRemesher.cpp:541
Scope (from outer to inner):
file
function void FNormalFlowRemesher::TrackedFaceProjectionPass_Serial
Source code excerpt:
double NewEdgeLength = Distance(ProjectedPosition, OtherVertexPosition);
if (NewEdgeLength < MinEdgeLength || NewEdgeLength > MaxEdgeLength)
{
QueueEdge(EdgeID);
}
}
}
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/QueueRemesher.cpp:95
Scope (from outer to inner):
file
function int FQueueRemesher::FastSplitIteration
Source code excerpt:
// Because of overhead in ProcessEdge, it is worth it to do a distance-check here
double MaxEdgeLengthSqr = MaxEdgeLength * MaxEdgeLength;
// Callback after an edge is split: enqueue new edges whose lengths are long enough
PostEdgeSplitFunction = [this, &MaxEdgeLengthSqr](int EdgeID, int VertexA, int VertexB, int NewVertex) //-V1047 - This lambda is cleared before routine exit
{
FVector3d NewVertexPosition = Mesh->GetVertex(NewVertex);
for (auto eid : Mesh->VtxEdgesItr(NewVertex))
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/QueueRemesher.cpp:361
Scope (from outer to inner):
file
function void FQueueRemesher::TrackedMoveVerticesParallel
lambda-function
Source code excerpt:
const FVector3d OtherVertexPosition = Mesh->GetVertex(VertexB);
const double NewEdgeLengthSqr = DistanceSquared(SmoothedPosition, OtherVertexPosition);
if (NewEdgeLengthSqr < MinEdgeLength*MinEdgeLength || NewEdgeLengthSqr > MaxEdgeLength*MaxEdgeLength)
{
EdgeShouldBeQueuedBuffer[EdgeID] = true;
}
}
if (TempFlagBuffer[VertexB] && !EdgeShouldBeQueuedBuffer[EdgeID])
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/QueueRemesher.cpp:372
Scope (from outer to inner):
file
function void FQueueRemesher::TrackedMoveVerticesParallel
lambda-function
Source code excerpt:
const FVector3d OtherVertexPosition = Mesh->GetVertex(VertexA);
const double NewEdgeLengthSqr = DistanceSquared(SmoothedPosition, OtherVertexPosition);
if (NewEdgeLengthSqr < MinEdgeLength * MinEdgeLength || NewEdgeLengthSqr > MaxEdgeLength* MaxEdgeLength)
{
EdgeShouldBeQueuedBuffer[EdgeID] = true;
}
}
}, false);
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/QueueRemesher.cpp:442
Scope (from outer to inner):
file
function void FQueueRemesher::TrackedFullSmoothPass_Buffer
lambda-function
Source code excerpt:
double NewEdgeLength = Distance(SmoothedPosition, OtherVertexPosition);
if (NewEdgeLength < MinEdgeLength || NewEdgeLength > MaxEdgeLength)
{
QueueEdge(EdgeID);
}
}
}
};
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/QueueRemesher.cpp:526
Scope (from outer to inner):
file
function void FQueueRemesher::TrackedFullProjectionPass
lambda-function
Source code excerpt:
double NewEdgeLength = Distance(ProjectedPosition, OtherVertexPosition);
if (NewEdgeLength < MinEdgeLength || NewEdgeLength > MaxEdgeLength)
{
QueueEdge(EdgeID);
}
}
}
};
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/Remesher.cpp:12
Scope (from outer to inner):
file
function void FRemesher::SetTargetEdgeLength
Source code excerpt:
// from Botsch paper
//MinEdgeLength = fLength * (4.0/5.0);
//MaxEdgeLength = fLength * (4.0/3.0);
// much nicer!! makes sense as when we split, edges are both > min !
MinEdgeLength = fLength * 0.66;
MaxEdgeLength = fLength * 1.33;
}
void FRemesher::Precompute()
{
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Private/Remesher.cpp:333
Scope (from outer to inner):
file
function FRemesher::EProcessResult FRemesher::ProcessEdge
Source code excerpt:
// if edge length is too long, we want to split it
bool bTriedSplit = false;
if (bEnableSplits && constraint.CanSplit() && edge_len_sqr > MaxEdgeLength*MaxEdgeLength)
{
SaveEdgeBeforeModify(edgeID);
FDynamicMesh3::FEdgeSplitInfo SplitInfo;
COUNT_SPLITS++;
EMeshResult result = Mesh->SplitEdge(edgeID, SplitInfo);
if (result == EMeshResult::Ok)
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/NormalFlowRemesher.h:37
Scope (from outer to inner):
file
namespace UE
namespace Geometry
function class DYNAMICMESH_API FNormalFlowRemesher : public FQueueRemesher { public: FNormalFlowRemesher
Source code excerpt:
bool bSmoothInFillAreas = true;
/// This is used as a multiplier on MaxEdgeLength to determine when we identify points as being in "free" areas
float FillAreaDistanceMultiplier = 0.25;
/// This is used as a multiplier on the Remesher smoothing rate, applied to points identified as being in "free" areas
float FillAreaSmoothMultiplier = 0.25;
/// cap on triangle count, to prevent runaway mesh messes. Ignored if zero.
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/QueueRemesher.h:81
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class FQueueRemesher : public FRemesher
Source code excerpt:
bool bEnableSmoothing;
double MinEdgeLength;
double MaxEdgeLength;
double SmoothSpeedT;
ESmoothTypes SmoothType;
ETargetProjectionMode ProjectionMode;
};
SettingState SavedState;
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/QueueRemesher.h:96
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class FQueueRemesher : public FRemesher
function void PushState
Source code excerpt:
SavedState.bEnableSmoothing = bEnableSmoothing;
SavedState.MinEdgeLength = MinEdgeLength;
SavedState.MaxEdgeLength = MaxEdgeLength;
SavedState.SmoothSpeedT = SmoothSpeedT;
SavedState.SmoothType = SmoothType;
SavedState.ProjectionMode = ProjectionMode;
}
void PopState()
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/QueueRemesher.h:109
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class FQueueRemesher : public FRemesher
function void PopState
Source code excerpt:
bEnableSmoothing = SavedState.bEnableSmoothing;
MinEdgeLength = SavedState.MinEdgeLength;
MaxEdgeLength = SavedState.MaxEdgeLength;
SmoothSpeedT = SavedState.SmoothSpeedT;
SmoothType = SavedState.SmoothType;
ProjectionMode = SavedState.ProjectionMode;
}
#Loc: <Workspace>/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/Remesher.h:80
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class FRemesher : public FMeshRefinerBase
Source code excerpt:
double MinEdgeLength = 1.0;
/** Maximum target edge length. Edges longer than this will be split if possible. */
double MaxEdgeLength = 3.0;
/** Smoothing speed, in range [0,1] */
double SmoothSpeedT = 0.1;
/** Built-in Smoothing types */
enum class ESmoothTypes
#Loc: <Workspace>/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingOperators/Public/CleaningOps/RemeshMeshOp.h:107
Scope (from outer to inner):
file
namespace UE
namespace Geometry
function class MODELINGOPERATORS_API FRemeshMeshOp : public FDynamicMeshOperator { public: virtual ~FRemeshMeshOp
Source code excerpt:
bool bSmoothInFillAreas = true;
/// This is used as a multiplier on MaxEdgeLength to determine when we identify points as being in "free" areas
float FillAreaDistanceMultiplier = 0.25;
/// This is used as a multiplier on the Remesher smoothing rate, applied to points identified as being in "free" areas
float FillAreaSmoothMultiplier = 0.25;
// End normal flow only
#Loc: <Workspace>/Engine/Source/Runtime/GeometryCore/Public/MeshQueries.h:498
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class TMeshQueries
function static double MaxEdgeLength
Source code excerpt:
/// Compute the longest edge length for the given mesh
static double MaxEdgeLength(const TriangleMeshType& Mesh)
{
double MaxLength = 0.0;
for (auto EdgeID : Mesh.EdgeIndicesItr())
{
FVector3d vA, vB;
Mesh.GetEdgeV(EdgeID, vA, vB);
#Loc: <Workspace>/Engine/Source/Runtime/GeometryCore/Public/MeshQueries.h:549
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class TMeshQueries
function static void EdgeLengthStatsFromEdges
Source code excerpt:
/// Given a mesh and a subset of mesh edges, compute the min, max, and mean edge lengths
static void EdgeLengthStatsFromEdges(const TriangleMeshType& Mesh, const TArray<int>& Edges, double& MinEdgeLength,
double& MaxEdgeLength, double& AverageEdgeLength)
{
if (Mesh.EdgeCount() == 0)
{
MinEdgeLength = 0.0;
MaxEdgeLength = 0.0;
AverageEdgeLength = 0.0;
return;
}
MinEdgeLength = BIG_NUMBER;
MaxEdgeLength = -BIG_NUMBER;
AverageEdgeLength = 0;
int EdgeCount = 0;
for (int EdgeID : Edges)
{
if (Mesh.IsEdge(EdgeID))
#Loc: <Workspace>/Engine/Source/Runtime/GeometryCore/Public/MeshQueries.h:572
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class TMeshQueries
function static void EdgeLengthStatsFromEdges
Source code excerpt:
double Length = Distance(A, B);
if (Length < MinEdgeLength) { MinEdgeLength = Length; }
if (Length > MaxEdgeLength) { MaxEdgeLength = Length; }
AverageEdgeLength += Length;
++EdgeCount;
}
}
AverageEdgeLength /= (double)EdgeCount;
#Loc: <Workspace>/Engine/Source/Runtime/GeometryCore/Public/MeshQueries.h:583
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class TMeshQueries
function static void EdgeLengthStats
Source code excerpt:
/// Compute the min, max, and mean edge lengths for the given mesh. Optionally, choose a subest of size NumSamples
/// and compute stats of that subset.
static void EdgeLengthStats(const TriangleMeshType& Mesh, double& MinEdgeLength, double& MaxEdgeLength,
double& AverageEdgeLength, int NumSamples = 0)
{
if (Mesh.EdgeCount() == 0)
{
MinEdgeLength = 0.0;
MaxEdgeLength = 0.0;
AverageEdgeLength = 0.0;
return;
}
MinEdgeLength = BIG_NUMBER;
MaxEdgeLength = -BIG_NUMBER;
AverageEdgeLength = 0;
int MaxID = Mesh.MaxEdgeID();
// if we are only taking some samples, use a prime-modulo-loop instead of random
int PrimeNumber = (NumSamples == 0) ? 1 : 31337;
int MaxCount = (NumSamples == 0) ? MaxID : NumSamples;
#Loc: <Workspace>/Engine/Source/Runtime/GeometryCore/Public/MeshQueries.h:613
Scope (from outer to inner):
file
namespace UE
namespace Geometry
class class TMeshQueries
function static void EdgeLengthStats
Source code excerpt:
double Length = Distance(A, B);
if (Length < MinEdgeLength) MinEdgeLength = Length;
if (Length > MaxEdgeLength) MaxEdgeLength = Length;
AverageEdgeLength += Length;
++EdgeCount;
}
EdgeID = (EdgeID + PrimeNumber) % MaxID;
} while (EdgeID != 0 && EdgeCount < MaxCount);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/TessellationTable.cpp:345
Scope (from outer to inner):
file
namespace Nanite
function void FTessellatedPatch::ProcessEdge
Source code excerpt:
void FTessellatedPatch::ProcessEdge( int EdgeIndex )
{
// MinEdgeLength < MaxEdgeLength/2
const float MinEdgeLength = 0.66f;
const float MaxEdgeLength = 1.33f;
FDynamicMesh3::FEdge Edge = Mesh.GetEdge( EdgeIndex );
FVector3d v0 = Mesh.GetVertex( Edge.Vert[0] );
FVector3d v1 = Mesh.GetVertex( Edge.Vert[1] );
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/TessellationTable.cpp:403
Scope (from outer to inner):
file
namespace Nanite
function void FTessellatedPatch::ProcessEdge
Source code excerpt:
}
if( EdgeLengthSqr > MaxEdgeLength * MaxEdgeLength )
{
float SplitT = 0.5f;
if( bBoundaryEdge )
{
float EdgeLength = FMath::Sqrt( EdgeLengthSqr );
float NumEdgeSplits = FMath::Floor( EdgeLength + 0.5f );