Files
michael balzer b8a1c9b6cf GeometryCore: Remove ExplicitUseGeometryMathTypes.h
#ROBOMERGE-AUTHOR: michael.balzer
#ROBOMERGE-SOURCE: CL 18227685 in //UE5/Release-5.0/... via CL 18229350
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469)
#ROBOMERGE[STARSHIP]: UE5-Main

[CL 18231457 by michael balzer in ue5-release-engine-test branch]
2021-11-17 19:02:44 -05:00

123 lines
3.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Operations/MeshAttributeTransfer.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "DynamicMesh/DynamicMeshAttributeSet.h"
#include "TriangleTypes.h"
#include "Util/IndexUtil.h"
#include "Async/ParallelFor.h"
using namespace UE::Geometry;
FMeshAttributeTransfer::FMeshAttributeTransfer(const FDynamicMesh3* SourceMeshIn, FDynamicMesh3* TargetMeshIn)
: SourceMesh(SourceMeshIn), TargetMesh(TargetMeshIn)
{
ensure(SourceMeshIn);
ensure(TargetMeshIn);
}
bool FMeshAttributeTransfer::Apply()
{
if (SourceMesh == nullptr)
{
Errors.Add(EMeshAttributeTransferError::InvalidSource);
return false;
}
if (TargetMesh == nullptr)
{
Errors.Add(EMeshAttributeTransferError::InvalidTarget);
return false;
}
if ( TransferType == EMeshAttributeTransferType::MaterialID)
{
return Apply_MaterialID();
}
else
{
Errors.Add(EMeshAttributeTransferError::InvalidOperationForInputs);
return false;
}
}
template<typename AllocType>
int32 SelectMostFrequentElement(TArray<int32, AllocType>& Samples)
{
Samples.Sort();
int32 N = Samples.Num();
int32 MaxVotes = 0;
int32 MaxVoteValue = Samples[0];
int32 CurValue = Samples[0];
int32 CurCount = 1;
for (int32 k = 1; k < N; ++k)
{
if (Samples[k] == CurValue)
{
CurCount++;
}
else
{
if (CurCount > MaxVotes)
{
MaxVotes = CurCount;
MaxVoteValue = CurValue;
}
CurCount = 1;
CurValue = Samples[k];
}
}
return MaxVoteValue;
}
bool FMeshAttributeTransfer::Apply_MaterialID()
{
const FDynamicMeshMaterialAttribute* SourceMaterialID = SourceMesh->HasAttributes() ? SourceMesh->Attributes()->GetMaterialID() : nullptr;
if (SourceMaterialID == nullptr)
{
Errors.Add(EMeshAttributeTransferError::SourceMissingAttribute);
return false;
}
FDynamicMeshMaterialAttribute* TargetMaterialID = TargetMesh->HasAttributes() ? TargetMesh->Attributes()->GetMaterialID() : nullptr;
if (TargetMaterialID == nullptr)
{
Errors.Add(EMeshAttributeTransferError::TargetMissingAttribute);
return false;
}
SourceSpatial = MakeUnique<FDynamicMeshAABBTree3>(SourceMesh, true);
static const FVector3d BarySamplePoints[7] = {
{1, 0, 0}, { 0,1,0 }, { 0,0,1 },
{ 0.5,0.5,0 }, {0.5,0,0.5}, {0,0.5,0.5},
{1.0/3.0, 1.0/3.0, 1.0/3.0}
};
constexpr int32 NumSamplePoints = 7; // must change Samples array below too!
// generate initial assignments
ParallelFor(TargetMesh->MaxTriangleID(), [&](int32 tid)
{
FTriangle3d TargetTriangle;
TargetMesh->GetTriVertices(tid, TargetTriangle.V[0], TargetTriangle.V[1], TargetTriangle.V[2]);
TArray<int32, TFixedAllocator<7>> Samples;
for (int32 k = 0; k < NumSamplePoints; ++k)
{
FVector3d SamplePoint = TargetTriangle.BarycentricPoint(BarySamplePoints[k]);
double DistSqr;
int32 SourceTriID = SourceSpatial->FindNearestTriangle(SamplePoint, DistSqr);
Samples.Add(SourceMaterialID->GetValue(SourceTriID));
}
int32 BestValue = SelectMostFrequentElement(Samples);
TargetMaterialID->SetValue(tid, BestValue);
});
return true;
}