159 lines
5.4 KiB
C++
159 lines
5.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "MathUtil.h"
|
|
#include "DynamicMesh/DynamicMesh3.h"
|
|
#include "DynamicMesh/DynamicMeshAttributeSet.h"
|
|
|
|
#define UE_API DYNAMICMESH_API
|
|
|
|
|
|
namespace UE
|
|
{
|
|
namespace Geometry
|
|
{
|
|
|
|
/**
|
|
* FPolygroupLayer represents a polygroup set on a FDynamicMesh3, which supports a "default"
|
|
* group set stored on the mesh, and then N extended group layers stored in the mesh AttributeSet.
|
|
* This struct can represent either.
|
|
*/
|
|
struct FPolygroupLayer
|
|
{
|
|
/** If true, layer is the default FDynamicMesh3 triangle groups layer */
|
|
bool bIsDefaultLayer = true;
|
|
/** If bIsDefaultLayer is false, this is the index of the AttributeSet Polygroup Layer */
|
|
int32 LayerIndex = -1;
|
|
|
|
/** Construct a FPolygroupLayer for the default layer */
|
|
static FPolygroupLayer Default() { return FPolygroupLayer{ true, -1 }; }
|
|
/** Construct a FPolygroupLayer for an extended layer */
|
|
static FPolygroupLayer Layer(int32 Index) { return FPolygroupLayer{ false, Index }; }
|
|
|
|
bool operator==(const FPolygroupLayer& OtherLayer) const
|
|
{
|
|
if (bIsDefaultLayer || OtherLayer.bIsDefaultLayer)
|
|
{
|
|
return bIsDefaultLayer && OtherLayer.bIsDefaultLayer;
|
|
}
|
|
else
|
|
{
|
|
return LayerIndex == OtherLayer.LayerIndex;
|
|
}
|
|
}
|
|
|
|
/** @return true if the specified layer (default or extended) exist and is initialized on the given Mesh */
|
|
UE_API bool CheckExists(const FDynamicMesh3* Mesh) const;
|
|
};
|
|
|
|
|
|
/**
|
|
* Polygroup sets can be stored in multiple places. The default location is in the per-triangle group integer stored
|
|
* directly on a FDynamicMesh3. Additional layers may be stored in the FDynamicMeshAttributeSet. Future iterations
|
|
* could store packed polygroups in other places, store them in separate arrays, and so on.
|
|
* FPolygroupSet can be used to abstract these different cases, by providing a standard Polygroup Get/Set API.
|
|
*
|
|
* To support unique Polygroup ID allocation, FPolygroupSet calculates the maximum GroupID on creation, and
|
|
* updates this maximum across SetGroup() calls. AllocateNewGroupID() can be used to provide new unused GroupIDs.
|
|
* For consistency with FDynamicMesh3, MaxGroupID is set such that all GroupIDs are less than MaxGroupID
|
|
*
|
|
*/
|
|
struct FPolygroupSet
|
|
{
|
|
const FDynamicMesh3* Mesh = nullptr;
|
|
const FDynamicMeshPolygroupAttribute* PolygroupAttrib = nullptr;
|
|
int32 GroupLayerIndex = -1;
|
|
int32 MaxGroupID = 0; // Note: all group IDs are less than MaxGroupID
|
|
|
|
/** Initialize a PolygroupSet for the given Mesh, and standard triangle group layer */
|
|
UE_API explicit FPolygroupSet(const FDynamicMesh3* MeshIn);
|
|
|
|
/** Initialize a PolygroupSet for the given Mesh, and standard triangle group layer */
|
|
UE_API explicit FPolygroupSet(const FDynamicMesh3* MeshIn, FPolygroupLayer GroupLayer);
|
|
|
|
/** Initialize a PolygroupSet for given Mesh and specific Polygroup attribute layer */
|
|
UE_API explicit FPolygroupSet(const FDynamicMesh3* MeshIn, const FDynamicMeshPolygroupAttribute* PolygroupAttribIn);
|
|
|
|
/** Initialize a PolygroupSet for given Mesh and specific Polygroup attribute layer, found by index. If not valid, fall back to standard triangle group layer. */
|
|
UE_API explicit FPolygroupSet(const FDynamicMesh3* MeshIn, int32 PolygroupLayerIndex);
|
|
|
|
/** Initialize a PolygroupSet for given Mesh and specific Polygroup attribute layer, found by name. If not valid, fall back to standard triangle group layer. */
|
|
UE_API explicit FPolygroupSet(const FDynamicMesh3* MeshIn, FName AttribName);
|
|
|
|
/** Initialize a PolygroupSet by copying an existing PolygroupSet */
|
|
UE_API explicit FPolygroupSet(const FPolygroupSet* CopyIn);
|
|
|
|
|
|
/** @return Mesh this PolygroupSet references */
|
|
const FDynamicMesh3* GetMesh() { return Mesh; }
|
|
|
|
/** @return PolygroupAttribute this PolygroupSet references, or null if no PolygroupAttribute is in use */
|
|
const FDynamicMeshPolygroupAttribute* GetPolygroup() { return PolygroupAttrib; }
|
|
|
|
/** @return index of current PolygroupAttribute into Mesh AttributeSet, or -1 if this information does not exist */
|
|
int32 GetPolygroupIndex() const { return GroupLayerIndex; }
|
|
|
|
|
|
/**
|
|
* @return PolygroupID for a TriangleID
|
|
*/
|
|
int32 GetGroup(int32 TriangleID) const
|
|
{
|
|
return (PolygroupAttrib) ? PolygroupAttrib->GetValue(TriangleID) : Mesh->GetTriangleGroup(TriangleID);
|
|
}
|
|
|
|
/**
|
|
* @return PolygroupID for a TriangleID
|
|
*/
|
|
int32 GetTriangleGroup(int32 TriangleID) const
|
|
{
|
|
return (PolygroupAttrib) ? PolygroupAttrib->GetValue(TriangleID) : Mesh->GetTriangleGroup(TriangleID);
|
|
}
|
|
|
|
/**
|
|
* Set the PolygroupID for a TriangleID
|
|
*/
|
|
void SetGroup(int32 TriangleID, int32 NewGroupID, FDynamicMesh3& WritableMesh)
|
|
{
|
|
checkSlow(&WritableMesh == this->Mesh); // require the same mesh
|
|
if (WritableMesh.IsTriangle(TriangleID))
|
|
{
|
|
if (PolygroupAttrib)
|
|
{
|
|
FDynamicMeshPolygroupAttribute* WritableGroupAttrib = WritableMesh.Attributes()->GetPolygroupLayer(GroupLayerIndex);
|
|
checkSlow(WritableGroupAttrib == PolygroupAttrib)
|
|
WritableGroupAttrib->SetValue(TriangleID, NewGroupID);
|
|
}
|
|
else
|
|
{
|
|
WritableMesh.SetTriangleGroup(TriangleID, NewGroupID);
|
|
}
|
|
}
|
|
MaxGroupID = FMath::Max(MaxGroupID, NewGroupID + 1);
|
|
}
|
|
|
|
/**
|
|
* Calculate the current maximum PolygroupID used in the active set and store in MaxGroupID member
|
|
*/
|
|
UE_API void RecalculateMaxGroupID();
|
|
|
|
/**
|
|
* Allocate a new unused PolygroupID by incrementing the MaxGroupID member
|
|
*/
|
|
int32 AllocateNewGroupID()
|
|
{
|
|
return MaxGroupID++;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // end namespace Geometry
|
|
} // end namespace UE
|
|
|
|
#undef UE_API
|