2#include "Engine/Primitives/Primitive.h"
4#include <tbb/spin_mutex.h>
5#include <unordered_set>
10class PointNormalHandle;
11class VertexNormalHandle;
14inline constexpr double kDefaultCuspAngle = 60;
24class Mesh :
public Primitive
27 Mesh(std::string_view path =
"/mesh");
28 Mesh(
const Mesh& other);
29 Mesh& operator=(
const Mesh& rhs);
30 ~Mesh()
override =
default;
32 PrimType getType()
const override {
return PrimType::MESH; }
33 std::shared_ptr<Primitive> clone()
const override {
return std::make_shared<Mesh>(*
this); }
34 TransformClass transformType()
const override
36 return TransformClass::POINT | TransformClass::PRIMITIVE;
40 TransformClass transformClass = TransformClass::POINT
43 const Transform& transform,
44 TransformClass transformClass = TransformClass::POINT
47 applyTransform(transform.getMatrix(), transformClass);
49 bool canMerge()
const override {
return true; }
50 void merge(std::shared_ptr<Primitive> other)
override;
59 Offset addFace(
const std::vector<Offset>& pointOffsets,
bool closed =
true);
69 std::span<const Offset> pointOffsetsFlat,
70 std::span<const Offset> vertexCounts,
73 Offset addPoint(
const Vector3& pos);
80 std::vector<Offset>
addPoints(std::span<const Vector3> positions);
90 duplicatePoints(std::span<const Offset> srcPointOffsets,
bool copyAttributes =
true);
92 void deleteFaces(
const std::vector<Offset>& faceOffsets,
bool andPoints =
true);
95 void deletePoints(
const std::vector<Offset>& pointOffsets)
override
97 deletePoints(pointOffsets,
false);
99 void deletePoints(
const std::vector<Offset>& pointOffsets,
bool andFaces);
100 void deleteVertices(
const std::vector<Offset>& vertOffsets);
102 void reverseFaces(
const std::vector<Offset>& faceOffsets);
103 bool isValidFace(
Offset offset)
const;
104 bool isValidVertex(
Offset offset)
const;
105 bool isValidPoint(
Offset offset)
const override;
109 void merge(Mesh& other);
111 std::unordered_set<Offset>::const_iterator soloPointsBegin()
const;
112 std::unordered_set<Offset>::const_iterator soloPointsEnd()
const;
114 void setPointPos(
const Offset offset,
const Vector3& pos);
120 Vector3 getPosFromVert(
Offset vertexOffset)
const;
121 Vector3 getPointPos(
Offset pointOffset)
const;
122 unsigned int getFaceVertCount(
Offset faceOffset)
const
124 return vertexCountFaceHandle_[faceOffset];
126 unsigned int getFacePointCount(Offset faceOffset)
const;
127 Offset getVertexFace(Offset vertexOffset)
const;
129 Offset getVertexPoint(Offset vertexOffset)
const
131 return pointOffsetVertexHandle_.
getValue(vertexOffset);
134 std::span<const intT> getFacePoints(Offset faceOffset)
const
137 const unsigned int count = getFaceVertCount(faceOffset);
138 return pointOffsetVertexHandle_.
getSpan().subspan(start, count);
155 Offset getNumSoloPoints()
const;
163 using iterator_category = std::forward_iterator_tag;
164 using difference_type = std::ptrdiff_t;
165 using value_type =
Offset;
168 value_type operator*()
const {
return curOffset_; }
182 return a.curOffset_ == b.curOffset_;
186 return a.curOffset_ != b.curOffset_;
193 Iterator end()
const {
return Iterator(mesh_.getNumFaces()); }
198 std::vector<Offset> offsets;
199 offsets.reserve(mesh_.getNumFaces());
200 for (
const Offset faceOffset : *
this)
201 offsets.push_back(faceOffset);
210 FaceOffsets getFaces()
const {
return FaceOffsets(*
this); }
215 return addGroup(attr::AttributeOwner::VERTEX, std::move(name));
220 return addGroup(attr::AttributeOwner::FACE, std::move(name));
225 addToGroup(attr::AttributeOwner::VERTEX, name, offsets);
230 addToGroup(attr::AttributeOwner::FACE, name, offsets);
233 boolT isClosed(
Offset faceOffset)
const;
235 void computeFaceStartVertices()
const;
286 void mergeAppend(std::shared_ptr<attr::Attribute> dst, std::shared_ptr<attr::Attribute> src);
287 template <
typename T>
288 void mergeAppendImpl(std::shared_ptr<attr::Attribute> dst, std::shared_ptr<attr::Attribute> src)
293 const Offset srcCount = srcHandle.getSize();
294 const Offset dstCount = dstHandle.getSize();
296 dstHandle.resize(dstCount + srcCount);
298 for (
Offset i = 0; i < srcCount; ++i)
300 const T value = srcHandle.getValue(i);
301 const Offset dstOffset = dstCount + i;
302 dstHandle.setValue(dstOffset, value);
306 attr::attribVector vertexAttributes_;
307 attr::attribVector faceAttributes_;
308 attr::attribVector vertexGroups_;
309 attr::attribVector faceGroups_;
311 mutable std::unordered_set<Offset> soloPoints_;
312 mutable bool soloPointsDirty_ =
true;
313 void rebuildSoloPoints()
const;
314 bool needsDefrag_ =
false;
316 mutable std::vector<Offset> faceStarts_;
317 mutable std::vector<Offset> vertexFaces_;
319 mutable std::atomic<bool> faceStartsDirty_{
true};
320 mutable tbb::spin_mutex faceStartsMutex_;
342class FaceNormalHandle
345 Vector3 operator[](Offset faceOffset)
const
347 if (cached_)
return (*cached_)[faceOffset];
348 if (!precomputed_.empty())
return precomputed_[faceOffset];
349 return computeNormal(faceOffset);
354 FaceNormalHandle(
const Mesh& mesh,
bool precompute);
355 Vector3 computeNormal(Offset faceOffset)
const;
357 std::optional<attr::AttributeHandleRO<Vector3>> cached_;
358 std::vector<Vector3> precomputed_;
369class PointNormalHandle
372 Vector3 operator[](Offset pointOffset)
const
374 if (attribute_)
return (*attribute_)[pointOffset];
375 return computed_[pointOffset];
380 explicit PointNormalHandle(
const Mesh& mesh);
381 std::optional<attr::AttributeHandleRO<Vector3>> attribute_;
382 std::vector<Vector3> computed_;
393class VertexNormalHandle
396 Vector3 operator[](Offset vertexOffset)
const;
400 VertexNormalHandle(
const Mesh& mesh,
double cuspAngle);
402 std::optional<attr::AttributeHandleRO<Vector3>> vertexAttribute_;
403 std::optional<attr::AttributeHandleRO<Vector3>> pointAttribute_;
404 std::vector<Vector3> computed_;
size_t Offset
enzo::Offset is the internal discontinuous index of an element in a given AttributeOwner.
Definition Types.h:182
AttributeOwner
The segment of geometry that owns a particular attribute.
Definition Types.h:27
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:668
FaceNormalHandle getFaceNormal(bool precompute=false) const
Returns a handle for reading per-face normals.
Definition Mesh.cpp:825
void deleteAllFaces(bool andPoints=true)
Removes every face from the mesh.
Definition Mesh.cpp:371
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:584
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:229
void addToVertexGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the vertex group.
Definition Mesh.h:223
std::span< const intT > vertexPointSpan() const
Contiguous view mapping each vertex offset to its point offset.
Definition Mesh.h:145
PointNormalHandle getPointNormal() const
Returns a handle for reading per-point normals.
Definition Mesh.cpp:830
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:269
attr::AttributeHandleBool addVertexGroup(std::string name)
Returns the vertex group of this name, adding one when the name is free.
Definition Mesh.h:213
bool hasOwner(attr::AttributeOwner owner) const override
Returns whether this primitive type stores elements of the owner.
Definition Mesh.h:51
attr::AttributeHandleBool addFaceGroup(std::string name)
Returns the face group of this name, adding one when the name is free.
Definition Mesh.h:218
void reverseFaces(const std::vector< Offset > &faceOffsets)
Reverses the vertex order of each face, carrying every vertex attribute along.
Definition Mesh.cpp:446
VertexNormalHandle getVertexNormal(double cuspAngle=kDefaultCuspAngle) const
Returns a handle for reading per-vertex normals.
Definition Mesh.cpp:835
std::vector< Offset > addPoints(std::span< const Vector3 > positions)
Adds many points in a single call.
Definition Mesh.cpp:552
void addToFaceGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the face group.
Definition Mesh.h:228
void defragment() override
Compacts storage, removing entries marked invalid so offsets are contiguous again.
Definition Mesh.cpp:466
std::span< const Vector3 > pointPosSpan() const
Contiguous view of every point position.
Definition Mesh.h:151
Read accessor for per-point normals.
attr::AttributeHandleBool addGroup(attr::AttributeOwner owner, std::string name)
Returns the group of this name on the given owner, adding one when the name is free.
Definition Primitive.cpp:216
size_t getElementCount(const attr::AttributeOwner &owner) const
Returns the number of elements in the given owner's store.
Definition Primitive.cpp:204
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:223
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:196