113 lines
3.2 KiB
C++
113 lines
3.2 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
// Port of geometry3Sharp SimpleHoleFiller
|
|
|
|
#pragma once
|
|
|
|
#include "HoleFiller.h"
|
|
#include "MathUtil.h"
|
|
#include "VectorTypes.h"
|
|
#include "GeometryTypes.h"
|
|
#include "MeshRegionBoundaryLoops.h"
|
|
|
|
#define UE_API DYNAMICMESH_API
|
|
|
|
namespace UE
|
|
{
|
|
namespace Geometry
|
|
{
|
|
|
|
class FDynamicMesh3;
|
|
|
|
/**
|
|
* Fill an EdgeLoop hole with triangles.
|
|
* Supports two fill modes, either a fan connected to a new central vertex, or a triangulation of the boundary polygon
|
|
*/
|
|
class FSimpleHoleFiller : public IHoleFiller
|
|
{
|
|
public:
|
|
enum class EFillType
|
|
{
|
|
TriangleFan,
|
|
PolygonEarClipping
|
|
};
|
|
|
|
//
|
|
// Inputs
|
|
//
|
|
FDynamicMesh3 *Mesh;
|
|
FEdgeLoop Loop;
|
|
EFillType FillType = EFillType::TriangleFan;
|
|
|
|
//
|
|
// Outputs
|
|
//
|
|
int32 NewVertex = IndexConstants::InvalidID;
|
|
|
|
public:
|
|
/**
|
|
* Construct simple hole filler (just adds a central vertex and a triangle fan)
|
|
*/
|
|
FSimpleHoleFiller(FDynamicMesh3* Mesh, FEdgeLoop Loop, EFillType InFillType = EFillType::TriangleFan) :
|
|
Mesh(Mesh),
|
|
Loop(Loop),
|
|
FillType(InFillType)
|
|
{
|
|
}
|
|
|
|
virtual ~FSimpleHoleFiller() {}
|
|
|
|
|
|
/**
|
|
* @return EOperationValidationResult::Ok if we can apply operation, or error code if we cannot
|
|
*/
|
|
virtual EOperationValidationResult Validate()
|
|
{
|
|
if (!Loop.IsBoundaryLoop(Mesh))
|
|
{
|
|
return EOperationValidationResult::Failed_UnknownReason;
|
|
}
|
|
// TODO: For EFillType::PolygonEarClipping, we actually have more constraints; specifically, there
|
|
// must not be any edges between non-adjacent loop vertices that we choose to connect (this can
|
|
// happen in a few weird topology cases, for instance if a hole is attached to a single triangle
|
|
// flap), because we would end up trying to add two more triangles to an existing edge.
|
|
// To do a proper check we'd need to know which verts we're planning to connect, which would require
|
|
// going through the whole retriangulation. That does not seem worthwhile...
|
|
|
|
return EOperationValidationResult::Ok;
|
|
}
|
|
|
|
UE_API bool Fill(int32 GroupID = -1) override;
|
|
|
|
/**
|
|
* Updates the normals and UV's of NewTriangles. UV's are taken from VidUVMaps,
|
|
* which is an array of maps (1:1 with UV layers) that map vid's of vertices on the
|
|
* boundary to their UV elements and values. If an entry for NewVertex is not provided,
|
|
* it is set to be the average of the boundary UV's. For other UV's, an entry must
|
|
* exist, though the UV element ID can be InvalidID if an element does not exist for
|
|
* that UV value. The function will update the element ID in the map to point to the
|
|
* new element once it inserts it.
|
|
|
|
* Normals are shared among NewTriangles but not with the surrounding portions of the mesh.
|
|
*
|
|
* @param VidsToUVsMap A map from vertex ID's of the boundary vertices to UV element ID's
|
|
* and/or their values. When the element ID is invalid, a new element is generated using
|
|
* the value, and the map is updated accordingly.
|
|
*
|
|
* @returns false if there is an error, usually if VidsToUVsMap did not have an entry
|
|
* for a needed vertex ID.
|
|
*/
|
|
UE_API bool UpdateAttributes(TArray<FMeshRegionBoundaryLoops::VidOverlayMap<FVector2f>>& VidUVMaps);
|
|
|
|
|
|
protected:
|
|
UE_API bool Fill_Fan(int32 NewGroupID);
|
|
UE_API bool Fill_EarClip(int32 NewGroupID);
|
|
};
|
|
|
|
|
|
} // end namespace UE::Geometry
|
|
} // end namespace UE
|
|
|
|
#undef UE_API
|