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