You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb jimmy.andrews, semion.piskarev #jira none [CL 15661651 by Ryan Schmidt in ue5-main branch]
157 lines
4.1 KiB
C++
157 lines
4.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "BoxTypes.h"
|
|
#include "IndexTypes.h"
|
|
#include "Polygon2.h"
|
|
#include "Curve/DynamicGraph2.h"
|
|
#include "Curve/GeneralPolygon2.h"
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
|
namespace UE {
|
|
namespace Geometry {
|
|
|
|
|
|
|
|
template<typename RealType>
|
|
struct TConstrainedDelaunay2
|
|
{
|
|
//
|
|
// inputs
|
|
//
|
|
TArray<FVector2<RealType>> Vertices;
|
|
|
|
// Edges and HoleEdges must not be intersecting; use Arrangment2D to pre-process any input w/ intersecting edges
|
|
TArray<FIndex2i> Edges; // Edges can be boundaries or not based on the EFillRule setting
|
|
TArray<FIndex2i> HoleEdges; // Any triangles inside 'hole' edges *must* be cut out
|
|
|
|
//TODO: also support FeatureEdges?
|
|
//TArray<FIndex2i> FeatureEdges; // Edges that should be preserved in mesh but do not correspond to a boundary and should not affect inside/outside classification at all
|
|
|
|
bool bOrientedEdges = true;
|
|
bool bOutputCCW = false;
|
|
bool bSplitBowties = false;
|
|
|
|
enum class EFillRule {
|
|
Odd = 0,
|
|
// bOrientedEdges must be true for the below
|
|
NonZero,
|
|
Positive,
|
|
Negative
|
|
};
|
|
EFillRule FillRule = EFillRule::Odd;
|
|
|
|
inline bool ClassifyFromRule(int Winding)
|
|
{
|
|
switch (FillRule)
|
|
{
|
|
case EFillRule::Odd:
|
|
return Winding % 2 != 0;
|
|
case EFillRule::NonZero:
|
|
return Winding != 0;
|
|
case EFillRule::Positive:
|
|
return Winding > 0;
|
|
case EFillRule::Negative:
|
|
return Winding < 0;
|
|
default:
|
|
check(false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template<class InputRealType>
|
|
void Add(const FDynamicGraph2<InputRealType>& Graph)
|
|
{
|
|
int32 VertexStart = Vertices.Num();
|
|
int32 GMaxVertID = Graph.MaxVertexID();
|
|
TArray<int32> GraphToDTVertIdxMap; GraphToDTVertIdxMap.SetNum(GMaxVertID);
|
|
for (int32 Idx = 0; Idx < GMaxVertID; Idx++)
|
|
{
|
|
if (Graph.IsVertex(Idx))
|
|
{
|
|
GraphToDTVertIdxMap[Idx] = Vertices.Num();
|
|
Vertices.Add((FVector2<RealType>)Graph.GetVertex(Idx));
|
|
}
|
|
else
|
|
{
|
|
GraphToDTVertIdxMap[Idx] = -1;
|
|
}
|
|
}
|
|
for (const FDynamicGraph::FEdge& Edge : Graph.Edges())
|
|
{
|
|
Edges.Add(FIndex2i(GraphToDTVertIdxMap[Edge.A], GraphToDTVertIdxMap[Edge.B]));
|
|
}
|
|
}
|
|
template<class InputRealType>
|
|
void Add(const TPolygon2<InputRealType>& Polygon, bool bIsHole = false)
|
|
{
|
|
int32 VertexStart = Vertices.Num();
|
|
int32 VertexEnd = VertexStart + Polygon.VertexCount();
|
|
for (const FVector2<InputRealType> &Vertex : Polygon.GetVertices())
|
|
{
|
|
Vertices.Add((FVector2<RealType>)Vertex);
|
|
}
|
|
|
|
TArray<FIndex2i>* EdgeArr;
|
|
if (bIsHole)
|
|
{
|
|
EdgeArr = &HoleEdges;
|
|
}
|
|
else
|
|
{
|
|
EdgeArr = &Edges;
|
|
}
|
|
for (int32 A = VertexEnd - 1, B = VertexStart; B < VertexEnd; A = B++)
|
|
{
|
|
EdgeArr->Add(FIndex2i(A, B));
|
|
}
|
|
}
|
|
template<class InputRealType>
|
|
void Add(const TGeneralPolygon2<InputRealType>& GPolygon)
|
|
{
|
|
Add(GPolygon.GetOuter(), false);
|
|
const TArray<TPolygon2<InputRealType>>& Holes = GPolygon.GetHoles();
|
|
for (int HoleIdx = 0, HolesNum = Holes.Num(); HoleIdx < HolesNum; HoleIdx++)
|
|
{
|
|
Add(Holes[HoleIdx], true);
|
|
}
|
|
}
|
|
|
|
//
|
|
// outputs
|
|
//
|
|
TArray<FIndex3i> Triangles;
|
|
|
|
/** If vertices were added to output (e.g. to split bowties), this is set to the index of the first added vertex */
|
|
int AddedVerticesStartIndex = -1;
|
|
|
|
/**
|
|
* Populate Triangles
|
|
*
|
|
* @return false if Triangulation failed
|
|
*/
|
|
bool GEOMETRYALGORITHMS_API Triangulate();
|
|
|
|
/**
|
|
* Populate Triangles with override function to determine which triangles are in or out.
|
|
* Note that boundary edges and hole edges are treated as equivalent by this function; only the KeepTriangle function determines what triangles are excluded.
|
|
*
|
|
* @param KeepTriangle Function to check whether the given triangle should be kept in the output
|
|
* @return false if Triangulation failed
|
|
*/
|
|
bool GEOMETRYALGORITHMS_API Triangulate(TFunctionRef<bool(const TArray<FVector2<RealType>>&, const FIndex3i&)> KeepTriangle);
|
|
};
|
|
|
|
template<typename RealType>
|
|
TArray<FIndex3i> GEOMETRYALGORITHMS_API ConstrainedDelaunayTriangulate(const TGeneralPolygon2<RealType>& GeneralPolygon);
|
|
|
|
typedef TConstrainedDelaunay2<float> FConstrainedDelaunay2f;
|
|
typedef TConstrainedDelaunay2<double> FConstrainedDelaunay2d;
|
|
|
|
|
|
|
|
} // end namespace UE::Geometry
|
|
} // end namespace UE
|