UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
UE::Geometry::FDynamicMeshEditor Class Reference

#include <DynamicMeshEditor.h>

Classes

struct  FLoopPairSet
 

Public Types

enum class  EDuplicateTriBehavior : uint8 { EnsureContinue , EnsureAbort , UseExisting , Replace }
 

Public Member Functions

 FDynamicMeshEditor (FDynamicMesh3 *MeshIn)
 
GEOMETRYCORE_API bool RemoveIsolatedVertices ()
 
GEOMETRYCORE_API bool StitchVertexLoopsMinimal (const TArray< int > &VertexLoop1, const TArray< int > &VertexLoop2, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API bool StitchVertexLoopToTriVidPairSequence (const TArray< TPair< int32, TPair< int8, int8 > > > &TriVidPairs1, const TArray< int > &VertexLoop2, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API bool StitchSparselyCorrespondedVertexLoops (const TArray< int > &VertexIDs1, const TArray< int > &MatchedIndices1, const TArray< int > &VertexIDs2, const TArray< int > &MatchedIndices2, FDynamicMeshEditResult &ResultOut, bool bReverseOrientation=false)
 
GEOMETRYCORE_API bool WeldVertexLoops (const TArray< int32 > &VertexLoop1, const TArray< int32 > &VertexLoop2)
 
GEOMETRYCORE_API bool AddTriangleFan_OrderedVertexLoop (int CenterVertex, const TArray< int > &VertexLoop, int GroupID, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API void DuplicateTriangles (const TArray< int > &Triangles, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API bool DisconnectTriangles (const TArray< int > &Triangles, TArray< FLoopPairSet > &LoopSetOut, bool bHandleBoundaryVertices)
 
GEOMETRYCORE_API bool DisconnectTriangles (const TSet< int > &TriangleSet, const TArray< FEdgeLoop > &BoundaryLoops, TArray< FLoopPairSet > &LoopSetOut, bool bAllowBoundaryVertices)
 
GEOMETRYCORE_API bool DisconnectTrianglesAlongEdges (const TSet< int32 > &Edges, TArray< int32 > *AddedVertexIDs=nullptr)
 
GEOMETRYCORE_API void DisconnectTriangles (const TArray< int > &Triangles, bool bPreventBowties=true)
 
GEOMETRYCORE_API void SplitBowties (FDynamicMeshEditResult &ResultOut)
 
void SplitBowties (int VertexID, TArray< int32 > *NewVertices=nullptr)
 
void SplitBowties (int VertexID, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API void SplitBowtiesAtTriangles (const TArray< int32 > &TriangleIDs, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API bool ReinsertSubmesh (const FDynamicSubmesh3 &Submesh, FOptionallySparseIndexMap &SubToNewV, TArray< int > *NewTris=nullptr, EDuplicateTriBehavior DuplicateBehavior=EDuplicateTriBehavior::EnsureAbort)
 
GEOMETRYCORE_API bool RemoveTriangles (const TArray< int > &Triangles, bool bRemoveIsolatedVerts)
 
GEOMETRYCORE_API int RemoveSmallComponents (double MinVolume, double MinArea=0.0, int MinTriangleCount=0)
 
GEOMETRYCORE_API bool RemoveTriangles (const TArray< int > &Triangles, bool bRemoveIsolatedVerts, TFunctionRef< void(int)> OnRemoveTriFunc)
 
GEOMETRYCORE_API void ReverseTriangleOrientations (const TArray< int > &Triangles, bool bInvertNormals)
 
GEOMETRYCORE_API void InvertTriangleNormals (const TArray< int > &Triangles)
 
GEOMETRYCORE_API FVector3f ComputeAndSetQuadNormal (const FIndex2i &QuadTris, bool bIsPlanar=false)
 
GEOMETRYCORE_API void SetQuadNormals (const FIndex2i &QuadTris, const FVector3f &Normal)
 
GEOMETRYCORE_API void SetTriangleNormals (const TArray< int > &Triangles, const FVector3f &Normal)
 
GEOMETRYCORE_API void SetTriangleNormals (const TArray< int > &Triangles)
 
GEOMETRYCORE_API void SetTubeNormals (const TArray< int > &Triangles, const TArray< int > &VertexIDs1, const TArray< int > &MatchedIndices1, const TArray< int > &VertexIDs2, const TArray< int > &MatchedIndices2, bool bReverseNormals=false)
 
GEOMETRYCORE_API void SetQuadUVsFromProjection (const FIndex2i &QuadTris, const FFrame3d &ProjectionFrame, float UVScaleFactor=1.0f, const FVector2f &UVTranslation=FVector2f::Zero(), int UVLayerIndex=0)
 
GEOMETRYCORE_API void SetTriangleUVsFromProjection (const TArray< int32 > &Triangles, const FFrame3d &ProjectionFrame, float UVScaleFactor=1.0f, const FVector2f &UVTranslation=FVector2f::Zero(), bool bShiftToOrigin=true, int32 UVLayerIndex=0)
 
GEOMETRYCORE_API void SetTriangleUVsFromProjection (const TArray< int > &Triangles, const FFrame3d &ProjectionFrame, const FVector2f &UVScale=FVector2f::One(), const FVector2f &UVTranslation=FVector2f::Zero(), int UVLayerIndex=0, bool bShiftToOrigin=true, bool bNormalizeBeforeScaling=false)
 
GEOMETRYCORE_API void SetGeneralTubeUVs (const TArray< int > &Triangles, const TArray< int > &VertexIDs1, const TArray< int > &MatchedIndices1, const TArray< int > &VertexIDs2, const TArray< int > &MatchedIndices2, const TArray< float > &UValues, const FVector3f &VDir, float UVScaleFactor=1.0f, const FVector2f &UVTranslation=FVector2f::Zero(), int UVLayerIndex=0)
 
GEOMETRYCORE_API void RescaleAttributeUVs (float UVScale=1.0f, bool bWorldSpace=false, int UVLayerIndex=0, TOptional< FTransformSRT3d > ToWorld=TOptional< FTransformSRT3d >())
 
GEOMETRYCORE_API int FindOrCreateDuplicateVertex (int VertexID, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API int FindOrCreateDuplicateGroup (int TriangleID, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API int FindOrCreateDuplicateUV (int ElementID, int UVLayerIndex, FMeshIndexMappings &IndexMaps)
 
GEOMETRYCORE_API int FindOrCreateDuplicateNormal (int ElementID, int NormalLayerIndex, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult *ResultOut=nullptr)
 
GEOMETRYCORE_API int FindOrCreateDuplicateColor (int ElementID, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult *ResultOut)
 
GEOMETRYCORE_API void CopyAttributes (int FromTriangleID, int ToTriangleID, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult &ResultOut)
 
GEOMETRYCORE_API void AppendMesh (const FDynamicMesh3 *AppendMesh, FMeshIndexMappings &IndexMapsOut, TFunction< FVector3d(int, const FVector3d &)> PositionTransform=nullptr, TFunction< FVector3d(int, const FVector3d &)> NormalTransform=nullptr, bool bReverseOrientation=false)
 
GEOMETRYCORE_API void AppendMesh (const TTriangleMeshAdapter< double > *AppendMesh, FMeshIndexMappings &IndexMapsOut, TFunction< FVector3d(int, const FVector3d &)> PositionTransform=nullptr)
 
GEOMETRYCORE_API void AppendNormals (const FDynamicMesh3 *AppendMesh, const FDynamicMeshNormalOverlay *FromNormals, FDynamicMeshNormalOverlay *ToNormals, const FIndexMapi &VertexMap, const FIndexMapi &TriangleMap, TFunction< FVector3d(int, const FVector3d &)> NormalTransform, FIndexMapi &NormalMapOut)
 
GEOMETRYCORE_API void AppendUVs (const FDynamicMesh3 *AppendMesh, const FDynamicMeshUVOverlay *FromUVs, FDynamicMeshUVOverlay *ToUVs, const FIndexMapi &VertexMap, const FIndexMapi &TriangleMap, FIndexMapi &UVMapOut)
 
GEOMETRYCORE_API void AppendColors (const FDynamicMesh3 *AppendMesh, const FDynamicMeshColorOverlay *FromOverlay, FDynamicMeshColorOverlay *ToOverlay, const FIndexMapi &VertexMap, const FIndexMapi &TriangleMap, FIndexMapi &ColorMapOut)
 
template<typename RealType , int ElementSize>
GEOMETRYCORE_API void AppendElementSubset (const FDynamicMesh3 *FromMesh, const TSet< int > &TriangleROI, const TSet< int > &VertexROI, const TDynamicMeshOverlay< RealType, ElementSize > *FromOverlay, TDynamicMeshOverlay< RealType, ElementSize > *ToOverlay)
 
GEOMETRYCORE_API void AppendTriangles (const FDynamicMesh3 *SourceMesh, const TArrayView< const int > &SourceTriangles, FMeshIndexMappings &IndexMaps, FDynamicMeshEditResult &ResultOut, bool bComputeTriangleMap=true)
 
template<typename RealType , int ElementSize>
void AppendElementSubset (const FDynamicMesh3 *FromMesh, const TSet< int > &TriangleROI, const TSet< int > &VertexROI, const TDynamicMeshOverlay< RealType, ElementSize > *FromOverlay, TDynamicMeshOverlay< RealType, ElementSize > *ToOverlay)
 

Static Public Member Functions

static GEOMETRYCORE_API bool ConvertLoopToTriVidPairSequence (const FDynamicMesh3 &Mesh, const TArray< int32 > &VidLoop, const TArray< int32 > &EdgeLoop, TArray< TPair< int32, TPair< int8, int8 > > > &TriVertPairsOut)
 
static GEOMETRYCORE_API bool SplitMesh (const FDynamicMesh3 *SourceMesh, TArray< FDynamicMesh3 > &SplitMeshes, TFunctionRef< int(int)> TriIDToMeshID, int DeleteMeshID=-1, TArray< int32 > *MeshIDPerSplitMesh=nullptr, bool bSortByMeshID=false)
 
static GEOMETRYCORE_API bool RemoveSeamsAtEdges (const TSet< int32 > &EidsToRemoveAsSeams, TDynamicMeshOverlay< float, 2 > *Overlay)
 
static GEOMETRYCORE_API bool RemoveSeamsAtEdges (const TSet< int32 > &EidsToRemoveAsSeams, TDynamicMeshOverlay< float, 3 > *Overlay)
 
static GEOMETRYCORE_API bool CreateSeamsAtEdges (const TSet< int32 > &EidsToMakeIntoSeams, TDynamicMeshOverlay< float, 2 > *Overlay, TArray< int32 > *AddedElementIDs=nullptr)
 
static GEOMETRYCORE_API bool CreateSeamsAtEdges (const TSet< int32 > &EidsToMakeIntoSeams, TDynamicMeshOverlay< float, 3 > *Overlay, TArray< int32 > *AddedElementIDs=nullptr)
 

Public Attributes

FDynamicMesh3Mesh
 

Detailed Description

FDynamicMeshEditor implements low-level mesh editing operations. These operations can be used to construct higher-level operations. For example an Extrude operation could be implemented via DuplicateTriangles() and StitchLoopMinimal().

Member Enumeration Documentation

◆ EDuplicateTriBehavior

In ReinsertSubmesh, a problem can arise where the mesh we are inserting has duplicate triangles of the base mesh.

This can lead to problematic behavior later. We can do various things, like delete and replace that existing triangle, or just use it instead of adding a new one. Or fail, or ignore it.

This enum/argument controls the behavior. However, fundamentally this kind of problem should be handled upstream!! For example by not trying to remesh areas that contain nonmanifold geometry...

Enumerator
EnsureContinue 
EnsureAbort 
UseExisting 
Replace 

Constructor & Destructor Documentation

◆ FDynamicMeshEditor()

UE::Geometry::FDynamicMeshEditor::FDynamicMeshEditor ( FDynamicMesh3 MeshIn)
inline

Member Function Documentation

◆ AddTriangleFan_OrderedVertexLoop()

bool FDynamicMeshEditor::AddTriangleFan_OrderedVertexLoop ( int  CenterVertex,
const TArray< int > &  VertexLoop,
int  GroupID,
FDynamicMeshEditResult ResultOut 
)

Fill hole with a triangle fan given an existing (unconnected) center vertex and an ordered loop of boundary vertices on the hole border.

Parameters
CenterVertexIndex of floating vertex in the center of the hole
VertexLoopIndices of vertices on the boundary of the hole, in order
ResultOutlists of newly created triangles
Returns
true if operation succeeded. If a failure occurs, any added triangles are removed via RemoveTriangles.

◆ AppendColors()

void FDynamicMeshEditor::AppendColors ( const FDynamicMesh3 AppendMesh,
const FDynamicMeshColorOverlay FromOverlay,
FDynamicMeshColorOverlay ToOverlay,
const FIndexMapi VertexMap,
const FIndexMapi TriangleMap,
FIndexMapi ColorMapOut 
)

Append Colors from one attribute overlay to another. Assumes that AppendMesh has already been appended to Mesh. Note that this function has no dependency on .Mesh, it could be static

Parameters
AppendMeshmesh that owns FromOverlay attribute overlay
FromOverlayColor overlay we want to append from (owned by AppendMesh)
ToOverlayColor overlay we want to append to (owned by Mesh)
VertexMapmap from AppendMesh vertex IDs to vertex IDs applicable to ToOverlay (ie of .Mesh)
TriangleMapmap from AppendMesh triangle IDs to triangle IDs applicable to ToOverlay (ie of .Mesh)
ColorMapOutMapping from element IDs of FromUVs to new element IDs in ToOverlay

◆ AppendElementSubset() [1/2]

template<typename RealType , int ElementSize>
void UE::Geometry::FDynamicMeshEditor::AppendElementSubset ( const FDynamicMesh3 FromMesh,
const TSet< int > &  TriangleROI,
const TSet< int > &  VertexROI,
const TDynamicMeshOverlay< RealType, ElementSize > *  FromOverlay,
TDynamicMeshOverlay< RealType, ElementSize > *  ToOverlay 
)

◆ AppendElementSubset() [2/2]

template<typename RealType , int ElementSize>
GEOMETRYCORE_API void UE::Geometry::FDynamicMeshEditor::AppendElementSubset ( const FDynamicMesh3 FromMesh,
const TSet< int > &  TriangleROI,
const TSet< int > &  VertexROI,
const TDynamicMeshOverlay< RealType, ElementSize > *  FromOverlay,
TDynamicMeshOverlay< RealType, ElementSize > *  ToOverlay 
)

Append overlay elements in both ROIs from one overlay to another

Parameters
FromMeshMesh that owns FromOverlay attribute overlay
TriangleROITriangles containing the copied overlay elements
VertexROIParent vertices of the copied overlay elements
FromOverlayOverlay we want to append from (owned by FromMesh)
ToOverlayOverlay we want to append into (owned by .Mesh)
Note
Required overloads should be declared in the .cpp file

◆ AppendMesh() [1/2]

void FDynamicMeshEditor::AppendMesh ( const FDynamicMesh3 AppendMesh,
FMeshIndexMappings IndexMapsOut,
TFunction< FVector3d(int, const FVector3d &)>  PositionTransform = nullptr,
TFunction< FVector3d(int, const FVector3d &)>  NormalTransform = nullptr,
bool  bReverseOrientation = false 
)

Append input mesh to our internal mesh

Parameters
AppendMeshmesh to append
IndexMapsOutmesh element index mappings generated in this append operation
PositionTransformoptional transformation function applied to mesh vertex positions
NormalTransformoptional transformation function applied to mesh normals

◆ AppendMesh() [2/2]

void FDynamicMeshEditor::AppendMesh ( const TTriangleMeshAdapter< double > *  AppendMesh,
FMeshIndexMappings IndexMapsOut,
TFunction< FVector3d(int, const FVector3d &)>  PositionTransform = nullptr 
)

Append input mesh to our internal Mesh. If the internal Mesh has attributes enabled, per-triangle normals will be computed and set. No other attributes are initialized.

Parameters
AppendMeshmesh to append
IndexMapsOutmesh element index mappings generated in this append operation
PositionTransformoptional transformation function applied to mesh vertex positions

◆ AppendNormals()

void FDynamicMeshEditor::AppendNormals ( const FDynamicMesh3 AppendMesh,
const FDynamicMeshNormalOverlay FromNormals,
FDynamicMeshNormalOverlay ToNormals,
const FIndexMapi VertexMap,
const FIndexMapi TriangleMap,
TFunction< FVector3d(int, const FVector3d &)>  NormalTransform,
FIndexMapi NormalMapOut 
)

Append normals from one attribute overlay to another. Assumes that AppendMesh has already been appended to Mesh. Note that this function has no dependency on .Mesh, it could be static

Parameters
AppendMeshmesh that owns FromNormals attribute overlay
FromNormalsNormals overlay we want to append from (owned by AppendMesh)
ToNormalsNormals overlay we want to append to (owned by Mesh)
VertexMapmap from AppendMesh vertex IDs to vertex IDs applicable to ToNormals (ie of .Mesh)
TriangleMapmap from AppendMesh triangle IDs to triangle IDs applicable to ToNormals (ie of .Mesh)
NormalTransformoptional transformation function applied to mesh normals
NormalMapOutMapping from element IDs of FromNormals to new element IDs in ToNormals

◆ AppendTriangles()

void FDynamicMeshEditor::AppendTriangles ( const FDynamicMesh3 SourceMesh,
const TArrayView< const int > &  SourceTriangles,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut,
bool  bComputeTriangleMap = true 
)

Append triangles of an existing mesh. This duplicates the current groups and also any attributes existing on the triangles.

Parameters
SourceMeshthe mesh to copy from
SourceTrianglesthe triangles to copy
IndexMapsreturned mappings from old to new triangles/vertices/etc (you may initialize to optimize memory usage, etc)
ResultOutlists of newly created triangles/vertices/etc
bComputeTriangleMapif true, computes the triangle map section of IndexMaps (which is not needed for the append to work, so is optional)

◆ AppendUVs()

void FDynamicMeshEditor::AppendUVs ( const FDynamicMesh3 AppendMesh,
const FDynamicMeshUVOverlay FromUVs,
FDynamicMeshUVOverlay ToUVs,
const FIndexMapi VertexMap,
const FIndexMapi TriangleMap,
FIndexMapi UVMapOut 
)

Append UVs from one attribute overlay to another. Assumes that AppendMesh has already been appended to Mesh. Note that this function has no dependency on .Mesh, it could be static

Parameters
AppendMeshmesh that owns FromUVs attribute overlay
FromUVsUV overlay we want to append from (owned by AppendMesh)
ToUVsUV overlay we want to append to (owned by Mesh)
VertexMapmap from AppendMesh vertex IDs to vertex IDs applicable to ToUVs (ie of .Mesh)
TriangleMapmap from AppendMesh triangle IDs to triangle IDs applicable to ToUVs (ie of .Mesh)
UVMapOutMapping from element IDs of FromUVs to new element IDs in ToUVs

◆ ComputeAndSetQuadNormal()

FVector3f FDynamicMeshEditor::ComputeAndSetQuadNormal ( const FIndex2i QuadTris,
bool  bIsPlanar = false 
)

Calculate and set the per-triangle normals of the two input quads. Average of the two face normals is used unless the quad is planar

Parameters
QuadTrispair of triangle IDs. If second ID is invalid, it is ignored
bIsPlanarif the quad is known to be planar, operation is more efficient
Returns
the normal vector that was set

◆ ConvertLoopToTriVidPairSequence()

bool FDynamicMeshEditor::ConvertLoopToTriVidPairSequence ( const FDynamicMesh3 Mesh,
const TArray< int32 > &  VidLoop,
const TArray< int32 > &  EdgeLoop,
TArray< TPair< int32, TPair< int8, int8 > > > &  TriVertPairsOut 
)
static

Converts a loop to a sequence of edge identifiers that are both Vid and Eid independent. The identifiers are of the form (TriangleID, ([0,2] vert sub index, [0,2] vert sub index)), and they are used in some cases (extrude, inset) where we want to perform vertex splits along a region boundary (to remove bowties) but need to maintain a record of the original loop path. We don't use (TriangleID, Eid sub index) because that makes it harder to keep track of individual edge directionality.

Parameters
VidLoopVertex IDs of loop to convert.
EdgeLoopEdge IDs of loop to convert, must match VidLoop.
TriVertPairsOutOutput
Returns
false if not successful (usually due to a mismatch between VidLoop and EdgeLoop).

◆ CopyAttributes()

void FDynamicMeshEditor::CopyAttributes ( int  FromTriangleID,
int  ToTriangleID,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut 
)

Copy all attribute-layer values from one triangle to another, using the IndexMaps to track and re-use shared attribute values.

Parameters
FromTriangleIDsource triangle
ToTriangleIDdestination triangle
IndexMapsmappings passed to FindOrCreateDuplicateX functions to track already-created attributes
ResultOutinformation about new attributes is stored here (

◆ CreateSeamsAtEdges() [1/2]

bool FDynamicMeshEditor::CreateSeamsAtEdges ( const TSet< int32 > &  EidsToMakeIntoSeams,
TDynamicMeshOverlay< float, 2 > *  Overlay,
TArray< int32 > *  AddedElementIDs = nullptr 
)
static

Cut existing 2D attribute overlay topology with a set of edges. This allows for creating partial seams/darts, interior cuts, etc.

Avoids creating bowties in the overlay. In cases where an edge is not next to any present or future seams/borders, some adjacent edge will be picked to be made into a seam as well, since it's impossible to make the original into a seam otherwise.

Parameters
EidsToMakeIntoSeamslist of edges to turn into seams
AddedElementIDsif non-null, list of new elements created along the path will be stored here (not ordered)
Returns
true on success

◆ CreateSeamsAtEdges() [2/2]

bool FDynamicMeshEditor::CreateSeamsAtEdges ( const TSet< int32 > &  EidsToMakeIntoSeams,
TDynamicMeshOverlay< float, 3 > *  Overlay,
TArray< int32 > *  AddedElementIDs = nullptr 
)
static

Cut existing 3D attribute overlay topology with a set of edges. This allows for creating partial seams/darts, interior cuts, etc.

Avoids creating bowties in the overlay. In cases where an edge is not next to any present or future seams/borders, some adjacent edge will be picked to be made into a seam as well, since it's impossible to make the original into a seam otherwise.

Parameters
EidsToMakeIntoSeamslist of edges to turn into seams
AddedElementIDsif non-null, list of new elements created along the path will be stored here (not ordered)
Returns
true on success

◆ DisconnectTriangles() [1/3]

void FDynamicMeshEditor::DisconnectTriangles ( const TArray< int > &  Triangles,
bool  bPreventBowties = true 
)

Disconnects triangles (without constructing boundary loops) such that the input Triangles are not connected to any other triangles in the mesh

Parameters
Trianglesset of triangles
bPreventBowtiesdo some additional processing and vertex splitting as needed to prevent the creation of any new bowties

◆ DisconnectTriangles() [2/3]

bool FDynamicMeshEditor::DisconnectTriangles ( const TArray< int > &  Triangles,
TArray< FLoopPairSet > &  LoopSetOut,
bool  bHandleBoundaryVertices 
)

Finds boundary loops of connected components of a set of triangles, and duplicates the vertices along the boundary, such that the triangles become disconnected. If the triangle set includes boundary vertices, they cannot be disconnected as they will become unreferenced. The function returns false if boundary vertices are found, unless bHandleBoundaryVertices = true. In that case, the boundary vertex is duplicated, and the original vertex is kept with the "Inner" loop. The new unreferenced vertex is left on the "Outer" loop, and the attached edges do not exist so are set as InvalidID. The FLoopPairSet.bOuterIncludesIsolatedVertices flag is set to true if boundary vertices are encountered. Note: This function can create a mesh with bowties if you pass in a subset of triangles that would have bowtie connectivity. (it is impossible to create the paired LoopSetOut with 1:1 vertex pairs without leaving in the bowties?)

Parameters
Trianglesset of triangles
LoopSetOutset of boundary loops. LoopA is original loop which remains with "outer" triangles, and LoopB is new boundary loop of triangle set
bHandleBoundaryVerticesif true, boundary vertices are handled as described above, otherwise function aborts and returns false if a boundary vertex is encountered
Returns
true on success

◆ DisconnectTriangles() [3/3]

bool FDynamicMeshEditor::DisconnectTriangles ( const TSet< int > &  TriangleSet,
const TArray< FEdgeLoop > &  BoundaryLoops,
TArray< FLoopPairSet > &  LoopSetOut,
bool  bAllowBoundaryVertices 
)

Variant of DisconnectTriangles that takes a precomputed set of BoundaryLoops of the triangles, and a TSet of Triangles. These are both computed internally by the version that only takes a TArray of Triangles.

Warning
If the BoundaryLoops are not correct for the provided TriangleSet, this version will likely crash.
Parameters
Trianglesset of triangles
BoundaryLoopsprecomputed set of boundary EdgeLoops of TriangleSet
LoopSetOutreturned set of boundary loops. LoopA is original loop which remains with "outer" triangles previously connected to TriangleSet, and LoopB is new boundary loop of TriangleSet
bAllowBoundaryVerticesif true, mesh boundary vertices are duplicated and left on the 'outer' loop, otherwise function aborts and returns false if a boundary vertex is encountered

◆ DisconnectTrianglesAlongEdges()

bool FDynamicMeshEditor::DisconnectTrianglesAlongEdges ( const TSet< int32 > &  Edges,
TArray< int32 > *  AddedVertexIDs = nullptr 
)

Disconnect triangles along the given Edges, so that all input edges become boundary edges.

Parameters
EdgesIDs of edges to disconnect
AddedVertexIDsOptional array of vertices added by this operation
Parameters
TIDsUntilNextBoundaryTIDs in a fan away from EID around VID until the next boundary. Will be the entire one-ring if the given EID is the only boundary attached to VID.

◆ DuplicateTriangles()

void FDynamicMeshEditor::DuplicateTriangles ( const TArray< int > &  Triangles,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut 
)

Duplicate triangles of a mesh. This duplicates the current groups and also any attributes existing on the triangles.

Parameters
Trianglesthe triangles to duplicate
IndexMapsreturned mappings from old to new triangles/vertices/etc (you may initialize to optimize memory usage, etc)
ResultOutlists of newly created triangles/vertices/etc

Make a copy of provided triangles, with new vertices. You provide IndexMaps because you know if you are doing a small subset or a full-mesh-copy.

◆ FindOrCreateDuplicateColor()

int FDynamicMeshEditor::FindOrCreateDuplicateColor ( int  ElementID,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut 
)

Find "new" color for input color element under Index mapping, or create new if missing

Parameters
ElementIDthe source color we want a duplicate of
IndexMapssource/destination mapping of already-duplicated colors
ResultOutany newly created element indices are stored in NewColorOverlayElements here.
Returns
index of duplicate color in given color layer

◆ FindOrCreateDuplicateGroup()

int FDynamicMeshEditor::FindOrCreateDuplicateGroup ( int  TriangleID,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut 
)

Find "new" group for input group under Index mapping, or create new if missing

Parameters
TriangleIDthe source triangle whose group we want a copy of
IndexMapssource/destination mapping of already-duplicated groups
ResultOutnewly-created groups are stored here
Returns
index of duplicate group

◆ FindOrCreateDuplicateNormal()

int FDynamicMeshEditor::FindOrCreateDuplicateNormal ( int  ElementID,
int  NormalLayerIndex,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut = nullptr 
)

Find "new" normal for input normal element under Index mapping, or create new if missing

Parameters
ElementIDthe source normal we want a duplicate of
NormalLayerIndexwhich normal layer to consider
IndexMapssource/destination mapping of already-duplicated normals
ResultOutany newly created element indices are stored in NewNormalOverlayElements here. Note that NewNormalOverlayElements must have size > NormalLayerIndex.
Returns
index of duplicate normal in given normal layer

◆ FindOrCreateDuplicateUV()

int FDynamicMeshEditor::FindOrCreateDuplicateUV ( int  ElementID,
int  UVLayerIndex,
FMeshIndexMappings IndexMaps 
)

Find "new" UV for input UV element under Index mapping, or create new if missing

Parameters
ElementIDthe source UV we want a duplicate of
UVLayerIndexwhich UV layer to consider
IndexMapssource/destination mapping of already-duplicated UVs
Returns
index of duplicate UV in given UV layer

◆ FindOrCreateDuplicateVertex()

int FDynamicMeshEditor::FindOrCreateDuplicateVertex ( int  VertexID,
FMeshIndexMappings IndexMaps,
FDynamicMeshEditResult ResultOut 
)

Find "new" vertex for input vertex under Index mapping, or create new if missing

Parameters
VertexIDthe source vertex we want a copy of
IndexMapssource/destination mapping of already-duplicated vertices
ResultOutnewly-created vertices are stored here
Returns
index of duplicate vertex

◆ InvertTriangleNormals()

void FDynamicMeshEditor::InvertTriangleNormals ( const TArray< int > &  Triangles)

Flip the normals of the given triangles. This includes their vertex normals, if they exist, as well as any per-triangle attribute normals.

Parameters
Trianglesthe triangles to modify

◆ ReinsertSubmesh()

bool FDynamicMeshEditor::ReinsertSubmesh ( const FDynamicSubmesh3 Submesh,
FOptionallySparseIndexMap SubToNewV,
TArray< int > *  NewTris = nullptr,
EDuplicateTriBehavior  DuplicateBehavior = EDuplicateTriBehavior::EnsureAbort 
)

Update a Base Mesh from a Submesh; See FMeshRegionOperator::BackPropropagate for a usage example.

Assumes that Submesh has been modified, but boundary loop has been preserved, and that old submesh has already been removed from this mesh. Just appends new vertices and rewrites triangles.

Parameters
SubmeshThe mesh to insert back into its BaseMesh. The original submesh triangles should have already been removed when this function is called
SubToNewVMapping from submesh to vertices in the updated base mesh
NewTrisIf not null, will be filled with IDs of triangles added to the base mesh
DuplicateBehaviorChoice of what to do if inserting a triangle from the submesh would duplicate a triangle in the base mesh
Returns
true if submesh successfully inserted, false if any triangles failed (which happens if triangle would result in non-manifold mesh)

◆ RemoveIsolatedVertices()

bool FDynamicMeshEditor::RemoveIsolatedVertices ( )

Remove any vertices that are not used by any triangles

◆ RemoveSeamsAtEdges() [1/2]

bool FDynamicMeshEditor::RemoveSeamsAtEdges ( const TSet< int32 > &  EidsToRemoveAsSeams,
TDynamicMeshOverlay< float, 2 > *  Overlay 
)
static

Merge any seams in the given 2D attribute Overlay along the given mesh edge IDs

Parameters
EidsToRemoveAsSeamslist of edges to remove seams from
Returns
true on success

◆ RemoveSeamsAtEdges() [2/2]

bool FDynamicMeshEditor::RemoveSeamsAtEdges ( const TSet< int32 > &  EidsToRemoveAsSeams,
TDynamicMeshOverlay< float, 3 > *  Overlay 
)
static

Merge any seams in the given (3D attribute) Overlay along the given mesh edge IDs

Parameters
EidsToRemoveAsSeamslist of edges to remove seams from
Returns
true on success

◆ RemoveSmallComponents()

int FDynamicMeshEditor::RemoveSmallComponents ( double  MinVolume,
double  MinArea = 0.0,
int  MinTriangleCount = 0 
)

Remove any connected components with volume or area below the given thresholds

Parameters
MinVolumeRemove components with less volume than this
MinAreaRemove components with less area than this
Returns
number of components removed

◆ RemoveTriangles() [1/2]

bool FDynamicMeshEditor::RemoveTriangles ( const TArray< int > &  Triangles,
bool  bRemoveIsolatedVerts 
)

Remove a list of triangles from the mesh, and optionally any vertices that are now orphaned

Parameters
Trianglesthe triangles to remove
bRemoveIsolatedVertsif true, remove vertices that end up with no triangles
Returns
true if all removes succeeded

◆ RemoveTriangles() [2/2]

bool FDynamicMeshEditor::RemoveTriangles ( const TArray< int > &  Triangles,
bool  bRemoveIsolatedVerts,
TFunctionRef< void(int)>  OnRemoveTriFunc 
)

Remove a list of triangles from the mesh, and optionally any vertices that are now orphaned

Parameters
Trianglesthe triangles to remove
bRemoveIsolatedVertsif true, remove vertices that end up with no triangles
OnRemoveTriFunccalled for each triangle to be removed
Returns
true if all removes succeeded

◆ RescaleAttributeUVs()

void FDynamicMeshEditor::RescaleAttributeUVs ( float  UVScale = 1.0f,
bool  bWorldSpace = false,
int  UVLayerIndex = 0,
TOptional< FTransformSRT3d ToWorld = TOptional<FTransformSRT3d>() 
)

Rescale UVs for the whole mesh, for the given UV attribute layer

Parameters
UVScaleScale factor to multiply into UVs. If in world space, this is in centimeters relative to the average UV scale
bWorldSpaceIf true, UVs are rescaled relative to an absolute world scale.
UVLayerIndexwhich UV layer to operate on (must exist)
ToWorldOptionally transform vertices for world space scaling

◆ ReverseTriangleOrientations()

void FDynamicMeshEditor::ReverseTriangleOrientations ( const TArray< int > &  Triangles,
bool  bInvertNormals 
)

Reverse the orientation of the given triangles, and optionally flip relevant normals

Parameters
Trianglesthe triangles to modify
bInvertNormalsif ture we call InvertTriangleNormals()

◆ SetGeneralTubeUVs()

void FDynamicMeshEditor::SetGeneralTubeUVs ( const TArray< int > &  Triangles,
const TArray< int > &  VertexIDs1,
const TArray< int > &  MatchedIndices1,
const TArray< int > &  VertexIDs2,
const TArray< int > &  MatchedIndices2,
const TArray< float > &  UValues,
const FVector3f VDir,
float  UVScaleFactor = 1.0f,
const FVector2f UVTranslation = FVector2f::Zero(),
int  UVLayerIndex = 0 
)

For triangles connecting loops of corresponded vertices, set UVs in a cylindrical pattern so that the U coordinate starts at 0 for the first corresponded pair of vertices, and cycles around to 1 Assumes Triangles array stores indices of triangles in progressively filling the tube, starting with VertexIDs*[0]. (This is used to set the UVs correctly at the seam joining the start & end of the loop)

◆ SetQuadNormals()

void FDynamicMeshEditor::SetQuadNormals ( const FIndex2i QuadTris,
const FVector3f Normal 
)

Create and set new shared per-triangle normals for a pair of triangles that share one edge (ie a quad)

Parameters
QuadTrispair of triangle IDs. If second ID is invalid, it is ignored
Normalnormal vector to set

◆ SetQuadUVsFromProjection()

void FDynamicMeshEditor::SetQuadUVsFromProjection ( const FIndex2i QuadTris,
const FFrame3d ProjectionFrame,
float  UVScaleFactor = 1.0f,
const FVector2f UVTranslation = FVector2f::Zero(),
int  UVLayerIndex = 0 
)

Project the two triangles of the quad onto a plane defined by the ProjectionFrame and use that to create/set new shared per-triangle UVs. UVs are translated so that their bbox min-corner is at origin, and scaled by given scale factor

Parameters
QuadTrispair of triangle IDs. If second ID is invalid, it is ignored
ProjectFramevertices are projected into XY axes of this frame
UVScaleFactorUVs are scaled by this uniform scale factor
UVTranslationUVs are translated after scaling
UVLayerIndexwhich UV layer to operate on (must exist)

◆ SetTriangleNormals() [1/2]

void FDynamicMeshEditor::SetTriangleNormals ( const TArray< int > &  Triangles)

Create and set new shared per-triangle normals for a list of triangles. Normal at each vertex is calculated based only on average of triangles in set

Parameters
Triangleslist of triangle IDs

◆ SetTriangleNormals() [2/2]

void FDynamicMeshEditor::SetTriangleNormals ( const TArray< int > &  Triangles,
const FVector3f Normal 
)

Create and set new shared per-triangle normals for a list of triangles

Parameters
Triangleslist of triangle IDs
Normalnormal vector to set

◆ SetTriangleUVsFromProjection() [1/2]

void FDynamicMeshEditor::SetTriangleUVsFromProjection ( const TArray< int > &  Triangles,
const FFrame3d ProjectionFrame,
const FVector2f UVScale = FVector2f::One(),
const FVector2f UVTranslation = FVector2f::Zero(),
int  UVLayerIndex = 0,
bool  bShiftToOrigin = true,
bool  bNormalizeBeforeScaling = false 
)

Project triangles onto a plane defined by the ProjectionFrame and use that to create/set new shared per-triangle UVs.

Parameters
TrianglesTArray of triangle IDs
ProjectFrameVertices are projected into XY axes of this frame
UVScaleFactorUVs are scaled by these factors
UVTranslationUVs are translated after scaling by these amounts
UVLayerIndexWhich UV layer to operate on (must exist)
bShiftToOriginWhether to translate the UV coordinates to make their bounding box min corner be (0,0) before applying UVTranslation
bNormalizeBeforeScalingWhether to place the UV coordinates into the range [0,1] before applying UVScaleFactor and UVTranslation

◆ SetTriangleUVsFromProjection() [2/2]

GEOMETRYCORE_API void UE::Geometry::FDynamicMeshEditor::SetTriangleUVsFromProjection ( const TArray< int32 > &  Triangles,
const FFrame3d ProjectionFrame,
float  UVScaleFactor = 1.0f,
const FVector2f UVTranslation = FVector2f::Zero(),
bool  bShiftToOrigin = true,
int32  UVLayerIndex = 0 
)

Project triangles onto a plane defined by the ProjectionFrame and use that to create/set new shared per-triangle UVs. UVs can be translated so that their bbox min-corner is at origin, and scaled by given scale factor This is an older function signature that forwards to the more specific one.

Parameters
TrianglesTArray of triangle IDs
ProjectFramevertices are projected into XY axes of this frame
UVScaleFactorUVs are scaled by this uniform scale factor
UVTranslationUVs are translated after scaling
bShiftToOriginWhether to translate the UV coordinates to make their bounding box min corner be (0,0) before applying UVTranslation
UVLayerIndexwhich UV layer to operate on (must exist)

◆ SetTubeNormals()

void FDynamicMeshEditor::SetTubeNormals ( const TArray< int > &  Triangles,
const TArray< int > &  VertexIDs1,
const TArray< int > &  MatchedIndices1,
const TArray< int > &  VertexIDs2,
const TArray< int > &  MatchedIndices2,
bool  bReverseNormals = false 
)

For a 'tube' of triangles connecting loops of corresponded vertices, set smooth normals such that corresponding vertices have corresponding normals

◆ SplitBowties() [1/3]

void FDynamicMeshEditor::SplitBowties ( FDynamicMeshEditResult ResultOut)

Splits all bowties across the whole mesh

◆ SplitBowties() [2/3]

void UE::Geometry::FDynamicMeshEditor::SplitBowties ( int  VertexID,
FDynamicMeshEditResult ResultOut 
)
inline

Splits any bowties specifically on the given vertex, and updates (does not reset!) ResultOut with any added vertices

◆ SplitBowties() [3/3]

void UE::Geometry::FDynamicMeshEditor::SplitBowties ( int  VertexID,
TArray< int32 > *  NewVertices = nullptr 
)
inline

Splits any bowties specifically on the given vertex, and (if not null) updates (does not reset!) NewVertices with any added vertices

◆ SplitBowtiesAtTriangles()

void FDynamicMeshEditor::SplitBowtiesAtTriangles ( const TArray< int32 > &  TriangleIDs,
FDynamicMeshEditResult ResultOut 
)

Splits bowties attached to any of the given triangles, and updates (does not reset!) ResultOut with any added vertices

◆ SplitMesh()

bool FDynamicMeshEditor::SplitMesh ( const FDynamicMesh3 SourceMesh,
TArray< FDynamicMesh3 > &  SplitMeshes,
TFunctionRef< int(int)>  TriIDToMeshID,
int  DeleteMeshID = -1,
TArray< int32 > *  MeshIDPerSplitMesh = nullptr,
bool  bSortByMeshID = false 
)
static

Create multiple meshes out of the source mesh by splitting triangles out. Static because it creates multiple output meshes, so doesn't quite fit in the FDynamicMeshEditor model of operating on a single mesh

Parameters
SourceMeshThe mesh to split
SplitMeshesAn array with one mesh per unique Mesh ID found in SourceMesh (optionally excluding the DeleteMeshID)
TriIDToMeshIDA function mapping Triangle IDs to Mesh IDs
DeleteMeshIDIf non-negative, triangles with this Mesh ID will be removed rather than being placed in a split mesh
MeshIDPerSplitMeshIf non-null, will be filled with the Mesh ID for each of the SplitMeshes generated
bSortByMeshIDIf true, SplitMeshes will be sorted in order of increasing Mesh ID
Returns
true if needed split, false if there were not multiple mesh ids so no split was needed

◆ StitchSparselyCorrespondedVertexLoops()

bool FDynamicMeshEditor::StitchSparselyCorrespondedVertexLoops ( const TArray< int > &  VertexIDs1,
const TArray< int > &  MatchedIndices1,
const TArray< int > &  VertexIDs2,
const TArray< int > &  MatchedIndices2,
FDynamicMeshEditResult ResultOut,
bool  bReverseOrientation = false 
)

Stitch together two loops of vertices where vertices are only sparsely corresponded

Parameters
VertexIDs1first array of sequential vertices
MatchedIndices1indices into the VertexIDs1 array of vertices that have a corresponding match in the VertexIDs2 array; Must be ordered
VertexIDs2second array of sequential vertices
MatchedIndices2indices into the VertexIDs2 array of vertices that have a corresponding match in the VertexIDs1 array; Must be ordered
ResultOutlists of newly created triangles/vertices/etc
Returns
true if operation succeeded. If a failure occurs, any added triangles are removed via RemoveTriangles

◆ StitchVertexLoopsMinimal()

bool FDynamicMeshEditor::StitchVertexLoopsMinimal ( const TArray< int > &  VertexLoop1,
const TArray< int > &  VertexLoop2,
FDynamicMeshEditResult ResultOut 
)

Stitch together two loops of vertices with a quad-strip of triangles. Loops must be oriented (ordered) correctly for your use case. If loop edges are [a,b] and [c,d], then tris added are [b,a,d] and [a,c,d]

Parameters
Loop1first loop of sequential vertices
Loop2second loop of sequential vertices
ResultOutlists of newly created triangles/vertices/etc
Returns
true if operation succeeded. If a failure occurs, any added triangles are removed via RemoveTriangles

◆ StitchVertexLoopToTriVidPairSequence()

bool FDynamicMeshEditor::StitchVertexLoopToTriVidPairSequence ( const TArray< TPair< int32, TPair< int8, int8 > > > &  TriVidPairs1,
const TArray< int > &  VertexLoop2,
FDynamicMeshEditResult ResultOut 
)

Given a sequence of edges in the form given by ConvertLoopToTriVidPairSequence and a loop of vertices, stitch the two together. Edges are identified as (TriangleID, (0-2 subindex of vert1, 0-2 subindex of vert2)), and should match the number of vertex ids in the corresponding vertex loop (each i corresponds to the edge between vert i and i+1 in the vertex loop). This works much like StitchVertexLoopsMinimal, but it can be used after one of the loops undergoes vertex splits (to remove bowties) as long as the "loop" (which may now be broken) can still be identified by the composing triangles. In particular, this is used in extrude and inset where the base loop needs to remain as a sequence of Vids (since some of these may be free vertices, unattached to a triangle) but the offset/inset loop is guaranteed to be attached to triangles yet may have its Vids change due to bowtie splits.

If an entry of TriVidPairs1 resolves to verts [a,b] and the corresponding pair of verts in VertexLoop2 are [c,d], then tris added are [b,a,d] and [a,c,d].

Parameters
TriVidPairs1First loop, given as output of ConvertLoopToTriVidPairSequence()
VertexLoop2Second loop, given as vertex IDs
ResultOutlists of newly created triangles/vertices/etc
Returns
true if operation succeeded. If a failure occurs, any added triangles are removed via RemoveTriangles

◆ WeldVertexLoops()

bool FDynamicMeshEditor::WeldVertexLoops ( const TArray< int32 > &  VertexLoop1,
const TArray< int32 > &  VertexLoop2 
)

Weld together two loops of vertices. Loops must be oriented (ordered) correctly for your use case.

Parameters
Loop1first loop of sequential vertices
Loop2second loop of sequential vertices. These vertices and their edges will not exist after the operation.
Returns
true if operation succeeded, false if any errors ocurred

Member Data Documentation

◆ Mesh

FDynamicMesh3* UE::Geometry::FDynamicMeshEditor::Mesh

The mesh we will be editing


The documentation for this class was generated from the following files: