1390 lines
55 KiB
C++
1390 lines
55 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Algo/Accumulate.h"
|
|
#include "Algo/Copy.h"
|
|
#include "Algo/Find.h"
|
|
#include "Containers/Array.h"
|
|
#include "Containers/ArrayView.h"
|
|
#include "Containers/BitArray.h"
|
|
#include "Containers/ContainerAllocationPolicies.h"
|
|
#include "Containers/ContainersFwd.h"
|
|
#include "Containers/Map.h"
|
|
#include "Containers/Set.h"
|
|
#include "Containers/StaticArray.h"
|
|
#include "Containers/UnrealString.h"
|
|
#include "CoreFwd.h"
|
|
#include "CoreTypes.h"
|
|
#include "HAL/CriticalSection.h"
|
|
#include "HAL/PlatformCrt.h"
|
|
#include "Math/Box.h"
|
|
#include "Math/MathFwd.h"
|
|
#include "Math/Plane.h"
|
|
#include "Math/Vector.h"
|
|
#include "MeshAttributeArray.h"
|
|
#include "MeshElementArray.h"
|
|
#include "MeshElementContainer.h"
|
|
#include "MeshElementIndexer.h"
|
|
#include "MeshTypes.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "Misc/EnumClassFlags.h"
|
|
#include "Misc/Guid.h"
|
|
#include "Serialization/CustomVersion.h"
|
|
#include "Serialization/EditorBulkData.h"
|
|
#include "Templates/Tuple.h"
|
|
#include "Templates/UnrealTemplate.h"
|
|
#include "UObject/EditorObjectVersion.h"
|
|
#include "UObject/NameTypes.h"
|
|
#include "UObject/Object.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "UObject/ReleaseObjectVersion.h"
|
|
|
|
#include "MeshDescription.generated.h"
|
|
|
|
class FArchive;
|
|
class UObject;
|
|
struct FElementIDRemappings;
|
|
|
|
enum
|
|
{
|
|
//Remove the _MD when FRawMesh will be remove
|
|
MAX_MESH_TEXTURE_COORDS_MD = 8,
|
|
};
|
|
|
|
|
|
/** Define container types */
|
|
using FVertexArray = TMeshElementContainer<FVertexID>;
|
|
using FVertexInstanceArray = TMeshElementContainer<FVertexInstanceID>;
|
|
using FEdgeArray = TMeshElementContainer<FEdgeID>;
|
|
using FUVArray = TMeshElementContainer<FUVID>;
|
|
using FTriangleArray = TMeshElementContainer<FTriangleID>;
|
|
using FPolygonArray = TMeshElementContainer<FPolygonID>;
|
|
using FPolygonGroupArray = TMeshElementContainer<FPolygonGroupID>;
|
|
|
|
/** Define aliases for element attributes */
|
|
template <typename AttributeType> using TVertexAttributesRef = TMeshAttributesRef<FVertexID, AttributeType>;
|
|
template <typename AttributeType> using TVertexInstanceAttributesRef = TMeshAttributesRef<FVertexInstanceID, AttributeType>;
|
|
template <typename AttributeType> using TEdgeAttributesRef = TMeshAttributesRef<FEdgeID, AttributeType>;
|
|
template <typename AttributeType> using TUVAttributesRef = TMeshAttributesRef<FUVID, AttributeType>;
|
|
template <typename AttributeType> using TTriangleAttributesRef = TMeshAttributesRef<FTriangleID, AttributeType>;
|
|
template <typename AttributeType> using TPolygonAttributesRef = TMeshAttributesRef<FPolygonID, AttributeType>;
|
|
template <typename AttributeType> using TPolygonGroupAttributesRef = TMeshAttributesRef<FPolygonGroupID, AttributeType>;
|
|
|
|
template <typename AttributeType> using TVertexAttributesConstRef = TMeshAttributesConstRef<FVertexID, AttributeType>;
|
|
template <typename AttributeType> using TVertexInstanceAttributesConstRef = TMeshAttributesConstRef<FVertexInstanceID, AttributeType>;
|
|
template <typename AttributeType> using TEdgeAttributesConstRef = TMeshAttributesConstRef<FEdgeID, AttributeType>;
|
|
template <typename AttributeType> using TUVAttributesConstRef = TMeshAttributesConstRef<FUVID, AttributeType>;
|
|
template <typename AttributeType> using TTriangleAttributesConstRef = TMeshAttributesConstRef<FTriangleID, AttributeType>;
|
|
template <typename AttributeType> using TPolygonAttributesConstRef = TMeshAttributesConstRef<FPolygonID, AttributeType>;
|
|
template <typename AttributeType> using TPolygonGroupAttributesConstRef = TMeshAttributesConstRef<FPolygonGroupID, AttributeType>;
|
|
|
|
UENUM()
|
|
enum class EComputeNTBsOptions : uint32
|
|
{
|
|
None = 0x00000000, // No flags
|
|
Normals = 0x00000001, //Compute the normals
|
|
Tangents = 0x00000002, //Compute the tangents
|
|
WeightedNTBs = 0x00000004, //Use weight angle when computing NTBs to proportionally distribute the vertex instance contribution to the normal/tangent/binormal in a smooth group. i.e. Weight solve the cylinder problem
|
|
};
|
|
ENUM_CLASS_FLAGS(EComputeNTBsOptions);
|
|
|
|
|
|
struct FMeshDescription
|
|
{
|
|
public:
|
|
|
|
// Mesh description should be a moveable type.
|
|
// Hence explicitly declare all the below as defaulted, to ensure they will be generated by the compiler.
|
|
MESHDESCRIPTION_API FMeshDescription();
|
|
~FMeshDescription() = default;
|
|
MESHDESCRIPTION_API FMeshDescription(const FMeshDescription&);
|
|
MESHDESCRIPTION_API FMeshDescription& operator=(const FMeshDescription&);
|
|
FMeshDescription(FMeshDescription&&) = default;
|
|
FMeshDescription& operator=(FMeshDescription&&) = default;
|
|
|
|
friend MESHDESCRIPTION_API FArchive& operator<<(FArchive& Ar, FMeshDescription& MeshDescription)
|
|
{
|
|
MeshDescription.Serialize(Ar);
|
|
return Ar;
|
|
}
|
|
|
|
// Serialize the mesh description
|
|
MESHDESCRIPTION_API void Serialize(FArchive& Ar);
|
|
|
|
// Legacy serialization for old assets
|
|
MESHDESCRIPTION_API void SerializeLegacy(FArchive& Ar);
|
|
|
|
// Empty the meshdescription
|
|
MESHDESCRIPTION_API void Empty();
|
|
|
|
// Operations on all the indexers
|
|
MESHDESCRIPTION_API void ResetIndexers();
|
|
MESHDESCRIPTION_API void BuildIndexers();
|
|
MESHDESCRIPTION_API void RebuildIndexers();
|
|
|
|
// Return whether the mesh description is empty
|
|
MESHDESCRIPTION_API bool IsEmpty() const;
|
|
|
|
FVertexArray& Vertices() { return static_cast<TMeshElementContainer<FVertexID>&>(VertexElements->Get()); }
|
|
const FVertexArray& Vertices() const { return static_cast<const TMeshElementContainer<FVertexID>&>(VertexElements->Get()); }
|
|
|
|
FVertexInstanceArray& VertexInstances() { return static_cast<TMeshElementContainer<FVertexInstanceID>&>(VertexInstanceElements->Get()); }
|
|
const FVertexInstanceArray& VertexInstances() const { return static_cast<const TMeshElementContainer<FVertexInstanceID>&>(VertexInstanceElements->Get()); }
|
|
|
|
FEdgeArray& Edges() { return static_cast<TMeshElementContainer<FEdgeID>&>(EdgeElements->Get()); }
|
|
const FEdgeArray& Edges() const { return static_cast<const TMeshElementContainer<FEdgeID>&>(EdgeElements->Get()); }
|
|
|
|
FUVArray& UVs(int32 Index) { return static_cast<TMeshElementContainer<FUVID>&>(UVElements->Get(Index)); }
|
|
const FUVArray& UVs(int32 Index) const { return static_cast<const TMeshElementContainer<FUVID>&>(UVElements->Get(Index)); }
|
|
|
|
FTriangleArray& Triangles() { return static_cast<TMeshElementContainer<FTriangleID>&>(TriangleElements->Get()); }
|
|
const FTriangleArray& Triangles() const { return static_cast<const TMeshElementContainer<FTriangleID>&>(TriangleElements->Get()); }
|
|
|
|
FPolygonArray& Polygons() { return static_cast<TMeshElementContainer<FPolygonID>&>(PolygonElements->Get()); }
|
|
const FPolygonArray& Polygons() const { return static_cast<const TMeshElementContainer<FPolygonID>&>(PolygonElements->Get()); }
|
|
|
|
FPolygonGroupArray& PolygonGroups() { return static_cast<TMeshElementContainer<FPolygonGroupID>&>(PolygonGroupElements->Get()); }
|
|
const FPolygonGroupArray& PolygonGroups() const { return static_cast<const TMeshElementContainer<FPolygonGroupID>&>(PolygonGroupElements->Get()); }
|
|
|
|
TAttributesSet<FVertexID>& VertexAttributes() { return Vertices().GetAttributes(); }
|
|
const TAttributesSet<FVertexID>& VertexAttributes() const { return Vertices().GetAttributes(); }
|
|
|
|
TAttributesSet<FVertexInstanceID>& VertexInstanceAttributes() { return VertexInstances().GetAttributes(); }
|
|
const TAttributesSet<FVertexInstanceID>& VertexInstanceAttributes() const { return VertexInstances().GetAttributes(); }
|
|
|
|
TAttributesSet<FEdgeID>& EdgeAttributes() { return Edges().GetAttributes(); }
|
|
const TAttributesSet<FEdgeID>& EdgeAttributes() const { return Edges().GetAttributes(); }
|
|
|
|
TAttributesSet<FUVID>& UVAttributes(int32 Index) { return UVs(Index).GetAttributes(); }
|
|
const TAttributesSet<FUVID>& UVAttributes(int32 Index) const { return UVs(Index).GetAttributes(); }
|
|
|
|
TAttributesSet<FTriangleID>& TriangleAttributes() { return Triangles().GetAttributes(); }
|
|
const TAttributesSet<FTriangleID>& TriangleAttributes() const { return Triangles().GetAttributes(); }
|
|
|
|
TAttributesSet<FPolygonID>& PolygonAttributes() { return Polygons().GetAttributes(); }
|
|
const TAttributesSet<FPolygonID>& PolygonAttributes() const { return Polygons().GetAttributes(); }
|
|
|
|
TAttributesSet<FPolygonGroupID>& PolygonGroupAttributes() { return PolygonGroups().GetAttributes(); }
|
|
const TAttributesSet<FPolygonGroupID>& PolygonGroupAttributes() const { return PolygonGroups().GetAttributes(); }
|
|
|
|
TMap<FName, FMeshElementTypeWrapper>& GetElements() { return Elements; }
|
|
const TMap<FName, FMeshElementTypeWrapper>& GetElements() const { return Elements; }
|
|
|
|
void SuspendVertexIndexing() { VertexToVertexInstances.Suspend(); VertexToEdges.Suspend(); }
|
|
void SuspendVertexInstanceIndexing() { VertexInstanceToTriangles.Suspend(); }
|
|
void SuspendEdgeIndexing() { EdgeToTriangles.Suspend(); }
|
|
void SuspendPolygonIndexing() { PolygonToTriangles.Suspend(); }
|
|
void SuspendPolygonGroupIndexing() { PolygonGroupToPolygons.Suspend(); PolygonGroupToTriangles.Suspend(); }
|
|
void SuspendUVIndexing() { UVToTriangles.Suspend(); }
|
|
|
|
void ResumeVertexIndexing() { VertexToVertexInstances.Resume(); VertexToEdges.Resume(); }
|
|
void ResumeVertexInstanceIndexing() { VertexInstanceToTriangles.Resume(); }
|
|
void ResumeEdgeIndexing() { EdgeToTriangles.Resume(); }
|
|
void ResumePolygonIndexing() { PolygonToTriangles.Resume(); }
|
|
void ResumePolygonGroupIndexing() { PolygonGroupToPolygons.Resume(); PolygonGroupToTriangles.Resume(); }
|
|
void ResumeUVIndexing() { UVToTriangles.Resume(); }
|
|
|
|
void BuildVertexIndexers() { VertexToVertexInstances.Build(); VertexToEdges.Build(); }
|
|
void BuildVertexInstanceIndexers() { VertexInstanceToTriangles.Build(); }
|
|
void BuildEdgeIndexers() { EdgeToTriangles.Build(); }
|
|
void BuildPolygonIndexers() { PolygonToTriangles.Build(); }
|
|
void BuildPolygonGroupIndexers() { PolygonGroupToPolygons.Build(), PolygonGroupToTriangles.Build(); }
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Create / remove mesh elements
|
|
|
|
/** Reserves space for this number of new vertices */
|
|
void ReserveNewVertices(const int32 NumVertices)
|
|
{
|
|
VertexElements->Get().Reserve(VertexElements->Get().Num() + NumVertices);
|
|
}
|
|
|
|
/** Adds a new vertex to the mesh and returns its ID */
|
|
FVertexID CreateVertex()
|
|
{
|
|
const FVertexID VertexID = VertexElements->Get().Add();
|
|
return VertexID;
|
|
}
|
|
|
|
/** Adds a new vertex to the mesh with the given ID */
|
|
void CreateVertexWithID(const FVertexID VertexID)
|
|
{
|
|
VertexElements->Get().Insert(VertexID);
|
|
}
|
|
|
|
/** Deletes a vertex from the mesh */
|
|
void DeleteVertex(const FVertexID VertexID)
|
|
{
|
|
check(VertexToVertexInstances.Find(VertexID).Num() == 0);
|
|
check(VertexToEdges.Find(VertexID).Num() == 0);
|
|
VertexElements->Get().Remove(VertexID);
|
|
VertexToVertexInstances.RemoveKey(VertexID);
|
|
VertexToEdges.RemoveKey(VertexID);
|
|
}
|
|
|
|
/** Returns whether the passed vertex ID is valid */
|
|
bool IsVertexValid(const FVertexID VertexID) const
|
|
{
|
|
return VertexElements->Get().IsValid(VertexID);
|
|
}
|
|
|
|
/** Reserves space for this number of new vertex instances */
|
|
void ReserveNewVertexInstances(const int32 NumVertexInstances)
|
|
{
|
|
VertexInstanceElements->Get().Reserve(VertexInstanceElements->Get().Num() + NumVertexInstances);
|
|
}
|
|
|
|
/** Adds a new vertex instance to the mesh and returns its ID */
|
|
FVertexInstanceID CreateVertexInstance(const FVertexID VertexID)
|
|
{
|
|
const FVertexInstanceID VertexInstanceID = VertexInstanceElements->Get().Add();
|
|
CreateVertexInstance_Internal(VertexInstanceID, VertexID);
|
|
return VertexInstanceID;
|
|
}
|
|
|
|
/** Adds a new vertex instance to the mesh with the given ID */
|
|
void CreateVertexInstanceWithID(const FVertexInstanceID VertexInstanceID, const FVertexID VertexID)
|
|
{
|
|
VertexInstanceElements->Get().Insert(VertexInstanceID);
|
|
CreateVertexInstance_Internal(VertexInstanceID, VertexID);
|
|
}
|
|
|
|
/** Deletes a vertex instance from a mesh */
|
|
MESHDESCRIPTION_API void DeleteVertexInstance(const FVertexInstanceID VertexInstanceID, TArray<FVertexID>* InOutOrphanedVerticesPtr = nullptr);
|
|
|
|
/** Returns whether the passed vertex instance ID is valid */
|
|
bool IsVertexInstanceValid(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return VertexInstanceElements->Get().IsValid(VertexInstanceID);
|
|
}
|
|
|
|
/** Reserves space for this number of new UVs */
|
|
void ReserveNewUVs(const int32 NumUVs, const int32 UVChannel = 0)
|
|
{
|
|
UVElements->Get(UVChannel).Reserve(UVElements->Get(UVChannel).Num() + NumUVs);
|
|
}
|
|
|
|
/** Adds a new UV to the mesh and returns its ID */
|
|
FUVID CreateUV(const int32 UVChannel = 0)
|
|
{
|
|
const FUVID UVID = UVElements->Get(UVChannel).Add();
|
|
return UVID;
|
|
}
|
|
|
|
/** Adds a new UV to the mesh with the given ID */
|
|
void CreateUVWithID(const FUVID UVID, const int32 UVChannel = 0)
|
|
{
|
|
UVElements->Get(UVChannel).Insert(UVID);
|
|
}
|
|
|
|
/** Deletes a UV from the mesh */
|
|
void DeleteUV(const FUVID UVID, const int32 UVChannel = 0)
|
|
{
|
|
check(UVToTriangles.Find(UVID).Num() == 0);
|
|
UVElements->Get(UVChannel).Remove(UVID);
|
|
UVToTriangles.RemoveKey(UVID);
|
|
}
|
|
|
|
/** Returns whether the passed UV ID is valid */
|
|
bool IsUVValid(const FUVID UVID, const int32 UVChannel = 0) const
|
|
{
|
|
return UVElements->Get(UVChannel).IsValid(UVID);
|
|
}
|
|
|
|
/** Reserves space for this number of new edges */
|
|
void ReserveNewEdges(const int32 NumEdges)
|
|
{
|
|
EdgeElements->Get().Reserve(EdgeElements->Get().Num() + NumEdges);
|
|
}
|
|
|
|
/** Adds a new edge to the mesh and returns its ID */
|
|
FEdgeID CreateEdge(const FVertexID VertexID0, const FVertexID VertexID1)
|
|
{
|
|
const FEdgeID EdgeID = EdgeElements->Get().Add();
|
|
CreateEdge_Internal(EdgeID, VertexID0, VertexID1);
|
|
return EdgeID;
|
|
}
|
|
|
|
/** Adds a new edge to the mesh with the given ID */
|
|
void CreateEdgeWithID(const FEdgeID EdgeID, const FVertexID VertexID0, const FVertexID VertexID1)
|
|
{
|
|
EdgeElements->Get().Insert(EdgeID);
|
|
CreateEdge_Internal(EdgeID, VertexID0, VertexID1);
|
|
}
|
|
|
|
/** Deletes an edge from the mesh */
|
|
MESHDESCRIPTION_API void DeleteEdge(const FEdgeID EdgeID, TArray<FVertexID>* InOutOrphanedVerticesPtr = nullptr);
|
|
|
|
/** Returns whether the passed edge ID is valid */
|
|
bool IsEdgeValid(const FEdgeID EdgeID) const
|
|
{
|
|
return EdgeElements->Get().IsValid(EdgeID);
|
|
}
|
|
|
|
/** Reserves space for this number of new triangles */
|
|
void ReserveNewTriangles(const int32 NumTriangles)
|
|
{
|
|
TriangleElements->Get().Reserve(TriangleElements->Get().Num() + NumTriangles);
|
|
}
|
|
|
|
/** Adds a new triangle to the mesh and returns its ID. This will also make an encapsulating polygon, and any missing edges. */
|
|
FTriangleID CreateTriangle(const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs = nullptr)
|
|
{
|
|
const FTriangleID TriangleID = TriangleElements->Get().Add();
|
|
CreateTriangle_Internal(TriangleID, PolygonGroupID, VertexInstanceIDs, OutEdgeIDs);
|
|
return TriangleID;
|
|
}
|
|
|
|
/** Adds a new triangle to the mesh with the given ID. This will also make an encapsulating polygon, and any missing edges. */
|
|
void CreateTriangleWithID(const FTriangleID TriangleID, const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs = nullptr)
|
|
{
|
|
TriangleElements->Get().Insert(TriangleID);
|
|
CreateTriangle_Internal(TriangleID, PolygonGroupID, VertexInstanceIDs, OutEdgeIDs);
|
|
}
|
|
|
|
/** Deletes a triangle from the mesh */
|
|
MESHDESCRIPTION_API void DeleteTriangle(const FTriangleID TriangleID, TArray<FEdgeID>* InOutOrphanedEdgesPtr = nullptr, TArray<FVertexInstanceID>* InOutOrphanedVertexInstancesPtr = nullptr, TArray<FPolygonGroupID>* InOutOrphanedPolygonGroupsPtr = nullptr);
|
|
|
|
/** Deletes triangles from the mesh and remove all orphaned polygon groups, vertex instances, edges and vertices.
|
|
Will not compact the internal arrays, you must call Compact() manually.
|
|
*/
|
|
MESHDESCRIPTION_API void DeleteTriangles(const TArray<FTriangleID>& Triangles);
|
|
|
|
/** Returns whether the passed triangle ID is valid */
|
|
bool IsTriangleValid(const FTriangleID TriangleID) const
|
|
{
|
|
return TriangleElements->Get().IsValid(TriangleID);
|
|
}
|
|
|
|
/** Reserves space for this number of new polygons */
|
|
void ReserveNewPolygons(const int32 NumPolygons)
|
|
{
|
|
PolygonElements->Get().Reserve(PolygonElements->Get().Num() + NumPolygons);
|
|
}
|
|
|
|
/** Adds a new polygon to the mesh and returns its ID. This will also make any missing edges, and all constituent triangles. */
|
|
FPolygonID CreatePolygon(const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs = nullptr)
|
|
{
|
|
const FPolygonID PolygonID = PolygonElements->Get().Add();
|
|
CreatePolygon_Internal(PolygonID, PolygonGroupID, VertexInstanceIDs, OutEdgeIDs);
|
|
return PolygonID;
|
|
}
|
|
|
|
/** Adds a new polygon to the mesh with the given ID. This will also make any missing edges, and all constituent triangles. */
|
|
void CreatePolygonWithID(const FPolygonID PolygonID, const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs = nullptr)
|
|
{
|
|
PolygonElements->Get().Insert(PolygonID);
|
|
CreatePolygon_Internal(PolygonID, PolygonGroupID, VertexInstanceIDs, OutEdgeIDs);
|
|
}
|
|
|
|
/** Deletes a polygon from the mesh */
|
|
MESHDESCRIPTION_API void DeletePolygon(const FPolygonID PolygonID, TArray<FEdgeID>* InOutOrphanedEdgesPtr = nullptr, TArray<FVertexInstanceID>* InOutOrphanedVertexInstancesPtr = nullptr, TArray<FPolygonGroupID>* InOutOrphanedPolygonGroupsPtr = nullptr);
|
|
|
|
/** Deletes polygons from the mesh and remove all orphaned polygon groups, vertex instances, edges and vertices.
|
|
Will not compact the internal arrays, you must call Compact() manually.
|
|
*/
|
|
MESHDESCRIPTION_API void DeletePolygons(const TArray<FPolygonID>& Polygons);
|
|
|
|
/** Returns whether the passed polygon ID is valid */
|
|
bool IsPolygonValid(const FPolygonID PolygonID) const
|
|
{
|
|
return PolygonElements->Get().IsValid(PolygonID);
|
|
}
|
|
|
|
/** Reserves space for this number of new polygon groups */
|
|
void ReserveNewPolygonGroups(const int32 NumPolygonGroups)
|
|
{
|
|
PolygonGroupElements->Get().Reserve(PolygonGroupElements->Get().Num() + NumPolygonGroups);
|
|
}
|
|
|
|
/** Adds a new polygon group to the mesh and returns its ID */
|
|
FPolygonGroupID CreatePolygonGroup()
|
|
{
|
|
const FPolygonGroupID PolygonGroupID = PolygonGroupElements->Get().Add();
|
|
return PolygonGroupID;
|
|
}
|
|
|
|
/** Adds a new polygon group to the mesh with the given ID */
|
|
void CreatePolygonGroupWithID(const FPolygonGroupID PolygonGroupID)
|
|
{
|
|
PolygonGroupElements->Get().Insert(PolygonGroupID);
|
|
}
|
|
|
|
/** Deletes a polygon group from the mesh */
|
|
void DeletePolygonGroup(const FPolygonGroupID PolygonGroupID)
|
|
{
|
|
check(PolygonGroupToPolygons.Find(PolygonGroupID).Num() == 0);
|
|
PolygonGroupElements->Get().Remove(PolygonGroupID);
|
|
PolygonGroupToPolygons.RemoveKey(PolygonGroupID);
|
|
PolygonGroupToTriangles.RemoveKey(PolygonGroupID);
|
|
}
|
|
|
|
/** Returns whether the passed polygon group ID is valid */
|
|
bool IsPolygonGroupValid(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return PolygonGroupElements->Get().IsValid(PolygonGroupID);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// MeshDescription general functions
|
|
|
|
public:
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Vertex operations
|
|
|
|
/** Returns whether a given vertex is orphaned, i.e. it doesn't form part of any polygon */
|
|
MESHDESCRIPTION_API bool IsVertexOrphaned(const FVertexID VertexID) const;
|
|
|
|
/** Returns the edge ID defined by the two given vertex IDs, if there is one; otherwise INDEX_NONE */
|
|
MESHDESCRIPTION_API FEdgeID GetVertexPairEdge(const FVertexID VertexID0, const FVertexID VertexID1) const;
|
|
|
|
/** Returns reference to an array of Edge IDs connected to this vertex */
|
|
TArrayView<const FEdgeID> GetVertexConnectedEdgeIDs(const FVertexID VertexID) const
|
|
{
|
|
return VertexToEdges.Find<FEdgeID>(VertexID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetVertexConnectedEdgeIDs instead.")
|
|
TArray<FEdgeID> GetVertexConnectedEdges(const FVertexID VertexID) const
|
|
{
|
|
return TArray<FEdgeID>(GetVertexConnectedEdgeIDs(VertexID));
|
|
}
|
|
|
|
/** Returns number of edges connected to this vertex */
|
|
int32 GetNumVertexConnectedEdges(const FVertexID VertexID) const
|
|
{
|
|
return VertexToEdges.Find(VertexID).Num();
|
|
}
|
|
|
|
/** Returns reference to an array of VertexInstance IDs instanced from this vertex */
|
|
TArrayView<const FVertexInstanceID> GetVertexVertexInstanceIDs(const FVertexID VertexID) const
|
|
{
|
|
return VertexToVertexInstances.Find<FVertexInstanceID>(VertexID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetVertexVertexInstanceIDs instead.")
|
|
TArray<FVertexInstanceID> GetVertexVertexInstances(const FVertexID VertexID) const
|
|
{
|
|
return TArray<FVertexInstanceID>(GetVertexVertexInstanceIDs(VertexID));
|
|
}
|
|
|
|
/** Returns number of vertex instances created from this vertex */
|
|
int32 GetNumVertexVertexInstances(const FVertexID VertexID) const
|
|
{
|
|
return VertexToVertexInstances.Find(VertexID).Num();
|
|
}
|
|
|
|
/** Populates the passed array of TriangleIDs with the triangles connected to this vertex */
|
|
template <typename Alloc>
|
|
void GetVertexConnectedTriangles(const FVertexID VertexID, TArray<FTriangleID, Alloc>& OutConnectedTriangleIDs) const
|
|
{
|
|
OutConnectedTriangleIDs.Reset(GetNumVertexConnectedTriangles(VertexID));
|
|
for (const FVertexInstanceID& VertexInstanceID : VertexToVertexInstances.Find<FVertexInstanceID>(VertexID))
|
|
{
|
|
TArrayView<const FTriangleID> ConnectedTris = VertexInstanceToTriangles.Find<FTriangleID>(VertexInstanceID);
|
|
OutConnectedTriangleIDs.Append(ConnectedTris.GetData(), ConnectedTris.Num());
|
|
}
|
|
}
|
|
|
|
/** Returns the triangles connected to this vertex as an array with the specified allocator template type. */
|
|
template <typename Alloc>
|
|
TArray<FTriangleID, Alloc> GetVertexConnectedTriangles(const FVertexID VertexID) const
|
|
{
|
|
TArray<FTriangleID, Alloc> Result;
|
|
this->GetVertexConnectedTriangles(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the triangles connected to this vertex */
|
|
TArray<FTriangleID> GetVertexConnectedTriangles(const FVertexID VertexID) const
|
|
{
|
|
TArray<FTriangleID> Result;
|
|
this->GetVertexConnectedTriangles(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns number of triangles connected to this vertex */
|
|
int32 GetNumVertexConnectedTriangles(const FVertexID VertexID) const
|
|
{
|
|
TArrayView<const FVertexInstanceID> VertexInstances = VertexToVertexInstances.Find<FVertexInstanceID>(VertexID);
|
|
return Algo::TransformAccumulate(VertexInstances,
|
|
[this](const FVertexInstanceID ID) { return VertexInstanceToTriangles.Find(ID).Num(); },
|
|
0);
|
|
}
|
|
|
|
/** Populates the passed array of PolygonIDs with the polygons connected to this vertex */
|
|
template <typename Alloc>
|
|
void GetVertexConnectedPolygons(const FVertexID VertexID, TArray<FPolygonID, Alloc>& OutConnectedPolygonIDs) const
|
|
{
|
|
OutConnectedPolygonIDs.Reset();
|
|
for (const FVertexInstanceID& VertexInstanceID : VertexToVertexInstances.Find<FVertexInstanceID>(VertexID))
|
|
{
|
|
for (const FTriangleID& TriangleID : VertexInstanceToTriangles.Find<FTriangleID>(VertexInstanceID))
|
|
{
|
|
OutConnectedPolygonIDs.AddUnique(TrianglePolygons[TriangleID]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Returns the polygons connected to this vertex as an array with the specified allocator template type. */
|
|
template <typename Alloc>
|
|
TArray<FPolygonID, Alloc> GetVertexConnectedPolygons(const FVertexID VertexID) const
|
|
{
|
|
TArray<FPolygonID, Alloc> Result;
|
|
this->GetVertexConnectedPolygons(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the polygons connected to this vertex */
|
|
TArray<FPolygonID> GetVertexConnectedPolygons(const FVertexID VertexID) const
|
|
{
|
|
TArray<FPolygonID> Result;
|
|
this->GetVertexConnectedPolygons(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the number of polygons connected to this vertex */
|
|
int32 GetNumVertexConnectedPolygons(const FVertexID VertexID) const
|
|
{
|
|
return GetVertexConnectedPolygons<TInlineAllocator<8>>(VertexID).Num();
|
|
}
|
|
|
|
/** Populates the passed array of VertexIDs with the vertices adjacent to this vertex */
|
|
template <typename Alloc>
|
|
void GetVertexAdjacentVertices(const FVertexID VertexID, TArray<FVertexID, Alloc>& OutAdjacentVertexIDs) const
|
|
{
|
|
TArrayView<const FEdgeID> ConnectedEdgeIDs = VertexToEdges.Find<FEdgeID>(VertexID);
|
|
OutAdjacentVertexIDs.SetNumUninitialized(ConnectedEdgeIDs.Num());
|
|
|
|
int32 Index = 0;
|
|
for (const FEdgeID& EdgeID : ConnectedEdgeIDs)
|
|
{
|
|
TArrayView<const FVertexID> EdgeVertexIDs = EdgeVertices[EdgeID];
|
|
OutAdjacentVertexIDs[Index] = (EdgeVertexIDs[0] == VertexID) ? EdgeVertexIDs[1] : EdgeVertexIDs[0];
|
|
Index++;
|
|
}
|
|
}
|
|
|
|
/** Returns the vertices adjacent to this vertex as an array with the specified allocator template type. */
|
|
template <typename Alloc>
|
|
TArray<FVertexID, Alloc> GetVertexAdjacentVertices(const FVertexID VertexID) const
|
|
{
|
|
TArray<FVertexID, Alloc> Result;
|
|
this->GetVertexAdjacentVertices(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the vertices adjacent to this vertex */
|
|
TArray<FVertexID> GetVertexAdjacentVertices(const FVertexID VertexID) const
|
|
{
|
|
TArray<FVertexID> Result;
|
|
this->GetVertexAdjacentVertices(VertexID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the position of this vertex */
|
|
FVector3f GetVertexPosition(const FVertexID VertexID) const
|
|
{
|
|
return VertexPositions[VertexID];
|
|
}
|
|
|
|
TVertexAttributesRef<FVector3f> GetVertexPositions()
|
|
{
|
|
return VertexPositions;
|
|
}
|
|
|
|
TVertexAttributesRef<const FVector3f> GetVertexPositions() const
|
|
{
|
|
return VertexPositions;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Vertex instance operations
|
|
|
|
/** Returns the vertex ID associated with the given vertex instance */
|
|
FVertexID GetVertexInstanceVertex(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return VertexInstanceVertices[VertexInstanceID];
|
|
}
|
|
|
|
/** Returns the edge ID defined by the two given vertex instance IDs, if there is one; otherwise INDEX_NONE */
|
|
MESHDESCRIPTION_API FEdgeID GetVertexInstancePairEdge(const FVertexInstanceID VertexInstanceID0, const FVertexInstanceID VertexInstanceID1) const;
|
|
|
|
/** Returns reference to an array of Triangle IDs connected to this vertex instance */
|
|
TArrayView<const FTriangleID> GetVertexInstanceConnectedTriangleIDs(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return VertexInstanceToTriangles.Find<FTriangleID>(VertexInstanceID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetVertexInstanceTriangleIDs() instead.")
|
|
TArray<FTriangleID> GetVertexInstanceConnectedTriangles(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return TArray<FTriangleID>(GetVertexInstanceConnectedTriangleIDs(VertexInstanceID));
|
|
}
|
|
|
|
/** Returns the number of triangles connected to this vertex instance */
|
|
int32 GetNumVertexInstanceConnectedTriangles(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return VertexInstanceToTriangles.Find(VertexInstanceID).Num();
|
|
}
|
|
|
|
/** Populates the passed array with the polygons connected to this vertex instance */
|
|
template <typename Alloc>
|
|
void GetVertexInstanceConnectedPolygons(const FVertexInstanceID VertexInstanceID, TArray<FPolygonID, Alloc>& OutPolygonIDs) const
|
|
{
|
|
OutPolygonIDs.Reset(VertexInstanceToTriangles.Find(VertexInstanceID).Num());
|
|
for (const FTriangleID& TriangleID : VertexInstanceToTriangles.Find<FTriangleID>(VertexInstanceID))
|
|
{
|
|
OutPolygonIDs.AddUnique(TrianglePolygons[TriangleID]);
|
|
}
|
|
}
|
|
|
|
/** Returns the polygons connected to this vertex instance as an array with the specified allocator template type. */
|
|
template <typename Alloc>
|
|
TArray<FPolygonID, Alloc> GetVertexInstanceConnectedPolygons(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
TArray<FPolygonID, Alloc> Result;
|
|
this->GetVertexInstanceConnectedPolygons(VertexInstanceID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the polygons connected to this vertex instance */
|
|
TArray<FPolygonID> GetVertexInstanceConnectedPolygons(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
TArray<FPolygonID> Result;
|
|
this->GetVertexInstanceConnectedPolygons(VertexInstanceID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the number of polygons connected to this vertex instance. */
|
|
int32 GetNumVertexInstanceConnectedPolygons(const FVertexInstanceID VertexInstanceID) const
|
|
{
|
|
return GetVertexInstanceConnectedPolygons<TInlineAllocator<8>>(VertexInstanceID).Num();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Edge operations
|
|
|
|
/** Determine whether a given edge is an internal edge between triangles of a polygon */
|
|
bool IsEdgeInternal(const FEdgeID EdgeID) const
|
|
{
|
|
TArrayView<const FTriangleID> ConnectedTriangles = EdgeToTriangles.Find<FTriangleID>(EdgeID);
|
|
return ConnectedTriangles.Num() == 2 &&
|
|
TrianglePolygons[ConnectedTriangles[0]] == TrianglePolygons[ConnectedTriangles[1]];
|
|
}
|
|
|
|
/** Determine whether a given edge is an internal edge between triangles of a specific polygon */
|
|
bool IsEdgeInternalToPolygon(const FEdgeID EdgeID, const FPolygonID PolygonID) const
|
|
{
|
|
TArrayView<const FTriangleID> ConnectedTriangles = EdgeToTriangles.Find<FTriangleID>(EdgeID);
|
|
return ConnectedTriangles.Num() == 2 &&
|
|
TrianglePolygons[ConnectedTriangles[0]] == PolygonID &&
|
|
TrianglePolygons[ConnectedTriangles[1]] == PolygonID;
|
|
}
|
|
|
|
/** Returns reference to an array of triangle IDs connected to this edge */
|
|
TArrayView<const FTriangleID> GetEdgeConnectedTriangleIDs(const FEdgeID EdgeID) const
|
|
{
|
|
return EdgeToTriangles.Find<FTriangleID>(EdgeID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetEdgeConnectedTriangleIDs() instead.")
|
|
TArray<FTriangleID> GetEdgeConnectedTriangles(const FEdgeID EdgeID) const
|
|
{
|
|
return TArray<FTriangleID>(GetEdgeConnectedTriangleIDs(EdgeID));
|
|
}
|
|
|
|
int32 GetNumEdgeConnectedTriangles(const FEdgeID EdgeID) const
|
|
{
|
|
return EdgeToTriangles.Find(EdgeID).Num();
|
|
}
|
|
|
|
/** Populates the passed array with polygon IDs connected to this edge */
|
|
template <typename Alloc>
|
|
void GetEdgeConnectedPolygons(const FEdgeID EdgeID, TArray<FPolygonID, Alloc>& OutPolygonIDs) const
|
|
{
|
|
OutPolygonIDs.Reset(EdgeToTriangles.Find(EdgeID).Num());
|
|
for (const FTriangleID& TriangleID : EdgeToTriangles.Find<FTriangleID>(EdgeID))
|
|
{
|
|
OutPolygonIDs.AddUnique(TrianglePolygons[TriangleID]);
|
|
}
|
|
}
|
|
|
|
/** Returns the polygons connected to this edge as an array with the specified allocator template type. */
|
|
template <typename Alloc>
|
|
TArray<FPolygonID, Alloc> GetEdgeConnectedPolygons(const FEdgeID EdgeID) const
|
|
{
|
|
TArray<FPolygonID, Alloc> Result;
|
|
this->GetEdgeConnectedPolygons(EdgeID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the polygons connected to this edge */
|
|
TArray<FPolygonID> GetEdgeConnectedPolygons(const FEdgeID EdgeID) const
|
|
{
|
|
TArray<FPolygonID> Result;
|
|
this->GetEdgeConnectedPolygons(EdgeID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the number of polygons connected to this edge */
|
|
int32 GetNumEdgeConnectedPolygons(const FEdgeID EdgeID) const
|
|
{
|
|
return GetEdgeConnectedPolygons<TInlineAllocator<8>>(EdgeID).Num();
|
|
}
|
|
|
|
/** Returns the vertex ID corresponding to one of the edge endpoints */
|
|
FVertexID GetEdgeVertex(const FEdgeID EdgeID, int32 VertexNumber) const
|
|
{
|
|
check(VertexNumber == 0 || VertexNumber == 1);
|
|
TArrayView<const FVertexID> EdgeVertexIDs = EdgeVertices[EdgeID];
|
|
return EdgeVertexIDs[VertexNumber];
|
|
}
|
|
|
|
/** Returns a pair of vertex IDs defining the edge */
|
|
TArrayView<const FVertexID> GetEdgeVertices(const FEdgeID EdgeID) const
|
|
{
|
|
return EdgeVertices[EdgeID];
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Triangle operations
|
|
|
|
/** Get the polygon which contains this triangle */
|
|
FPolygonID GetTrianglePolygon(const FTriangleID TriangleID) const
|
|
{
|
|
return TrianglePolygons[TriangleID];
|
|
}
|
|
|
|
/** Get the polygon group which contains this triangle */
|
|
FPolygonGroupID GetTrianglePolygonGroup(const FTriangleID TriangleID) const
|
|
{
|
|
return TrianglePolygonGroups[TriangleID];
|
|
}
|
|
|
|
/** Determines if this triangle is part of an n-gon */
|
|
bool IsTrianglePartOfNgon(const FTriangleID TriangleID) const
|
|
{
|
|
return PolygonToTriangles.Find(TrianglePolygons[TriangleID]).Num() > 1;
|
|
}
|
|
|
|
/** Get the vertex instances which define this triangle */
|
|
TArrayView<const FVertexInstanceID> GetTriangleVertexInstances(const FTriangleID TriangleID) const
|
|
{
|
|
return TriangleVertexInstances[TriangleID];
|
|
}
|
|
|
|
/** Get the specified vertex instance by index */
|
|
FVertexInstanceID GetTriangleVertexInstance(const FTriangleID TriangleID, const int32 Index) const
|
|
{
|
|
check(Index >= 0 && Index < 3);
|
|
TArrayView<const FVertexInstanceID> TriVertexInstanceIDs = TriangleVertexInstances[TriangleID];
|
|
return TriVertexInstanceIDs[Index];
|
|
}
|
|
|
|
/** Populates the passed array with the vertices which define this triangle */
|
|
UE_DEPRECATED(4.26, "Use the other form of GetTriangleVertices")
|
|
void GetTriangleVertices(const FTriangleID TriangleID, TArrayView<FVertexID> OutVertexIDs) const
|
|
{
|
|
check(OutVertexIDs.Num() >= 3);
|
|
TArrayView<const FVertexID> TriVerts = TriangleVertices[TriangleID];
|
|
for (int32 Index = 0; Index < 3; ++Index)
|
|
{
|
|
OutVertexIDs[Index] = TriVerts[Index];
|
|
}
|
|
}
|
|
|
|
/** Return the vertices which define this triangle */
|
|
TArrayView<const FVertexID> GetTriangleVertices(const FTriangleID TriangleID) const
|
|
{
|
|
return TriangleVertices[TriangleID];
|
|
}
|
|
|
|
/** Populates the passed array with the edges which define this triangle */
|
|
UE_DEPRECATED(4.26, "Use the other form of GetTriangleEdges")
|
|
void GetTriangleEdges(const FTriangleID TriangleID, TArrayView<FEdgeID> OutEdgeIDs) const
|
|
{
|
|
check(OutEdgeIDs.Num() >= 3);
|
|
TArrayView<const FEdgeID> TriEdges = TriangleEdges[TriangleID];
|
|
for (int32 Index = 0; Index < 3; ++Index)
|
|
{
|
|
OutEdgeIDs[Index] = TriEdges[Index];
|
|
}
|
|
}
|
|
|
|
/** Return the edges which form this triangle */
|
|
TArrayView<FEdgeID> GetTriangleEdges(const FTriangleID TriangleID) const
|
|
{
|
|
return TriangleEdges[TriangleID];
|
|
}
|
|
|
|
/** Populates the passed array with adjacent triangles */
|
|
template <typename Alloc>
|
|
void GetTriangleAdjacentTriangles(const FTriangleID TriangleID, TArray<FTriangleID, Alloc>& OutTriangleIDs) const
|
|
{
|
|
OutTriangleIDs.Reset();
|
|
for (const FEdgeID& EdgeID : GetTriangleEdges(TriangleID))
|
|
{
|
|
for (const int32& TriangleIndex : EdgeToTriangles.Find(EdgeID))
|
|
{
|
|
FTriangleID OtherTriangleID(TriangleIndex);
|
|
if (OtherTriangleID != TriangleID)
|
|
{
|
|
OutTriangleIDs.Add(OtherTriangleID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Return adjacent triangles into a TArray with the specified allocator */
|
|
template <typename Alloc>
|
|
TArray<FTriangleID, Alloc> GetTriangleAdjacentTriangles(const FTriangleID TriangleID) const
|
|
{
|
|
TArray<FTriangleID, Alloc> Result;
|
|
this->GetTriangleAdjacentTriangles(TriangleID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return adjacent triangles to this triangle */
|
|
TArray<FTriangleID> GetTriangleAdjacentTriangles(const FTriangleID TriangleID) const
|
|
{
|
|
TArray<FTriangleID> Result;
|
|
this->GetTriangleAdjacentTriangles(TriangleID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return UV indices for this triangle for the given channel */
|
|
TArrayView<FUVID> GetTriangleUVIndices(const FTriangleID TriangleID, int32 UVChannel = 0) const
|
|
{
|
|
return TriangleUVs.Get(TriangleID, UVChannel);
|
|
}
|
|
|
|
/** Return the vertex instance which corresponds to the given vertex on the given triangle, or INDEX_NONE */
|
|
FVertexInstanceID GetVertexInstanceForTriangleVertex(const FTriangleID TriangleID, const FVertexID VertexID) const
|
|
{
|
|
const FVertexInstanceID* VertexInstanceIDPtr = Algo::FindByPredicate(
|
|
GetTriangleVertexInstances(TriangleID),
|
|
[this, VertexID](const FVertexInstanceID VertexInstanceID) { return (GetVertexInstanceVertex(VertexInstanceID) == VertexID); });
|
|
|
|
return VertexInstanceIDPtr ? *VertexInstanceIDPtr : FVertexInstanceID(INDEX_NONE);
|
|
}
|
|
|
|
/** Reverse the winding order of the vertices of this triangle */
|
|
MESHDESCRIPTION_API void ReverseTriangleFacing(const FTriangleID TriangleID);
|
|
|
|
/** Set the UV indices for this triangle */
|
|
MESHDESCRIPTION_API void SetTriangleUVIndices(const FTriangleID TriangleID, TArrayView<const FUVID> UVIDs, int32 UVChannel = 0);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Polygon operations
|
|
|
|
/** Return reference to an array of triangle IDs which comprise this polygon */
|
|
TArrayView<const FTriangleID> GetPolygonTriangles(const FPolygonID PolygonID) const
|
|
{
|
|
return PolygonToTriangles.Find<FTriangleID>(PolygonID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetPolygonTriangles() instead.")
|
|
TArray<FTriangleID> GetPolygonTriangleIDs(const FPolygonID PolygonID) const
|
|
{
|
|
return TArray<FTriangleID>(GetPolygonTriangles(PolygonID));
|
|
}
|
|
|
|
/** Return the number of triangles which comprise this polygon */
|
|
int32 GetNumPolygonTriangles(const FPolygonID PolygonID) const
|
|
{
|
|
return PolygonToTriangles.Find(PolygonID).Num();
|
|
}
|
|
|
|
/** Returns reference to an array of VertexInstance IDs forming the perimeter of this polygon */
|
|
template <typename Alloc>
|
|
void GetPolygonVertexInstances(const FPolygonID PolygonID, TArray<FVertexInstanceID, Alloc>& OutVertexInstanceIDs) const
|
|
{
|
|
OutVertexInstanceIDs.SetNumUninitialized(GetNumPolygonVertices(PolygonID));
|
|
TArrayView<const FTriangleID> Tris = PolygonToTriangles.Find<FTriangleID>(PolygonID);
|
|
if (Tris.Num() == 1)
|
|
{
|
|
OutVertexInstanceIDs = TriangleVertexInstances[Tris[0]];
|
|
}
|
|
else
|
|
{
|
|
TArray<TTuple<int32, int32>, TInlineAllocator<8>> Result;
|
|
Result.SetNumUninitialized(Tris.Num() + 2);
|
|
FindPolygonPerimeter(Tris, Result);
|
|
for (int32 Index = 0; Index < Result.Num(); Index++)
|
|
{
|
|
FTriangleID TriangleID = Tris[Result[Index].Get<0>()];
|
|
int32 VertexInstanceNumber = Result[Index].Get<1>();
|
|
OutVertexInstanceIDs[Index] = TriangleVertexInstances[TriangleID][VertexInstanceNumber];
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename Alloc>
|
|
TArray<FVertexInstanceID, Alloc> GetPolygonVertexInstances(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FVertexInstanceID, Alloc> Result;
|
|
this->GetPolygonVertexInstances(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
TArray<FVertexInstanceID> GetPolygonVertexInstances(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FVertexInstanceID> Result;
|
|
this->GetPolygonVertexInstances(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the number of vertices this polygon has */
|
|
int32 GetNumPolygonVertices(const FPolygonID PolygonID) const
|
|
{
|
|
TArrayView<const FTriangleID> Tris = PolygonToTriangles.Find<FTriangleID>(PolygonID);
|
|
return Tris.Num() + 2;
|
|
}
|
|
|
|
/** Populates the passed array of VertexIDs with the vertices which form the polygon perimeter */
|
|
template <typename Alloc>
|
|
void GetPolygonVertices(const FPolygonID PolygonID, TArray<FVertexID, Alloc>& OutVertexIDs) const
|
|
{
|
|
OutVertexIDs.SetNumUninitialized(GetNumPolygonVertices(PolygonID));
|
|
TArrayView<const FTriangleID> Tris = PolygonToTriangles.Find<FTriangleID>(PolygonID);
|
|
if (Tris.Num() == 1)
|
|
{
|
|
OutVertexIDs = TriangleVertices[Tris[0]];
|
|
}
|
|
else
|
|
{
|
|
TArray<TTuple<int32, int32>, TInlineAllocator<8>> Result;
|
|
Result.SetNumUninitialized(Tris.Num() + 2);
|
|
FindPolygonPerimeter(Tris, Result);
|
|
for (int32 Index = 0; Index < Result.Num(); Index++)
|
|
{
|
|
FTriangleID TriangleID = Tris[Result[Index].Get<0>()];
|
|
int32 VertexNumber = Result[Index].Get<1>();
|
|
OutVertexIDs[Index] = TriangleVertices[TriangleID][VertexNumber];
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Returns the vertices which form the polygon perimeter as an array templated on the given allocator */
|
|
template <typename Alloc>
|
|
TArray<FVertexID, Alloc> GetPolygonVertices(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FVertexID, Alloc> Result;
|
|
this->GetPolygonVertices(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the vertices which form the polygon perimeter */
|
|
TArray<FVertexID> GetPolygonVertices(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FVertexID> Result;
|
|
this->GetPolygonVertices(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Populates the passed array with the edges which form the polygon perimeter */
|
|
template <typename Alloc>
|
|
void GetPolygonPerimeterEdges(const FPolygonID PolygonID, TArray<FEdgeID, Alloc>& OutEdgeIDs) const
|
|
{
|
|
OutEdgeIDs.SetNumUninitialized(GetNumPolygonVertices(PolygonID));
|
|
TArrayView<const FTriangleID> Tris = PolygonToTriangles.Find<FTriangleID>(PolygonID);
|
|
if (Tris.Num() == 1)
|
|
{
|
|
OutEdgeIDs = TriangleEdges[Tris[0]];
|
|
}
|
|
else
|
|
{
|
|
TArray<TTuple<int32, int32>, TInlineAllocator<8>> Result;
|
|
Result.SetNumUninitialized(Tris.Num() + 2);
|
|
FindPolygonPerimeter(Tris, Result);
|
|
for (int32 Index = 0; Index < Result.Num(); Index++)
|
|
{
|
|
FTriangleID TriangleID = Tris[Result[Index].Get<0>()];
|
|
int32 EdgeNumber = Result[Index].Get<1>();
|
|
OutEdgeIDs[Index] = TriangleEdges[TriangleID][EdgeNumber];
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Returns the vertices which form the polygon perimeter as an array templated on the given allocator */
|
|
template <typename Alloc>
|
|
TArray<FEdgeID, Alloc> GetPolygonPerimeterEdges(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FEdgeID, Alloc> Result;
|
|
this->GetPolygonPerimeterEdges(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Returns the vertices which form the polygon perimeter */
|
|
TArray<FEdgeID> GetPolygonPerimeterEdges(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FEdgeID> Result;
|
|
this->GetPolygonPerimeterEdges(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Populate the provided array with a list of edges which are internal to the polygon, i.e. those which separate
|
|
constituent triangles. */
|
|
template <typename Alloc>
|
|
void GetPolygonInternalEdges(const FPolygonID PolygonID, TArray<FEdgeID, Alloc>& OutEdgeIDs) const
|
|
{
|
|
OutEdgeIDs.Reset(GetNumPolygonVertices(PolygonID) - 3);
|
|
if (GetNumPolygonVertices(PolygonID) > 3)
|
|
{
|
|
TArray<FVertexInstanceID> VertexInstanceIDs = GetPolygonVertexInstances(PolygonID);
|
|
for (const FVertexInstanceID& VertexInstanceID : VertexInstanceIDs)
|
|
{
|
|
for (const FEdgeID& EdgeID : GetVertexConnectedEdgeIDs(GetVertexInstanceVertex(VertexInstanceID)))
|
|
{
|
|
if (!OutEdgeIDs.Contains(EdgeID) && IsEdgeInternalToPolygon(EdgeID, PolygonID))
|
|
{
|
|
OutEdgeIDs.Add(EdgeID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Return the internal edges of this polygon, i.e. those which separate constituent triangles */
|
|
template <typename Alloc>
|
|
TArray<FEdgeID, Alloc> GetPolygonInternalEdges(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FEdgeID, Alloc> Result;
|
|
this->GetPolygonInternalEdges(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return the internal edges of this polygon, i.e. those which separate constituent triangles */
|
|
TArray<FEdgeID> GetPolygonInternalEdges(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FEdgeID> Result;
|
|
this->GetPolygonInternalEdges(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return the number of internal edges in this polygon */
|
|
int32 GetNumPolygonInternalEdges(const FPolygonID PolygonID) const
|
|
{
|
|
return PolygonToTriangles.Find(PolygonID).Num() - 1;
|
|
}
|
|
|
|
/** Populates the passed array with adjacent polygons */
|
|
template <typename Alloc>
|
|
void GetPolygonAdjacentPolygons(const FPolygonID PolygonID, TArray<FPolygonID, Alloc>& OutPolygonIDs) const
|
|
{
|
|
OutPolygonIDs.Reset();
|
|
for (const FEdgeID& EdgeID : GetPolygonPerimeterEdges<TInlineAllocator<16>>(PolygonID))
|
|
{
|
|
for (const FPolygonID& OtherPolygonID : GetEdgeConnectedPolygons<TInlineAllocator<8>>(EdgeID))
|
|
{
|
|
if (OtherPolygonID != PolygonID)
|
|
{
|
|
OutPolygonIDs.Add(OtherPolygonID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Return adjacent polygons into a TArray with the specified allocator */
|
|
template <typename Alloc>
|
|
TArray<FPolygonID, Alloc> GetPolygonAdjacentPolygons(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FPolygonID, Alloc> Result;
|
|
this->GetPolygonAdjacentPolygons(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return adjacent polygons to this polygon */
|
|
TArray<FPolygonID> GetPolygonAdjacentPolygons(const FPolygonID PolygonID) const
|
|
{
|
|
TArray<FPolygonID> Result;
|
|
this->GetPolygonAdjacentPolygons(PolygonID, Result);
|
|
return Result;
|
|
}
|
|
|
|
/** Return the polygon group associated with a polygon */
|
|
FPolygonGroupID GetPolygonPolygonGroup(const FPolygonID PolygonID) const
|
|
{
|
|
return PolygonPolygonGroups[PolygonID];
|
|
}
|
|
|
|
/** Return the vertex instance which corresponds to the given vertex on the given polygon, or INDEX_NONE */
|
|
FVertexInstanceID GetVertexInstanceForPolygonVertex(const FPolygonID PolygonID, const FVertexID VertexID) const
|
|
{
|
|
TArray<FVertexInstanceID> VertexInstanceIDs = GetPolygonVertexInstances(PolygonID);
|
|
const FVertexInstanceID* VertexInstanceIDPtr = VertexInstanceIDs.FindByPredicate(
|
|
[this, VertexID](const FVertexInstanceID VertexInstanceID) { return (GetVertexInstanceVertex(VertexInstanceID) == VertexID); });
|
|
|
|
return VertexInstanceIDPtr ? *VertexInstanceIDPtr : FVertexInstanceID(INDEX_NONE);
|
|
}
|
|
|
|
/** Set the vertex instance at the given index around the polygon to the new value */
|
|
MESHDESCRIPTION_API void SetPolygonVertexInstance(const FPolygonID PolygonID, const int32 PerimeterIndex, const FVertexInstanceID VertexInstanceID);
|
|
MESHDESCRIPTION_API void SetPolygonVertexInstances(const FPolygonID PolygonID, TArrayView<const FVertexInstanceID> VertexInstanceIDs);
|
|
|
|
/** Sets the polygon group associated with a polygon */
|
|
void SetPolygonPolygonGroup(const FPolygonID PolygonID, const FPolygonGroupID PolygonGroupID)
|
|
{
|
|
FPolygonGroupID OldPolygonGroupID = PolygonPolygonGroups[PolygonID];
|
|
PolygonGroupToPolygons.RemoveReferenceFromKey(OldPolygonGroupID, PolygonID);
|
|
|
|
PolygonPolygonGroups[PolygonID] = PolygonGroupID;
|
|
PolygonGroupToPolygons.AddReferenceToKey(PolygonGroupID, PolygonID);
|
|
|
|
for (const int32& TriangleIndex: PolygonToTriangles.Find(PolygonID))
|
|
{
|
|
const FTriangleID TriangleID(TriangleIndex);
|
|
check(TrianglePolygonGroups[TriangleID] == OldPolygonGroupID);
|
|
PolygonGroupToTriangles.RemoveReferenceFromKey(OldPolygonGroupID, TriangleID);
|
|
|
|
TrianglePolygonGroups[TriangleID] = PolygonGroupID;
|
|
PolygonGroupToTriangles.AddReferenceToKey(PolygonGroupID, TriangleID);
|
|
}
|
|
}
|
|
|
|
/** Reverse the winding order of the vertices of this polygon */
|
|
MESHDESCRIPTION_API void ReversePolygonFacing(const FPolygonID PolygonID);
|
|
|
|
/** Determines the vertex instances which form the perimeter of a polygon */
|
|
MESHDESCRIPTION_API void FindPolygonPerimeter(TArrayView<const FTriangleID> Triangles, TArrayView<TTuple<int32, int32>> Result) const;
|
|
MESHDESCRIPTION_API void FindPolygonPerimeter(const FPolygonID PolygonID, TArrayView<FEdgeID> Edges) const;
|
|
|
|
/** Generates triangles and internal edges for the given polygon */
|
|
MESHDESCRIPTION_API void ComputePolygonTriangulation(const FPolygonID PolygonID);
|
|
|
|
MESHDESCRIPTION_API void SplitPolygon(FPolygonID PolygonID);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Polygon group operations
|
|
|
|
/** Returns the polygons associated with the given polygon group */
|
|
TArrayView<const FPolygonID> GetPolygonGroupPolygonIDs(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return PolygonGroupToPolygons.Find<FPolygonID>(PolygonGroupID);
|
|
}
|
|
|
|
UE_DEPRECATED(4.26, "Please use GetPolygonGroupPolygonIDs() instead.")
|
|
TArray<FPolygonID> GetPolygonGroupPolygons(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return TArray<FPolygonID>(GetPolygonGroupPolygonIDs(PolygonGroupID));
|
|
}
|
|
|
|
/** Returns the triangles associated with the given polygon group */
|
|
TArrayView<const FTriangleID> GetPolygonGroupTriangles(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return PolygonGroupToTriangles.Find<FTriangleID>(PolygonGroupID);
|
|
}
|
|
|
|
/** Returns the number of polygons in this polygon group */
|
|
int32 GetNumPolygonGroupPolygons(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return PolygonGroupToPolygons.Find(PolygonGroupID).Num();
|
|
}
|
|
|
|
/** Returns the number of triangles in this polygon group */
|
|
int32 GetNumPolygonGroupTriangles(const FPolygonGroupID PolygonGroupID) const
|
|
{
|
|
return PolygonGroupToTriangles.Find(PolygonGroupID).Num();
|
|
}
|
|
|
|
/** Remaps polygon groups according to the supplied map */
|
|
MESHDESCRIPTION_API void RemapPolygonGroups(const TMap<FPolygonGroupID, FPolygonGroupID>& Remap);
|
|
|
|
/** Transfer the source polygon group data to the destination polygon group. The source data is append to the destination */
|
|
MESHDESCRIPTION_API void TransferPolygonGroup(FPolygonGroupID SourceID, FPolygonGroupID DestinationID);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Whole mesh operations
|
|
|
|
/** Determines if calling Compact() would perform actual compaction or not. */
|
|
MESHDESCRIPTION_API bool NeedsCompact() const;
|
|
|
|
/** Compacts the data held in the mesh description, and returns an object describing how the IDs have been remapped. */
|
|
MESHDESCRIPTION_API void Compact( FElementIDRemappings& OutRemappings );
|
|
|
|
/** Remaps the element IDs in the mesh description according to the passed in object */
|
|
MESHDESCRIPTION_API void Remap( const FElementIDRemappings& Remappings );
|
|
|
|
/** Gets the number of UV element channels */
|
|
int32 GetNumUVElementChannels() const { return UVElements->GetNumChannels(); }
|
|
|
|
/** Sets the specified number of UV channels */
|
|
MESHDESCRIPTION_API void SetNumUVChannels(const int32 NumUVChannels);
|
|
|
|
/** Returns bounds of vertices */
|
|
MESHDESCRIPTION_API FBoxSphereBounds GetBounds() const;
|
|
|
|
/** Retriangulates the entire mesh */
|
|
MESHDESCRIPTION_API void TriangulateMesh();
|
|
|
|
/** Reverses the winding order of all polygons in the mesh */
|
|
MESHDESCRIPTION_API void ReverseAllPolygonFacing();
|
|
|
|
MESHDESCRIPTION_API float GetTriangleCornerAngleForVertex(const FTriangleID TriangleID, const FVertexID VertexID) const;
|
|
MESHDESCRIPTION_API float GetPolygonCornerAngleForVertex(const FPolygonID PolygonID, const FVertexID VertexID) const;
|
|
|
|
MESHDESCRIPTION_API FBox ComputeBoundingBox() const;
|
|
|
|
private:
|
|
|
|
MESHDESCRIPTION_API FPlane ComputePolygonPlane(TArrayView<const FVertexInstanceID> PerimeterVertexInstanceIDs) const;
|
|
MESHDESCRIPTION_API FVector ComputePolygonNormal(TArrayView<const FVertexInstanceID> PerimeterVertexInstanceIDs) const;
|
|
|
|
private:
|
|
|
|
MESHDESCRIPTION_API void Initialize();
|
|
MESHDESCRIPTION_API void InitializeIndexers();
|
|
MESHDESCRIPTION_API void Cache();
|
|
|
|
MESHDESCRIPTION_API void CreateVertexInstance_Internal(const FVertexInstanceID VertexInstanceID, const FVertexID VertexID);
|
|
MESHDESCRIPTION_API void CreateEdge_Internal(const FEdgeID EdgeID, const FVertexID VertexID0, const FVertexID VertexID1);
|
|
MESHDESCRIPTION_API void CreateTriangle_Internal(const FTriangleID TriangleID, const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs);
|
|
MESHDESCRIPTION_API void CreatePolygon_Internal(const FPolygonID PolygonID, const FPolygonGroupID PolygonGroupID, TArrayView<const FVertexInstanceID> VertexInstanceIDs, TArray<FEdgeID>* OutEdgeIDs);
|
|
MESHDESCRIPTION_API void CreatePolygonTriangles(const FPolygonID PolygonID, TArrayView<const FVertexInstanceID> VertexInstanceIDs);
|
|
MESHDESCRIPTION_API void RemovePolygonTriangles(const FPolygonID PolygonID);
|
|
|
|
template <template <typename...> class TContainer>
|
|
void DeleteVertexInstance_Internal(const FVertexInstanceID VertexInstanceID, TContainer<FVertexID>* InOutOrphanedVerticesPtr = nullptr);
|
|
template <template <typename...> class TContainer>
|
|
void DeleteEdge_Internal(const FEdgeID EdgeID, TContainer<FVertexID>* InOutOrphanedVerticesPtr = nullptr);
|
|
template <template <typename...> class TContainer>
|
|
void DeleteTriangle_Internal(const FTriangleID TriangleID, TContainer<FEdgeID>* InOutOrphanedEdgesPtr = nullptr, TContainer<FVertexInstanceID>* InOutOrphanedVertexInstancesPtr = nullptr, TContainer<FPolygonGroupID>* InOutOrphanedPolygonGroupsPtr = nullptr);
|
|
template <template <typename...> class TContainer>
|
|
void DeletePolygon_Internal(const FPolygonID PolygonID, TContainer<FEdgeID>* InOutOrphanedEdgesPtr = nullptr, TContainer<FVertexInstanceID>* InOutOrphanedVertexInstancesPtr = nullptr, TContainer<FPolygonGroupID>* InOutOrphanedPolygonGroupsPtr = nullptr);
|
|
|
|
/** Given a set of index remappings, fixes up references to element IDs */
|
|
MESHDESCRIPTION_API void FixUpElementIDs(const FElementIDRemappings& Remappings);
|
|
|
|
template <class T>
|
|
void AddUnique(TArray<T>& Container, const T& Item)
|
|
{
|
|
Container.AddUnique(Item);
|
|
}
|
|
|
|
template <class T>
|
|
void AddUnique(TSet<T>& Container, const T& Item)
|
|
{
|
|
Container.Add(Item);
|
|
}
|
|
|
|
public:
|
|
static MESHDESCRIPTION_API FName VerticesName;
|
|
static MESHDESCRIPTION_API FName VertexInstancesName;
|
|
static MESHDESCRIPTION_API FName UVsName;
|
|
static MESHDESCRIPTION_API FName EdgesName;
|
|
static MESHDESCRIPTION_API FName TrianglesName;
|
|
static MESHDESCRIPTION_API FName PolygonsName;
|
|
static MESHDESCRIPTION_API FName PolygonGroupsName;
|
|
|
|
private:
|
|
TMap<FName, FMeshElementTypeWrapper> Elements;
|
|
|
|
FMeshElementChannels* VertexElements;
|
|
FMeshElementChannels* VertexInstanceElements;
|
|
FMeshElementChannels* UVElements;
|
|
FMeshElementChannels* EdgeElements;
|
|
FMeshElementChannels* TriangleElements;
|
|
FMeshElementChannels* PolygonElements;
|
|
FMeshElementChannels* PolygonGroupElements;
|
|
|
|
TMeshAttributesArray<FVertexID> VertexInstanceVertices;
|
|
TMeshAttributesArray<TArrayView<FVertexID>> EdgeVertices;
|
|
TMeshAttributesArray<TArrayView<FVertexInstanceID>> TriangleVertexInstances;
|
|
TMeshAttributesArray<FPolygonID> TrianglePolygons;
|
|
TMeshAttributesArray<TArrayView<FEdgeID>> TriangleEdges;
|
|
TMeshAttributesArray<TArrayView<FVertexID>> TriangleVertices;
|
|
TMeshAttributesArray<TArrayView<FUVID>> TriangleUVs;
|
|
TMeshAttributesArray<FPolygonGroupID> TrianglePolygonGroups;
|
|
TMeshAttributesArray<FPolygonGroupID> PolygonPolygonGroups;
|
|
TMeshAttributesArray<FVector3f> VertexPositions;
|
|
|
|
// The indexers are all mutable because they may be rebuilt during what is essentially a get operation
|
|
mutable FMeshElementIndexer VertexToVertexInstances;
|
|
mutable FMeshElementIndexer VertexToEdges;
|
|
mutable FMeshElementIndexer VertexInstanceToTriangles;
|
|
mutable FMeshElementIndexer EdgeToTriangles;
|
|
mutable FMeshElementIndexer UVToTriangles;
|
|
mutable FMeshElementIndexer PolygonToTriangles;
|
|
mutable FMeshElementIndexer PolygonGroupToTriangles;
|
|
mutable FMeshElementIndexer PolygonGroupToPolygons;
|
|
};
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
|
|
/**
|
|
* Bulk data storage for FMeshDescription
|
|
*/
|
|
struct FMeshDescriptionBulkData
|
|
{
|
|
public:
|
|
FMeshDescriptionBulkData()
|
|
: bBulkDataUpdated(false)
|
|
, bGuidIsHash(false)
|
|
{
|
|
}
|
|
|
|
/** Serialization */
|
|
MESHDESCRIPTION_API void Serialize(FArchive& Ar, UObject* Owner);
|
|
|
|
/** Store a new mesh description in the bulk data */
|
|
MESHDESCRIPTION_API void SaveMeshDescription(FMeshDescription& MeshDescription);
|
|
|
|
/** Load the mesh description from the bulk data */
|
|
MESHDESCRIPTION_API void LoadMeshDescription(FMeshDescription& MeshDescription);
|
|
|
|
/** Empties the bulk data */
|
|
MESHDESCRIPTION_API void Empty();
|
|
|
|
/** Returns true if there is no bulk data available */
|
|
bool IsEmpty() const { return !BulkData.HasPayloadData(); }
|
|
|
|
/** Return unique ID string for this bulk data */
|
|
MESHDESCRIPTION_API FString GetIdString() const;
|
|
|
|
/** Uses a hash as the GUID, useful to prevent recomputing content already in cache. */
|
|
MESHDESCRIPTION_API void UseHashAsGuid();
|
|
|
|
/** Gets the size of the serialized bulk data */
|
|
int64 GetBulkDataSize() { return BulkData.GetPayloadSize(); }
|
|
|
|
/** Returns all of the CustomVersions that can be used when serializing an FMeshDescription. */
|
|
static MESHDESCRIPTION_API TConstArrayView<FGuid> GetMeshDescriptionCustomVersions();
|
|
|
|
private:
|
|
MESHDESCRIPTION_API void UpdateMeshDescriptionFormat();
|
|
|
|
#if WITH_EDITOR
|
|
/** Protects simultaneous access to BulkData */
|
|
FRWLock BulkDataLock;
|
|
#endif
|
|
/** Internally store bulk data as bytes */
|
|
UE::Serialization::FEditorBulkData BulkData;
|
|
|
|
/** GUID associated with the data stored herein. */
|
|
FGuid Guid;
|
|
|
|
/** Gets this bulk data hash */
|
|
MESHDESCRIPTION_API FGuid GetHash() const;
|
|
|
|
/** Take a copy of the bulk data versioning so it can be propagated to the bulk data reader when deserializing MeshDescription */
|
|
FCustomVersionContainer CustomVersions;
|
|
FPackageFileVersion UEVersion;
|
|
int32 LicenseeUEVersion;
|
|
|
|
|
|
/** Whether the bulk data has been written via SaveMeshDescription */
|
|
bool bBulkDataUpdated;
|
|
|
|
/** Uses hash instead of guid to identify content to improve DDC cache hit. */
|
|
bool bGuidIsHash;
|
|
};
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|