Files
UnrealEngine/Engine/Plugins/Runtime/MeshModelingToolset/Source/MeshModelingTools/Private/Properties/RevolveProperties.cpp
2025-05-18 13:04:45 +08:00

116 lines
4.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Properties/RevolveProperties.h"
#include "CompositionOps/CurveSweepOp.h"
#include "Properties/MeshMaterialProperties.h"
#include "Util/RevolveUtil.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(RevolveProperties)
using namespace UE::Geometry;
void URevolveProperties::ApplyToCurveSweepOp(const UNewMeshMaterialProperties& MaterialProperties,
const FVector3d& RevolutionAxisOrigin, const FVector3d& RevolutionAxisDirection,
FCurveSweepOp& CurveSweepOpOut) const
{
// Reversing the profile curve flips the mesh. This may need to be done if the curve wasn't drawn in the default
// (counterclockwise) direction or if we're not revolving in the default (counterclockwise) direction, or if
// the user asks.
bool bReverseProfileCurve = !RevolveUtil::ProfileIsCCWRelativeRevolve(CurveSweepOpOut.ProfileCurve,
RevolutionAxisOrigin, RevolutionAxisDirection, CurveSweepOpOut.bProfileCurveIsClosed);
bReverseProfileCurve = bReverseProfileCurve ^ bFlipMesh ^ bReverseRevolutionDirection;
if (bReverseProfileCurve)
{
for (int32 i = 0; i < CurveSweepOpOut.ProfileCurve.Num() / 2; ++i)
{
Swap(CurveSweepOpOut.ProfileCurve[i], CurveSweepOpOut.ProfileCurve[CurveSweepOpOut.ProfileCurve.Num() - 1 - i]);
}
}
const double TotalRevolutionDegrees = (HeightOffsetPerDegree == 0) ? RevolveDegreesClamped : RevolveDegrees;
const int32 Steps = bExplicitSteps ? NumExplicitSteps : FMath::CeilToInt(TotalRevolutionDegrees / StepsMaxDegrees);
double DegreesPerStep = TotalRevolutionDegrees / Steps;
double DegreesOffset = RevolveDegreesOffset;
if (bReverseRevolutionDirection)
{
DegreesPerStep *= -1;
DegreesOffset *= -1;
}
const double DownAxisOffsetPerStep = TotalRevolutionDegrees * HeightOffsetPerDegree / Steps;
if (bPathAtMidpointOfStep && DegreesPerStep != 0 && abs(DegreesPerStep) < 180)
{
RevolveUtil::MakeProfileCurveMidpointOfFirstStep(CurveSweepOpOut.ProfileCurve, DegreesPerStep, RevolutionAxisOrigin, RevolutionAxisDirection);
}
// Generate the sweep curve
CurveSweepOpOut.bSweepCurveIsClosed = bWeldFullRevolution && HeightOffsetPerDegree == 0 && TotalRevolutionDegrees == 360;
const int32 NumSweepFrames = CurveSweepOpOut.bSweepCurveIsClosed ? Steps : Steps + 1; // If closed, last sweep frame is also first
CurveSweepOpOut.SweepCurve.Reserve(NumSweepFrames);
RevolveUtil::GenerateSweepCurve(RevolutionAxisOrigin, RevolutionAxisDirection, DegreesOffset,
DegreesPerStep, DownAxisOffsetPerStep, NumSweepFrames, CurveSweepOpOut.SweepCurve);
// Weld any vertices that are on the axis
if (bWeldVertsOnAxis && DownAxisOffsetPerStep == 0)
{
RevolveUtil::WeldPointsOnAxis(CurveSweepOpOut.ProfileCurve, RevolutionAxisOrigin,
RevolutionAxisDirection, AxisWeldTolerance, CurveSweepOpOut.ProfileVerticesToWeld);
}
CurveSweepOpOut.bSharpNormals = bSharpNormals;
CurveSweepOpOut.SharpNormalAngleTolerance = SharpNormalsDegreeThreshold;
CurveSweepOpOut.DiagonalTolerance = QuadSplitCompactTolerance;
const double UVScale = MaterialProperties.UVScale;
CurveSweepOpOut.UVScale = FVector2d(UVScale, UVScale);
if (bReverseProfileCurve ^ bFlipVs)
{
CurveSweepOpOut.UVScale[1] *= -1;
CurveSweepOpOut.UVOffset = FVector2d(0, UVScale);
}
CurveSweepOpOut.bUVsSkipFullyWeldedEdges = bUVsSkipFullyWeldedEdges;
CurveSweepOpOut.bUVScaleRelativeWorld = MaterialProperties.bWorldSpaceUVScale;
CurveSweepOpOut.UnitUVInWorldCoordinates = 100; // This seems to be the case in the AddPrimitiveTool
switch (PolygroupMode)
{
case ERevolvePropertiesPolygroupMode::PerShape:
CurveSweepOpOut.PolygonGroupingMode = EProfileSweepPolygonGrouping::Single;
break;
case ERevolvePropertiesPolygroupMode::PerFace:
CurveSweepOpOut.PolygonGroupingMode = EProfileSweepPolygonGrouping::PerFace;
break;
case ERevolvePropertiesPolygroupMode::PerRevolveStep:
CurveSweepOpOut.PolygonGroupingMode = EProfileSweepPolygonGrouping::PerSweepSegment;
break;
case ERevolvePropertiesPolygroupMode::PerPathSegment:
CurveSweepOpOut.PolygonGroupingMode = EProfileSweepPolygonGrouping::PerProfileSegment;
break;
}
switch (QuadSplitMode)
{
case ERevolvePropertiesQuadSplit::Compact:
CurveSweepOpOut.QuadSplitMode = EProfileSweepQuadSplit::ShortestDiagonal;
break;
case ERevolvePropertiesQuadSplit::Uniform:
CurveSweepOpOut.QuadSplitMode = EProfileSweepQuadSplit::Uniform;
break;
}
switch (GetCapFillMode())
{
case ERevolvePropertiesCapFillMode::None:
CurveSweepOpOut.CapFillMode = FCurveSweepOp::ECapFillMode::None;
break;
case ERevolvePropertiesCapFillMode::Delaunay:
CurveSweepOpOut.CapFillMode = FCurveSweepOp::ECapFillMode::Delaunay;
break;
case ERevolvePropertiesCapFillMode::EarClipping:
CurveSweepOpOut.CapFillMode = FCurveSweepOp::ECapFillMode::EarClipping;
break;
case ERevolvePropertiesCapFillMode::CenterFan:
CurveSweepOpOut.CapFillMode = FCurveSweepOp::ECapFillMode::CenterFan;
break;
}
}