2#include "Engine/Primitives/Primitive.h"
3#include <CGAL/Simple_cartesian.h>
4#include <CGAL/Surface_mesh/Surface_mesh.h>
6#include <tbb/spin_mutex.h>
7#include <unordered_set>
10using Kernel = CGAL::Simple_cartesian<double>;
11using Point = Kernel::Point_3;
12using Vector = Kernel::Vector_3;
13using HeMesh = CGAL::Surface_mesh<Point>;
14using vertexDescriptor = HeMesh::Vertex_index;
15using faceDescriptor = HeMesh::Face_index;
16using V_index = HeMesh::Vertex_index;
17using F_index = HeMesh::Face_index;
20class FaceNormalHandle;
21class VertexNormalHandle;
31class Mesh :
public Primitive
34 Mesh(std::string_view path =
"/mesh");
35 Mesh(
const Mesh& other);
36 Mesh& operator=(
const Mesh& rhs);
37 ~Mesh()
override =
default;
39 PrimType getType()
const override {
return PrimType::MESH; }
40 std::shared_ptr<Primitive> clone()
const override {
return std::make_shared<Mesh>(*
this); }
41 TransformClass transformType()
const override
43 return TransformClass::POINT | TransformClass::PRIMITIVE;
47 TransformClass transformClass = TransformClass::POINT
50 const Transform& transform,
51 TransformClass transformClass = TransformClass::POINT
54 applyTransform(transform.getMatrix(), transformClass);
56 bool canMerge()
const override {
return true; }
57 void merge(std::shared_ptr<Primitive> other)
override;
58 bool hasPoints()
const override {
return true; }
66 Offset addFace(
const std::vector<Offset>& pointOffsets,
bool closed =
true);
76 std::span<const Offset> pointOffsetsFlat,
77 std::span<const Offset> vertexCounts,
80 Offset addPoint(
const Vector3& pos);
87 std::vector<Offset>
addPoints(std::span<const Vector3> positions);
97 duplicatePoints(std::span<const Offset> srcPointOffsets,
bool copyAttributes =
true);
99 void deleteFaces(
const std::vector<Offset>& faceOffsets,
bool andPoints =
true);
102 void deletePoints(
const std::vector<Offset>& pointOffsets)
override
104 deletePoints(pointOffsets,
false);
106 void deletePoints(
const std::vector<Offset>& pointOffsets,
bool andFaces);
107 void deleteVertices(
const std::vector<Offset>& vertOffsets);
108 bool isValidFace(Offset offset)
const;
109 bool isValidVertex(Offset offset)
const;
110 bool isValidPoint(Offset offset)
const override;
114 void merge(Mesh& other);
116 HeMesh computeHalfEdgeMesh();
118 std::unordered_set<Offset>::const_iterator soloPointsBegin()
const;
119 std::unordered_set<Offset>::const_iterator soloPointsEnd()
const;
121 void setPointPos(
const Offset offset,
const Vector3& pos);
127 Vector3 getPosFromVert(Offset vertexOffset)
const;
128 Vector3 getPointPos(Offset pointOffset)
const;
129 unsigned int getFaceVertCount(Offset faceOffset)
const
131 return vertexCountFaceHandle_[faceOffset];
133 unsigned int getFacePointCount(Offset faceOffset)
const;
134 Offset getVertexFace(Offset vertexOffset)
const;
136 Offset getPointVertex(Offset vertexOffset)
const
138 return pointOffsetVertexHandle_.
getValue(vertexOffset);
141 std::span<const intT> getFacePoints(Offset faceOffset)
const
144 const unsigned int count = getFaceVertCount(faceOffset);
145 return pointOffsetVertexHandle_.
getSpan().subspan(start, count);
162 Offset getNumSoloPoints()
const;
170 using iterator_category = std::forward_iterator_tag;
171 using difference_type = std::ptrdiff_t;
172 using value_type =
Offset;
175 value_type operator*()
const {
return curOffset_; }
189 return a.curOffset_ == b.curOffset_;
193 return a.curOffset_ != b.curOffset_;
200 Iterator end()
const {
return Iterator(mesh_.getNumFaces()); }
205 std::vector<Offset> offsets;
206 offsets.reserve(mesh_.getNumFaces());
207 for (
const Offset faceOffset : *
this)
208 offsets.push_back(faceOffset);
217 FaceOffsets getFaces()
const {
return FaceOffsets(*
this); }
223 return createGroup(attr::AttributeOwner::VERTEX, std::move(name));
229 return createGroup(attr::AttributeOwner::FACE, std::move(name));
234 addToGroup(attr::AttributeOwner::VERTEX, name, offsets);
239 addToGroup(attr::AttributeOwner::FACE, name, offsets);
242 boolT isClosed(
Offset faceOffset)
const;
244 void computeFaceStartVertices()
const;
284 void mergeAppend(std::shared_ptr<attr::Attribute> dst, std::shared_ptr<attr::Attribute> src);
285 template <
typename T>
286 void mergeAppendImpl(std::shared_ptr<attr::Attribute> dst, std::shared_ptr<attr::Attribute> src)
291 const Offset srcCount = srcHandle.getSize();
292 const Offset dstCount = dstHandle.getSize();
294 dstHandle.resize(dstCount + srcCount);
296 for (
Offset i = 0; i < srcCount; ++i)
298 const T value = srcHandle.getValue(i);
299 const Offset dstOffset = dstCount + i;
300 dstHandle.setValue(dstOffset, value);
304 attr::attribVector vertexAttributes_;
305 attr::attribVector faceAttributes_;
306 attr::attribVector vertexGroups_;
307 attr::attribVector faceGroups_;
309 mutable std::unordered_set<Offset> soloPoints_;
310 mutable bool soloPointsDirty_ =
true;
311 void rebuildSoloPoints()
const;
312 bool needsDefrag_ =
false;
314 mutable std::vector<Offset> faceStarts_;
315 mutable std::vector<Offset> vertexFaces_;
317 mutable std::atomic<bool> faceStartsDirty_{
true};
318 mutable tbb::spin_mutex faceStartsMutex_;
340class FaceNormalHandle
343 Vector3 operator[](Offset faceOffset)
const
345 if (cached_)
return (*cached_)[faceOffset];
346 if (!precomputed_.empty())
return precomputed_[faceOffset];
347 return computeNormal(faceOffset);
352 FaceNormalHandle(
const Mesh& mesh,
bool precompute);
353 Vector3 computeNormal(Offset faceOffset)
const;
355 std::optional<attr::AttributeHandleRO<Vector3>> cached_;
356 std::vector<Vector3> precomputed_;
367class VertexNormalHandle
370 Vector3 operator[](Offset vertexOffset)
const;
374 VertexNormalHandle(
const Mesh& mesh,
bool precompute);
376 std::optional<attr::AttributeHandleRO<Vector3>> cached_;
377 FaceNormalHandle faceNormals_;
size_t Offset
enzo::Offset is the internal discontinuous index of an element in a given AttributeOwner.
Definition Types.h:100
AttributeOwner
The segment of geometry that owns a particular attribute.
Definition Types.h:22
Read write accessor for enzo::attr::Attribute.
std::span< const T > getSpan() const
Contiguous read only view over all stored values.
Definition AttributeHandle.h:153
T getValue(size_t offset) const
Gets the value at a given offset.
Definition AttributeHandle.h:134
Read accessor for per-face normals.
Polygonal mesh primitive with point, vertex, and face attributes.
std::span< const Offset > getFaceStartVertices() const
Contiguous view of each face's starting vertex offset.
Definition Mesh.cpp:749
FaceNormalHandle getFaceNormal(bool precompute=false) const
Returns a handle for reading per-face normals.
Definition Mesh.cpp:876
void deleteAllFaces(bool andPoints=true)
Removes every face from the mesh.
Definition Mesh.cpp:387
std::vector< Offset > duplicatePoints(std::span< const Offset > srcPointOffsets, bool copyAttributes=true)
Duplicates existing points into new points carrying the same positions.
Definition Mesh.cpp:586
Offset addFace(const std::vector< Offset > &pointOffsets, bool closed=true)
Adds a single face. Avoid for multiple faces in a loop as a single call to addFaces is much more perf...
Definition Mesh.cpp:245
void addToVertexGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the vertex group.
Definition Mesh.h:232
VertexNormalHandle getVertexNormal(bool precompute=false) const
Returns a handle for reading per-vertex normals.
Definition Mesh.cpp:881
std::span< const intT > vertexPointSpan() const
Contiguous view mapping each vertex offset to its point offset.
Definition Mesh.h:152
std::vector< Offset > addFaces(std::span< const Offset > pointOffsetsFlat, std::span< const Offset > vertexCounts, bool closed=true)
Adds many faces in a single call.
Definition Mesh.cpp:285
attr::AttributeHandleBool createVertexGroup(std::string name)
Creates a vertex group.
Definition Mesh.h:221
attr::AttributeHandleBool createFaceGroup(std::string name)
Creates a face group.
Definition Mesh.h:227
std::vector< Offset > addPoints(std::span< const Vector3 > positions)
Adds many points in a single call.
Definition Mesh.cpp:554
void addToFaceGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the face group.
Definition Mesh.h:237
void defragment() override
Compacts storage, removing entries marked invalid so offsets are contiguous again.
Definition Mesh.cpp:468
std::span< const Vector3 > pointPosSpan() const
Contiguous view of every point position.
Definition Mesh.h:158
size_t getElementCount(const attr::AttributeOwner &owner) const
Returns the number of elements in the given owner's store.
Definition Primitive.cpp:154
attr::AttributeHandleBool createGroup(attr::AttributeOwner owner, std::string name)
Creates a group on the given owner.
Definition Primitive.cpp:166
void addToGroup(attr::AttributeOwner owner, const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the group.
Definition Primitive.cpp:175
Read accessor for per-vertex normals.
std::vector< Offset > toVector() const
Collects the face offsets into a vector for callers that need one.
Definition Mesh.h:203