Files
2025-05-18 13:04:45 +08:00

150 lines
4.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Containers/Array.h"
#include "FrameTypes.h"
#include "HAL/Platform.h" //int32
#include "Misc/Optional.h"
#include "VectorTypes.h"
#define UE_API DYNAMICMESH_API
class FProgressCancel;
namespace UE::Geometry
{
class FDynamicMesh3;
// Hacky base class to avoid 8 bytes of padding after the vtable
class FExtrudeBoundaryEdgesFixLayout
{
public:
virtual ~FExtrudeBoundaryEdgesFixLayout() = default;
};
class FExtrudeBoundaryEdges : public FExtrudeBoundaryEdgesFixLayout
{
public:
using FFrame3d = UE::Geometry::FFrame3d;
// Represents a frame where the axes might not be unit scaled (but are still orthogonal).
// Allows vertices to adjust the extrusion distance along one of their extrusion frame
// axes when trying to keep edges parallel.
// When using extrusion frames, vertices will be moved in the XZ plane, usually along X.
struct FExtrudeFrame
{
FExtrudeFrame() {}
FExtrudeFrame(const FFrame3d& FrameIn)
: Frame(FrameIn)
{}
FExtrudeFrame(const FFrame3d& FrameIn, const FVector3d& InFrameScaleDirection, double ScalingIn)
: Frame(FrameIn)
, InFrameScaleDirection(InFrameScaleDirection)
, Scaling(ScalingIn)
{}
UE_API FVector3d FromFramePoint(FVector3d FramePoint) const;
UE_API FVector3d ToFramePoint(FVector3d WorldPoint) const;
FFrame3d Frame;
// Extra scaling direction used to support adjusting extruded vertices when trying to keep
// edges parallel. The input is scaled along this axis in frame space. See comment inside
// ExtrudeBoundaryEdgesLocals::GetExtrudeFrameAtVertex.
TOptional<FVector3d> InFrameScaleDirection;
double Scaling = 1.0;
};
// Data needed to create a new vert and its extrude frame
struct FNewVertSourceData
{
int32 SourceVid = IndexConstants::InvalidID;
// Neighboring edges, ordered by (incoming, outgoing)
FIndex2i SourceEidPair = FIndex2i::Invalid();
};
// Inputs:
/** The mesh that we are modifying */
FDynamicMesh3* Mesh;
/** The edges we're extruding */
TArray<int32> InputEids;
/** Whether to calculate local extrude frames and supply them to OffsetPositionFunc */
bool bUsePerVertexExtrudeFrames = true;
/** When generating extrude frames, whether to use unselected neighbors for setting the frame. */
bool bAssignAnyBoundaryNeighborToUnmatched = false;
/**
* Function queried for new vertex positions. ExtrudeFrame origin is Position, unless it is not initialized
* due to bUsePerVertexExtrudeFrames being false.
* The default given here assumes that bUsePerVertexExtrudeFrames is true, and extrudes along the X axis of the extrude frame.
*/
TFunction<FVector3d(const FVector3d& Position, const FExtrudeFrame& ExtrudeFrame, int32 SourceVid)> OffsetPositionFunc =
[this](const FVector3d& Position, const FExtrudeFrame& ExtrudeFrame, int32 SourceVid)
{
return ExtrudeFrame.FromFramePoint(FVector3d(this->DefaultOffsetDistance, 0, 0));
};
/**
* If greater than 1, maximal amount by which a vertex can be moved in an attempt to keep edges parallel to
* original edges while extruding. This "movement" is done by scaling the X axis of the extrude frame.
*/
double ScalingAdjustmentLimit = 1.0;
/**
* Optional mapping, 1:1 with Eids, that gives the group id to use for each generated quad. Otherwise all generated
* triangles will be given the same new group id.
*/
TOptional<TArray<int32>> GroupsToSetPerEid;
/** Used in the default OffsetPositionFunc. */
double DefaultOffsetDistance = 1.0;
// Outputs:
TArray<int32> NewTids;
TArray<int32> NewExtrudedEids;
public:
UE_API FExtrudeBoundaryEdges(FDynamicMesh3* mesh);
virtual ~FExtrudeBoundaryEdges() {}
/**
* Apply the operation to the input mesh.
* @return true if the algorithm succeeds
*/
UE_API virtual bool Apply(FProgressCancel* Progress);
/**
* Pairs up edges across vertices to help in extrusion frame calculation. Public because it is used by
* the extrude edges activity to find an operational space for the gizmos used to set extrude distance.
*
* @return false if there is an error.
*/
static UE_API bool GetInputEdgePairings(
const FDynamicMesh3& Mesh, TArray<int32>& InputEids, bool bAssignAnyBoundaryNeighborToUnmatched,
TArray<FNewVertSourceData>& NewVertDataOut, TMap<int32, FIndex2i>& EidToIndicesIntoNewVertsOut);
/**
* Gets an extrude frame given a vert and its neighboring boundary edges. Like GetInputEdgePairings,
* public because it is used to set up UX for setting extrude distance.
*
@return false if there is an error.
*/
static UE_API bool GetExtrudeFrame(const FDynamicMesh3& Mesh, int32 Vid,
int32 IncomingEid, int32 OutgoingEid, FExtrudeFrame& ExtrudeFrameOut,
double ScalingLimit);
};
} // end namespace UE::Geometry
#undef UE_API