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;
51 bool hasPoints()
const override {
return true; }
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);
101 bool isValidFace(Offset offset)
const;
102 bool isValidVertex(Offset offset)
const;
103 bool isValidPoint(Offset offset)
const override;
107 void merge(Mesh& other);
109 std::unordered_set<Offset>::const_iterator soloPointsBegin()
const;
110 std::unordered_set<Offset>::const_iterator soloPointsEnd()
const;
112 void setPointPos(
const Offset offset,
const Vector3& pos);
118 Vector3 getPosFromVert(Offset vertexOffset)
const;
119 Vector3 getPointPos(Offset pointOffset)
const;
120 unsigned int getFaceVertCount(Offset faceOffset)
const
122 return vertexCountFaceHandle_[faceOffset];
124 unsigned int getFacePointCount(Offset faceOffset)
const;
125 Offset getVertexFace(Offset vertexOffset)
const;
127 Offset getVertexPoint(Offset vertexOffset)
const
129 return pointOffsetVertexHandle_.
getValue(vertexOffset);
132 std::span<const intT> getFacePoints(Offset faceOffset)
const
135 const unsigned int count = getFaceVertCount(faceOffset);
136 return pointOffsetVertexHandle_.
getSpan().subspan(start, count);
153 Offset getNumSoloPoints()
const;
161 using iterator_category = std::forward_iterator_tag;
162 using difference_type = std::ptrdiff_t;
163 using value_type =
Offset;
166 value_type operator*()
const {
return curOffset_; }
180 return a.curOffset_ == b.curOffset_;
184 return a.curOffset_ != b.curOffset_;
191 Iterator end()
const {
return Iterator(mesh_.getNumFaces()); }
196 std::vector<Offset> offsets;
197 offsets.reserve(mesh_.getNumFaces());
198 for (
const Offset faceOffset : *
this)
199 offsets.push_back(faceOffset);
208 FaceOffsets getFaces()
const {
return FaceOffsets(*
this); }
213 return addGroup(attr::AttributeOwner::VERTEX, std::move(name));
218 return addGroup(attr::AttributeOwner::FACE, std::move(name));
223 addToGroup(attr::AttributeOwner::VERTEX, name, offsets);
228 addToGroup(attr::AttributeOwner::FACE, name, offsets);
231 boolT isClosed(
Offset faceOffset)
const;
233 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 PointNormalHandle
370 Vector3 operator[](Offset pointOffset)
const
372 if (attribute_)
return (*attribute_)[pointOffset];
373 return computed_[pointOffset];
378 explicit PointNormalHandle(
const Mesh& mesh);
379 std::optional<attr::AttributeHandleRO<Vector3>> attribute_;
380 std::vector<Vector3> computed_;
391class VertexNormalHandle
394 Vector3 operator[](Offset vertexOffset)
const;
398 VertexNormalHandle(
const Mesh& mesh,
double cuspAngle);
400 std::optional<attr::AttributeHandleRO<Vector3>> vertexAttribute_;
401 std::optional<attr::AttributeHandleRO<Vector3>> pointAttribute_;
402 std::vector<Vector3> computed_;
size_t Offset
enzo::Offset is the internal discontinuous index of an element in a given AttributeOwner.
Definition Types.h:181
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:670
FaceNormalHandle getFaceNormal(bool precompute=false) const
Returns a handle for reading per-face normals.
Definition Mesh.cpp:824
void deleteAllFaces(bool andPoints=true)
Removes every face from the mesh.
Definition Mesh.cpp:389
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:588
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:247
void addToVertexGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the vertex group.
Definition Mesh.h:221
std::span< const intT > vertexPointSpan() const
Contiguous view mapping each vertex offset to its point offset.
Definition Mesh.h:143
PointNormalHandle getPointNormal() const
Returns a handle for reading per-point normals.
Definition Mesh.cpp:829
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:287
attr::AttributeHandleBool addVertexGroup(std::string name)
Returns the vertex group of this name, adding one when the name is free.
Definition Mesh.h:211
attr::AttributeHandleBool addFaceGroup(std::string name)
Returns the face group of this name, adding one when the name is free.
Definition Mesh.h:216
VertexNormalHandle getVertexNormal(double cuspAngle=kDefaultCuspAngle) const
Returns a handle for reading per-vertex normals.
Definition Mesh.cpp:834
std::vector< Offset > addPoints(std::span< const Vector3 > positions)
Adds many points in a single call.
Definition Mesh.cpp:556
void addToFaceGroup(const std::string &name, const std::vector< Offset > &offsets)
Marks the given offsets as members of the face group.
Definition Mesh.h:226
void defragment() override
Compacts storage, removing entries marked invalid so offsets are contiguous again.
Definition Mesh.cpp:470
std::span< const Vector3 > pointPosSpan() const
Contiguous view of every point position.
Definition Mesh.h:149
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:194