OpenVDB 14.0.0
Loading...
Searching...
No Matches
PointDataGrid.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @author Dan Bailey
5///
6/// @file points/PointDataGrid.h
7///
8/// @brief Attribute-owned data structure for points. Point attributes are
9/// stored in leaf nodes and ordered by voxel for fast random and
10/// sequential access.
11
12#ifndef OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
13#define OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
14
15#include <openvdb/version.h>
16#include <openvdb/Grid.h>
17#include <openvdb/tree/Tree.h>
20#include <openvdb/util/Assert.h>
21#include "AttributeArray.h"
23#include "AttributeGroup.h"
24#include "AttributeSet.h"
25#include "StreamCompression.h"
26#include <cstring> // std::memcpy
27#include <iostream>
28#include <limits>
29#include <memory>
30#include <type_traits> // std::is_same
31#include <utility> // std::pair, std::make_pair
32#include <vector>
33
34// This header is only needed when PointData I/O methods are present (ie ABI<14)
35// otherwise, this header is included in the PointDataCodec instead.
36#if OPENVDB_ABI_VERSION_NUMBER < 14
37#include <openvdb/points/PointDataIO.h> // io::readCompressedValues(), io::writeCompressedValues(), io::writeCompressedValuesSize()
38#endif
39
40class TestPointDataLeaf;
41
42namespace openvdb {
44namespace OPENVDB_VERSION_NAME {
45
46
47// forward declaration
48namespace tree {
49 template<Index, typename> struct SameLeafConfig;
50}
51
52
53////////////////////////////////////////
54
55
56namespace points {
57
58
59// forward declaration
60template<typename T, Index Log2Dim> class PointDataLeafNode;
61
62// these aliases are disabled in one of the unit tests to ensure that
63// they are not used by the Point headers
64
65#ifndef OPENVDB_DISABLE_POINT_DATA_TREE_ALIAS
66
67/// @brief Point index tree configured to match the default VDB configurations.
70
71
72/// @brief Point data grid.
74
75#endif
76
77/// @brief Deep copy the descriptor across all leaf nodes.
78///
79/// @param tree the PointDataTree.
80///
81/// @return the new descriptor.
82///
83/// @note This method will fail if the Descriptors in the tree are not all identical.
84template <typename PointDataTreeT>
86makeDescriptorUnique(PointDataTreeT& tree);
87
88
89
90
91////////////////////////////////////////
92
93
94template <typename T, Index Log2Dim>
96
97public:
99 using Ptr = std::shared_ptr<PointDataLeafNode>;
100
101 using ValueType = T;
102 using ValueTypePair = std::pair<ValueType, ValueType>;
103 using IndexArray = std::vector<ValueType>;
104
106
107 ////////////////////////////////////////
108
109 // The following methods had to be copied from the LeafNode class
110 // to make the derived PointDataLeafNode class compatible with the tree structure.
111
114
115 using BaseLeaf::LOG2DIM;
116 using BaseLeaf::TOTAL;
117 using BaseLeaf::DIM;
120 using BaseLeaf::SIZE;
121 using BaseLeaf::LEVEL;
122
123 /// Default constructor
125 : mAttributeSet(new AttributeSet) { }
126
128
129 /// Construct using deep copy of other PointDataLeafNode
131 : BaseLeaf(other)
132 , mAttributeSet(new AttributeSet(*other.mAttributeSet)) { }
133
134 /// Construct using supplied origin, value and active status
135 explicit
136 PointDataLeafNode(const Coord& coords, const T& value = zeroVal<T>(), bool active = false)
137 : BaseLeaf(coords, zeroVal<T>(), active)
138 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
139
140 /// Construct using supplied origin, value and active status
141 /// use attribute map from another PointDataLeafNode
142 PointDataLeafNode(const PointDataLeafNode& other, const Coord& coords,
143 const T& value = zeroVal<T>(), bool active = false)
144 : BaseLeaf(coords, zeroVal<T>(), active)
145 , mAttributeSet(new AttributeSet(*other.mAttributeSet))
146 {
148 }
149
150 // Copy-construct from a PointIndexLeafNode with the same configuration but a different ValueType.
151 template<typename OtherValueType>
153 : BaseLeaf(other)
154 , mAttributeSet(new AttributeSet) { }
155
156 // Copy-construct from a LeafNode with the same configuration but a different ValueType.
157 // Used for topology copies - explicitly sets the value (background) to zeroVal
158 template <typename ValueType>
160 : BaseLeaf(other, zeroVal<T>(), TopologyCopy())
161 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
162
163 // Copy-construct from a LeafNode with the same configuration but a different ValueType.
164 // Used for topology copies - explicitly sets the on and off value (background) to zeroVal
165 template <typename ValueType>
166 PointDataLeafNode(const tree::LeafNode<ValueType, Log2Dim>& other, const T& /*offValue*/, const T& /*onValue*/, TopologyCopy)
167 : BaseLeaf(other, zeroVal<T>(), zeroVal<T>(), TopologyCopy())
168 , mAttributeSet(new AttributeSet) { }
169
171 const T& value = zeroVal<T>(), bool active = false)
172 : BaseLeaf(PartialCreate(), coords, value, active)
173 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
174
175public:
176
177 /// Retrieve the attribute set.
178 const AttributeSet& attributeSet() const { return *mAttributeSet; }
179
180 /// @brief Steal the attribute set, a new, empty attribute set is inserted in it's place.
182
183 /// @brief Create a new attribute set. Existing attributes will be removed.
184 void initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
185 const AttributeArray::ScopedRegistryLock* lock = nullptr);
186 /// @brief Clear the attribute set.
187 void clearAttributes(const bool updateValueMask = true,
188 const AttributeArray::ScopedRegistryLock* lock = nullptr);
189
190 /// @brief Returns @c true if an attribute with this index exists.
191 /// @param pos Index of the attribute
192 bool hasAttribute(const size_t pos) const;
193 /// @brief Returns @c true if an attribute with this name exists.
194 /// @param attributeName Name of the attribute
195 bool hasAttribute(const Name& attributeName) const;
196
197 /// @brief Append an attribute to the leaf.
198 /// @param expected Existing descriptor is expected to match this parameter.
199 /// @param replacement New descriptor to replace the existing one.
200 /// @param pos Index of the new attribute in the descriptor replacement.
201 /// @param strideOrTotalSize Stride of the attribute array (if constantStride), total size otherwise
202 /// @param constantStride if @c false, stride is interpreted as total size of the array
203 /// @param metadata optional default value metadata
204 /// @param lock an optional scoped registry lock to avoid contention
206 const size_t pos, const Index strideOrTotalSize = 1,
207 const bool constantStride = true,
208 const Metadata* metadata = nullptr,
209 const AttributeArray::ScopedRegistryLock* lock = nullptr);
210
211 /// @brief Drop list of attributes.
212 /// @param pos vector of attribute indices to drop
213 /// @param expected Existing descriptor is expected to match this parameter.
214 /// @param replacement New descriptor to replace the existing one.
215 void dropAttributes(const std::vector<size_t>& pos,
216 const Descriptor& expected, Descriptor::Ptr& replacement);
217 /// @brief Reorder attribute set.
218 /// @param replacement New descriptor to replace the existing one.
219 void reorderAttributes(const Descriptor::Ptr& replacement);
220 /// @brief Rename attributes in attribute set (order must remain the same).
221 /// @param expected Existing descriptor is expected to match this parameter.
222 /// @param replacement New descriptor to replace the existing one.
223 void renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement);
224 /// @brief Compact all attributes in attribute set.
226
227 /// @brief Replace the underlying attribute set with the given @a attributeSet.
228 /// @details This leaf will assume ownership of the given attribute set. The descriptors must
229 /// match and the voxel offsets values will need updating if the point order is different.
230 /// @throws ValueError if @a allowMismatchingDescriptors is @c false and the descriptors
231 /// do not match
232 void replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors = false);
233
234 /// @brief Replace the descriptor with a new one
235 /// The new Descriptor must exactly match the old one
236 void resetDescriptor(const Descriptor::Ptr& replacement);
237
238 /// @brief Sets all of the voxel offset values on this leaf, from the given vector
239 /// of @a offsets. If @a updateValueMask is true, then the active value mask will
240 /// be updated so voxels with points are active and empty voxels are inactive.
241 void setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask = true);
242
243 /// @brief Throws an error if the voxel values on this leaf are not monotonically
244 /// increasing or within the bounds of the attribute arrays
245 void validateOffsets() const;
246
247 /// @brief Read-write attribute array reference from index
248 /// @details Attribute arrays can be shared across leaf nodes, so non-const
249 /// access will deep-copy the array to make it unique. Always prefer
250 /// accessing const arrays where possible to eliminate this copying.
251 /// {
252 AttributeArray& attributeArray(const size_t pos);
253 const AttributeArray& attributeArray(const size_t pos) const;
254 const AttributeArray& constAttributeArray(const size_t pos) const;
255 /// }
256 /// @brief Read-write attribute array reference from name
257 /// @details Attribute arrays can be shared across leaf nodes, so non-const
258 /// access will deep-copy the array to make it unique. Always prefer
259 /// accessing const arrays where possible to eliminate this copying.
260 /// {
261 AttributeArray& attributeArray(const Name& attributeName);
262 const AttributeArray& attributeArray(const Name& attributeName) const;
263 const AttributeArray& constAttributeArray(const Name& attributeName) const;
264 /// }
265
266 /// @brief Read-only group handle from group index
268 /// @brief Read-only group handle from group name
269 GroupHandle groupHandle(const Name& group) const;
270 /// @brief Read-write group handle from group index
272 /// @brief Read-write group handle from group name
274
275 /// @brief Compute the total point count for the leaf
277 /// @brief Compute the total active (on) point count for the leaf
279 /// @brief Compute the total inactive (off) point count for the leaf
281 /// @brief Compute the point count in a specific group for the leaf
282 Index64 groupPointCount(const Name& groupName) const;
283
284 /// @brief Activate voxels with non-zero points, deactivate voxels with zero points.
286
287 ////////////////////////////////////////
288
289 void setOffsetOn(Index offset, const ValueType& val);
290 void setOffsetOnly(Index offset, const ValueType& val);
291
292 /// @brief Return @c true if the given node (which may have a different @c ValueType
293 /// than this node) has the same active value topology as this node.
294 template<typename OtherType, Index OtherLog2Dim>
298
299 /// Check for buffer, state and origin equivalence first.
300 /// If this returns true, do a deeper comparison on the attribute set to check
301 bool operator==(const PointDataLeafNode& other) const {
302 if(BaseLeaf::operator==(other) != true) return false;
303 return (*this->mAttributeSet == *other.mAttributeSet);
304 }
305
306 bool operator!=(const PointDataLeafNode& other) const { return !(other == *this); }
307
309 template<typename AccessorT>
310 void addLeafAndCache(PointDataLeafNode*, AccessorT&) {}
311
312 //@{
313 /// @brief Return a pointer to this node.
314 PointDataLeafNode* touchLeaf(const Coord&) { return this; }
315 template<typename AccessorT>
316 PointDataLeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
317
318 template<typename NodeT, typename AccessorT>
319 NodeT* probeNodeAndCache(const Coord&, AccessorT&)
320 {
322 if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
323 return reinterpret_cast<NodeT*>(this);
325 }
326 PointDataLeafNode* probeLeaf(const Coord&) { return this; }
327 template<typename AccessorT>
328 PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
329 //@}
330
331 //@{
332 /// @brief Return a @const pointer to this node.
333 const PointDataLeafNode* probeConstLeaf(const Coord&) const { return this; }
334 template<typename AccessorT>
335 const PointDataLeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
336 template<typename AccessorT>
337 const PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
338 const PointDataLeafNode* probeLeaf(const Coord&) const { return this; }
339 template<typename NodeT, typename AccessorT>
340 const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
341 {
343 if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
344 return reinterpret_cast<const NodeT*>(this);
346 }
347 //@}
348
349 // I/O methods
350
351#if OPENVDB_ABI_VERSION_NUMBER < 14
352 void readTopology(std::istream& is, bool fromHalf = false);
353 void writeTopology(std::ostream& os, bool toHalf = false) const;
354
355 Index buffers() const;
356
357 void readBuffers(std::istream& is, bool fromHalf = false);
358 void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
359 void writeBuffers(std::ostream& os, bool toHalf = false) const;
360
361 OPENVDB_DEPRECATED_MESSAGE("Use memUsage() instead. This method is deprecated and will be removed. Delayed loading is no longer supported.")
362 Index64 memUsageIfLoaded() const { return memUsage(); }
363#endif // OPENVDB_ABI_VERSION_NUMBER < 14
364
366
367 void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
368
369 /// @brief Return the bounding box of this node, i.e., the full index space
370 /// spanned by this leaf node.
372
373 ////////////////////////////////////////
374
375 // Disable all write methods to avoid unintentional changes
376 // to the point-array offsets.
377
379 OPENVDB_ASSERT(false && "Cannot modify voxel values in a PointDataTree.");
380 }
381
382 // some methods silently ignore attempts to modify the
383 // point-array offsets if a zero value is used
384
386 if (value != zeroVal<T>()) this->assertNonmodifiable();
387 }
388
389 void setActiveState(const Coord& xyz, bool on) { BaseLeaf::setActiveState(xyz, on); }
390 void setActiveState(Index offset, bool on) { BaseLeaf::setActiveState(offset, on); }
391
394
395 void setValueOff(const Coord& xyz) { BaseLeaf::setValueOff(xyz); }
396 void setValueOff(Index offset) { BaseLeaf::setValueOff(offset); }
397
398 void setValueOff(const Coord&, const ValueType&) { assertNonmodifiable(); }
400
401 void setValueOn(const Coord& xyz) { BaseLeaf::setValueOn(xyz); }
402 void setValueOn(Index offset) { BaseLeaf::setValueOn(offset); }
403
404 void setValueOn(const Coord&, const ValueType&) { assertNonmodifiable(); }
406
407 void setValue(const Coord&, const ValueType&) { assertNonmodifiable(); }
408
411
412 template<typename ModifyOp>
413 void modifyValue(Index, const ModifyOp&) { assertNonmodifiable(); }
414
415 template<typename ModifyOp>
416 void modifyValue(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
417
418 template<typename ModifyOp>
419 void modifyValueAndActiveState(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
420
421 // clipping is not yet supported
422 void clip(const CoordBBox&, const ValueType& value) { assertNonModifiableUnlessZero(value); }
423
424 void fill(const CoordBBox&, const ValueType&, bool);
425 void fill(const ValueType& value) { assertNonModifiableUnlessZero(value); }
426 void fill(const ValueType&, bool);
427
428 template<typename AccessorT>
429 void setValueOnlyAndCache(const Coord&, const ValueType&, AccessorT&) {assertNonmodifiable();}
430
431 template<typename ModifyOp, typename AccessorT>
432 void modifyValueAndActiveStateAndCache(const Coord&, const ModifyOp&, AccessorT&) {
434 }
435
436 template<typename AccessorT>
437 void setValueOffAndCache(const Coord&, const ValueType&, AccessorT&) { assertNonmodifiable(); }
438
439 template<typename AccessorT>
440 void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& parent) {
441 BaseLeaf::setActiveStateAndCache(xyz, on, parent);
442 }
443
444 void resetBackground(const ValueType&, const ValueType& newBackground) {
445 assertNonModifiableUnlessZero(newBackground);
446 }
447
450
452
453 friend class ::TestPointDataLeaf;
454
455 using ValueOn = typename BaseLeaf::ValueOn;
456 using ValueOff = typename BaseLeaf::ValueOff;
457 using ValueAll = typename BaseLeaf::ValueAll;
458
459private:
460 AttributeSet::UniquePtr mAttributeSet;
461 uint16_t mVoxelBufferSize = 0;
462
463protected:
464 using ChildOn = typename BaseLeaf::ChildOn;
465 using ChildOff = typename BaseLeaf::ChildOff;
466 using ChildAll = typename BaseLeaf::ChildAll;
467
471
472 // During topology-only construction, access is needed
473 // to protected/private members of other template instances.
474 template<typename, Index> friend class PointDataLeafNode;
475
479
480public:
481 /// @brief Leaf value voxel iterator
483
484public:
485
486 using ValueOnIter = typename BaseLeaf::template ValueIter<
488 using ValueOnCIter = typename BaseLeaf::template ValueIter<
490 using ValueOffIter = typename BaseLeaf::template ValueIter<
492 using ValueOffCIter = typename BaseLeaf::template ValueIter<
494 using ValueAllIter = typename BaseLeaf::template ValueIter<
496 using ValueAllCIter = typename BaseLeaf::template ValueIter<
498 using ChildOnIter = typename BaseLeaf::template ChildIter<
500 using ChildOnCIter = typename BaseLeaf::template ChildIter<
502 using ChildOffIter = typename BaseLeaf::template ChildIter<
504 using ChildOffCIter = typename BaseLeaf::template ChildIter<
506 using ChildAllIter = typename BaseLeaf::template DenseIter<
508 using ChildAllCIter = typename BaseLeaf::template DenseIter<
509 const PointDataLeafNode, const ValueType, ChildAll>;
510
515
516 /// @brief Leaf index iterator
518 {
519 NullFilter filter;
520 return this->beginIndex<ValueAllCIter, NullFilter>(filter);
521 }
523 {
524 NullFilter filter;
525 return this->beginIndex<ValueOnCIter, NullFilter>(filter);
526 }
528 {
529 NullFilter filter;
530 return this->beginIndex<ValueOffCIter, NullFilter>(filter);
531 }
532
533 template<typename IterT, typename FilterT>
534 IndexIter<IterT, FilterT> beginIndex(const FilterT& filter) const;
535
536 /// @brief Filtered leaf index iterator
537 template<typename FilterT>
539 {
540 return this->beginIndex<ValueAllCIter, FilterT>(filter);
541 }
542 template<typename FilterT>
544 {
545 return this->beginIndex<ValueOnCIter, FilterT>(filter);
546 }
547 template<typename FilterT>
549 {
550 return this->beginIndex<ValueOffCIter, FilterT>(filter);
551 }
552
553 /// @brief Leaf index iterator from voxel
555
556 /// @brief Filtered leaf index iterator from voxel
557 template<typename FilterT>
558 IndexIter<ValueVoxelCIter, FilterT> beginIndexVoxel(const Coord& ijk, const FilterT& filter) const;
559
560#define VMASK_ this->getValueMask()
561 ValueOnCIter cbeginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
562 ValueOnCIter beginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
563 ValueOnIter beginValueOn() { return ValueOnIter(VMASK_.beginOn(), this); }
564 ValueOffCIter cbeginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
565 ValueOffCIter beginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
566 ValueOffIter beginValueOff() { return ValueOffIter(VMASK_.beginOff(), this); }
567 ValueAllCIter cbeginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
568 ValueAllCIter beginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
569 ValueAllIter beginValueAll() { return ValueAllIter(VMASK_.beginDense(), this); }
570
571 ValueOnCIter cendValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
572 ValueOnCIter endValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
573 ValueOnIter endValueOn() { return ValueOnIter(VMASK_.endOn(), this); }
574 ValueOffCIter cendValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
575 ValueOffCIter endValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
576 ValueOffIter endValueOff() { return ValueOffIter(VMASK_.endOff(), this); }
577 ValueAllCIter cendValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
578 ValueAllCIter endValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
579 ValueAllIter endValueAll() { return ValueAllIter(VMASK_.endDense(), this); }
580
581 ChildOnCIter cbeginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
582 ChildOnCIter beginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
583 ChildOnIter beginChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
584 ChildOffCIter cbeginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
585 ChildOffCIter beginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
586 ChildOffIter beginChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
587 ChildAllCIter cbeginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
588 ChildAllCIter beginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
589 ChildAllIter beginChildAll() { return ChildAllIter(VMASK_.beginDense(), this); }
590
591 ChildOnCIter cendChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
592 ChildOnCIter endChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
593 ChildOnIter endChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
594 ChildOffCIter cendChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
595 ChildOffCIter endChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
596 ChildOffIter endChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
597 ChildAllCIter cendChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
598 ChildAllCIter endChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
599 ChildAllIter endChildAll() { return ChildAllIter(VMASK_.endDense(), this); }
600#undef VMASK_
601}; // struct PointDataLeafNode
602
603////////////////////////////////////////
604
605// PointDataLeafNode implementation
606
607template<typename T, Index Log2Dim>
608inline AttributeSet::UniquePtr
610{
611 AttributeSet::UniquePtr ptr = std::make_unique<AttributeSet>();
612 std::swap(ptr, mAttributeSet);
613 return ptr;
614}
615
616template<typename T, Index Log2Dim>
617inline void
620{
621 if (descriptor->size() != 1 ||
622 descriptor->find("P") == AttributeSet::INVALID_POS ||
623 descriptor->valueType(0) != typeNameAsString<Vec3f>())
624 {
625 OPENVDB_THROW(IndexError, "Initializing attributes only allowed with one Vec3f position attribute.");
626 }
627
628 mAttributeSet.reset(new AttributeSet(descriptor, arrayLength, lock));
629}
630
631template<typename T, Index Log2Dim>
632inline void
635{
636 mAttributeSet.reset(new AttributeSet(*mAttributeSet, 0, lock));
637
638 // zero voxel values
639
640 this->buffer().fill(ValueType(0));
641
642 // if updateValueMask, also de-activate all voxels
643
644 if (updateValueMask) this->setValuesOff();
645}
646
647template<typename T, Index Log2Dim>
648inline bool
650{
651 return pos < mAttributeSet->size();
652}
653
654template<typename T, Index Log2Dim>
655inline bool
657{
658 const size_t pos = mAttributeSet->find(attributeName);
659 return pos != AttributeSet::INVALID_POS;
660}
661
662template<typename T, Index Log2Dim>
665 const size_t pos, const Index strideOrTotalSize,
666 const bool constantStride,
667 const Metadata* metadata,
669{
670 return mAttributeSet->appendAttribute(
671 expected, replacement, pos, strideOrTotalSize, constantStride, metadata, lock);
672}
673
674template<typename T, Index Log2Dim>
675inline void
677 const Descriptor& expected, Descriptor::Ptr& replacement)
678{
679 mAttributeSet->dropAttributes(pos, expected, replacement);
680}
681
682template<typename T, Index Log2Dim>
683inline void
685{
686 mAttributeSet->reorderAttributes(replacement);
687}
688
689template<typename T, Index Log2Dim>
690inline void
692{
693 mAttributeSet->renameAttributes(expected, replacement);
694}
695
696template<typename T, Index Log2Dim>
697inline void
699{
700 for (size_t i = 0; i < mAttributeSet->size(); i++) {
701 AttributeArray* array = mAttributeSet->get(i);
702 array->compact();
703 }
704}
705
706template<typename T, Index Log2Dim>
707inline void
709{
710 if (!attributeSet) {
711 OPENVDB_THROW(ValueError, "Cannot replace with a null attribute set");
712 }
713
714 if (!allowMismatchingDescriptors && mAttributeSet->descriptor() != attributeSet->descriptor()) {
715 OPENVDB_THROW(ValueError, "Attribute set descriptors are not equal.");
716 }
717
718 mAttributeSet.reset(attributeSet);
719}
720
721template<typename T, Index Log2Dim>
722inline void
724{
725 mAttributeSet->resetDescriptor(replacement);
726}
727
728template<typename T, Index Log2Dim>
729inline void
730PointDataLeafNode<T, Log2Dim>::setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask)
731{
732 if (offsets.size() != LeafNodeType::NUM_VALUES) {
733 OPENVDB_THROW(ValueError, "Offset vector size doesn't match number of voxels.")
734 }
735
736 for (Index index = 0; index < offsets.size(); ++index) {
737 setOffsetOnly(index, offsets[index]);
738 }
739
740 if (updateValueMask) this->updateValueMask();
741}
742
743template<typename T, Index Log2Dim>
744inline void
746{
747 // Ensure all of the offset values are monotonically increasing
748 for (Index index = 1; index < BaseLeaf::SIZE; ++index) {
749 if (this->getValue(index-1) > this->getValue(index)) {
750 OPENVDB_THROW(ValueError, "Voxel offset values are not monotonically increasing");
751 }
752 }
753
754 // Ensure all attribute arrays are of equal length
755 for (size_t attributeIndex = 1; attributeIndex < mAttributeSet->size(); ++attributeIndex ) {
756 if (mAttributeSet->getConst(attributeIndex-1)->size() != mAttributeSet->getConst(attributeIndex)->size()) {
757 OPENVDB_THROW(ValueError, "Attribute arrays have inconsistent length");
758 }
759 }
760
761 // Ensure the last voxel's offset value matches the size of each attribute array
762 if (mAttributeSet->size() > 0 && this->getValue(BaseLeaf::SIZE-1) != mAttributeSet->getConst(0)->size()) {
763 OPENVDB_THROW(ValueError, "Last voxel offset value does not match attribute array length");
764 }
765}
766
767template<typename T, Index Log2Dim>
768inline AttributeArray&
770{
771 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
772 return *mAttributeSet->get(pos);
773}
774
775template<typename T, Index Log2Dim>
776inline const AttributeArray&
778{
779 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
780 return *mAttributeSet->getConst(pos);
781}
782
783template<typename T, Index Log2Dim>
784inline const AttributeArray&
786{
787 return this->attributeArray(pos);
788}
789
790template<typename T, Index Log2Dim>
791inline AttributeArray&
793{
794 const size_t pos = mAttributeSet->find(attributeName);
795 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
796 return *mAttributeSet->get(pos);
797}
798
799template<typename T, Index Log2Dim>
800inline const AttributeArray&
802{
803 const size_t pos = mAttributeSet->find(attributeName);
804 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
805 return *mAttributeSet->getConst(pos);
806}
807
808template<typename T, Index Log2Dim>
809inline const AttributeArray&
811{
812 return this->attributeArray(attributeName);
813}
814
815template<typename T, Index Log2Dim>
816inline GroupHandle
818{
819 const AttributeArray& array = this->attributeArray(index.first);
820 OPENVDB_ASSERT(isGroup(array));
821
822 const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
823
824 return GroupHandle(groupArray, index.second);
825}
826
827template<typename T, Index Log2Dim>
828inline GroupHandle
830{
831 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
832 return this->groupHandle(index);
833}
834
835template<typename T, Index Log2Dim>
836inline GroupWriteHandle
846
847template<typename T, Index Log2Dim>
848inline GroupWriteHandle
850{
851 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
852 return this->groupWriteHandle(index);
853}
854
855template<typename T, Index Log2Dim>
856template<typename ValueIterT, typename FilterT>
859{
860 // generate no-op iterator if filter evaluates no indices
861
862 if (filter.state() == index::NONE) {
863 return IndexIter<ValueIterT, FilterT>(ValueIterT(), filter);
864 }
865
866 // copy filter to ensure thread-safety
867
868 FilterT newFilter(filter);
869 newFilter.reset(*this);
870
872
873 // construct the value iterator and reset the filter to use this leaf
874
875 ValueIterT valueIter = IterTraitsT::begin(*this);
876
877 return IndexIter<ValueIterT, FilterT>(valueIter, newFilter);
878}
879
880template<typename T, Index Log2Dim>
881inline ValueVoxelCIter
883{
886 const ValueType end = this->getValue(index);
887 const ValueType start = (index == 0) ? ValueType(0) : this->getValue(index - 1);
888 return ValueVoxelCIter(start, end);
889}
890
891template<typename T, Index Log2Dim>
894{
895 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
896 return IndexVoxelIter(iter, NullFilter());
897}
898
899template<typename T, Index Log2Dim>
900template<typename FilterT>
902PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk, const FilterT& filter) const
903{
904 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
905 FilterT newFilter(filter);
906 newFilter.reset(*this);
907 return IndexIter<ValueVoxelCIter, FilterT>(iter, newFilter);
908}
909
910template<typename T, Index Log2Dim>
911inline Index64
913{
914 return this->getLastValue();
915}
916
917template<typename T, Index Log2Dim>
918inline Index64
920{
921 if (this->isEmpty()) return 0;
922 else if (this->isDense()) return this->pointCount();
923 return iterCount(this->beginIndexOn());
924}
925
926template<typename T, Index Log2Dim>
927inline Index64
929{
930 if (this->isEmpty()) return this->pointCount();
931 else if (this->isDense()) return 0;
932 return iterCount(this->beginIndexOff());
933}
934
935template<typename T, Index Log2Dim>
936inline Index64
938{
939 if (!this->attributeSet().descriptor().hasGroup(groupName)) {
940 return Index64(0);
941 }
942 GroupFilter filter(groupName, this->attributeSet());
943 if (filter.state() == index::ALL) {
944 return this->pointCount();
945 } else {
946 return iterCount(this->beginIndexAll(filter));
947 }
948}
949
950template<typename T, Index Log2Dim>
951inline void
953{
954 ValueType start = 0, end = 0;
955 for (Index n = 0; n < LeafNodeType::NUM_VALUES; n++) {
956 end = this->getValue(n);
957 this->setValueMask(n, (end - start) > 0);
958 start = end;
959 }
960}
961
962template<typename T, Index Log2Dim>
963inline void
965{
966 this->buffer().setValue(offset, val);
967 this->setValueMaskOn(offset);
968}
969
970template<typename T, Index Log2Dim>
971inline void
973{
974 this->buffer().setValue(offset, val);
975}
976
977#if OPENVDB_ABI_VERSION_NUMBER < 14
978
979namespace internal {
980
981/// Throws an IoError if a voxel offset could index past the end of an attribute array
982/// or if an array was not read. Offsets and array sizes are separate values in the file.
983template <typename LeafT>
984inline void validateReadOffsets(const LeafT& leaf)
985{
986 // offsets may be 64-bit, so compare them without narrowing
987 const Index64 lastOffset(leaf.getValue(LeafT::SIZE-1));
988 for (Index index = 0; index < LeafT::SIZE; ++index) {
989 if (Index64(leaf.getValue(index)) > lastOffset) {
990 OPENVDB_THROW(IoError, "PointDataGrid voxel offset " << Index64(leaf.getValue(index))
991 << " exceeds the last voxel offset " << lastOffset << ".");
992 }
993 }
994
995 const AttributeSet& attributeSet = leaf.attributeSet();
996 for (size_t attributeIndex = 0; attributeIndex < attributeSet.size(); ++attributeIndex) {
997 const AttributeArray* array = attributeSet.getConst(attributeIndex);
998 if (array->flags() & AttributeArray::PARTIALREAD) {
999 OPENVDB_THROW(IoError, "PointDataGrid attribute array was not read.");
1000 }
1001 if (lastOffset > array->size()) {
1002 OPENVDB_THROW(IoError, "PointDataGrid voxel offset " << lastOffset
1003 << " exceeds attribute array size " << array->size() << ".");
1004 }
1005 }
1006}
1007
1008} // namespace internal
1009
1010template<typename T, Index Log2Dim>
1011inline void
1012PointDataLeafNode<T, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1013{
1014 BaseLeaf::readTopology(is, fromHalf);
1015}
1016
1017template<typename T, Index Log2Dim>
1018inline void
1019PointDataLeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1020{
1021 BaseLeaf::writeTopology(os, toHalf);
1022}
1023
1024template<typename T, Index Log2Dim>
1025inline Index
1026PointDataLeafNode<T, Log2Dim>::buffers() const
1027{
1028 return Index( /*voxel buffer sizes*/ 1 +
1029 /*voxel buffers*/ 1 +
1030 /*attribute metadata*/ 1 +
1031 /*attribute uniform values*/ mAttributeSet->size() +
1032 /*attribute buffers*/ mAttributeSet->size() +
1033 /*cleanup*/ 1);
1034}
1035
1036template<typename T, Index Log2Dim>
1037inline void
1038PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1039{
1040 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1041}
1042
1043template<typename T, Index Log2Dim>
1044inline void
1045PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*bbox*/, bool fromHalf)
1046{
1047 struct Local
1048 {
1049 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1050 {
1051 // if paged stream exists, delete it
1052 std::string key("paged:" + std::to_string(index));
1053 auto it = auxData.find(key);
1054 if (it != auxData.end()) {
1055 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1056 }
1057 }
1058
1059 static compression::PagedInputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1060 const Index index)
1061 {
1062 std::string key("paged:" + std::to_string(index));
1063 auto it = auxData.find(key);
1064 if (it != auxData.end()) {
1065 return *(std::any_cast<compression::PagedInputStream::Ptr>(it->second));
1066 }
1067 else {
1068 compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
1069 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1070 return *pagedStream;
1071 }
1072 }
1073
1074 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1075 {
1076 std::string matchingKey("hasMatchingDescriptor");
1077 auto itMatching = auxData.find(matchingKey);
1078 return itMatching != auxData.end();
1079 }
1080
1081 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1082 {
1083 std::string matchingKey("hasMatchingDescriptor");
1084 std::string descriptorKey("descriptorPtr");
1085 auto itMatching = auxData.find(matchingKey);
1086 auto itDescriptor = auxData.find(descriptorKey);
1087 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1088 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1089 }
1090
1091 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1092 const Descriptor::Ptr descriptor)
1093 {
1094 std::string descriptorKey("descriptorPtr");
1095 std::string matchingKey("hasMatchingDescriptor");
1096 auto itMatching = auxData.find(matchingKey);
1097 if (itMatching == auxData.end()) {
1098 // if matching bool is not found, insert "true" and the descriptor
1099 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1100 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1101 }
1102 }
1103
1104 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1105 {
1106 std::string descriptorKey("descriptorPtr");
1107 auto itDescriptor = auxData.find(descriptorKey);
1108 OPENVDB_ASSERT(itDescriptor != auxData.end());
1109 const Descriptor::Ptr descriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1110 return descriptor;
1111 }
1112 };
1113
1114 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
1115
1116 if (!meta) {
1117 OPENVDB_THROW(IoError, "Cannot read in a PointDataLeaf without StreamMetadata.");
1118 }
1119
1120 const Index pass(static_cast<uint16_t>(meta->pass()));
1121 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1122
1123 // the pass count comes from the file, so guard against unsigned underflow
1124 const Index attributes = maximumPass >= 4 ? (maximumPass - 4) / 2 : 0;
1125
1126 if (pass == 0) {
1127 // pass 0 - voxel data sizes
1128 is.read(reinterpret_cast<char*>(&mVoxelBufferSize), sizeof(uint16_t));
1129 Local::clearMatchingDescriptor(meta->auxData());
1130 }
1131 else if (pass == 1) {
1132 // pass 1 - descriptor and attribute metadata
1133 if (Local::hasMatchingDescriptor(meta->auxData())) {
1134 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1135 mAttributeSet->resetDescriptor(descriptor, /*allowMismatchingDescriptors=*/true);
1136 }
1137 else {
1138 uint8_t header;
1139 is.read(reinterpret_cast<char*>(&header), sizeof(uint8_t));
1140 mAttributeSet->readDescriptor(is);
1141 if (header & uint8_t(1)) {
1142 AttributeSet::DescriptorPtr descriptor = mAttributeSet->descriptorPtr();
1143 Local::insertDescriptor(meta->auxData(), descriptor);
1144 }
1145 // a forwards-compatibility mechanism for future use,
1146 // if a 0x2 bit is set, read and skip over a specific number of bytes
1147 if (header & uint8_t(2)) {
1148 uint64_t bytesToSkip;
1149 is.read(reinterpret_cast<char*>(&bytesToSkip), sizeof(uint64_t));
1150 if (bytesToSkip > uint64_t(0)) {
1151 auto metadata = io::getStreamMetadataPtr(is);
1152 if (metadata && metadata->seekable()) {
1153 is.seekg(bytesToSkip, std::ios_base::cur);
1154 }
1155 else {
1156 std::vector<uint8_t> tempData(bytesToSkip);
1157 is.read(reinterpret_cast<char*>(&tempData[0]), bytesToSkip);
1158 }
1159 }
1160 }
1161 // this reader is only able to read headers with 0x1 and 0x2 bits set
1162 if (header > uint8_t(3)) {
1163 OPENVDB_THROW(IoError, "Unrecognised header flags in PointDataLeafNode");
1164 }
1165 }
1166 mAttributeSet->readMetadata(is);
1167 // arrays beyond the pass count would never be read
1168 if (mAttributeSet->size() > attributes) {
1169 OPENVDB_THROW(IoError, "PointDataGrid declares " << mAttributeSet->size()
1170 << " attributes, but only " << attributes << " can be read.");
1171 }
1172 }
1173 else if (pass < (attributes + 2)) {
1174 // pass 2...n+2 - attribute uniform values
1175 const size_t attributeIndex = pass - 2;
1176 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1177 mAttributeSet->get(attributeIndex) : nullptr;
1178 if (array) {
1179 compression::PagedInputStream& pagedStream =
1180 Local::getOrInsertPagedStream(meta->auxData(), static_cast<Index>(attributeIndex));
1181 pagedStream.setInputStream(is);
1182 pagedStream.setSizeOnly(true);
1183 array->readPagedBuffers(pagedStream);
1184 }
1185 }
1186 else if (pass == attributes + 2) {
1187 // pass n+2 - voxel data
1188
1189 const Index passValue(meta->pass());
1190
1191 // StreamMetadata pass variable used to temporarily store voxel buffer size
1192 io::StreamMetadata& nonConstMeta = const_cast<io::StreamMetadata&>(*meta);
1193 nonConstMeta.setPass(mVoxelBufferSize);
1194
1195 // readBuffers() calls readCompressedValues specialization above
1196 BaseLeaf::readBuffers(is, fromHalf);
1197
1198 // pass now reset to original value
1199 nonConstMeta.setPass(passValue);
1200 }
1201 else if (pass < (attributes*2 + 3)) {
1202 // pass n+2..2n+2 - attribute buffers
1203 const Index attributeIndex = pass - attributes - 3;
1204 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1205 mAttributeSet->get(attributeIndex) : nullptr;
1206 if (array) {
1207 compression::PagedInputStream& pagedStream =
1208 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1209 pagedStream.setInputStream(is);
1210 pagedStream.setSizeOnly(false);
1211 array->readPagedBuffers(pagedStream);
1212 }
1213 // cleanup paged stream reference in auxiliary metadata
1214 if (pass > attributes + 3) {
1215 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1216 }
1217 }
1218 else if (pass < buffers()) {
1219 // pass 2n+3 - cleanup last paged stream
1220 const Index attributeIndex = pass - attributes - 4;
1221 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1222 }
1223
1224 // all data for this leaf has been read after the last pass of the grid
1225 if (pass + 1 == maximumPass) {
1226 internal::validateReadOffsets(*this);
1227 }
1228}
1229
1230template<typename T, Index Log2Dim>
1231inline void
1232PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1233{
1234 struct Local
1235 {
1236 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1237 {
1238 // if paged stream exists, flush and delete it
1239 std::string key("paged:" + std::to_string(index));
1240 auto it = auxData.find(key);
1241 if (it != auxData.end()) {
1242 compression::PagedOutputStream& stream = *(std::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1243 stream.flush();
1244 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1245 }
1246 }
1247
1248 static compression::PagedOutputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1249 const Index index)
1250 {
1251 std::string key("paged:" + std::to_string(index));
1252 auto it = auxData.find(key);
1253 if (it != auxData.end()) {
1254 return *(std::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1255 }
1256 else {
1257 compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
1258 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1259 return *pagedStream;
1260 }
1261 }
1262
1263 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1264 const Descriptor::Ptr descriptor)
1265 {
1266 std::string descriptorKey("descriptorPtr");
1267 std::string matchingKey("hasMatchingDescriptor");
1268 auto itMatching = auxData.find(matchingKey);
1269 auto itDescriptor = auxData.find(descriptorKey);
1270 if (itMatching == auxData.end()) {
1271 // if matching bool is not found, insert "true" and the descriptor
1272 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1273 OPENVDB_ASSERT(itDescriptor == auxData.end());
1274 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1275 }
1276 else {
1277 // if matching bool is found and is false, early exit (a previous descriptor did not match)
1278 bool matching = std::any_cast<bool>(itMatching->second);
1279 if (!matching) return;
1280 OPENVDB_ASSERT(itDescriptor != auxData.end());
1281 // if matching bool is true, check whether the existing descriptor matches the current one and set
1282 // matching bool to false if not
1283 const Descriptor::Ptr existingDescriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1284 if (*existingDescriptor != *descriptor) {
1285 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
1286 }
1287 }
1288 }
1289
1290 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1291 {
1292 std::string matchingKey("hasMatchingDescriptor");
1293 auto itMatching = auxData.find(matchingKey);
1294 // if matching key is not found, no matching descriptor
1295 if (itMatching == auxData.end()) return false;
1296 // if matching key is found and is false, no matching descriptor
1297 if (!std::any_cast<bool>(itMatching->second)) return false;
1298 return true;
1299 }
1300
1301 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1302 {
1303 std::string descriptorKey("descriptorPtr");
1304 auto itDescriptor = auxData.find(descriptorKey);
1305 // if matching key is true, however descriptor is not found, it has already been retrieved
1306 if (itDescriptor == auxData.end()) return nullptr;
1307 // otherwise remove it and return it
1308 const Descriptor::Ptr descriptor = std::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1309 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1310 return descriptor;
1311 }
1312
1313 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1314 {
1315 std::string matchingKey("hasMatchingDescriptor");
1316 std::string descriptorKey("descriptorPtr");
1317 auto itMatching = auxData.find(matchingKey);
1318 auto itDescriptor = auxData.find(descriptorKey);
1319 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1320 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1321 }
1322 };
1323
1324 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(os);
1325
1326 if (!meta) {
1327 OPENVDB_THROW(IoError, "Cannot write out a PointDataLeaf without StreamMetadata.");
1328 }
1329
1330 const Index pass(static_cast<uint16_t>(meta->pass()));
1331
1332 // leaf traversal analysis deduces the number of passes to perform for this leaf
1333 // then updates the leaf traversal value to ensure all passes will be written
1334
1335 if (meta->countingPasses()) {
1336 const Index requiredPasses = this->buffers();
1337 if (requiredPasses > pass) {
1338 meta->setPass(requiredPasses);
1339 }
1340 return;
1341 }
1342
1343 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1344 const Index attributes = (maximumPass - 4) / 2;
1345
1346 if (pass == 0) {
1347 // pass 0 - voxel data sizes
1348 io::writeCompressedValuesSize(os, this->buffer().data(), SIZE);
1349 // track if descriptor is shared or not
1350 Local::insertDescriptor(meta->auxData(), mAttributeSet->descriptorPtr());
1351 }
1352 else if (pass == 1) {
1353 // pass 1 - descriptor and attribute metadata
1354 bool matchingDescriptor = Local::hasMatchingDescriptor(meta->auxData());
1355 if (matchingDescriptor) {
1356 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1357 if (descriptor) {
1358 // write a header to indicate a shared descriptor
1359 uint8_t header(1);
1360 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1361 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1362 }
1363 }
1364 else {
1365 // write a header to indicate a non-shared descriptor
1366 uint8_t header(0);
1367 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1368 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1369 }
1370 mAttributeSet->writeMetadata(os, /*transient=*/false, /*paged=*/true);
1371 }
1372 else if (pass < attributes + 2) {
1373 // pass 2...n+2 - attribute buffer sizes
1374 const Index attributeIndex = pass - 2;
1375 // destroy previous paged stream
1376 if (pass > 2) {
1377 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1378 }
1379 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1380 mAttributeSet->getConst(attributeIndex) : nullptr;
1381 if (array) {
1382 compression::PagedOutputStream& pagedStream =
1383 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1384 pagedStream.setOutputStream(os);
1385 pagedStream.setSizeOnly(true);
1386 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1387 }
1388 }
1389 else if (pass == attributes + 2) {
1390 const Index attributeIndex = pass - 3;
1391 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1392 // pass n+2 - voxel data
1393 BaseLeaf::writeBuffers(os, toHalf);
1394 }
1395 else if (pass < (attributes*2 + 3)) {
1396 // pass n+3...2n+3 - attribute buffers
1397 const Index attributeIndex = pass - attributes - 3;
1398 // destroy previous paged stream
1399 if (pass > attributes + 2) {
1400 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1401 }
1402 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1403 mAttributeSet->getConst(attributeIndex) : nullptr;
1404 if (array) {
1405 compression::PagedOutputStream& pagedStream =
1406 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1407 pagedStream.setOutputStream(os);
1408 pagedStream.setSizeOnly(false);
1409 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1410 }
1411 }
1412 else if (pass < buffers()) {
1413 Local::clearMatchingDescriptor(meta->auxData());
1414 // pass 2n+3 - cleanup last paged stream
1415 const Index attributeIndex = pass - attributes - 4;
1416 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1417 }
1418}
1419
1420#endif // OPENVDB_ABI_VERSION_NUMBER < 14
1421
1422template<typename T, Index Log2Dim>
1423inline Index64
1425{
1426 return BaseLeaf::memUsage() + mAttributeSet->memUsage();
1427}
1428
1429template<typename T, Index Log2Dim>
1430inline void
1432{
1433 BaseLeaf::evalActiveBoundingBox(bbox, visitVoxels);
1434}
1435
1436template<typename T, Index Log2Dim>
1437inline CoordBBox
1442
1443template<typename T, Index Log2Dim>
1444inline void
1445PointDataLeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1446{
1447 if (!this->allocate()) return;
1448
1449 this->assertNonModifiableUnlessZero(value);
1450
1451 // active state is permitted to be updated
1452
1453 for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1454 const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1455 for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1456 const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1457 for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1458 const Index offset = offsetXY + (z & (DIM-1u));
1459 this->setValueMask(offset, active);
1460 }
1461 }
1462 }
1463}
1464
1465template<typename T, Index Log2Dim>
1466inline void
1468{
1469 this->assertNonModifiableUnlessZero(value);
1470
1471 // active state is permitted to be updated
1472
1473 if (active) this->setValuesOn();
1474 else this->setValuesOff();
1475}
1476
1477
1478////////////////////////////////////////
1479
1480
1481template <typename PointDataTreeT>
1484{
1485 auto leafIter = tree.beginLeaf();
1486 if (!leafIter) return nullptr;
1487
1488 const AttributeSet::Descriptor& descriptor = leafIter->attributeSet().descriptor();
1489 auto newDescriptor = std::make_shared<AttributeSet::Descriptor>(descriptor);
1490 for (; leafIter; ++leafIter) {
1491 leafIter->resetDescriptor(newDescriptor);
1492 }
1493
1494 return newDescriptor;
1495}
1496
1497
1498namespace internal {
1499
1500/// @brief Global registration of point data-related types
1501/// @note This is called from @c openvdb::initialize, so there is
1502/// no need to call it directly.
1503void initialize();
1504
1505/// @brief Global deregistration of point data-related types
1506/// @note This is called from @c openvdb::uninitialize, so there is
1507/// no need to call it directly.
1508void uninitialize();
1509
1510
1511/// @brief Recursive node chain which generates a openvdb::TypeList value
1512/// converted types of nodes to PointDataGrid nodes of the same configuration,
1513/// rooted at RootNodeType in reverse order, from LeafNode to RootNode.
1514/// See also TreeConverter<>.
1515template<typename HeadT, int HeadLevel>
1516struct PointDataNodeChain
1517{
1518 using SubtreeT = typename PointDataNodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
1520 using Type = typename SubtreeT::template Append<RootNodeT>;
1521};
1522
1523// Specialization for internal nodes which require their embedded child type to
1524// be switched
1525template <typename ChildT, Index Log2Dim, int HeadLevel>
1526struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, HeadLevel>
1527{
1528 using SubtreeT = typename PointDataNodeChain<ChildT, HeadLevel-1>::Type;
1530 using Type = typename SubtreeT::template Append<InternalNodeT>;
1531};
1532
1533// Specialization for the last internal node of a node chain, expected
1534// to be templated on a leaf node
1535template <typename ChildT, Index Log2Dim>
1536struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, /*HeadLevel=*/1>
1537{
1538 using LeafNodeT = PointDataLeafNode<PointDataIndex32, ChildT::LOG2DIM>;
1539 using InternalNodeT = tree::InternalNode<LeafNodeT, Log2Dim>;
1540 using Type = TypeList<LeafNodeT, InternalNodeT>;
1541};
1542
1543} // namespace internal
1544
1545
1546/// @brief Similiar to ValueConverter, but allows for tree configuration conversion
1547/// to a PointDataTree. ValueConverter<PointDataIndex32> cannot be used as a
1548/// PointDataLeafNode is not a specialization of LeafNode
1549template <typename TreeType>
1551 using RootNodeT = typename TreeType::RootNodeType;
1552 using NodeChainT = typename internal::PointDataNodeChain<RootNodeT, RootNodeT::LEVEL>::Type;
1554};
1555
1556
1557} // namespace points
1558
1559
1560////////////////////////////////////////
1561
1562
1563namespace tree
1564{
1565
1566/// Helper metafunction used to implement LeafNode::SameConfiguration
1567/// (which, as an inner class, can't be independently specialized)
1568template<Index Dim1, typename T2>
1569struct SameLeafConfig<Dim1, points::PointDataLeafNode<T2, Dim1>> { static const bool value = true; };
1570
1571} // namespace tree
1572} // namespace OPENVDB_VERSION_NAME
1573} // namespace openvdb
1574
1575#endif // OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Attribute array storage for string data using Descriptor Metadata.
Attribute Array storage templated on type and compression codec.
Attribute Group access and filtering for iteration.
Set of Attribute Arrays which tracks metadata about each array.
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition Platform.h:151
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition Platform.h:150
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition Platform.h:158
#define VMASK_
Definition PointDataGrid.h:560
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
Convenience wrappers to using Blosc and reading and writing of Paged data.
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
Definition Exceptions.h:57
Definition Exceptions.h:58
Definition Exceptions.h:60
Base class for storing metadata information in a grid.
Definition Metadata.h:25
Tag dispatch class that distinguishes constructors during file input.
Definition Types.h:760
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:754
Definition Exceptions.h:65
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
const Coord & min() const
Definition Coord.h:324
const Coord & max() const
Definition Coord.h:325
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Int32 y() const
Definition Coord.h:132
Int32 x() const
Definition Coord.h:131
Int32 z() const
Definition Coord.h:133
Base class for storing attribute data.
Definition AttributeArray.h:94
std::shared_ptr< AttributeArray > Ptr
Definition AttributeArray.h:126
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
An immutable object that stores name, type and AttributeSet position for a constant collection of att...
Definition AttributeSet.h:306
Util::GroupIndex GroupIndex
Definition AttributeSet.h:312
std::shared_ptr< Descriptor > Ptr
Definition AttributeSet.h:308
Ordered collection of uniquely-named attribute arrays.
Definition AttributeSet.h:40
@ INVALID_POS
Definition AttributeSet.h:42
std::unique_ptr< AttributeSet > UniquePtr
Definition AttributeSet.h:46
Index filtering on group membership.
Definition AttributeGroup.h:136
static index::State state()
Definition AttributeGroup.h:146
Definition AttributeGroup.h:74
Definition AttributeGroup.h:103
A forward iterator over array indices with filtering IteratorT can be either IndexIter or ValueIndexI...
Definition IndexIterator.h:141
A no-op filter that can be used when iterating over all indices.
Definition IndexIterator.h:52
Definition PointDataGrid.h:95
ChildOnCIter cbeginChildOn() const
Definition PointDataGrid.h:581
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node.
Definition PointDataGrid.h:1438
IndexIter< ValueAllCIter, NullFilter > IndexAllIter
Definition PointDataGrid.h:512
void setValueOn(Index offset)
Definition PointDataGrid.h:402
void setValueOff(const Coord &, const ValueType &)
Definition PointDataGrid.h:398
ChildOnCIter beginChildOn() const
Definition PointDataGrid.h:582
ChildOnIter beginChildOn()
Definition PointDataGrid.h:583
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &parent)
Definition PointDataGrid.h:440
void replaceAttributeSet(AttributeSet *attributeSet, bool allowMismatchingDescriptors=false)
Replace the underlying attribute set with the given attributeSet.
Definition PointDataGrid.h:708
typename BaseLeaf::template ValueIter< MaskOffIterator, const PointDataLeafNode, const ValueType, ValueOff > ValueOffCIter
Definition PointDataGrid.h:492
GroupWriteHandle groupWriteHandle(const Name &name)
Read-write group handle from group name.
Definition PointDataGrid.h:849
const AttributeArray & constAttributeArray(const Name &attributeName) const
Definition PointDataGrid.h:810
IndexIter< ValueOffCIter, NullFilter > IndexOffIter
Definition PointDataGrid.h:514
ValueOnIter endValueOn()
Definition PointDataGrid.h:573
PointDataLeafNode< T, Log2Dim > LeafNodeType
Definition PointDataGrid.h:98
util::NodeMask< Log2Dim > NodeMaskType
Definition PointDataGrid.h:113
AttributeArray::Ptr appendAttribute(const Descriptor &expected, Descriptor::Ptr &replacement, const size_t pos, const Index strideOrTotalSize=1, const bool constantStride=true, const Metadata *metadata=nullptr, const AttributeArray::ScopedRegistryLock *lock=nullptr)
Append an attribute to the leaf.
Definition PointDataGrid.h:664
PointDataLeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
Definition PointDataGrid.h:314
PointDataLeafNode(const tools::PointIndexLeafNode< OtherValueType, Log2Dim > &other)
Definition PointDataGrid.h:152
ValueOffCIter cbeginValueOff() const
Definition PointDataGrid.h:564
PointDataLeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Definition PointDataGrid.h:316
void validateOffsets() const
Throws an error if the voxel values on this leaf are not monotonically increasing or within the bound...
Definition PointDataGrid.h:745
PointDataLeafNode(const PointDataLeafNode &other, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition PointDataGrid.h:142
bool operator==(const PointDataLeafNode &other) const
Definition PointDataGrid.h:301
const AttributeArray & attributeArray(const size_t pos) const
Definition PointDataGrid.h:777
bool hasSameTopology(const PointDataLeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition PointDataGrid.h:295
ChildOnIter endChildOn()
Definition PointDataGrid.h:593
ValueAllIter endValueAll()
Definition PointDataGrid.h:579
GroupWriteHandle groupWriteHandle(const AttributeSet::Descriptor::GroupIndex &index)
Read-write group handle from group index.
Definition PointDataGrid.h:837
typename BaseLeaf::template ChildIter< MaskOnIterator, PointDataLeafNode, ChildOn > ChildOnIter
Definition PointDataGrid.h:498
void modifyValue(Index, const ModifyOp &)
Definition PointDataGrid.h:413
Index64 groupPointCount(const Name &groupName) const
Compute the point count in a specific group for the leaf.
Definition PointDataGrid.h:937
void setValueOn(Index, const ValueType &)
Definition PointDataGrid.h:405
void setValuesOff()
Definition PointDataGrid.h:410
ValueAllCIter endValueAll() const
Definition PointDataGrid.h:578
const PointDataLeafNode * probeLeaf(const Coord &) const
Definition PointDataGrid.h:338
ChildOffCIter endChildOff() const
Definition PointDataGrid.h:595
void setValueOff(Index, const ValueType &)
Definition PointDataGrid.h:399
PointDataLeafNode(PartialCreate, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition PointDataGrid.h:170
ValueAllCIter cbeginValueAll() const
Definition PointDataGrid.h:567
typename BaseLeaf::ChildOff ChildOff
Definition PointDataGrid.h:465
AttributeArray & attributeArray(const size_t pos)
Read-write attribute array reference from index.
Definition PointDataGrid.h:769
typename BaseLeaf::template ValueIter< MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn > ValueOnCIter
Definition PointDataGrid.h:488
const PointDataLeafNode * probeConstLeaf(const Coord &) const
Return a const pointer to this node.
Definition PointDataGrid.h:333
void setValueOnly(Index, const ValueType &)
Definition PointDataGrid.h:393
tree::LeafNode< T, Log2Dim > BaseLeaf
Definition PointDataGrid.h:112
GroupHandle groupHandle(const Name &group) const
Read-only group handle from group name.
Definition PointDataGrid.h:829
std::shared_ptr< PointDataLeafNode > Ptr
Definition PointDataGrid.h:99
IndexAllIter beginIndexAll() const
Leaf index iterator.
Definition PointDataGrid.h:517
ValueOnCIter beginValueOn() const
Definition PointDataGrid.h:562
void clearAttributes(const bool updateValueMask=true, const AttributeArray::ScopedRegistryLock *lock=nullptr)
Clear the attribute set.
Definition PointDataGrid.h:633
bool hasAttribute(const Name &attributeName) const
Returns true if an attribute with this name exists.
Definition PointDataGrid.h:656
typename BaseLeaf::ChildOn ChildOn
Definition PointDataGrid.h:464
void signedFloodFill(const ValueType &, const ValueType &)
Definition PointDataGrid.h:449
PointDataLeafNode(const PointDataLeafNode &other)
Construct using deep copy of other PointDataLeafNode.
Definition PointDataGrid.h:130
void modifyValueAndActiveState(const Coord &, const ModifyOp &)
Definition PointDataGrid.h:419
typename BaseLeaf::ChildAll ChildAll
Definition PointDataGrid.h:466
IndexIter< IterT, FilterT > beginIndex(const FilterT &filter) const
IndexIter< ValueVoxelCIter, NullFilter > IndexVoxelIter
Definition PointDataGrid.h:511
ValueOnCIter cendValueOn() const
Definition PointDataGrid.h:571
void setOffsetOnly(Index offset, const ValueType &val)
Definition PointDataGrid.h:972
Index64 pointCount() const
Compute the total point count for the leaf.
Definition PointDataGrid.h:912
ValueOffCIter beginValueOff() const
Definition PointDataGrid.h:565
void resetDescriptor(const Descriptor::Ptr &replacement)
Replace the descriptor with a new one The new Descriptor must exactly match the old one.
Definition PointDataGrid.h:723
typename BaseLeaf::template ChildIter< MaskOffIterator, PointDataLeafNode, ChildOff > ChildOffIter
Definition PointDataGrid.h:502
IndexOffIter beginIndexOff() const
Definition PointDataGrid.h:527
ChildAllCIter cbeginChildAll() const
Definition PointDataGrid.h:587
ChildOffIter endChildOff()
Definition PointDataGrid.h:596
void modifyValueAndActiveStateAndCache(const Coord &, const ModifyOp &, AccessorT &)
Definition PointDataGrid.h:432
void setValueOnly(const Coord &, const ValueType &)
Definition PointDataGrid.h:392
ChildAllIter beginChildAll()
Definition PointDataGrid.h:589
void renameAttributes(const Descriptor &expected, Descriptor::Ptr &replacement)
Rename attributes in attribute set (order must remain the same).
Definition PointDataGrid.h:691
const PointDataLeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Definition PointDataGrid.h:335
static const Index DIM
Definition LeafNode.h:51
void setActiveState(const Coord &xyz, bool on)
Definition PointDataGrid.h:389
ValueOnIter beginValueOn()
Definition PointDataGrid.h:563
void initializeAttributes(const Descriptor::Ptr &descriptor, const Index arrayLength, const AttributeArray::ScopedRegistryLock *lock=nullptr)
Create a new attribute set. Existing attributes will be removed.
Definition PointDataGrid.h:618
ValueVoxelCIter beginValueVoxel(const Coord &ijk) const
Leaf value voxel iterator.
Definition PointDataGrid.h:882
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Definition PointDataGrid.h:319
IndexIter< ValueAllCIter, FilterT > beginIndexAll(const FilterT &filter) const
Filtered leaf index iterator.
Definition PointDataGrid.h:538
void assertNonModifiableUnlessZero(const ValueType &value)
Definition PointDataGrid.h:385
const PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Definition PointDataGrid.h:337
ChildOffCIter cbeginChildOff() const
Definition PointDataGrid.h:584
ChildOffIter beginChildOff()
Definition PointDataGrid.h:586
ChildOffCIter beginChildOff() const
Definition PointDataGrid.h:585
void dropAttributes(const std::vector< size_t > &pos, const Descriptor &expected, Descriptor::Ptr &replacement)
Drop list of attributes.
Definition PointDataGrid.h:676
void compactAttributes()
Compact all attributes in attribute set.
Definition PointDataGrid.h:698
void setValueOff(const Coord &xyz)
Definition PointDataGrid.h:395
bool operator!=(const PointDataLeafNode &other) const
Definition PointDataGrid.h:306
ValueOffIter endValueOff()
Definition PointDataGrid.h:576
void setValueOff(Index offset)
Definition PointDataGrid.h:396
IndexIter< ValueOnCIter, FilterT > beginIndexOn(const FilterT &filter) const
Definition PointDataGrid.h:543
ChildAllCIter endChildAll() const
Definition PointDataGrid.h:598
void setOffsets(const std::vector< ValueType > &offsets, const bool updateValueMask=true)
Sets all of the voxel offset values on this leaf, from the given vector of offsets....
Definition PointDataGrid.h:730
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Definition PointDataGrid.h:340
void setOffsetOn(Index offset, const ValueType &val)
Definition PointDataGrid.h:964
ValueOnCIter cbeginValueOn() const
Definition PointDataGrid.h:561
IndexIter< ValueOnCIter, NullFilter > IndexOnIter
Definition PointDataGrid.h:513
void clip(const CoordBBox &, const ValueType &value)
Definition PointDataGrid.h:422
ChildOnCIter endChildOn() const
Definition PointDataGrid.h:592
void reorderAttributes(const Descriptor::Ptr &replacement)
Reorder attribute set.
Definition PointDataGrid.h:684
ChildOnCIter cendChildOn() const
Definition PointDataGrid.h:591
void fill(const ValueType &, bool)
Definition PointDataGrid.h:1467
ChildAllCIter cendChildAll() const
Definition PointDataGrid.h:597
PointDataLeafNode()
Default constructor.
Definition PointDataGrid.h:124
const AttributeSet & attributeSet() const
Retrieve the attribute set.
Definition PointDataGrid.h:178
void assertNonmodifiable()
Definition PointDataGrid.h:378
void setValueOffAndCache(const Coord &, const ValueType &, AccessorT &)
Definition PointDataGrid.h:437
ChildAllIter endChildAll()
Definition PointDataGrid.h:599
IndexIter< ValueOffCIter, FilterT > beginIndexOff(const FilterT &filter) const
Definition PointDataGrid.h:548
bool hasAttribute(const size_t pos) const
Returns true if an attribute with this index exists.
Definition PointDataGrid.h:649
GroupHandle groupHandle(const AttributeSet::Descriptor::GroupIndex &index) const
}
Definition PointDataGrid.h:817
void resetBackground(const ValueType &, const ValueType &newBackground)
Definition PointDataGrid.h:444
typename NodeMaskType::OffIterator MaskOffIterator
Definition PointDataGrid.h:469
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &value, TopologyCopy)
Definition PointDataGrid.h:159
AttributeSet::UniquePtr stealAttributeSet()
Steal the attribute set, a new, empty attribute set is inserted in it's place.
Definition PointDataGrid.h:609
void setValue(const Coord &, const ValueType &)
Definition PointDataGrid.h:407
ValueAllCIter cendValueAll() const
Definition PointDataGrid.h:577
static const Index NUM_VALUES
Definition LeafNode.h:52
void negate()
Definition PointDataGrid.h:451
typename BaseLeaf::template ValueIter< MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn > ValueOnIter
Definition PointDataGrid.h:486
ChildAllCIter beginChildAll() const
Definition PointDataGrid.h:588
typename BaseLeaf::ValueAll ValueAll
Definition PointDataGrid.h:457
std::pair< ValueType, ValueType > ValueTypePair
Definition PointDataGrid.h:102
void setValuesOn()
Definition PointDataGrid.h:409
AttributeSet::Descriptor Descriptor
Definition PointDataGrid.h:105
typename BaseLeaf::template DenseIter< const PointDataLeafNode, const ValueType, ChildAll > ChildAllCIter
Definition PointDataGrid.h:508
typename BaseLeaf::ValueOn ValueOn
Definition PointDataGrid.h:455
ChildOffCIter cendChildOff() const
Definition PointDataGrid.h:594
typename BaseLeaf::template ChildIter< MaskOnIterator, const PointDataLeafNode, ChildOn > ChildOnCIter
Definition PointDataGrid.h:500
void addLeafAndCache(PointDataLeafNode *, AccessorT &)
Definition PointDataGrid.h:310
void setValueOnlyAndCache(const Coord &, const ValueType &, AccessorT &)
Definition PointDataGrid.h:429
IndexIter< ValueVoxelCIter, FilterT > beginIndexVoxel(const Coord &ijk, const FilterT &filter) const
Filtered leaf index iterator from voxel.
Definition PointDataGrid.h:902
void fill(const ValueType &value)
Definition PointDataGrid.h:425
typename NodeMaskType::OnIterator MaskOnIterator
Definition PointDataGrid.h:468
void addLeaf(PointDataLeafNode *)
Definition PointDataGrid.h:308
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition PointDataGrid.h:1431
const AttributeArray & constAttributeArray(const size_t pos) const
Definition PointDataGrid.h:785
void signedFloodFill(const ValueType &)
Definition PointDataGrid.h:448
typename BaseLeaf::template ValueIter< MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff > ValueOffIter
Definition PointDataGrid.h:490
ValueOffIter beginValueOff()
Definition PointDataGrid.h:566
void setValueOn(const Coord &xyz)
Definition PointDataGrid.h:401
void setActiveState(Index offset, bool on)
Definition PointDataGrid.h:390
AttributeArray & attributeArray(const Name &attributeName)
Read-write attribute array reference from name.
Definition PointDataGrid.h:792
IndexOnIter beginIndexOn() const
Definition PointDataGrid.h:522
typename BaseLeaf::ValueOff ValueOff
Definition PointDataGrid.h:456
typename BaseLeaf::template DenseIter< PointDataLeafNode, ValueType, ChildAll > ChildAllIter
Definition PointDataGrid.h:506
IndexVoxelIter beginIndexVoxel(const Coord &ijk) const
Leaf index iterator from voxel.
Definition PointDataGrid.h:893
Index64 offPointCount() const
Compute the total inactive (off) point count for the leaf.
Definition PointDataGrid.h:928
void modifyValue(const Coord &, const ModifyOp &)
Definition PointDataGrid.h:416
ValueOffCIter cendValueOff() const
Definition PointDataGrid.h:574
Index64 memUsage() const
Definition PointDataGrid.h:1424
void fill(const CoordBBox &, const ValueType &, bool)
Definition PointDataGrid.h:1445
Index64 onPointCount() const
Compute the total active (on) point count for the leaf.
Definition PointDataGrid.h:919
ValueOffCIter endValueOff() const
Definition PointDataGrid.h:575
typename BaseLeaf::template ValueIter< MaskDenseIterator, const PointDataLeafNode, const ValueType, ValueAll > ValueAllCIter
Definition PointDataGrid.h:496
typename BaseLeaf::template ChildIter< MaskOffIterator, const PointDataLeafNode, ChildOff > ChildOffCIter
Definition PointDataGrid.h:504
PointDataLeafNode * probeLeaf(const Coord &)
Definition PointDataGrid.h:326
T ValueType
Definition PointDataGrid.h:101
PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Definition PointDataGrid.h:328
ValueOnCIter endValueOn() const
Definition PointDataGrid.h:572
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition PointDataGrid.h:470
ValueAllCIter beginValueAll() const
Definition PointDataGrid.h:568
PointDataLeafNode(const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Construct using supplied origin, value and active status.
Definition PointDataGrid.h:136
typename BaseLeaf::template ValueIter< MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll > ValueAllIter
Definition PointDataGrid.h:494
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &, const T &, TopologyCopy)
Definition PointDataGrid.h:166
const AttributeArray & attributeArray(const Name &attributeName) const
Definition PointDataGrid.h:801
friend class PointDataLeafNode
Definition PointDataGrid.h:474
void setValueOn(const Coord &, const ValueType &)
Definition PointDataGrid.h:404
ValueAllIter beginValueAll()
Definition PointDataGrid.h:569
std::vector< ValueType > IndexArray
Definition PointDataGrid.h:103
static TypedAttributeArray & cast(AttributeArray &attributeArray)
A forward iterator over array indices in a single voxel.
Definition IndexIterator.h:66
Definition InternalNode.h:35
Base class for iterators over internal and leaf nodes.
Definition Iterator.h:30
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition LeafNode.h:39
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node.
Definition LeafNode.h:170
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition LeafNode.h:1111
void setValueMask(const NodeMaskType &mask)
Definition LeafNode.h:916
void setValuesOff()
Mark all voxels as inactive but don't change their values.
Definition LeafNode.h:504
const Buffer & buffer() const
Definition LeafNode.h:377
void setValueMaskOn(Index n)
Definition LeafNode.h:922
static const Index NUM_VOXELS
Definition LeafNode.h:53
static const Index DIM
Definition LeafNode.h:51
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition LeafNode.h:1161
static const Index LEVEL
Definition LeafNode.h:55
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition LeafNode.h:1076
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition LeafNode.h:441
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition LeafNode.h:1488
static const Index NUM_VALUES
Definition LeafNode.h:52
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition LeafNode.h:627
void setValuesOn()
Mark all voxels as active but don't change their values.
Definition LeafNode.h:502
static const Index LOG2DIM
Definition LeafNode.h:49
static const Index SIZE
Definition LeafNode.h:54
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition LeafNode.h:1470
bool isEmpty() const
Return true if this node has no active voxels.
Definition LeafNode.h:152
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition LeafNode.h:451
bool allocate()
Allocate memory for this node's buffer if it has not already been allocated.
Definition LeafNode.h:158
static const Index TOTAL
Definition LeafNode.h:50
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition LeafNode.h:1460
bool isDense() const
Return true if this node contains only active voxels.
Definition LeafNode.h:154
const ValueType & getLastValue() const
Return a const reference to the last value in the buffer.
Definition LeafNode.h:663
Definition RootNode.h:39
Definition Tree.h:172
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition NodeMasks.h:309
DenseMaskIterator< NodeMask > DenseIterator
Definition NodeMasks.h:351
OnMaskIterator< NodeMask > OnIterator
Definition NodeMasks.h:349
OffMaskIterator< NodeMask > OffIterator
Definition NodeMasks.h:350
@ AttributeArray
Definition NanoVDB.h:416
Definition IndexIterator.h:35
@ ALL
Definition IndexIterator.h:44
@ NONE
Definition IndexIterator.h:43
Definition Grid.h:1187
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > > PointDataTree
Point index tree configured to match the default VDB configurations.
Definition PointDataGrid.h:68
bool isGroup(const AttributeArray &array)
Definition AttributeGroup.h:64
TypedAttributeArray< GroupType, GroupCodec > GroupAttributeArray
Definition AttributeGroup.h:41
Grid< PointDataTree > PointDataGrid
Point data grid.
Definition PointDataGrid.h:73
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition IndexIterator.h:315
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition PointDataGrid.h:1483
Definition PointDataGrid.h:48
std::string Name
Definition Name.h:19
Index32 Index
Definition Types.h:34
void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types.
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
void uninitialize()
Global deregistration of native Grid, Transform, Metadata and Point attribute types.
int32_t Int32
Definition Types.h:36
uint64_t Index64
Definition Types.h:33
const char * typeNameAsString()
Definition Types.h:587
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Tag for multi-pass I/O. Only points::PointDataLeafNode may inherit from this.
Definition io.h:124
Similiar to ValueConverter, but allows for tree configuration conversion to a PointDataTree....
Definition PointDataGrid.h:1550
tree::Tree< typename NodeChainT::Back > Type
Definition PointDataGrid.h:1553
typename TreeType::RootNodeType RootNodeT
Definition PointDataGrid.h:1551
typename internal::PointDataNodeChain< RootNodeT, RootNodeT::LEVEL >::Type NodeChainT
Definition PointDataGrid.h:1552
Definition PointIndexGrid.h:1359
Definition TreeIterator.h:61
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition LeafNode.h:282
Definition LeafNode.h:952
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:291