OpenVDB  8.0.1
PointDataGrid.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
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>
18 #include <openvdb/tree/LeafNode.h>
20 #include "AttributeArray.h"
21 #include "AttributeArrayString.h"
22 #include "AttributeGroup.h"
23 #include "AttributeSet.h"
24 #include "StreamCompression.h"
25 #include <cstring> // std::memcpy
26 #include <iostream>
27 #include <limits>
28 #include <memory>
29 #include <type_traits> // std::is_same
30 #include <utility> // std::pair, std::make_pair
31 #include <vector>
32 
33 class TestPointDataLeaf;
34 
35 namespace openvdb {
37 namespace OPENVDB_VERSION_NAME {
38 
39 namespace io
40 {
41 
44 template<>
45 inline void
46 readCompressedValues( std::istream& is, PointDataIndex32* destBuf, Index destCount,
47  const util::NodeMask<3>& /*valueMask*/, bool /*fromHalf*/)
48 {
50 
51  const bool seek = destBuf == nullptr;
52 
53  const size_t destBytes = destCount*sizeof(PointDataIndex32);
54  const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
55  if (destBytes >= maximumBytes) {
56  OPENVDB_THROW(openvdb::IoError, "Cannot read more than " <<
57  maximumBytes << " bytes in voxel values.")
58  }
59 
60  uint16_t bytes16;
61 
63 
64  if (seek && meta) {
65  // buffer size temporarily stored in the StreamMetadata pass
66  // to avoid having to perform an expensive disk read for 2-bytes
67  bytes16 = static_cast<uint16_t>(meta->pass());
68  // seek over size of the compressed buffer
69  is.seekg(sizeof(uint16_t), std::ios_base::cur);
70  }
71  else {
72  // otherwise read from disk
73  is.read(reinterpret_cast<char*>(&bytes16), sizeof(uint16_t));
74  }
75 
76  if (bytes16 == std::numeric_limits<uint16_t>::max()) {
77  // read or seek uncompressed data
78  if (seek) {
79  is.seekg(destBytes, std::ios_base::cur);
80  }
81  else {
82  is.read(reinterpret_cast<char*>(destBuf), destBytes);
83  }
84  }
85  else {
86  // read or seek uncompressed data
87  if (seek) {
88  is.seekg(int(bytes16), std::ios_base::cur);
89  }
90  else {
91  // decompress into the destination buffer
92  std::unique_ptr<char[]> bloscBuffer(new char[int(bytes16)]);
93  is.read(bloscBuffer.get(), bytes16);
94  std::unique_ptr<char[]> buffer = bloscDecompress( bloscBuffer.get(),
95  destBytes,
96  /*resize=*/false);
97  std::memcpy(destBuf, buffer.get(), destBytes);
98  }
99  }
100 }
101 
104 template<>
105 inline void
106 writeCompressedValues( std::ostream& os, PointDataIndex32* srcBuf, Index srcCount,
107  const util::NodeMask<3>& /*valueMask*/,
108  const util::NodeMask<3>& /*childMask*/, bool /*toHalf*/)
109 {
111 
112  const size_t srcBytes = srcCount*sizeof(PointDataIndex32);
113  const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
114  if (srcBytes >= maximumBytes) {
115  OPENVDB_THROW(openvdb::IoError, "Cannot write more than " <<
116  maximumBytes << " bytes in voxel values.")
117  }
118 
119  const char* charBuffer = reinterpret_cast<const char*>(srcBuf);
120 
121  size_t compressedBytes;
122  std::unique_ptr<char[]> buffer = bloscCompress( charBuffer, srcBytes,
123  compressedBytes, /*resize=*/false);
124 
125  if (compressedBytes > 0) {
126  auto bytes16 = static_cast<uint16_t>(compressedBytes); // clamp to 16-bit unsigned integer
127  os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
128  os.write(reinterpret_cast<const char*>(buffer.get()), compressedBytes);
129  }
130  else {
131  auto bytes16 = static_cast<uint16_t>(maximumBytes); // max value indicates uncompressed
132  os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
133  os.write(reinterpret_cast<const char*>(srcBuf), srcBytes);
134  }
135 }
136 
137 template <typename T>
138 inline void
139 writeCompressedValuesSize(std::ostream& os, const T* srcBuf, Index srcCount)
140 {
142 
143  const size_t srcBytes = srcCount*sizeof(T);
144  const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
145  if (srcBytes >= maximumBytes) {
146  OPENVDB_THROW(openvdb::IoError, "Cannot write more than " <<
147  maximumBytes << " bytes in voxel values.")
148  }
149 
150  const char* charBuffer = reinterpret_cast<const char*>(srcBuf);
151 
152  // calculate voxel buffer size after compression
153  size_t compressedBytes = bloscCompressedSize(charBuffer, srcBytes);
154 
155  if (compressedBytes > 0) {
156  auto bytes16 = static_cast<uint16_t>(compressedBytes); // clamp to 16-bit unsigned integer
157  os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
158  }
159  else {
160  auto bytes16 = static_cast<uint16_t>(maximumBytes); // max value indicates uncompressed
161  os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
162  }
163 }
164 
165 } // namespace io
166 
167 
168 // forward declaration
169 namespace tree {
170  template<Index, typename> struct SameLeafConfig;
171 }
172 
173 
175 
176 
177 namespace points {
178 
179 
180 // forward declaration
181 template<typename T, Index Log2Dim> class PointDataLeafNode;
182 
186 
187 
190 
191 
199 template <typename PointDataTreeT>
200 inline AttributeSet::Descriptor::Ptr
201 makeDescriptorUnique(PointDataTreeT& tree);
202 
203 
213 template <typename PointDataTreeT>
214 inline void
215 setStreamingMode(PointDataTreeT& tree, bool on = true);
216 
217 
224 template <typename PointDataTreeT>
225 inline void
226 prefetch(PointDataTreeT& tree, bool position = true, bool otherAttributes = true);
227 
228 
230 
231 
232 template <typename T, Index Log2Dim>
233 class PointDataLeafNode : public tree::LeafNode<T, Log2Dim>, io::MultiPass {
234 
235 public:
237  using Ptr = std::shared_ptr<PointDataLeafNode>;
238 
239  using ValueType = T;
240  using ValueTypePair = std::pair<ValueType, ValueType>;
241  using IndexArray = std::vector<ValueType>;
242 
243  using Descriptor = AttributeSet::Descriptor;
244 
246 
247  // The following methods had to be copied from the LeafNode class
248  // to make the derived PointDataLeafNode class compatible with the tree structure.
249 
252 
253  using BaseLeaf::LOG2DIM;
254  using BaseLeaf::TOTAL;
255  using BaseLeaf::DIM;
256  using BaseLeaf::NUM_VALUES;
257  using BaseLeaf::NUM_VOXELS;
258  using BaseLeaf::SIZE;
259  using BaseLeaf::LEVEL;
260 
263  : mAttributeSet(new AttributeSet) { }
264 
265  ~PointDataLeafNode() = default;
266 
268  explicit PointDataLeafNode(const PointDataLeafNode& other)
269  : BaseLeaf(other)
270  , mAttributeSet(new AttributeSet(*other.mAttributeSet)) { }
271 
273  explicit
274  PointDataLeafNode(const Coord& coords, const T& value = zeroVal<T>(), bool active = false)
275  : BaseLeaf(coords, zeroVal<T>(), active)
276  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
277 
280  PointDataLeafNode(const PointDataLeafNode& other, const Coord& coords,
281  const T& value = zeroVal<T>(), bool active = false)
282  : BaseLeaf(coords, zeroVal<T>(), active)
283  , mAttributeSet(new AttributeSet(*other.mAttributeSet))
284  {
285  assertNonModifiableUnlessZero(value);
286  }
287 
288  // Copy-construct from a PointIndexLeafNode with the same configuration but a different ValueType.
289  template<typename OtherValueType>
291  : BaseLeaf(other)
292  , mAttributeSet(new AttributeSet) { }
293 
294  // Copy-construct from a LeafNode with the same configuration but a different ValueType.
295  // Used for topology copies - explicitly sets the value (background) to zeroVal
296  template <typename ValueType>
298  : BaseLeaf(other, zeroVal<T>(), TopologyCopy())
299  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
300 
301  // Copy-construct from a LeafNode with the same configuration but a different ValueType.
302  // Used for topology copies - explicitly sets the on and off value (background) to zeroVal
303  template <typename ValueType>
304  PointDataLeafNode(const tree::LeafNode<ValueType, Log2Dim>& other, const T& /*offValue*/, const T& /*onValue*/, TopologyCopy)
305  : BaseLeaf(other, zeroVal<T>(), zeroVal<T>(), TopologyCopy())
306  , mAttributeSet(new AttributeSet) { }
307 
309  const T& value = zeroVal<T>(), bool active = false)
310  : BaseLeaf(PartialCreate(), coords, value, active)
311  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
312 
313 public:
314 
316  const AttributeSet& attributeSet() const { return *mAttributeSet; }
317 
319  AttributeSet::UniquePtr stealAttributeSet();
320 
322  void initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
323  const AttributeArray::ScopedRegistryLock* lock = nullptr);
325  void clearAttributes(const bool updateValueMask = true,
326  const AttributeArray::ScopedRegistryLock* lock = nullptr);
327 
330  bool hasAttribute(const size_t pos) const;
333  bool hasAttribute(const Name& attributeName) const;
334 
343  AttributeArray::Ptr appendAttribute(const Descriptor& expected, Descriptor::Ptr& replacement,
344  const size_t pos, const Index strideOrTotalSize = 1,
345  const bool constantStride = true,
346  const Metadata* metadata = nullptr,
347  const AttributeArray::ScopedRegistryLock* lock = nullptr);
348 
353  void dropAttributes(const std::vector<size_t>& pos,
354  const Descriptor& expected, Descriptor::Ptr& replacement);
357  void reorderAttributes(const Descriptor::Ptr& replacement);
361  void renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement);
363  void compactAttributes();
364 
370  void replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors = false);
371 
374  void resetDescriptor(const Descriptor::Ptr& replacement);
375 
379  void setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask = true);
380 
383  void validateOffsets() const;
384 
390  AttributeArray& attributeArray(const size_t pos);
391  const AttributeArray& attributeArray(const size_t pos) const;
392  const AttributeArray& constAttributeArray(const size_t pos) const;
399  AttributeArray& attributeArray(const Name& attributeName);
400  const AttributeArray& attributeArray(const Name& attributeName) const;
401  const AttributeArray& constAttributeArray(const Name& attributeName) const;
403 
405  GroupHandle groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const;
407  GroupHandle groupHandle(const Name& group) const;
409  GroupWriteHandle groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index);
411  GroupWriteHandle groupWriteHandle(const Name& name);
412 
414  Index64 pointCount() const;
416  Index64 onPointCount() const;
418  Index64 offPointCount() const;
420  Index64 groupPointCount(const Name& groupName) const;
421 
423  void updateValueMask();
424 
426 
427  void setOffsetOn(Index offset, const ValueType& val);
428  void setOffsetOnly(Index offset, const ValueType& val);
429 
432  template<typename OtherType, Index OtherLog2Dim>
434  return BaseLeaf::hasSameTopology(other);
435  }
436 
439  bool operator==(const PointDataLeafNode& other) const {
440  if(BaseLeaf::operator==(other) != true) return false;
441  return (*this->mAttributeSet == *other.mAttributeSet);
442  }
443 
444  bool operator!=(const PointDataLeafNode& other) const { return !(other == *this); }
445 
447  template<typename AccessorT>
448  void addLeafAndCache(PointDataLeafNode*, AccessorT&) {}
449 
451  PointDataLeafNode* touchLeaf(const Coord&) { return this; }
453  template<typename AccessorT>
454  PointDataLeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
455 
456  template<typename NodeT, typename AccessorT>
457  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
458  {
460  if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
461  return reinterpret_cast<NodeT*>(this);
463  }
464  PointDataLeafNode* probeLeaf(const Coord&) { return this; }
465  template<typename AccessorT>
466  PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
468 
470  const PointDataLeafNode* probeConstLeaf(const Coord&) const { return this; }
472  template<typename AccessorT>
473  const PointDataLeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
474  template<typename AccessorT>
475  const PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
476  const PointDataLeafNode* probeLeaf(const Coord&) const { return this; }
477  template<typename NodeT, typename AccessorT>
478  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
479  {
481  if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
482  return reinterpret_cast<const NodeT*>(this);
484  }
486 
487  // I/O methods
488 
489  void readTopology(std::istream& is, bool fromHalf = false);
490  void writeTopology(std::ostream& os, bool toHalf = false) const;
491 
492  Index buffers() const;
493 
494  void readBuffers(std::istream& is, bool fromHalf = false);
495  void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
496  void writeBuffers(std::ostream& os, bool toHalf = false) const;
497 
498 
499  Index64 memUsage() const;
500 
501  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
502 
505  CoordBBox getNodeBoundingBox() const;
506 
508 
509  // Disable all write methods to avoid unintentional changes
510  // to the point-array offsets.
511 
513  assert(false && "Cannot modify voxel values in a PointDataTree.");
514  }
515 
516  // some methods silently ignore attempts to modify the
517  // point-array offsets if a zero value is used
518 
520  if (value != zeroVal<T>()) this->assertNonmodifiable();
521  }
522 
523  void setActiveState(const Coord& xyz, bool on) { BaseLeaf::setActiveState(xyz, on); }
524  void setActiveState(Index offset, bool on) { BaseLeaf::setActiveState(offset, on); }
525 
526  void setValueOnly(const Coord&, const ValueType&) { assertNonmodifiable(); }
527  void setValueOnly(Index, const ValueType&) { assertNonmodifiable(); }
528 
529  void setValueOff(const Coord& xyz) { BaseLeaf::setValueOff(xyz); }
530  void setValueOff(Index offset) { BaseLeaf::setValueOff(offset); }
531 
532  void setValueOff(const Coord&, const ValueType&) { assertNonmodifiable(); }
533  void setValueOff(Index, const ValueType&) { assertNonmodifiable(); }
534 
535  void setValueOn(const Coord& xyz) { BaseLeaf::setValueOn(xyz); }
536  void setValueOn(Index offset) { BaseLeaf::setValueOn(offset); }
537 
538  void setValueOn(const Coord&, const ValueType&) { assertNonmodifiable(); }
539  void setValueOn(Index, const ValueType&) { assertNonmodifiable(); }
540 
541  void setValue(const Coord&, const ValueType&) { assertNonmodifiable(); }
542 
543  void setValuesOn() { BaseLeaf::setValuesOn(); }
544  void setValuesOff() { BaseLeaf::setValuesOff(); }
545 
546  template<typename ModifyOp>
547  void modifyValue(Index, const ModifyOp&) { assertNonmodifiable(); }
548 
549  template<typename ModifyOp>
550  void modifyValue(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
551 
552  template<typename ModifyOp>
553  void modifyValueAndActiveState(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
554 
555  // clipping is not yet supported
556  void clip(const CoordBBox&, const ValueType& value) { assertNonModifiableUnlessZero(value); }
557 
558  void fill(const CoordBBox&, const ValueType&, bool);
559  void fill(const ValueType& value) { assertNonModifiableUnlessZero(value); }
560  void fill(const ValueType&, bool);
561 
562  template<typename AccessorT>
563  void setValueOnlyAndCache(const Coord&, const ValueType&, AccessorT&) {assertNonmodifiable();}
564 
565  template<typename ModifyOp, typename AccessorT>
566  void modifyValueAndActiveStateAndCache(const Coord&, const ModifyOp&, AccessorT&) {
567  assertNonmodifiable();
568  }
569 
570  template<typename AccessorT>
571  void setValueOffAndCache(const Coord&, const ValueType&, AccessorT&) { assertNonmodifiable(); }
572 
573  template<typename AccessorT>
574  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& parent) {
575  BaseLeaf::setActiveStateAndCache(xyz, on, parent);
576  }
577 
578  void resetBackground(const ValueType&, const ValueType& newBackground) {
579  assertNonModifiableUnlessZero(newBackground);
580  }
581 
582  void signedFloodFill(const ValueType&) { assertNonmodifiable(); }
583  void signedFloodFill(const ValueType&, const ValueType&) { assertNonmodifiable(); }
584 
585  void negate() { assertNonmodifiable(); }
586 
587  friend class ::TestPointDataLeaf;
588 
589  using ValueOn = typename BaseLeaf::ValueOn;
590  using ValueOff = typename BaseLeaf::ValueOff;
591  using ValueAll = typename BaseLeaf::ValueAll;
592 
593 private:
594  AttributeSet::UniquePtr mAttributeSet;
595  uint16_t mVoxelBufferSize = 0;
596 
597 protected:
598  using ChildOn = typename BaseLeaf::ChildOn;
599  using ChildOff = typename BaseLeaf::ChildOff;
600  using ChildAll = typename BaseLeaf::ChildAll;
601 
605 
606  // During topology-only construction, access is needed
607  // to protected/private members of other template instances.
608  template<typename, Index> friend class PointDataLeafNode;
609 
613 
614 public:
616  ValueVoxelCIter beginValueVoxel(const Coord& ijk) const;
617 
618 public:
619 
620  using ValueOnIter = typename BaseLeaf::template ValueIter<
622  using ValueOnCIter = typename BaseLeaf::template ValueIter<
624  using ValueOffIter = typename BaseLeaf::template ValueIter<
626  using ValueOffCIter = typename BaseLeaf::template ValueIter<
628  using ValueAllIter = typename BaseLeaf::template ValueIter<
630  using ValueAllCIter = typename BaseLeaf::template ValueIter<
632  using ChildOnIter = typename BaseLeaf::template ChildIter<
634  using ChildOnCIter = typename BaseLeaf::template ChildIter<
636  using ChildOffIter = typename BaseLeaf::template ChildIter<
638  using ChildOffCIter = typename BaseLeaf::template ChildIter<
640  using ChildAllIter = typename BaseLeaf::template DenseIter<
642  using ChildAllCIter = typename BaseLeaf::template DenseIter<
643  const PointDataLeafNode, const ValueType, ChildAll>;
644 
649 
652  {
653  NullFilter filter;
654  return this->beginIndex<ValueAllCIter, NullFilter>(filter);
655  }
657  {
658  NullFilter filter;
659  return this->beginIndex<ValueOnCIter, NullFilter>(filter);
660  }
662  {
663  NullFilter filter;
664  return this->beginIndex<ValueOffCIter, NullFilter>(filter);
665  }
666 
667  template<typename IterT, typename FilterT>
668  IndexIter<IterT, FilterT> beginIndex(const FilterT& filter) const;
669 
671  template<typename FilterT>
673  {
674  return this->beginIndex<ValueAllCIter, FilterT>(filter);
675  }
676  template<typename FilterT>
677  IndexIter<ValueOnCIter, FilterT> beginIndexOn(const FilterT& filter) const
678  {
679  return this->beginIndex<ValueOnCIter, FilterT>(filter);
680  }
681  template<typename FilterT>
683  {
684  return this->beginIndex<ValueOffCIter, FilterT>(filter);
685  }
686 
688  IndexVoxelIter beginIndexVoxel(const Coord& ijk) const;
689 
691  template<typename FilterT>
692  IndexIter<ValueVoxelCIter, FilterT> beginIndexVoxel(const Coord& ijk, const FilterT& filter) const;
693 
694 #define VMASK_ this->getValueMask()
695  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
696  ValueOnCIter beginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
697  ValueOnIter beginValueOn() { return ValueOnIter(VMASK_.beginOn(), this); }
698  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
699  ValueOffCIter beginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
700  ValueOffIter beginValueOff() { return ValueOffIter(VMASK_.beginOff(), this); }
701  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
702  ValueAllCIter beginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
703  ValueAllIter beginValueAll() { return ValueAllIter(VMASK_.beginDense(), this); }
704 
705  ValueOnCIter cendValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
706  ValueOnCIter endValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
707  ValueOnIter endValueOn() { return ValueOnIter(VMASK_.endOn(), this); }
708  ValueOffCIter cendValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
709  ValueOffCIter endValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
710  ValueOffIter endValueOff() { return ValueOffIter(VMASK_.endOff(), this); }
711  ValueAllCIter cendValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
712  ValueAllCIter endValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
713  ValueAllIter endValueAll() { return ValueAllIter(VMASK_.endDense(), this); }
714 
715  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
716  ChildOnCIter beginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
717  ChildOnIter beginChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
718  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
719  ChildOffCIter beginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
720  ChildOffIter beginChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
721  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
722  ChildAllCIter beginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
723  ChildAllIter beginChildAll() { return ChildAllIter(VMASK_.beginDense(), this); }
724 
725  ChildOnCIter cendChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
726  ChildOnCIter endChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
727  ChildOnIter endChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
728  ChildOffCIter cendChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
729  ChildOffCIter endChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
730  ChildOffIter endChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
731  ChildAllCIter cendChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
732  ChildAllCIter endChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
733  ChildAllIter endChildAll() { return ChildAllIter(VMASK_.endDense(), this); }
734 #undef VMASK_
735 }; // struct PointDataLeafNode
736 
738 
739 // PointDataLeafNode implementation
740 
741 template<typename T, Index Log2Dim>
742 inline AttributeSet::UniquePtr
744 {
745  AttributeSet::UniquePtr ptr = std::make_unique<AttributeSet>();
746  std::swap(ptr, mAttributeSet);
747  return ptr;
748 }
749 
750 template<typename T, Index Log2Dim>
751 inline void
752 PointDataLeafNode<T, Log2Dim>::initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
754 {
755  if (descriptor->size() != 1 ||
756  descriptor->find("P") == AttributeSet::INVALID_POS ||
757  descriptor->valueType(0) != typeNameAsString<Vec3f>())
758  {
759  OPENVDB_THROW(IndexError, "Initializing attributes only allowed with one Vec3f position attribute.");
760  }
761 
762  mAttributeSet.reset(new AttributeSet(descriptor, arrayLength, lock));
763 }
764 
765 template<typename T, Index Log2Dim>
766 inline void
769 {
770  mAttributeSet.reset(new AttributeSet(*mAttributeSet, 0, lock));
771 
772  // zero voxel values
773 
774  this->buffer().fill(ValueType(0));
775 
776  // if updateValueMask, also de-activate all voxels
777 
778  if (updateValueMask) this->setValuesOff();
779 }
780 
781 template<typename T, Index Log2Dim>
782 inline bool
784 {
785  return pos < mAttributeSet->size();
786 }
787 
788 template<typename T, Index Log2Dim>
789 inline bool
791 {
792  const size_t pos = mAttributeSet->find(attributeName);
793  return pos != AttributeSet::INVALID_POS;
794 }
795 
796 template<typename T, Index Log2Dim>
797 inline AttributeArray::Ptr
798 PointDataLeafNode<T, Log2Dim>::appendAttribute( const Descriptor& expected, Descriptor::Ptr& replacement,
799  const size_t pos, const Index strideOrTotalSize,
800  const bool constantStride,
801  const Metadata* metadata,
803 {
804  return mAttributeSet->appendAttribute(
805  expected, replacement, pos, strideOrTotalSize, constantStride, metadata, lock);
806 }
807 
808 template<typename T, Index Log2Dim>
809 inline void
810 PointDataLeafNode<T, Log2Dim>::dropAttributes(const std::vector<size_t>& pos,
811  const Descriptor& expected, Descriptor::Ptr& replacement)
812 {
813  mAttributeSet->dropAttributes(pos, expected, replacement);
814 }
815 
816 template<typename T, Index Log2Dim>
817 inline void
818 PointDataLeafNode<T, Log2Dim>::reorderAttributes(const Descriptor::Ptr& replacement)
819 {
820  mAttributeSet->reorderAttributes(replacement);
821 }
822 
823 template<typename T, Index Log2Dim>
824 inline void
825 PointDataLeafNode<T, Log2Dim>::renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement)
826 {
827  mAttributeSet->renameAttributes(expected, replacement);
828 }
829 
830 template<typename T, Index Log2Dim>
831 inline void
833 {
834  for (size_t i = 0; i < mAttributeSet->size(); i++) {
835  AttributeArray* array = mAttributeSet->get(i);
836  array->compact();
837  }
838 }
839 
840 template<typename T, Index Log2Dim>
841 inline void
842 PointDataLeafNode<T, Log2Dim>::replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors)
843 {
844  if (!attributeSet) {
845  OPENVDB_THROW(ValueError, "Cannot replace with a null attribute set");
846  }
847 
848  if (!allowMismatchingDescriptors && mAttributeSet->descriptor() != attributeSet->descriptor()) {
849  OPENVDB_THROW(ValueError, "Attribute set descriptors are not equal.");
850  }
851 
852  mAttributeSet.reset(attributeSet);
853 }
854 
855 template<typename T, Index Log2Dim>
856 inline void
857 PointDataLeafNode<T, Log2Dim>::resetDescriptor(const Descriptor::Ptr& replacement)
858 {
859  mAttributeSet->resetDescriptor(replacement);
860 }
861 
862 template<typename T, Index Log2Dim>
863 inline void
864 PointDataLeafNode<T, Log2Dim>::setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask)
865 {
866  if (offsets.size() != LeafNodeType::NUM_VALUES) {
867  OPENVDB_THROW(ValueError, "Offset vector size doesn't match number of voxels.")
868  }
869 
870  for (Index index = 0; index < offsets.size(); ++index) {
871  setOffsetOnly(index, offsets[index]);
872  }
873 
874  if (updateValueMask) this->updateValueMask();
875 }
876 
877 template<typename T, Index Log2Dim>
878 inline void
880 {
881  // Ensure all of the offset values are monotonically increasing
882  for (Index index = 1; index < BaseLeaf::SIZE; ++index) {
883  if (this->getValue(index-1) > this->getValue(index)) {
884  OPENVDB_THROW(ValueError, "Voxel offset values are not monotonically increasing");
885  }
886  }
887 
888  // Ensure all attribute arrays are of equal length
889  for (size_t attributeIndex = 1; attributeIndex < mAttributeSet->size(); ++attributeIndex ) {
890  if (mAttributeSet->getConst(attributeIndex-1)->size() != mAttributeSet->getConst(attributeIndex)->size()) {
891  OPENVDB_THROW(ValueError, "Attribute arrays have inconsistent length");
892  }
893  }
894 
895  // Ensure the last voxel's offset value matches the size of each attribute array
896  if (mAttributeSet->size() > 0 && this->getValue(BaseLeaf::SIZE-1) != mAttributeSet->getConst(0)->size()) {
897  OPENVDB_THROW(ValueError, "Last voxel offset value does not match attribute array length");
898  }
899 }
900 
901 template<typename T, Index Log2Dim>
902 inline AttributeArray&
904 {
905  if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
906  return *mAttributeSet->get(pos);
907 }
908 
909 template<typename T, Index Log2Dim>
910 inline const AttributeArray&
912 {
913  if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
914  return *mAttributeSet->getConst(pos);
915 }
916 
917 template<typename T, Index Log2Dim>
918 inline const AttributeArray&
920 {
921  return this->attributeArray(pos);
922 }
923 
924 template<typename T, Index Log2Dim>
925 inline AttributeArray&
927 {
928  const size_t pos = mAttributeSet->find(attributeName);
929  if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
930  return *mAttributeSet->get(pos);
931 }
932 
933 template<typename T, Index Log2Dim>
934 inline const AttributeArray&
936 {
937  const size_t pos = mAttributeSet->find(attributeName);
938  if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
939  return *mAttributeSet->getConst(pos);
940 }
941 
942 template<typename T, Index Log2Dim>
943 inline const AttributeArray&
945 {
946  return this->attributeArray(attributeName);
947 }
948 
949 template<typename T, Index Log2Dim>
950 inline GroupHandle
951 PointDataLeafNode<T, Log2Dim>::groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const
952 {
953  const AttributeArray& array = this->attributeArray(index.first);
954  assert(isGroup(array));
955 
956  const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
957 
958  return GroupHandle(groupArray, index.second);
959 }
960 
961 template<typename T, Index Log2Dim>
962 inline GroupHandle
964 {
965  const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
966  return this->groupHandle(index);
967 }
968 
969 template<typename T, Index Log2Dim>
970 inline GroupWriteHandle
971 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index)
972 {
973  AttributeArray& array = this->attributeArray(index.first);
974  assert(isGroup(array));
975 
976  GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
977 
978  return GroupWriteHandle(groupArray, index.second);
979 }
980 
981 template<typename T, Index Log2Dim>
982 inline GroupWriteHandle
984 {
985  const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
986  return this->groupWriteHandle(index);
987 }
988 
989 template<typename T, Index Log2Dim>
990 template<typename ValueIterT, typename FilterT>
992 PointDataLeafNode<T, Log2Dim>::beginIndex(const FilterT& filter) const
993 {
994  // generate no-op iterator if filter evaluates no indices
995 
996  if (filter.state() == index::NONE) {
997  return IndexIter<ValueIterT, FilterT>(ValueIterT(), filter);
998  }
999 
1000  // copy filter to ensure thread-safety
1001 
1002  FilterT newFilter(filter);
1003  newFilter.reset(*this);
1004 
1005  using IterTraitsT = tree::IterTraits<LeafNodeType, ValueIterT>;
1006 
1007  // construct the value iterator and reset the filter to use this leaf
1008 
1009  ValueIterT valueIter = IterTraitsT::begin(*this);
1010 
1011  return IndexIter<ValueIterT, FilterT>(valueIter, newFilter);
1012 }
1013 
1014 template<typename T, Index Log2Dim>
1015 inline ValueVoxelCIter
1017 {
1018  const Index index = LeafNodeType::coordToOffset(ijk);
1019  assert(index < BaseLeaf::SIZE);
1020  const ValueType end = this->getValue(index);
1021  const ValueType start = (index == 0) ? ValueType(0) : this->getValue(index - 1);
1022  return ValueVoxelCIter(start, end);
1023 }
1024 
1025 template<typename T, Index Log2Dim>
1028 {
1029  ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1030  return IndexVoxelIter(iter, NullFilter());
1031 }
1032 
1033 template<typename T, Index Log2Dim>
1034 template<typename FilterT>
1036 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk, const FilterT& filter) const
1037 {
1038  ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1039  FilterT newFilter(filter);
1040  newFilter.reset(*this);
1041  return IndexIter<ValueVoxelCIter, FilterT>(iter, newFilter);
1042 }
1043 
1044 template<typename T, Index Log2Dim>
1045 inline Index64
1047 {
1048  return this->getLastValue();
1049 }
1050 
1051 template<typename T, Index Log2Dim>
1052 inline Index64
1054 {
1055  if (this->isEmpty()) return 0;
1056  else if (this->isDense()) return this->pointCount();
1057  return iterCount(this->beginIndexOn());
1058 }
1059 
1060 template<typename T, Index Log2Dim>
1061 inline Index64
1063 {
1064  if (this->isEmpty()) return this->pointCount();
1065  else if (this->isDense()) return 0;
1066  return iterCount(this->beginIndexOff());
1067 }
1068 
1069 template<typename T, Index Log2Dim>
1070 inline Index64
1072 {
1073  if (!this->attributeSet().descriptor().hasGroup(groupName)) {
1074  return Index64(0);
1075  }
1076  GroupFilter filter(groupName, this->attributeSet());
1077  if (filter.state() == index::ALL) {
1078  return this->pointCount();
1079  } else {
1080  return iterCount(this->beginIndexAll(filter));
1081  }
1082 }
1083 
1084 template<typename T, Index Log2Dim>
1085 inline void
1087 {
1088  ValueType start = 0, end = 0;
1089  for (Index n = 0; n < LeafNodeType::NUM_VALUES; n++) {
1090  end = this->getValue(n);
1091  this->setValueMask(n, (end - start) > 0);
1092  start = end;
1093  }
1094 }
1095 
1096 template<typename T, Index Log2Dim>
1097 inline void
1099 {
1100  this->buffer().setValue(offset, val);
1101  this->setValueMaskOn(offset);
1102 }
1103 
1104 template<typename T, Index Log2Dim>
1105 inline void
1107 {
1108  this->buffer().setValue(offset, val);
1109 }
1110 
1111 template<typename T, Index Log2Dim>
1112 inline void
1113 PointDataLeafNode<T, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1114 {
1115  BaseLeaf::readTopology(is, fromHalf);
1116 }
1117 
1118 template<typename T, Index Log2Dim>
1119 inline void
1120 PointDataLeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1121 {
1122  BaseLeaf::writeTopology(os, toHalf);
1123 }
1124 
1125 template<typename T, Index Log2Dim>
1126 inline Index
1128 {
1129  return Index( /*voxel buffer sizes*/ 1 +
1130  /*voxel buffers*/ 1 +
1131  /*attribute metadata*/ 1 +
1132  /*attribute uniform values*/ mAttributeSet->size() +
1133  /*attribute buffers*/ mAttributeSet->size() +
1134  /*cleanup*/ 1);
1135 }
1136 
1137 template<typename T, Index Log2Dim>
1138 inline void
1139 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1140 {
1141  this->readBuffers(is, CoordBBox::inf(), fromHalf);
1142 }
1143 
1144 template<typename T, Index Log2Dim>
1145 inline void
1146 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*bbox*/, bool fromHalf)
1147 {
1148  struct Local
1149  {
1150  static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1151  {
1152  // if paged stream exists, delete it
1153  std::string key("paged:" + std::to_string(index));
1154  auto it = auxData.find(key);
1155  if (it != auxData.end()) {
1156  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1157  }
1158  }
1159 
1160  static compression::PagedInputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1161  const Index index)
1162  {
1163  std::string key("paged:" + std::to_string(index));
1164  auto it = auxData.find(key);
1165  if (it != auxData.end()) {
1166  return *(boost::any_cast<compression::PagedInputStream::Ptr>(it->second));
1167  }
1168  else {
1169  compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
1170  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1171  return *pagedStream;
1172  }
1173  }
1174 
1175  static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1176  {
1177  std::string matchingKey("hasMatchingDescriptor");
1178  auto itMatching = auxData.find(matchingKey);
1179  return itMatching != auxData.end();
1180  }
1181 
1182  static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1183  {
1184  std::string matchingKey("hasMatchingDescriptor");
1185  std::string descriptorKey("descriptorPtr");
1186  auto itMatching = auxData.find(matchingKey);
1187  auto itDescriptor = auxData.find(descriptorKey);
1188  if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1189  if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1190  }
1191 
1192  static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1193  const Descriptor::Ptr descriptor)
1194  {
1195  std::string descriptorKey("descriptorPtr");
1196  std::string matchingKey("hasMatchingDescriptor");
1197  auto itMatching = auxData.find(matchingKey);
1198  if (itMatching == auxData.end()) {
1199  // if matching bool is not found, insert "true" and the descriptor
1200  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1201  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1202  }
1203  }
1204 
1205  static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1206  {
1207  std::string descriptorKey("descriptorPtr");
1208  auto itDescriptor = auxData.find(descriptorKey);
1209  assert(itDescriptor != auxData.end());
1210  const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1211  return descriptor;
1212  }
1213  };
1214 
1216 
1217  if (!meta) {
1218  OPENVDB_THROW(IoError, "Cannot read in a PointDataLeaf without StreamMetadata.");
1219  }
1220 
1221  const Index pass(static_cast<uint16_t>(meta->pass()));
1222  const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1223 
1224  const Index attributes = (maximumPass - 4) / 2;
1225 
1226  if (pass == 0) {
1227  // pass 0 - voxel data sizes
1228  is.read(reinterpret_cast<char*>(&mVoxelBufferSize), sizeof(uint16_t));
1229  Local::clearMatchingDescriptor(meta->auxData());
1230  }
1231  else if (pass == 1) {
1232  // pass 1 - descriptor and attribute metadata
1233  if (Local::hasMatchingDescriptor(meta->auxData())) {
1234  AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1235  mAttributeSet->resetDescriptor(descriptor, /*allowMismatchingDescriptors=*/true);
1236  }
1237  else {
1238  uint8_t header;
1239  is.read(reinterpret_cast<char*>(&header), sizeof(uint8_t));
1240  mAttributeSet->readDescriptor(is);
1241  if (header & uint8_t(1)) {
1242  AttributeSet::DescriptorPtr descriptor = mAttributeSet->descriptorPtr();
1243  Local::insertDescriptor(meta->auxData(), descriptor);
1244  }
1245  // a forwards-compatibility mechanism for future use,
1246  // if a 0x2 bit is set, read and skip over a specific number of bytes
1247  if (header & uint8_t(2)) {
1248  uint64_t bytesToSkip;
1249  is.read(reinterpret_cast<char*>(&bytesToSkip), sizeof(uint64_t));
1250  if (bytesToSkip > uint64_t(0)) {
1251  auto metadata = io::getStreamMetadataPtr(is);
1252  if (metadata && metadata->seekable()) {
1253  is.seekg(bytesToSkip, std::ios_base::cur);
1254  }
1255  else {
1256  std::vector<uint8_t> tempData(bytesToSkip);
1257  is.read(reinterpret_cast<char*>(&tempData[0]), bytesToSkip);
1258  }
1259  }
1260  }
1261  // this reader is only able to read headers with 0x1 and 0x2 bits set
1262  if (header > uint8_t(3)) {
1263  OPENVDB_THROW(IoError, "Unrecognised header flags in PointDataLeafNode");
1264  }
1265  }
1266  mAttributeSet->readMetadata(is);
1267  }
1268  else if (pass < (attributes + 2)) {
1269  // pass 2...n+2 - attribute uniform values
1270  const size_t attributeIndex = pass - 2;
1271  AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1272  mAttributeSet->get(attributeIndex) : nullptr;
1273  if (array) {
1274  compression::PagedInputStream& pagedStream =
1275  Local::getOrInsertPagedStream(meta->auxData(), static_cast<Index>(attributeIndex));
1276  pagedStream.setInputStream(is);
1277  pagedStream.setSizeOnly(true);
1278  array->readPagedBuffers(pagedStream);
1279  }
1280  }
1281  else if (pass == attributes + 2) {
1282  // pass n+2 - voxel data
1283 
1284  const Index passValue(meta->pass());
1285 
1286  // StreamMetadata pass variable used to temporarily store voxel buffer size
1287  io::StreamMetadata& nonConstMeta = const_cast<io::StreamMetadata&>(*meta);
1288  nonConstMeta.setPass(mVoxelBufferSize);
1289 
1290  // readBuffers() calls readCompressedValues specialization above
1291  BaseLeaf::readBuffers(is, fromHalf);
1292 
1293  // pass now reset to original value
1294  nonConstMeta.setPass(passValue);
1295  }
1296  else if (pass < (attributes*2 + 3)) {
1297  // pass n+2..2n+2 - attribute buffers
1298  const Index attributeIndex = pass - attributes - 3;
1299  AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1300  mAttributeSet->get(attributeIndex) : nullptr;
1301  if (array) {
1302  compression::PagedInputStream& pagedStream =
1303  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1304  pagedStream.setInputStream(is);
1305  pagedStream.setSizeOnly(false);
1306  array->readPagedBuffers(pagedStream);
1307  }
1308  // cleanup paged stream reference in auxiliary metadata
1309  if (pass > attributes + 3) {
1310  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1311  }
1312  }
1313  else if (pass < buffers()) {
1314  // pass 2n+3 - cleanup last paged stream
1315  const Index attributeIndex = pass - attributes - 4;
1316  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1317  }
1318 }
1319 
1320 template<typename T, Index Log2Dim>
1321 inline void
1322 PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1323 {
1324  struct Local
1325  {
1326  static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1327  {
1328  // if paged stream exists, flush and delete it
1329  std::string key("paged:" + std::to_string(index));
1330  auto it = auxData.find(key);
1331  if (it != auxData.end()) {
1332  compression::PagedOutputStream& stream = *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1333  stream.flush();
1334  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1335  }
1336  }
1337 
1338  static compression::PagedOutputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1339  const Index index)
1340  {
1341  std::string key("paged:" + std::to_string(index));
1342  auto it = auxData.find(key);
1343  if (it != auxData.end()) {
1344  return *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1345  }
1346  else {
1347  compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
1348  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1349  return *pagedStream;
1350  }
1351  }
1352 
1353  static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1354  const Descriptor::Ptr descriptor)
1355  {
1356  std::string descriptorKey("descriptorPtr");
1357  std::string matchingKey("hasMatchingDescriptor");
1358  auto itMatching = auxData.find(matchingKey);
1359  auto itDescriptor = auxData.find(descriptorKey);
1360  if (itMatching == auxData.end()) {
1361  // if matching bool is not found, insert "true" and the descriptor
1362  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1363  assert(itDescriptor == auxData.end());
1364  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1365  }
1366  else {
1367  // if matching bool is found and is false, early exit (a previous descriptor did not match)
1368  bool matching = boost::any_cast<bool>(itMatching->second);
1369  if (!matching) return;
1370  assert(itDescriptor != auxData.end());
1371  // if matching bool is true, check whether the existing descriptor matches the current one and set
1372  // matching bool to false if not
1373  const Descriptor::Ptr existingDescriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1374  if (*existingDescriptor != *descriptor) {
1375  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
1376  }
1377  }
1378  }
1379 
1380  static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1381  {
1382  std::string matchingKey("hasMatchingDescriptor");
1383  auto itMatching = auxData.find(matchingKey);
1384  // if matching key is not found, no matching descriptor
1385  if (itMatching == auxData.end()) return false;
1386  // if matching key is found and is false, no matching descriptor
1387  if (!boost::any_cast<bool>(itMatching->second)) return false;
1388  return true;
1389  }
1390 
1391  static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1392  {
1393  std::string descriptorKey("descriptorPtr");
1394  auto itDescriptor = auxData.find(descriptorKey);
1395  // if matching key is true, however descriptor is not found, it has already been retrieved
1396  if (itDescriptor == auxData.end()) return nullptr;
1397  // otherwise remove it and return it
1398  const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1399  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1400  return descriptor;
1401  }
1402 
1403  static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1404  {
1405  std::string matchingKey("hasMatchingDescriptor");
1406  std::string descriptorKey("descriptorPtr");
1407  auto itMatching = auxData.find(matchingKey);
1408  auto itDescriptor = auxData.find(descriptorKey);
1409  if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1410  if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1411  }
1412  };
1413 
1415 
1416  if (!meta) {
1417  OPENVDB_THROW(IoError, "Cannot write out a PointDataLeaf without StreamMetadata.");
1418  }
1419 
1420  const Index pass(static_cast<uint16_t>(meta->pass()));
1421 
1422  // leaf traversal analysis deduces the number of passes to perform for this leaf
1423  // then updates the leaf traversal value to ensure all passes will be written
1424 
1425  if (meta->countingPasses()) {
1426  const Index requiredPasses = this->buffers();
1427  if (requiredPasses > pass) {
1428  meta->setPass(requiredPasses);
1429  }
1430  return;
1431  }
1432 
1433  const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1434  const Index attributes = (maximumPass - 4) / 2;
1435 
1436  if (pass == 0) {
1437  // pass 0 - voxel data sizes
1438  io::writeCompressedValuesSize(os, this->buffer().data(), SIZE);
1439  // track if descriptor is shared or not
1440  Local::insertDescriptor(meta->auxData(), mAttributeSet->descriptorPtr());
1441  }
1442  else if (pass == 1) {
1443  // pass 1 - descriptor and attribute metadata
1444  bool matchingDescriptor = Local::hasMatchingDescriptor(meta->auxData());
1445  if (matchingDescriptor) {
1446  AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1447  if (descriptor) {
1448  // write a header to indicate a shared descriptor
1449  uint8_t header(1);
1450  os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1451  mAttributeSet->writeDescriptor(os, /*transient=*/false);
1452  }
1453  }
1454  else {
1455  // write a header to indicate a non-shared descriptor
1456  uint8_t header(0);
1457  os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1458  mAttributeSet->writeDescriptor(os, /*transient=*/false);
1459  }
1460  mAttributeSet->writeMetadata(os, /*transient=*/false, /*paged=*/true);
1461  }
1462  else if (pass < attributes + 2) {
1463  // pass 2...n+2 - attribute buffer sizes
1464  const Index attributeIndex = pass - 2;
1465  // destroy previous paged stream
1466  if (pass > 2) {
1467  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1468  }
1469  const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1470  mAttributeSet->getConst(attributeIndex) : nullptr;
1471  if (array) {
1472  compression::PagedOutputStream& pagedStream =
1473  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1474  pagedStream.setOutputStream(os);
1475  pagedStream.setSizeOnly(true);
1476  array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1477  }
1478  }
1479  else if (pass == attributes + 2) {
1480  const Index attributeIndex = pass - 3;
1481  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1482  // pass n+2 - voxel data
1483  BaseLeaf::writeBuffers(os, toHalf);
1484  }
1485  else if (pass < (attributes*2 + 3)) {
1486  // pass n+3...2n+3 - attribute buffers
1487  const Index attributeIndex = pass - attributes - 3;
1488  // destroy previous paged stream
1489  if (pass > attributes + 2) {
1490  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1491  }
1492  const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1493  mAttributeSet->getConst(attributeIndex) : nullptr;
1494  if (array) {
1495  compression::PagedOutputStream& pagedStream =
1496  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1497  pagedStream.setOutputStream(os);
1498  pagedStream.setSizeOnly(false);
1499  array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1500  }
1501  }
1502  else if (pass < buffers()) {
1503  Local::clearMatchingDescriptor(meta->auxData());
1504  // pass 2n+3 - cleanup last paged stream
1505  const Index attributeIndex = pass - attributes - 4;
1506  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1507  }
1508 }
1509 
1510 template<typename T, Index Log2Dim>
1511 inline Index64
1513 {
1514  return BaseLeaf::memUsage() + mAttributeSet->memUsage();
1515 }
1516 
1517 template<typename T, Index Log2Dim>
1518 inline void
1520 {
1521  BaseLeaf::evalActiveBoundingBox(bbox, visitVoxels);
1522 }
1523 
1524 template<typename T, Index Log2Dim>
1525 inline CoordBBox
1527 {
1528  return BaseLeaf::getNodeBoundingBox();
1529 }
1530 
1531 template<typename T, Index Log2Dim>
1532 inline void
1533 PointDataLeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1534 {
1535  if (!this->allocate()) return;
1536 
1537  this->assertNonModifiableUnlessZero(value);
1538 
1539  // active state is permitted to be updated
1540 
1541  for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1542  const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1543  for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1544  const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1545  for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1546  const Index offset = offsetXY + (z & (DIM-1u));
1547  this->setValueMask(offset, active);
1548  }
1549  }
1550  }
1551 }
1552 
1553 template<typename T, Index Log2Dim>
1554 inline void
1556 {
1557  this->assertNonModifiableUnlessZero(value);
1558 
1559  // active state is permitted to be updated
1560 
1561  if (active) this->setValuesOn();
1562  else this->setValuesOff();
1563 }
1564 
1565 
1567 
1568 
1569 template <typename PointDataTreeT>
1570 inline AttributeSet::Descriptor::Ptr
1571 makeDescriptorUnique(PointDataTreeT& tree)
1572 {
1573  auto leafIter = tree.beginLeaf();
1574  if (!leafIter) return nullptr;
1575 
1576  const AttributeSet::Descriptor& descriptor = leafIter->attributeSet().descriptor();
1577  auto newDescriptor = std::make_shared<AttributeSet::Descriptor>(descriptor);
1578  for (; leafIter; ++leafIter) {
1579  leafIter->resetDescriptor(newDescriptor);
1580  }
1581 
1582  return newDescriptor;
1583 }
1584 
1585 
1586 template <typename PointDataTreeT>
1587 inline void
1588 setStreamingMode(PointDataTreeT& tree, bool on)
1589 {
1590  auto leafIter = tree.beginLeaf();
1591  for (; leafIter; ++leafIter) {
1592  for (size_t i = 0; i < leafIter->attributeSet().size(); i++) {
1593  leafIter->attributeArray(i).setStreaming(on);
1594  }
1595  }
1596 }
1597 
1598 
1599 template <typename PointDataTreeT>
1600 inline void
1601 prefetch(PointDataTreeT& tree, bool position, bool otherAttributes)
1602 {
1603  // NOTE: the following is intentionally not multi-threaded, as the I/O
1604  // is faster if done in the order in which it is stored in the file
1605 
1606  auto leaf = tree.cbeginLeaf();
1607  if (!leaf) return;
1608 
1609  const auto& attributeSet = leaf->attributeSet();
1610 
1611  // pre-fetch leaf data
1612 
1613  for ( ; leaf; ++leaf) {
1614  leaf->buffer().data();
1615  }
1616 
1617  // pre-fetch position attribute data (position will typically have index 0)
1618 
1619  size_t positionIndex = attributeSet.find("P");
1620 
1621  if (position && positionIndex != AttributeSet::INVALID_POS) {
1622  for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1623  assert(leaf->hasAttribute(positionIndex));
1624  leaf->constAttributeArray(positionIndex).loadData();
1625  }
1626  }
1627 
1628  // pre-fetch other attribute data
1629 
1630  if (otherAttributes) {
1631  const size_t attributes = attributeSet.size();
1632  for (size_t attributeIndex = 0; attributeIndex < attributes; attributeIndex++) {
1633  if (attributeIndex == positionIndex) continue;
1634  for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1635  assert(leaf->hasAttribute(attributeIndex));
1636  leaf->constAttributeArray(attributeIndex).loadData();
1637  }
1638  }
1639  }
1640 }
1641 
1642 
1643 namespace internal {
1644 
1648 void initialize();
1649 
1654 
1655 
1660 template<typename HeadT, int HeadLevel>
1662 {
1663  using SubtreeT = typename PointDataNodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
1665  using Type = typename SubtreeT::template Append<RootNodeT>;
1666 };
1667 
1668 // Specialization for internal nodes which require their embedded child type to
1669 // be switched
1670 template <typename ChildT, Index Log2Dim, int HeadLevel>
1671 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, HeadLevel>
1672 {
1673  using SubtreeT = typename PointDataNodeChain<ChildT, HeadLevel-1>::Type;
1675  using Type = typename SubtreeT::template Append<InternalNodeT>;
1676 };
1677 
1678 // Specialization for the last internal node of a node chain, expected
1679 // to be templated on a leaf node
1680 template <typename ChildT, Index Log2Dim>
1681 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, /*HeadLevel=*/1>
1682 {
1686 };
1687 
1688 } // namespace internal
1689 
1690 
1694 template <typename TreeType>
1696  using RootNodeT = typename TreeType::RootNodeType;
1699 };
1700 
1701 
1702 } // namespace points
1703 
1704 
1706 
1707 
1708 namespace tree
1709 {
1710 
1713 template<Index Dim1, typename T2>
1714 struct SameLeafConfig<Dim1, points::PointDataLeafNode<T2, Dim1>> { static const bool value = true; };
1715 
1716 } // namespace tree
1717 } // namespace OPENVDB_VERSION_NAME
1718 } // namespace openvdb
1719 
1720 #endif // OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
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:93
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:92
#define VMASK_
Definition: PointDataGrid.h:694
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:577
Definition: openvdb/Exceptions.h:57
Definition: openvdb/Exceptions.h:58
Definition: openvdb/Exceptions.h:60
Base class for storing metadata information in a grid.
Definition: Metadata.h:24
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
Definition: openvdb/Exceptions.h:65
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:209
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only reading size data.
Definition: StreamCompression.h:218
void setInputStream(std::istream &is)
Definition: StreamCompression.h:223
std::shared_ptr< PagedInputStream > Ptr
Definition: StreamCompression.h:211
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:246
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only writing size data.
Definition: StreamCompression.h:255
void setOutputStream(std::ostream &os)
Definition: StreamCompression.h:260
std::shared_ptr< PagedOutputStream > Ptr
Definition: StreamCompression.h:248
void flush()
Manually flushes the current page to disk if non-zero.
Container for metadata describing how to unserialize grids from and/or serialize grids to a stream (w...
Definition: io.h:31
SharedPtr< StreamMetadata > Ptr
Definition: io.h:33
std::map< std::string, boost::any > AuxDataMap
Definition: io.h:92
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
const Coord & max() const
Definition: Coord.h:322
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:319
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:93
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:125
virtual Index size() const =0
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
virtual void writePagedBuffers(compression::PagedOutputStream &, bool outputTransient) const =0
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:39
std::unique_ptr< AttributeSet > UniquePtr
Definition: AttributeSet.h:45
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets.
Definition: AttributeSet.h:102
std::shared_ptr< Descriptor > DescriptorPtr
Definition: AttributeSet.h:49
Index filtering on group membership.
Definition: AttributeGroup.h:135
static index::State state()
Definition: AttributeGroup.h:145
Definition: AttributeGroup.h:73
Definition: AttributeGroup.h:102
A forward iterator over array indices with filtering IteratorT can be either IndexIter or ValueIndexI...
Definition: IndexIterator.h:140
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
Definition: PointDataGrid.h:233
ChildOnCIter cbeginChildOn() const
Definition: PointDataGrid.h:715
void setValueOn(Index offset)
Definition: PointDataGrid.h:536
void setValueOff(const Coord &, const ValueType &)
Definition: PointDataGrid.h:532
ChildOnCIter beginChildOn() const
Definition: PointDataGrid.h:716
ChildOnIter beginChildOn()
Definition: PointDataGrid.h:717
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &parent)
Definition: PointDataGrid.h:574
IndexIter< ValueOnCIter, FilterT > beginIndexOn(const FilterT &filter) const
Definition: PointDataGrid.h:677
ValueOnIter endValueOn()
Definition: PointDataGrid.h:707
const PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:475
PointDataLeafNode(const tools::PointIndexLeafNode< OtherValueType, Log2Dim > &other)
Definition: PointDataGrid.h:290
ValueOffCIter cbeginValueOff() const
Definition: PointDataGrid.h:698
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:478
typename BaseLeaf::template ChildIter< MaskOnIterator, PointDataLeafNode, ChildOn > ChildOnIter
Definition: PointDataGrid.h:633
PointDataLeafNode(const PointDataLeafNode &other, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:280
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:457
bool operator==(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:439
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:433
ChildOnIter endChildOn()
Definition: PointDataGrid.h:727
ValueAllIter endValueAll()
Definition: PointDataGrid.h:713
void modifyValue(Index, const ModifyOp &)
Definition: PointDataGrid.h:547
void setValueOn(Index, const ValueType &)
Definition: PointDataGrid.h:539
void setValuesOff()
Definition: PointDataGrid.h:544
ValueAllCIter endValueAll() const
Definition: PointDataGrid.h:712
ChildOffCIter endChildOff() const
Definition: PointDataGrid.h:729
void setValueOff(Index, const ValueType &)
Definition: PointDataGrid.h:533
PointDataLeafNode(PartialCreate, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:308
ValueAllCIter cbeginValueAll() const
Definition: PointDataGrid.h:701
typename BaseLeaf::ChildOff ChildOff
Definition: PointDataGrid.h:599
void setValueOnly(Index, const ValueType &)
Definition: PointDataGrid.h:527
std::shared_ptr< PointDataLeafNode > Ptr
Definition: PointDataGrid.h:237
IndexAllIter beginIndexAll() const
Leaf index iterator.
Definition: PointDataGrid.h:651
PointDataLeafNode * probeLeaf(const Coord &)
Definition: PointDataGrid.h:464
ValueOnCIter beginValueOn() const
Definition: PointDataGrid.h:696
typename BaseLeaf::ChildOn ChildOn
Definition: PointDataGrid.h:598
void signedFloodFill(const ValueType &, const ValueType &)
Definition: PointDataGrid.h:583
PointDataLeafNode(const PointDataLeafNode &other)
Construct using deep copy of other PointDataLeafNode.
Definition: PointDataGrid.h:268
void modifyValueAndActiveState(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:553
typename BaseLeaf::template ValueIter< MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll > ValueAllIter
Definition: PointDataGrid.h:629
typename BaseLeaf::ChildAll ChildAll
Definition: PointDataGrid.h:600
typename BaseLeaf::template ValueIter< MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff > ValueOffIter
Definition: PointDataGrid.h:625
const PointDataLeafNode * probeLeaf(const Coord &) const
Definition: PointDataGrid.h:476
ValueOnCIter cendValueOn() const
Definition: PointDataGrid.h:705
ValueOffCIter beginValueOff() const
Definition: PointDataGrid.h:699
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:857
IndexOffIter beginIndexOff() const
Definition: PointDataGrid.h:661
ChildAllCIter cbeginChildAll() const
Definition: PointDataGrid.h:721
ChildOffIter endChildOff()
Definition: PointDataGrid.h:730
void modifyValueAndActiveStateAndCache(const Coord &, const ModifyOp &, AccessorT &)
Definition: PointDataGrid.h:566
void setValueOnly(const Coord &, const ValueType &)
Definition: PointDataGrid.h:526
ChildAllIter beginChildAll()
Definition: PointDataGrid.h:723
IndexIter< ValueOffCIter, FilterT > beginIndexOff(const FilterT &filter) const
Definition: PointDataGrid.h:682
void setActiveState(const Coord &xyz, bool on)
Definition: PointDataGrid.h:523
ValueOnIter beginValueOn()
Definition: PointDataGrid.h:697
typename BaseLeaf::template ChildIter< MaskOffIterator, const PointDataLeafNode, ChildOff > ChildOffCIter
Definition: PointDataGrid.h:639
void assertNonModifiableUnlessZero(const ValueType &value)
Definition: PointDataGrid.h:519
ChildOffCIter cbeginChildOff() const
Definition: PointDataGrid.h:718
ChildOffIter beginChildOff()
Definition: PointDataGrid.h:720
ChildOffCIter beginChildOff() const
Definition: PointDataGrid.h:719
void setValueOff(const Coord &xyz)
Definition: PointDataGrid.h:529
bool operator!=(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:444
ValueOffIter endValueOff()
Definition: PointDataGrid.h:710
void setValueOff(Index offset)
Definition: PointDataGrid.h:530
ChildAllCIter endChildAll() const
Definition: PointDataGrid.h:732
const AttributeSet & attributeSet() const
Retrieve the attribute set.
Definition: PointDataGrid.h:316
ValueOnCIter cbeginValueOn() const
Definition: PointDataGrid.h:695
typename BaseLeaf::template DenseIter< const PointDataLeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: PointDataGrid.h:643
void clip(const CoordBBox &, const ValueType &value)
Definition: PointDataGrid.h:556
ChildOnCIter endChildOn() const
Definition: PointDataGrid.h:726
void reorderAttributes(const Descriptor::Ptr &replacement)
Reorder attribute set.
Definition: PointDataGrid.h:818
typename BaseLeaf::template ValueIter< MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: PointDataGrid.h:623
ChildOnCIter cendChildOn() const
Definition: PointDataGrid.h:725
ChildAllCIter cendChildAll() const
Definition: PointDataGrid.h:731
IndexIter< IterT, FilterT > beginIndex(const FilterT &filter) const
PointDataLeafNode()
Default constructor.
Definition: PointDataGrid.h:262
void assertNonmodifiable()
Definition: PointDataGrid.h:512
void setValueOffAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:571
ChildAllIter endChildAll()
Definition: PointDataGrid.h:733
void resetBackground(const ValueType &, const ValueType &newBackground)
Definition: PointDataGrid.h:578
typename NodeMaskType::OffIterator MaskOffIterator
Definition: PointDataGrid.h:603
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &value, TopologyCopy)
Definition: PointDataGrid.h:297
void setValue(const Coord &, const ValueType &)
Definition: PointDataGrid.h:541
ValueAllCIter cendValueAll() const
Definition: PointDataGrid.h:711
void negate()
Definition: PointDataGrid.h:585
ChildAllCIter beginChildAll() const
Definition: PointDataGrid.h:722
typename BaseLeaf::ValueAll ValueAll
Definition: PointDataGrid.h:591
PointDataLeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:454
std::pair< ValueType, ValueType > ValueTypePair
Definition: PointDataGrid.h:240
void setValuesOn()
Definition: PointDataGrid.h:543
AttributeSet::Descriptor Descriptor
Definition: PointDataGrid.h:243
typename BaseLeaf::ValueOn ValueOn
Definition: PointDataGrid.h:589
ChildOffCIter cendChildOff() const
Definition: PointDataGrid.h:728
void addLeafAndCache(PointDataLeafNode *, AccessorT &)
Definition: PointDataGrid.h:448
void setValueOnlyAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:563
void fill(const ValueType &value)
Definition: PointDataGrid.h:559
typename NodeMaskType::OnIterator MaskOnIterator
Definition: PointDataGrid.h:602
typename BaseLeaf::template ChildIter< MaskOffIterator, PointDataLeafNode, ChildOff > ChildOffIter
Definition: PointDataGrid.h:637
void addLeaf(PointDataLeafNode *)
Definition: PointDataGrid.h:446
const PointDataLeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:473
void signedFloodFill(const ValueType &)
Definition: PointDataGrid.h:582
ValueOffIter beginValueOff()
Definition: PointDataGrid.h:700
void setValueOn(const Coord &xyz)
Definition: PointDataGrid.h:535
void setActiveState(Index offset, bool on)
Definition: PointDataGrid.h:524
typename BaseLeaf::template ValueIter< MaskOffIterator, const PointDataLeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: PointDataGrid.h:627
IndexOnIter beginIndexOn() const
Definition: PointDataGrid.h:656
typename BaseLeaf::ValueOff ValueOff
Definition: PointDataGrid.h:590
void modifyValue(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:550
ValueOffCIter cendValueOff() const
Definition: PointDataGrid.h:708
Index64 memUsage() const
Definition: PointDataGrid.h:1512
typename BaseLeaf::template ChildIter< MaskOnIterator, const PointDataLeafNode, ChildOn > ChildOnCIter
Definition: PointDataGrid.h:635
void fill(const CoordBBox &, const ValueType &, bool)
Definition: PointDataGrid.h:1533
ValueOffCIter endValueOff() const
Definition: PointDataGrid.h:709
typename BaseLeaf::template ValueIter< MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn > ValueOnIter
Definition: PointDataGrid.h:621
T ValueType
Definition: PointDataGrid.h:239
ValueOnCIter endValueOn() const
Definition: PointDataGrid.h:706
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: PointDataGrid.h:604
PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:466
ValueAllCIter beginValueAll() const
Definition: PointDataGrid.h:702
typename BaseLeaf::template DenseIter< PointDataLeafNode, ValueType, ChildAll > ChildAllIter
Definition: PointDataGrid.h:641
IndexIter< ValueAllCIter, FilterT > beginIndexAll(const FilterT &filter) const
Filtered leaf index iterator.
Definition: PointDataGrid.h:672
PointDataLeafNode(const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Construct using supplied origin, value and active status.
Definition: PointDataGrid.h:274
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &, const T &, TopologyCopy)
Definition: PointDataGrid.h:304
typename BaseLeaf::template ValueIter< MaskDenseIterator, const PointDataLeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: PointDataGrid.h:631
void setValueOn(const Coord &, const ValueType &)
Definition: PointDataGrid.h:538
ValueAllIter beginValueAll()
Definition: PointDataGrid.h:703
std::vector< ValueType > IndexArray
Definition: PointDataGrid.h:241
Typed class for storing attribute data.
Definition: AttributeArray.h:559
A forward iterator over array indices in a single voxel.
Definition: IndexIterator.h:65
Definition: InternalNode.h:34
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:38
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:121
Definition: RootNode.h:39
Definition: Tree.h:175
Definition: NodeMasks.h:271
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:308
Definition: NodeMasks.h:240
Definition: NodeMasks.h:209
OPENVDB_API void bloscCompress(char *compressedBuffer, size_t &compressedBytes, const size_t bufferBytes, const char *uncompressedBuffer, const size_t uncompressedBytes)
Compress into the supplied buffer.
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
OPENVDB_API void bloscDecompress(char *uncompressedBuffer, const size_t expectedBytes, const size_t bufferBytes, const char *compressedBuffer)
Decompress into the supplied buffer. Will throw if decompression fails or uncompressed buffer has ins...
OPENVDB_API SharedPtr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme,...
void readCompressedValues(std::istream &is, PointDataIndex32 *destBuf, Index destCount, const util::NodeMask< 3 > &, bool)
openvdb::io::readCompressedValues specialized on PointDataIndex32 arrays to ignore the value mask,...
Definition: PointDataGrid.h:46
void writeCompressedValues(std::ostream &os, PointDataIndex32 *srcBuf, Index srcCount, const util::NodeMask< 3 > &, const util::NodeMask< 3 > &, bool)
openvdb::io::writeCompressedValues specialized on PointDataIndex32 arrays to ignore the value mask,...
Definition: PointDataGrid.h:106
void writeCompressedValuesSize(std::ostream &os, const T *srcBuf, Index srcCount)
Definition: PointDataGrid.h:139
@ ALL
Definition: IndexIterator.h:43
@ NONE
Definition: IndexIterator.h:42
void initialize()
Global registration of point data-related types.
void uninitialize()
Global deregistration of point data-related types.
void setStreamingMode(PointDataTreeT &tree, bool on=true)
Toggle the streaming mode on all attributes in the tree to collapse the attributes after deconstructi...
Definition: PointDataGrid.h:1588
void prefetch(PointDataTreeT &tree, bool position=true, bool otherAttributes=true)
Sequentially pre-fetch all delayed-load voxel and attribute data from disk in order to accelerate sub...
Definition: PointDataGrid.h:1601
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:524
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:63
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:88
void appendAttribute(PointDataTreeT &tree, const Name &name, const NamePair &type, const Index strideOrTotalSize=1, const bool constantStride=true, const Metadata *defaultValue=nullptr, const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree (this method does not require a templated AttributeType)
Definition: PointAttribute.h:242
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:377
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition: PointAttribute.h:465
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1571
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
std::string Name
Definition: Name.h:17
Index32 Index
Definition: openvdb/Types.h:32
const char * typeNameAsString< Vec3f >()
Definition: openvdb/Types.h:395
int32_t Int32
Definition: openvdb/Types.h:34
uint64_t Index64
Definition: openvdb/Types.h:31
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
PointIndex< Index32, 1 > PointDataIndex32
Definition: openvdb/Types.h:159
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Integer wrapper, required to distinguish PointIndexGrid and PointDataGrid from Int32Grid and Int64Gri...
Definition: openvdb/Types.h:135
A list of types (not necessarily unique)
Definition: TypeList.h:366
Leaf nodes that require multi-pass I/O must inherit from this struct.
Definition: io.h:124
Similiar to ValueConverter, but allows for tree configuration conversion to a PointDataTree....
Definition: PointDataGrid.h:1695
typename TreeType::RootNodeType RootNodeT
Definition: PointDataGrid.h:1696
typename internal::PointDataNodeChain< RootNodeT, RootNodeT::LEVEL >::Type NodeChainT
Definition: PointDataGrid.h:1697
typename PointDataNodeChain< ChildT, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1673
typename SubtreeT::template Append< InternalNodeT > Type
Definition: PointDataGrid.h:1675
Recursive node chain which generates a openvdb::TypeList value converted types of nodes to PointDataG...
Definition: PointDataGrid.h:1662
typename PointDataNodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1663
typename SubtreeT::template Append< RootNodeT > Type
Definition: PointDataGrid.h:1665
Definition: PointIndexGrid.h:1355
Definition: TreeIterator.h:60
Definition: LeafNode.h:204
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:244
Definition: LeafNode.h:204
Definition: LeafNode.h:204
Definition: LeafNode.h:203
Definition: LeafNode.h:203
Definition: LeafNode.h:203
Definition: LeafNode.h:912
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153