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

144 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Util/ElementLinearization.h"
#include "DynamicMesh/DynamicMesh3.h"
namespace UE
{
namespace Geometry
{
class FDynamicMesh3;
/**
* Used to linearize the VtxIds in a mesh as a single array and allow mapping from array offset to mesh VtxId.
* Generally, the array offset will correspond to a matrix row when forming a Laplacian.
* The last NumBoundaryVerts are the boundary verts. This may be zero.
*/
class FVertexLinearization : public FElementLinearization
{
public:
FVertexLinearization() = default;
/**
* @param Mesh The mesh to lineralize.
* @param bRemapBoundary If true, will move the boundary vertices to the end of the arrays and record the number of
* boundary vertices.
*/
template<typename MeshType>
FVertexLinearization(const MeshType& Mesh, bool bRemapBoundary = true)
{
Reset(Mesh, bRemapBoundary);
}
template<typename MeshType>
void Reset(const MeshType& Mesh, bool bRemapBoundary = true)
{
Empty();
FElementLinearization::Populate(Mesh.MaxVertexID(), Mesh.VertexCount(), Mesh.VertexIndicesItr());
if (bRemapBoundary)
{
RemapBoundaryVerts(Mesh);
}
}
int32 NumVerts() const { return FElementLinearization::NumIds(); }
int32 NumBoundaryVerts() const { return NumBndryVerts; }
private:
// Moves the boundary verts to the end of the arrays and records the number of boundary verts
template<typename MeshType>
void RemapBoundaryVerts(const MeshType& DynamicMesh)
{
int32 VertCount = NumVerts();
// Collect the BoundaryVerts and the internal verts in two array
TArray<int32> BoundaryVertIds;
TArray<int32> TmpToIdMap;
TmpToIdMap.Reserve(VertCount);
for (int32 i = 0, I = ToIdMap.Num(); i < I; ++i)
{
int32 VtxId = ToIdMap[i];
// Test if the vertex has a one ring
bool bEmptyOneRing = DynamicMesh.GetVtxEdgeCount(VtxId) < 1;
if (bEmptyOneRing || DynamicMesh.IsBoundaryVertex(VtxId))
{
BoundaryVertIds.Add(VtxId);
}
else
{
TmpToIdMap.Add(VtxId);
}
}
// The number of boundary verts
NumBndryVerts = BoundaryVertIds.Num();
// Merge the boundary verts at the tail
// Add the Boundary verts at the end of the array.
TmpToIdMap.Append(BoundaryVertIds);
// rebuild the 'to' Index
for (int32 i = 0, I = ToIndexMap.Num(); i < I; ++i)
{
ToIndexMap[i] = FDynamicMesh3::InvalidID;
}
for (int32 i = 0, I = TmpToIdMap.Num(); i < I; ++i)
{
int32 Id = TmpToIdMap[i];
ToIndexMap[Id] = i;
}
// swap the temp
Swap(TmpToIdMap, ToIdMap);
}
private:
FVertexLinearization(const FVertexLinearization&);
int32 NumBndryVerts = 0;
};
/**
* Used linearize the TriIds in a mesh as a single array and allow mapping from array offset to mesh TriId.
*
*/
class FTriangleLinearization : public FElementLinearization
{
public:
FTriangleLinearization() = default;
FTriangleLinearization(const FDynamicMesh3& DynamicMesh)
{
Reset(DynamicMesh);
}
void Reset(const FDynamicMesh3& DynamicMesh)
{
Empty();
FElementLinearization::Populate(DynamicMesh.MaxTriangleID(), DynamicMesh.TriangleCount(), DynamicMesh.TriangleIndicesItr());
}
int32 NumTris() const { return FElementLinearization::NumIds(); }
private:
FTriangleLinearization(const FTriangleLinearization&);
};
} // end namespace UE::Geometry
} // end namespace UE