OpenVDB  6.1.0
PointDataGrid.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 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 
255 template <typename PointDataTreeT>
256 inline void
257 prefetch(PointDataTreeT& tree, bool position = true, bool otherAttributes = true);
258 
259 
261 
262 
263 template <typename T, Index Log2Dim>
264 class PointDataLeafNode : public tree::LeafNode<T, Log2Dim>, io::MultiPass {
265 
266 public:
268  using Ptr = std::shared_ptr<PointDataLeafNode>;
269 
270  using ValueType = T;
271  using ValueTypePair = std::pair<ValueType, ValueType>;
272  using IndexArray = std::vector<ValueType>;
273 
274  using Descriptor = AttributeSet::Descriptor;
275 
277 
278  // The following methods had to be copied from the LeafNode class
279  // to make the derived PointDataLeafNode class compatible with the tree structure.
280 
283 
284  using BaseLeaf::LOG2DIM;
285  using BaseLeaf::TOTAL;
286  using BaseLeaf::DIM;
287  using BaseLeaf::NUM_VALUES;
288  using BaseLeaf::NUM_VOXELS;
289  using BaseLeaf::SIZE;
290  using BaseLeaf::LEVEL;
291 
294  : mAttributeSet(new AttributeSet) { }
295 
296  ~PointDataLeafNode() = default;
297 
299  explicit PointDataLeafNode(const PointDataLeafNode& other)
300  : BaseLeaf(other)
301  , mAttributeSet(new AttributeSet(*other.mAttributeSet)) { }
302 
304  explicit
305  PointDataLeafNode(const Coord& coords, const T& value = zeroVal<T>(), bool active = false)
306  : BaseLeaf(coords, zeroVal<T>(), active)
307  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
308 
311  PointDataLeafNode(const PointDataLeafNode& other, const Coord& coords,
312  const T& value = zeroVal<T>(), bool active = false)
313  : BaseLeaf(coords, zeroVal<T>(), active)
314  , mAttributeSet(new AttributeSet(*other.mAttributeSet))
315  {
316  assertNonModifiableUnlessZero(value);
317  }
318 
319  // Copy-construct from a PointIndexLeafNode with the same configuration but a different ValueType.
320  template<typename OtherValueType>
322  : BaseLeaf(other)
323  , mAttributeSet(new AttributeSet) { }
324 
325  // Copy-construct from a LeafNode with the same configuration but a different ValueType.
326  // Used for topology copies - explicitly sets the value (background) to zeroVal
327  template <typename ValueType>
329  : BaseLeaf(other, zeroVal<T>(), TopologyCopy())
330  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
331 
332  // Copy-construct from a LeafNode with the same configuration but a different ValueType.
333  // Used for topology copies - explicitly sets the on and off value (background) to zeroVal
334  template <typename ValueType>
335  PointDataLeafNode(const tree::LeafNode<ValueType, Log2Dim>& other, const T& /*offValue*/, const T& /*onValue*/, TopologyCopy)
336  : BaseLeaf(other, zeroVal<T>(), zeroVal<T>(), TopologyCopy())
337  , mAttributeSet(new AttributeSet) { }
338 
339 #if OPENVDB_ABI_VERSION_NUMBER >= 3
340  PointDataLeafNode(PartialCreate, const Coord& coords,
341  const T& value = zeroVal<T>(), bool active = false)
342  : BaseLeaf(PartialCreate(), coords, value, active)
343  , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
344 #endif
345 
346 public:
347 
349  const AttributeSet& attributeSet() const { return *mAttributeSet; }
350 
352  void initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength);
354  void clearAttributes(const bool updateValueMask = true);
355 
358  bool hasAttribute(const size_t pos) const;
361  bool hasAttribute(const Name& attributeName) const;
362 
369  AttributeArray::Ptr appendAttribute(const Descriptor& expected, Descriptor::Ptr& replacement,
370  const size_t pos, const Index strideOrTotalSize = 1,
371  const bool constantStride = true);
372 
377  void dropAttributes(const std::vector<size_t>& pos,
378  const Descriptor& expected, Descriptor::Ptr& replacement);
381  void reorderAttributes(const Descriptor::Ptr& replacement);
385  void renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement);
387  void compactAttributes();
388 
394  void replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors = false);
395 
398  void resetDescriptor(const Descriptor::Ptr& replacement);
399 
403  void setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask = true);
404 
407  void validateOffsets() const;
408 
414  AttributeArray& attributeArray(const size_t pos);
415  const AttributeArray& attributeArray(const size_t pos) const;
416  const AttributeArray& constAttributeArray(const size_t pos) const;
423  AttributeArray& attributeArray(const Name& attributeName);
424  const AttributeArray& attributeArray(const Name& attributeName) const;
425  const AttributeArray& constAttributeArray(const Name& attributeName) const;
427 
429  GroupHandle groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const;
431  GroupHandle groupHandle(const Name& group) const;
433  GroupWriteHandle groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index);
435  GroupWriteHandle groupWriteHandle(const Name& name);
436 
438  Index64 pointCount() const;
440  Index64 onPointCount() const;
442  Index64 offPointCount() const;
444  Index64 groupPointCount(const Name& groupName) const;
445 
447  void updateValueMask();
448 
450 
451  void setOffsetOn(Index offset, const ValueType& val);
452  void setOffsetOnly(Index offset, const ValueType& val);
453 
456  template<typename OtherType, Index OtherLog2Dim>
458  return BaseLeaf::hasSameTopology(other);
459  }
460 
463  bool operator==(const PointDataLeafNode& other) const {
464  if(BaseLeaf::operator==(other) != true) return false;
465  return (*this->mAttributeSet == *other.mAttributeSet);
466  }
467 
468  bool operator!=(const PointDataLeafNode& other) const { return !(other == *this); }
469 
471  template<typename AccessorT>
472  void addLeafAndCache(PointDataLeafNode*, AccessorT&) {}
473 
475  PointDataLeafNode* touchLeaf(const Coord&) { return this; }
477  template<typename AccessorT>
478  PointDataLeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
479 
480  template<typename NodeT, typename AccessorT>
481  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
482  {
484  if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
485  return reinterpret_cast<NodeT*>(this);
487  }
488  PointDataLeafNode* probeLeaf(const Coord&) { return this; }
489  template<typename AccessorT>
490  PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
492 
494  const PointDataLeafNode* probeConstLeaf(const Coord&) const { return this; }
496  template<typename AccessorT>
497  const PointDataLeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
498  template<typename AccessorT>
499  const PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
500  const PointDataLeafNode* probeLeaf(const Coord&) const { return this; }
501  template<typename NodeT, typename AccessorT>
502  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
503  {
505  if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
506  return reinterpret_cast<const NodeT*>(this);
508  }
510 
511  // I/O methods
512 
513  void readTopology(std::istream& is, bool fromHalf = false);
514  void writeTopology(std::ostream& os, bool toHalf = false) const;
515 
516  Index buffers() const;
517 
518  void readBuffers(std::istream& is, bool fromHalf = false);
519  void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
520  void writeBuffers(std::ostream& os, bool toHalf = false) const;
521 
522 
523  Index64 memUsage() const;
524 
525  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
526 
529  CoordBBox getNodeBoundingBox() const;
530 
532 
533  // Disable all write methods to avoid unintentional changes
534  // to the point-array offsets.
535 
537  assert(false && "Cannot modify voxel values in a PointDataTree.");
538  }
539 
540  // some methods silently ignore attempts to modify the
541  // point-array offsets if a zero value is used
542 
544  if (value != zeroVal<T>()) this->assertNonmodifiable();
545  }
546 
547  void setActiveState(const Coord& xyz, bool on) { BaseLeaf::setActiveState(xyz, on); }
548  void setActiveState(Index offset, bool on) { BaseLeaf::setActiveState(offset, on); }
549 
550  void setValueOnly(const Coord&, const ValueType&) { assertNonmodifiable(); }
551  void setValueOnly(Index, const ValueType&) { assertNonmodifiable(); }
552 
553  void setValueOff(const Coord& xyz) { BaseLeaf::setValueOff(xyz); }
554  void setValueOff(Index offset) { BaseLeaf::setValueOff(offset); }
555 
556  void setValueOff(const Coord&, const ValueType&) { assertNonmodifiable(); }
557  void setValueOff(Index, const ValueType&) { assertNonmodifiable(); }
558 
559  void setValueOn(const Coord& xyz) { BaseLeaf::setValueOn(xyz); }
560  void setValueOn(Index offset) { BaseLeaf::setValueOn(offset); }
561 
562  void setValueOn(const Coord&, const ValueType&) { assertNonmodifiable(); }
563  void setValueOn(Index, const ValueType&) { assertNonmodifiable(); }
564 
565  void setValue(const Coord&, const ValueType&) { assertNonmodifiable(); }
566 
567  void setValuesOn() { BaseLeaf::setValuesOn(); }
568  void setValuesOff() { BaseLeaf::setValuesOff(); }
569 
570  template<typename ModifyOp>
571  void modifyValue(Index, const ModifyOp&) { assertNonmodifiable(); }
572 
573  template<typename ModifyOp>
574  void modifyValue(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
575 
576  template<typename ModifyOp>
577  void modifyValueAndActiveState(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
578 
579  // clipping is not yet supported
580  void clip(const CoordBBox&, const ValueType& value) { assertNonModifiableUnlessZero(value); }
581 
582  void fill(const CoordBBox&, const ValueType&, bool);
583  void fill(const ValueType& value) { assertNonModifiableUnlessZero(value); }
584  void fill(const ValueType&, bool);
585 
586  template<typename AccessorT>
587  void setValueOnlyAndCache(const Coord&, const ValueType&, AccessorT&) {assertNonmodifiable();}
588 
589  template<typename ModifyOp, typename AccessorT>
590  void modifyValueAndActiveStateAndCache(const Coord&, const ModifyOp&, AccessorT&) {
591  assertNonmodifiable();
592  }
593 
594  template<typename AccessorT>
595  void setValueOffAndCache(const Coord&, const ValueType&, AccessorT&) { assertNonmodifiable(); }
596 
597  template<typename AccessorT>
598  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& parent) {
599  BaseLeaf::setActiveStateAndCache(xyz, on, parent);
600  }
601 
602  void resetBackground(const ValueType&, const ValueType& newBackground) {
603  assertNonModifiableUnlessZero(newBackground);
604  }
605 
606  void signedFloodFill(const ValueType&) { assertNonmodifiable(); }
607  void signedFloodFill(const ValueType&, const ValueType&) { assertNonmodifiable(); }
608 
609  void negate() { assertNonmodifiable(); }
610 
611  friend class ::TestPointDataLeaf;
612 
613  using ValueOn = typename BaseLeaf::ValueOn;
614  using ValueOff = typename BaseLeaf::ValueOff;
615  using ValueAll = typename BaseLeaf::ValueAll;
616 
617 private:
618  std::unique_ptr<AttributeSet> mAttributeSet;
619  uint16_t mVoxelBufferSize = 0;
620 
621 protected:
622  using ChildOn = typename BaseLeaf::ChildOn;
623  using ChildOff = typename BaseLeaf::ChildOff;
624  using ChildAll = typename BaseLeaf::ChildAll;
625 
629 
630  // During topology-only construction, access is needed
631  // to protected/private members of other template instances.
632  template<typename, Index> friend class PointDataLeafNode;
633 
637 
638 public:
640  ValueVoxelCIter beginValueVoxel(const Coord& ijk) const;
641 
642 public:
643 
644 #if defined(_MSC_VER) && (_MSC_VER < 1914)
645  using ValueOnIter = typename BaseLeaf::ValueIter<
647  using ValueOnCIter = typename BaseLeaf::ValueIter<
648  MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn>;
649  using ValueOffIter = typename BaseLeaf::ValueIter<
650  MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff>;
651  using ValueOffCIter = typename BaseLeaf::ValueIter<
652  MaskOffIterator,const PointDataLeafNode,const ValueType,ValueOff>;
653  using ValueAllIter = typename BaseLeaf::ValueIter<
654  MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll>;
655  using ValueAllCIter = typename BaseLeaf::ValueIter<
656  MaskDenseIterator,const PointDataLeafNode,const ValueType,ValueAll>;
657  using ChildOnIter = typename BaseLeaf::ChildIter<
658  MaskOnIterator, PointDataLeafNode, ChildOn>;
659  using ChildOnCIter = typename BaseLeaf::ChildIter<
660  MaskOnIterator, const PointDataLeafNode, ChildOn>;
661  using ChildOffIter = typename BaseLeaf::ChildIter<
662  MaskOffIterator, PointDataLeafNode, ChildOff>;
663  using ChildOffCIter = typename BaseLeaf::ChildIter<
664  MaskOffIterator, const PointDataLeafNode, ChildOff>;
665  using ChildAllIter = typename BaseLeaf::DenseIter<
666  PointDataLeafNode, ValueType, ChildAll>;
667  using ChildAllCIter = typename BaseLeaf::DenseIter<
668  const PointDataLeafNode, const ValueType, ChildAll>;
669 #else
670  using ValueOnIter = typename BaseLeaf::template ValueIter<
671  MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn>;
672  using ValueOnCIter = typename BaseLeaf::template ValueIter<
673  MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn>;
674  using ValueOffIter = typename BaseLeaf::template ValueIter<
675  MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff>;
676  using ValueOffCIter = typename BaseLeaf::template ValueIter<
677  MaskOffIterator,const PointDataLeafNode,const ValueType,ValueOff>;
678  using ValueAllIter = typename BaseLeaf::template ValueIter<
679  MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll>;
680  using ValueAllCIter = typename BaseLeaf::template ValueIter<
681  MaskDenseIterator,const PointDataLeafNode,const ValueType,ValueAll>;
682  using ChildOnIter = typename BaseLeaf::template ChildIter<
683  MaskOnIterator, PointDataLeafNode, ChildOn>;
684  using ChildOnCIter = typename BaseLeaf::template ChildIter<
685  MaskOnIterator, const PointDataLeafNode, ChildOn>;
686  using ChildOffIter = typename BaseLeaf::template ChildIter<
687  MaskOffIterator, PointDataLeafNode, ChildOff>;
688  using ChildOffCIter = typename BaseLeaf::template ChildIter<
689  MaskOffIterator, const PointDataLeafNode, ChildOff>;
690  using ChildAllIter = typename BaseLeaf::template DenseIter<
691  PointDataLeafNode, ValueType, ChildAll>;
692  using ChildAllCIter = typename BaseLeaf::template DenseIter<
693  const PointDataLeafNode, const ValueType, ChildAll>;
694 #endif
695 
700 
703  {
704  NullFilter filter;
705  return this->beginIndex<ValueAllCIter, NullFilter>(filter);
706  }
708  {
709  NullFilter filter;
710  return this->beginIndex<ValueOnCIter, NullFilter>(filter);
711  }
713  {
714  NullFilter filter;
715  return this->beginIndex<ValueOffCIter, NullFilter>(filter);
716  }
717 
718  template<typename IterT, typename FilterT>
719  IndexIter<IterT, FilterT> beginIndex(const FilterT& filter) const;
720 
722  template<typename FilterT>
724  {
725  return this->beginIndex<ValueAllCIter, FilterT>(filter);
726  }
727  template<typename FilterT>
728  IndexIter<ValueOnCIter, FilterT> beginIndexOn(const FilterT& filter) const
729  {
730  return this->beginIndex<ValueOnCIter, FilterT>(filter);
731  }
732  template<typename FilterT>
734  {
735  return this->beginIndex<ValueOffCIter, FilterT>(filter);
736  }
737 
739  IndexVoxelIter beginIndexVoxel(const Coord& ijk) const;
740 
742  template<typename FilterT>
743  IndexIter<ValueVoxelCIter, FilterT> beginIndexVoxel(const Coord& ijk, const FilterT& filter) const;
744 
745 #define VMASK_ this->getValueMask()
746  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
747  ValueOnCIter beginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
748  ValueOnIter beginValueOn() { return ValueOnIter(VMASK_.beginOn(), this); }
749  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
750  ValueOffCIter beginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
751  ValueOffIter beginValueOff() { return ValueOffIter(VMASK_.beginOff(), this); }
752  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
753  ValueAllCIter beginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
754  ValueAllIter beginValueAll() { return ValueAllIter(VMASK_.beginDense(), this); }
755 
756  ValueOnCIter cendValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
757  ValueOnCIter endValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
758  ValueOnIter endValueOn() { return ValueOnIter(VMASK_.endOn(), this); }
759  ValueOffCIter cendValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
760  ValueOffCIter endValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
761  ValueOffIter endValueOff() { return ValueOffIter(VMASK_.endOff(), this); }
762  ValueAllCIter cendValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
763  ValueAllCIter endValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
764  ValueAllIter endValueAll() { return ValueAllIter(VMASK_.endDense(), this); }
765 
766  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
767  ChildOnCIter beginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
768  ChildOnIter beginChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
769  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
770  ChildOffCIter beginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
771  ChildOffIter beginChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
772  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
773  ChildAllCIter beginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
774  ChildAllIter beginChildAll() { return ChildAllIter(VMASK_.beginDense(), this); }
775 
776  ChildOnCIter cendChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
777  ChildOnCIter endChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
778  ChildOnIter endChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
779  ChildOffCIter cendChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
780  ChildOffCIter endChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
781  ChildOffIter endChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
782  ChildAllCIter cendChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
783  ChildAllCIter endChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
784  ChildAllIter endChildAll() { return ChildAllIter(VMASK_.endDense(), this); }
785 #undef VMASK_
786 }; // struct PointDataLeafNode
787 
789 
790 // PointDataLeafNode implementation
791 
792 template<typename T, Index Log2Dim>
793 inline void
794 PointDataLeafNode<T, Log2Dim>::initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength)
795 {
796  if (descriptor->size() != 1 ||
797  descriptor->find("P") == AttributeSet::INVALID_POS ||
798  descriptor->valueType(0) != typeNameAsString<Vec3f>())
799  {
800  OPENVDB_THROW(IndexError, "Initializing attributes only allowed with one Vec3f position attribute.");
801  }
802 
803  mAttributeSet.reset(new AttributeSet(descriptor, arrayLength));
804 }
805 
806 template<typename T, Index Log2Dim>
807 inline void
809 {
810  mAttributeSet.reset(new AttributeSet(*mAttributeSet, 0));
811 
812  // zero voxel values
813 
814  this->buffer().fill(ValueType(0));
815 
816  // if updateValueMask, also de-activate all voxels
817 
818  if (updateValueMask) this->setValuesOff();
819 }
820 
821 template<typename T, Index Log2Dim>
822 inline bool
824 {
825  return pos < mAttributeSet->size();
826 }
827 
828 template<typename T, Index Log2Dim>
829 inline bool
831 {
832  const size_t pos = mAttributeSet->find(attributeName);
833  return pos != AttributeSet::INVALID_POS;
834 }
835 
836 template<typename T, Index Log2Dim>
837 inline AttributeArray::Ptr
838 PointDataLeafNode<T, Log2Dim>::appendAttribute( const Descriptor& expected, Descriptor::Ptr& replacement,
839  const size_t pos, const Index strideOrTotalSize,
840  const bool constantStride)
841 {
842  return mAttributeSet->appendAttribute(expected, replacement, pos, strideOrTotalSize, constantStride);
843 }
844 
845 template<typename T, Index Log2Dim>
846 inline void
847 PointDataLeafNode<T, Log2Dim>::dropAttributes(const std::vector<size_t>& pos,
848  const Descriptor& expected, Descriptor::Ptr& replacement)
849 {
850  mAttributeSet->dropAttributes(pos, expected, replacement);
851 }
852 
853 template<typename T, Index Log2Dim>
854 inline void
855 PointDataLeafNode<T, Log2Dim>::reorderAttributes(const Descriptor::Ptr& replacement)
856 {
857  mAttributeSet->reorderAttributes(replacement);
858 }
859 
860 template<typename T, Index Log2Dim>
861 inline void
862 PointDataLeafNode<T, Log2Dim>::renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement)
863 {
864  mAttributeSet->renameAttributes(expected, replacement);
865 }
866 
867 template<typename T, Index Log2Dim>
868 inline void
870 {
871  for (size_t i = 0; i < mAttributeSet->size(); i++) {
872  AttributeArray* array = mAttributeSet->get(i);
873  array->compact();
874  }
875 }
876 
877 template<typename T, Index Log2Dim>
878 inline void
879 PointDataLeafNode<T, Log2Dim>::replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors)
880 {
881  if (!attributeSet) {
882  OPENVDB_THROW(ValueError, "Cannot replace with a null attribute set");
883  }
884 
885  if (!allowMismatchingDescriptors && mAttributeSet->descriptor() != attributeSet->descriptor()) {
886  OPENVDB_THROW(ValueError, "Attribute set descriptors are not equal.");
887  }
888 
889  mAttributeSet.reset(attributeSet);
890 }
891 
892 template<typename T, Index Log2Dim>
893 inline void
894 PointDataLeafNode<T, Log2Dim>::resetDescriptor(const Descriptor::Ptr& replacement)
895 {
896  mAttributeSet->resetDescriptor(replacement);
897 }
898 
899 template<typename T, Index Log2Dim>
900 inline void
901 PointDataLeafNode<T, Log2Dim>::setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask)
902 {
903  if (offsets.size() != LeafNodeType::NUM_VALUES) {
904  OPENVDB_THROW(ValueError, "Offset vector size doesn't match number of voxels.")
905  }
906 
907  for (Index index = 0; index < offsets.size(); ++index) {
908  setOffsetOnly(index, offsets[index]);
909  }
910 
911  if (updateValueMask) this->updateValueMask();
912 }
913 
914 template<typename T, Index Log2Dim>
915 inline void
917 {
918  // Ensure all of the offset values are monotonically increasing
919  for (Index index = 1; index < BaseLeaf::SIZE; ++index) {
920  if (this->getValue(index-1) > this->getValue(index)) {
921  OPENVDB_THROW(ValueError, "Voxel offset values are not monotonically increasing");
922  }
923  }
924 
925  // Ensure all attribute arrays are of equal length
926  for (size_t attributeIndex = 1; attributeIndex < mAttributeSet->size(); ++attributeIndex ) {
927  if (mAttributeSet->getConst(attributeIndex-1)->size() != mAttributeSet->getConst(attributeIndex)->size()) {
928  OPENVDB_THROW(ValueError, "Attribute arrays have inconsistent length");
929  }
930  }
931 
932  // Ensure the last voxel's offset value matches the size of each attribute array
933  if (mAttributeSet->size() > 0 && this->getValue(BaseLeaf::SIZE-1) != mAttributeSet->getConst(0)->size()) {
934  OPENVDB_THROW(ValueError, "Last voxel offset value does not match attribute array length");
935  }
936 }
937 
938 template<typename T, Index Log2Dim>
939 inline AttributeArray&
941 {
942  if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
943  return *mAttributeSet->get(pos);
944 }
945 
946 template<typename T, Index Log2Dim>
947 inline const AttributeArray&
949 {
950  if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
951  return *mAttributeSet->getConst(pos);
952 }
953 
954 template<typename T, Index Log2Dim>
955 inline const AttributeArray&
957 {
958  return this->attributeArray(pos);
959 }
960 
961 template<typename T, Index Log2Dim>
962 inline AttributeArray&
964 {
965  const size_t pos = mAttributeSet->find(attributeName);
966  if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
967  return *mAttributeSet->get(pos);
968 }
969 
970 template<typename T, Index Log2Dim>
971 inline const AttributeArray&
973 {
974  const size_t pos = mAttributeSet->find(attributeName);
975  if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
976  return *mAttributeSet->getConst(pos);
977 }
978 
979 template<typename T, Index Log2Dim>
980 inline const AttributeArray&
982 {
983  return this->attributeArray(attributeName);
984 }
985 
986 template<typename T, Index Log2Dim>
987 inline GroupHandle
988 PointDataLeafNode<T, Log2Dim>::groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const
989 {
990  const AttributeArray& array = this->attributeArray(index.first);
991  assert(isGroup(array));
992 
993  const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
994 
995  return GroupHandle(groupArray, index.second);
996 }
997 
998 template<typename T, Index Log2Dim>
999 inline GroupHandle
1001 {
1002  const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
1003  return this->groupHandle(index);
1004 }
1005 
1006 template<typename T, Index Log2Dim>
1007 inline GroupWriteHandle
1008 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index)
1009 {
1010  AttributeArray& array = this->attributeArray(index.first);
1011  assert(isGroup(array));
1012 
1013  GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
1014 
1015  return GroupWriteHandle(groupArray, index.second);
1016 }
1017 
1018 template<typename T, Index Log2Dim>
1019 inline GroupWriteHandle
1021 {
1022  const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
1023  return this->groupWriteHandle(index);
1024 }
1025 
1026 template<typename T, Index Log2Dim>
1027 template<typename ValueIterT, typename FilterT>
1029 PointDataLeafNode<T, Log2Dim>::beginIndex(const FilterT& filter) const
1030 {
1031  // generate no-op iterator if filter evaluates no indices
1032 
1033  if (filter.state() == index::NONE) {
1034  return IndexIter<ValueIterT, FilterT>(ValueIterT(), filter);
1035  }
1036 
1037  // copy filter to ensure thread-safety
1038 
1039  FilterT newFilter(filter);
1040  newFilter.reset(*this);
1041 
1042  using IterTraitsT = tree::IterTraits<LeafNodeType, ValueIterT>;
1043 
1044  // construct the value iterator and reset the filter to use this leaf
1045 
1046  ValueIterT valueIter = IterTraitsT::begin(*this);
1047 
1048  return IndexIter<ValueIterT, FilterT>(valueIter, newFilter);
1049 }
1050 
1051 template<typename T, Index Log2Dim>
1052 inline ValueVoxelCIter
1054 {
1055  const Index index = LeafNodeType::coordToOffset(ijk);
1056  assert(index < BaseLeaf::SIZE);
1057  const ValueType end = this->getValue(index);
1058  const ValueType start = (index == 0) ? ValueType(0) : this->getValue(index - 1);
1059  return ValueVoxelCIter(start, end);
1060 }
1061 
1062 template<typename T, Index Log2Dim>
1065 {
1066  ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1067  return IndexVoxelIter(iter, NullFilter());
1068 }
1069 
1070 template<typename T, Index Log2Dim>
1071 template<typename FilterT>
1073 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk, const FilterT& filter) const
1074 {
1075  ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1076  FilterT newFilter(filter);
1077  newFilter.reset(*this);
1078  return IndexIter<ValueVoxelCIter, FilterT>(iter, newFilter);
1079 }
1080 
1081 template<typename T, Index Log2Dim>
1082 inline Index64
1084 {
1085  return this->getLastValue();
1086 }
1087 
1088 template<typename T, Index Log2Dim>
1089 inline Index64
1091 {
1092  if (this->isEmpty()) return 0;
1093  else if (this->isDense()) return this->pointCount();
1094  return iterCount(this->beginIndexOn());
1095 }
1096 
1097 template<typename T, Index Log2Dim>
1098 inline Index64
1100 {
1101  if (this->isEmpty()) return this->pointCount();
1102  else if (this->isDense()) return 0;
1103  return iterCount(this->beginIndexOff());
1104 }
1105 
1106 template<typename T, Index Log2Dim>
1107 inline Index64
1109 {
1110  if (!this->attributeSet().descriptor().hasGroup(groupName)) {
1111  return Index64(0);
1112  }
1113  GroupFilter filter(groupName, this->attributeSet());
1114  if (filter.state() == index::ALL) {
1115  return this->pointCount();
1116  } else {
1117  return iterCount(this->beginIndexAll(filter));
1118  }
1119 }
1120 
1121 template<typename T, Index Log2Dim>
1122 inline void
1124 {
1125  ValueType start = 0, end = 0;
1126  for (Index n = 0; n < LeafNodeType::NUM_VALUES; n++) {
1127  end = this->getValue(n);
1128  this->setValueMask(n, (end - start) > 0);
1129  start = end;
1130  }
1131 }
1132 
1133 template<typename T, Index Log2Dim>
1134 inline void
1136 {
1137  this->buffer().setValue(offset, val);
1138  this->setValueMaskOn(offset);
1139 }
1140 
1141 template<typename T, Index Log2Dim>
1142 inline void
1144 {
1145  this->buffer().setValue(offset, val);
1146 }
1147 
1148 template<typename T, Index Log2Dim>
1149 inline void
1150 PointDataLeafNode<T, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1151 {
1152  BaseLeaf::readTopology(is, fromHalf);
1153 }
1154 
1155 template<typename T, Index Log2Dim>
1156 inline void
1157 PointDataLeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1158 {
1159  BaseLeaf::writeTopology(os, toHalf);
1160 }
1161 
1162 template<typename T, Index Log2Dim>
1163 inline Index
1165 {
1166  return Index( /*voxel buffer sizes*/ 1 +
1167  /*voxel buffers*/ 1 +
1168  /*attribute metadata*/ 1 +
1169  /*attribute uniform values*/ mAttributeSet->size() +
1170  /*attribute buffers*/ mAttributeSet->size() +
1171  /*cleanup*/ 1);
1172 }
1173 
1174 template<typename T, Index Log2Dim>
1175 inline void
1176 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1177 {
1178  this->readBuffers(is, CoordBBox::inf(), fromHalf);
1179 }
1180 
1181 template<typename T, Index Log2Dim>
1182 inline void
1183 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*bbox*/, bool fromHalf)
1184 {
1185  struct Local
1186  {
1187  static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1188  {
1189  // if paged stream exists, delete it
1190  std::string key("paged:" + std::to_string(index));
1191  auto it = auxData.find(key);
1192  if (it != auxData.end()) {
1193  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1194  }
1195  }
1196 
1197  static compression::PagedInputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1198  const Index index)
1199  {
1200  std::string key("paged:" + std::to_string(index));
1201  auto it = auxData.find(key);
1202  if (it != auxData.end()) {
1203  return *(boost::any_cast<compression::PagedInputStream::Ptr>(it->second));
1204  }
1205  else {
1206  compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
1207  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1208  return *pagedStream;
1209  }
1210  }
1211 
1212  static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1213  {
1214  std::string matchingKey("hasMatchingDescriptor");
1215  auto itMatching = auxData.find(matchingKey);
1216  return itMatching != auxData.end();
1217  }
1218 
1219  static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1220  {
1221  std::string matchingKey("hasMatchingDescriptor");
1222  std::string descriptorKey("descriptorPtr");
1223  auto itMatching = auxData.find(matchingKey);
1224  auto itDescriptor = auxData.find(descriptorKey);
1225  if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1226  if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1227  }
1228 
1229  static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1230  const Descriptor::Ptr descriptor)
1231  {
1232  std::string descriptorKey("descriptorPtr");
1233  std::string matchingKey("hasMatchingDescriptor");
1234  auto itMatching = auxData.find(matchingKey);
1235  if (itMatching == auxData.end()) {
1236  // if matching bool is not found, insert "true" and the descriptor
1237  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1238  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1239  }
1240  }
1241 
1242  static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1243  {
1244  std::string descriptorKey("descriptorPtr");
1245  auto itDescriptor = auxData.find(descriptorKey);
1246  assert(itDescriptor != auxData.end());
1247  const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1248  return descriptor;
1249  }
1250  };
1251 
1253 
1254  if (!meta) {
1255  OPENVDB_THROW(IoError, "Cannot read in a PointDataLeaf without StreamMetadata.");
1256  }
1257 
1258  const Index pass(static_cast<uint16_t>(meta->pass()));
1259  const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1260 
1261  const Index attributes = (maximumPass - 4) / 2;
1262 
1263  if (pass == 0) {
1264  // pass 0 - voxel data sizes
1265  is.read(reinterpret_cast<char*>(&mVoxelBufferSize), sizeof(uint16_t));
1266  Local::clearMatchingDescriptor(meta->auxData());
1267  }
1268  else if (pass == 1) {
1269  // pass 1 - descriptor and attribute metadata
1270  if (Local::hasMatchingDescriptor(meta->auxData())) {
1271  AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1272  mAttributeSet->resetDescriptor(descriptor, /*allowMismatchingDescriptors=*/true);
1273  }
1274  else {
1275  uint8_t header;
1276  is.read(reinterpret_cast<char*>(&header), sizeof(uint8_t));
1277  mAttributeSet->readDescriptor(is);
1278  if (header & uint8_t(1)) {
1279  AttributeSet::DescriptorPtr descriptor = mAttributeSet->descriptorPtr();
1280  Local::insertDescriptor(meta->auxData(), descriptor);
1281  }
1282  // a forwards-compatibility mechanism for future use,
1283  // if a 0x2 bit is set, read and skip over a specific number of bytes
1284  if (header & uint8_t(2)) {
1285  uint64_t bytesToSkip;
1286  is.read(reinterpret_cast<char*>(&bytesToSkip), sizeof(uint64_t));
1287  if (bytesToSkip > uint64_t(0)) {
1288  auto metadata = io::getStreamMetadataPtr(is);
1289  if (metadata && metadata->seekable()) {
1290  is.seekg(bytesToSkip, std::ios_base::cur);
1291  }
1292  else {
1293  std::vector<uint8_t> tempData(bytesToSkip);
1294  is.read(reinterpret_cast<char*>(&tempData[0]), bytesToSkip);
1295  }
1296  }
1297  }
1298  // this reader is only able to read headers with 0x1 and 0x2 bits set
1299  if (header > uint8_t(3)) {
1300  OPENVDB_THROW(IoError, "Unrecognised header flags in PointDataLeafNode");
1301  }
1302  }
1303  mAttributeSet->readMetadata(is);
1304  }
1305  else if (pass < (attributes + 2)) {
1306  // pass 2...n+2 - attribute uniform values
1307  const size_t attributeIndex = pass - 2;
1308  AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1309  mAttributeSet->get(attributeIndex) : nullptr;
1310  if (array) {
1311  compression::PagedInputStream& pagedStream =
1312  Local::getOrInsertPagedStream(meta->auxData(), static_cast<Index>(attributeIndex));
1313  pagedStream.setInputStream(is);
1314  pagedStream.setSizeOnly(true);
1315  array->readPagedBuffers(pagedStream);
1316  }
1317  }
1318  else if (pass == attributes + 2) {
1319  // pass n+2 - voxel data
1320 
1321  const Index passValue(meta->pass());
1322 
1323  // StreamMetadata pass variable used to temporarily store voxel buffer size
1324  io::StreamMetadata& nonConstMeta = const_cast<io::StreamMetadata&>(*meta);
1325  nonConstMeta.setPass(mVoxelBufferSize);
1326 
1327  // readBuffers() calls readCompressedValues specialization above
1328  BaseLeaf::readBuffers(is, fromHalf);
1329 
1330  // pass now reset to original value
1331  nonConstMeta.setPass(passValue);
1332  }
1333  else if (pass < (attributes*2 + 3)) {
1334  // pass n+2..2n+2 - attribute buffers
1335  const Index attributeIndex = pass - attributes - 3;
1336  AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1337  mAttributeSet->get(attributeIndex) : nullptr;
1338  if (array) {
1339  compression::PagedInputStream& pagedStream =
1340  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1341  pagedStream.setInputStream(is);
1342  pagedStream.setSizeOnly(false);
1343  array->readPagedBuffers(pagedStream);
1344  }
1345  // cleanup paged stream reference in auxiliary metadata
1346  if (pass > attributes + 3) {
1347  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1348  }
1349  }
1350  else if (pass < buffers()) {
1351  // pass 2n+3 - cleanup last paged stream
1352  const Index attributeIndex = pass - attributes - 4;
1353  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1354  }
1355 }
1356 
1357 template<typename T, Index Log2Dim>
1358 inline void
1359 PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1360 {
1361  struct Local
1362  {
1363  static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1364  {
1365  // if paged stream exists, flush and delete it
1366  std::string key("paged:" + std::to_string(index));
1367  auto it = auxData.find(key);
1368  if (it != auxData.end()) {
1369  compression::PagedOutputStream& stream = *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1370  stream.flush();
1371  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1372  }
1373  }
1374 
1375  static compression::PagedOutputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1376  const Index index)
1377  {
1378  std::string key("paged:" + std::to_string(index));
1379  auto it = auxData.find(key);
1380  if (it != auxData.end()) {
1381  return *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1382  }
1383  else {
1384  compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
1385  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1386  return *pagedStream;
1387  }
1388  }
1389 
1390  static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1391  const Descriptor::Ptr descriptor)
1392  {
1393  std::string descriptorKey("descriptorPtr");
1394  std::string matchingKey("hasMatchingDescriptor");
1395  auto itMatching = auxData.find(matchingKey);
1396  auto itDescriptor = auxData.find(descriptorKey);
1397  if (itMatching == auxData.end()) {
1398  // if matching bool is not found, insert "true" and the descriptor
1399  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1400  assert(itDescriptor == auxData.end());
1401  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1402  }
1403  else {
1404  // if matching bool is found and is false, early exit (a previous descriptor did not match)
1405  bool matching = boost::any_cast<bool>(itMatching->second);
1406  if (!matching) return;
1407  assert(itDescriptor != auxData.end());
1408  // if matching bool is true, check whether the existing descriptor matches the current one and set
1409  // matching bool to false if not
1410  const Descriptor::Ptr existingDescriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1411  if (*existingDescriptor != *descriptor) {
1412  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
1413  }
1414  }
1415  }
1416 
1417  static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1418  {
1419  std::string matchingKey("hasMatchingDescriptor");
1420  auto itMatching = auxData.find(matchingKey);
1421  // if matching key is not found, no matching descriptor
1422  if (itMatching == auxData.end()) return false;
1423  // if matching key is found and is false, no matching descriptor
1424  if (!boost::any_cast<bool>(itMatching->second)) return false;
1425  return true;
1426  }
1427 
1428  static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1429  {
1430  std::string descriptorKey("descriptorPtr");
1431  auto itDescriptor = auxData.find(descriptorKey);
1432  // if matching key is true, however descriptor is not found, it has already been retrieved
1433  if (itDescriptor == auxData.end()) return nullptr;
1434  // otherwise remove it and return it
1435  const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1436  (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1437  return descriptor;
1438  }
1439 
1440  static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1441  {
1442  std::string matchingKey("hasMatchingDescriptor");
1443  std::string descriptorKey("descriptorPtr");
1444  auto itMatching = auxData.find(matchingKey);
1445  auto itDescriptor = auxData.find(descriptorKey);
1446  if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1447  if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1448  }
1449  };
1450 
1452 
1453  if (!meta) {
1454  OPENVDB_THROW(IoError, "Cannot write out a PointDataLeaf without StreamMetadata.");
1455  }
1456 
1457  const Index pass(static_cast<uint16_t>(meta->pass()));
1458 
1459  // leaf traversal analysis deduces the number of passes to perform for this leaf
1460  // then updates the leaf traversal value to ensure all passes will be written
1461 
1462  if (meta->countingPasses()) {
1463  const Index requiredPasses = this->buffers();
1464  if (requiredPasses > pass) {
1465  meta->setPass(requiredPasses);
1466  }
1467  return;
1468  }
1469 
1470  const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1471  const Index attributes = (maximumPass - 4) / 2;
1472 
1473  if (pass == 0) {
1474  // pass 0 - voxel data sizes
1475  io::writeCompressedValuesSize(os, this->buffer().data(), SIZE);
1476  // track if descriptor is shared or not
1477  Local::insertDescriptor(meta->auxData(), mAttributeSet->descriptorPtr());
1478  }
1479  else if (pass == 1) {
1480  // pass 1 - descriptor and attribute metadata
1481  bool matchingDescriptor = Local::hasMatchingDescriptor(meta->auxData());
1482  if (matchingDescriptor) {
1483  AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1484  if (descriptor) {
1485  // write a header to indicate a shared descriptor
1486  uint8_t header(1);
1487  os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1488  mAttributeSet->writeDescriptor(os, /*transient=*/false);
1489  }
1490  }
1491  else {
1492  // write a header to indicate a non-shared descriptor
1493  uint8_t header(0);
1494  os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1495  mAttributeSet->writeDescriptor(os, /*transient=*/false);
1496  }
1497  mAttributeSet->writeMetadata(os, /*transient=*/false, /*paged=*/true);
1498  }
1499  else if (pass < attributes + 2) {
1500  // pass 2...n+2 - attribute buffer sizes
1501  const Index attributeIndex = pass - 2;
1502  // destroy previous paged stream
1503  if (pass > 2) {
1504  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1505  }
1506  const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1507  mAttributeSet->getConst(attributeIndex) : nullptr;
1508  if (array) {
1509  compression::PagedOutputStream& pagedStream =
1510  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1511  pagedStream.setOutputStream(os);
1512  pagedStream.setSizeOnly(true);
1513  array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1514  }
1515  }
1516  else if (pass == attributes + 2) {
1517  const Index attributeIndex = pass - 3;
1518  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1519  // pass n+2 - voxel data
1520  BaseLeaf::writeBuffers(os, toHalf);
1521  }
1522  else if (pass < (attributes*2 + 3)) {
1523  // pass n+3...2n+3 - attribute buffers
1524  const Index attributeIndex = pass - attributes - 3;
1525  // destroy previous paged stream
1526  if (pass > attributes + 2) {
1527  Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1528  }
1529  const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1530  mAttributeSet->getConst(attributeIndex) : nullptr;
1531  if (array) {
1532  compression::PagedOutputStream& pagedStream =
1533  Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1534  pagedStream.setOutputStream(os);
1535  pagedStream.setSizeOnly(false);
1536  array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1537  }
1538  }
1539  else if (pass < buffers()) {
1540  Local::clearMatchingDescriptor(meta->auxData());
1541  // pass 2n+3 - cleanup last paged stream
1542  const Index attributeIndex = pass - attributes - 4;
1543  Local::destroyPagedStream(meta->auxData(), attributeIndex);
1544  }
1545 }
1546 
1547 template<typename T, Index Log2Dim>
1548 inline Index64
1550 {
1551  return BaseLeaf::memUsage() + mAttributeSet->memUsage();
1552 }
1553 
1554 template<typename T, Index Log2Dim>
1555 inline void
1556 PointDataLeafNode<T, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1557 {
1558  BaseLeaf::evalActiveBoundingBox(bbox, visitVoxels);
1559 }
1560 
1561 template<typename T, Index Log2Dim>
1562 inline CoordBBox
1564 {
1565  return BaseLeaf::getNodeBoundingBox();
1566 }
1567 
1568 template<typename T, Index Log2Dim>
1569 inline void
1570 PointDataLeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1571 {
1572 #if OPENVDB_ABI_VERSION_NUMBER >= 3
1573  if (!this->allocate()) return;
1574 #endif
1575 
1576  this->assertNonModifiableUnlessZero(value);
1577 
1578  // active state is permitted to be updated
1579 
1580  for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1581  const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1582  for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1583  const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1584  for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1585  const Index offset = offsetXY + (z & (DIM-1u));
1586  this->setValueMask(offset, active);
1587  }
1588  }
1589  }
1590 }
1591 
1592 template<typename T, Index Log2Dim>
1593 inline void
1595 {
1596  this->assertNonModifiableUnlessZero(value);
1597 
1598  // active state is permitted to be updated
1599 
1600  if (active) this->setValuesOn();
1601  else this->setValuesOff();
1602 }
1603 
1604 
1606 
1607 
1608 template <typename PointDataTreeT>
1609 inline AttributeSet::Descriptor::Ptr
1610 makeDescriptorUnique(PointDataTreeT& tree)
1611 {
1612  auto leafIter = tree.beginLeaf();
1613  if (!leafIter) return nullptr;
1614 
1615  const AttributeSet::Descriptor& descriptor = leafIter->attributeSet().descriptor();
1616  auto newDescriptor = std::make_shared<AttributeSet::Descriptor>(descriptor);
1617  for (; leafIter; ++leafIter) {
1618  leafIter->resetDescriptor(newDescriptor);
1619  }
1620 
1621  return newDescriptor;
1622 }
1623 
1624 
1625 template <typename PointDataTreeT>
1626 inline void
1627 setStreamingMode(PointDataTreeT& tree, bool on)
1628 {
1629  auto leafIter = tree.beginLeaf();
1630  for (; leafIter; ++leafIter) {
1631  for (size_t i = 0; i < leafIter->attributeSet().size(); i++) {
1632  leafIter->attributeArray(i).setStreaming(on);
1633  }
1634  }
1635 }
1636 
1637 
1638 template <typename PointDataTreeT>
1639 inline void
1640 prefetch(PointDataTreeT& tree, bool position, bool otherAttributes)
1641 {
1642  // NOTE: the following is intentionally not multi-threaded, as the I/O
1643  // is faster if done in the order in which it is stored in the file
1644 
1645  auto leaf = tree.cbeginLeaf();
1646  if (!leaf) return;
1647 
1648  const auto& attributeSet = leaf->attributeSet();
1649 
1650  // pre-fetch leaf data
1651 
1652  for ( ; leaf; ++leaf) {
1653  leaf->buffer().data();
1654  }
1655 
1656  // pre-fetch position attribute data (position will typically have index 0)
1657 
1658  size_t positionIndex = attributeSet.find("P");
1659 
1660  if (position && positionIndex != AttributeSet::INVALID_POS) {
1661  for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1662  assert(leaf->hasAttribute(positionIndex));
1663  leaf->constAttributeArray(positionIndex).loadData();
1664  }
1665  }
1666 
1667  // pre-fetch other attribute data
1668 
1669  if (otherAttributes) {
1670  const size_t attributes = attributeSet.size();
1671  for (size_t attributeIndex = 0; attributeIndex < attributes; attributeIndex++) {
1672  if (attributeIndex == positionIndex) continue;
1673  for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1674  assert(leaf->hasAttribute(attributeIndex));
1675  leaf->constAttributeArray(attributeIndex).loadData();
1676  }
1677  }
1678  }
1679 }
1680 
1681 
1682 namespace internal {
1683 
1687 void initialize();
1688 
1692 void uninitialize();
1693 
1694 
1699 template<typename HeadT, int HeadLevel>
1701 {
1702  using SubtreeT = typename PointDataNodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
1704  using Type = typename boost::mpl::push_back<SubtreeT, RootNodeT>::type;
1705 };
1706 
1707 // Specialization for internal nodes which require their embedded child type to
1708 // be switched
1709 template <typename ChildT, Index Log2Dim, int HeadLevel>
1710 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, HeadLevel>
1711 {
1712  using SubtreeT = typename PointDataNodeChain<ChildT, HeadLevel-1>::Type;
1714  using Type = typename boost::mpl::push_back<SubtreeT, InternalNodeT>::type;
1715 };
1716 
1717 // Specialization for the last internal node of a node chain, expected
1718 // to be templated on a leaf node
1719 template <typename ChildT, Index Log2Dim>
1720 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, /*HeadLevel=*/1>
1721 {
1724  using Type = typename boost::mpl::vector<LeafNodeT, InternalNodeT>::type;
1725 };
1726 
1727 } // namespace internal
1728 
1729 
1733 template <typename TreeType>
1735  using RootNodeT = typename TreeType::RootNodeType;
1738 };
1739 
1740 
1741 } // namespace points
1742 
1743 
1745 
1746 
1747 namespace tree
1748 {
1749 
1752 template<Index Dim1, typename T2>
1753 struct SameLeafConfig<Dim1, points::PointDataLeafNode<T2, Dim1>> { static const bool value = true; };
1754 
1755 } // namespace tree
1756 } // namespace OPENVDB_VERSION_NAME
1757 } // namespace openvdb
1758 
1759 #endif // OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
1760 
1761 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1762 // All rights reserved. This software is distributed under the
1763 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
void writeCompressedValuesSize(std::ostream &os, const T *srcBuf, Index srcCount)
Definition: PointDataGrid.h:170
ValueOnIter endValueOn()
Definition: PointDataGrid.h:758
Definition: LeafNode.h:233
ChildOnCIter beginChildOn() const
Definition: PointDataGrid.h:767
Definition: PointDataGrid.h:212
Container for metadata describing how to unserialize grids from and/or serialize grids to a stream (w...
Definition: io.h:57
typename BaseLeaf::template ChildIter< MaskOffIterator, const PointDataLeafNode, ChildOff > ChildOffCIter
Definition: PointDataGrid.h:689
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:1640
void setValuesOff()
Definition: PointDataGrid.h:568
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: PointDataGrid.h:481
void setValueOff(const Coord &, const ValueType &)
Definition: PointDataGrid.h:556
ChildAllCIter cbeginChildAll() const
Definition: PointDataGrid.h:772
Attribute Group access and filtering for iteration.
void fill(const CoordBBox &, const ValueType &, bool)
Definition: PointDataGrid.h:1570
void setValueOffAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:595
ChildAllCIter beginChildAll() const
Definition: PointDataGrid.h:773
void modifyValue(Index, const ModifyOp &)
Definition: PointDataGrid.h:571
typename TreeType::RootNodeType RootNodeT
Definition: PointDataGrid.h:1735
ValueOffCIter endValueOff() const
Definition: PointDataGrid.h:760
ChildOffIter endChildOff()
Definition: PointDataGrid.h:781
void setValueOn(Index, const ValueType &)
Definition: PointDataGrid.h:563
IndexOnIter beginIndexOn() const
Definition: PointDataGrid.h:707
ValueOnCIter beginValueOn() const
Definition: PointDataGrid.h:747
typename BaseLeaf::template DenseIter< PointDataLeafNode, ValueType, ChildAll > ChildAllIter
Definition: PointDataGrid.h:691
std::vector< ValueType > IndexArray
Definition: PointDataGrid.h:272
void setValueOnlyAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:587
Typed class for storing attribute data.
Definition: AttributeArray.h:584
typename boost::mpl::push_back< SubtreeT, RootNodeT >::type Type
Definition: PointDataGrid.h:1704
ChildOffIter beginChildOff()
Definition: PointDataGrid.h:771
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
ValueOffCIter beginValueOff() const
Definition: PointDataGrid.h:750
#define VMASK_
Definition: PointDataGrid.h:745
typename BaseLeaf::template ChildIter< MaskOnIterator, PointDataLeafNode, ChildOn > ChildOnIter
Definition: PointDataGrid.h:683
void modifyValue(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:574
ChildAllIter endChildAll()
Definition: PointDataGrid.h:784
typename BaseLeaf::ChildOff ChildOff
Definition: PointDataGrid.h:623
void setInputStream(std::istream &is)
Definition: StreamCompression.h:250
void reset(Index32 begin, Index32 end)
Reset the begining and end of the iterator.
Definition: IndexIterator.h:279
void clip(const CoordBBox &, const ValueType &value)
Definition: PointDataGrid.h:580
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
const char * typeNameAsString< Vec3f >()
Definition: Types.h:584
ChildOnIter beginChildOn()
Definition: PointDataGrid.h:768
Attribute Array storage templated on type and compression codec.
Definition: AttributeGroup.h:102
typename BaseLeaf::template ValueIter< MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff > ValueOffIter
Definition: PointDataGrid.h:675
Integer wrapper, required to distinguish PointIndexGrid and PointDataGrid from Int32Grid and Int64Gri...
Definition: Types.h:183
void setValuesOn()
Definition: PointDataGrid.h:567
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &value, TopologyCopy)
Definition: PointDataGrid.h:328
ValueOffIter beginValueOff()
Definition: PointDataGrid.h:751
ChildOnCIter endChildOn() const
Definition: PointDataGrid.h:777
IndexOffIter beginIndexOff() const
Definition: PointDataGrid.h:712
ChildAllCIter endChildAll() const
Definition: PointDataGrid.h:783
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...
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:309
A forward iterator over array indices with filtering IteratorT can be either IndexIter or ValueIndexI...
Definition: IndexIterator.h:166
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:1734
std::shared_ptr< PagedOutputStream > Ptr
Definition: StreamCompression.h:275
typename BaseLeaf::template ValueIter< MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn > ValueOnIter
Definition: PointDataGrid.h:671
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:77
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:271
ChildOnCIter cbeginChildOn() const
Definition: PointDataGrid.h:766
void signedFloodFill(const ValueType &, const ValueType &)
Definition: PointDataGrid.h:607
typename BaseLeaf::template DenseIter< const PointDataLeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: PointDataGrid.h:693
ChildOffCIter endChildOff() const
Definition: PointDataGrid.h:780
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:677
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:894
IndexIter< ValueAllCIter, FilterT > beginIndexAll(const FilterT &filter) const
Filtered leaf index iterator.
Definition: PointDataGrid.h:723
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
Definition: Exceptions.h:85
ValueAllCIter beginValueAll() const
Definition: PointDataGrid.h:753
PointDataLeafNode(const PointDataLeafNode &other)
Construct using deep copy of other PointDataLeafNode.
Definition: PointDataGrid.h:299
Base class for storing attribute data.
Definition: AttributeArray.h:118
std::string Name
Definition: Name.h:44
ValueAllCIter endValueAll() const
Definition: PointDataGrid.h:763
std::shared_ptr< Descriptor > DescriptorPtr
Definition: AttributeSet.h:72
void signedFloodFill(const ValueType &)
Definition: PointDataGrid.h:606
void setActiveState(Index offset, bool on)
Definition: PointDataGrid.h:548
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:502
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:752
void assertNonmodifiable()
Definition: PointDataGrid.h:536
void setValueOff(Index, const ValueType &)
Definition: PointDataGrid.h:557
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1610
Definition: LeafNode.h:233
void initialize()
Global registration of point data-related types.
Definition: AttributeGroup.h:130
typename BaseLeaf::ValueOn ValueOn
Definition: PointDataGrid.h:613
Definition: TreeIterator.h:91
Recursive node chain which generates a boost::mpl::vector listing value converted types of nodes to P...
Definition: PointDataGrid.h:1700
typename internal::PointDataNodeChain< RootNodeT, RootNodeT::LEVEL >::Type NodeChainT
Definition: PointDataGrid.h:1736
Definition: NodeMasks.h:210
ValueAllIter beginValueAll()
Definition: PointDataGrid.h:754
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:1627
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
Convenience wrappers to using Blosc and reading and writing of Paged data.
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:457
bool operator!=(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:468
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
Definition: NodeMasks.h:241
ChildOnIter endChildOn()
Definition: PointDataGrid.h:778
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
typename BaseLeaf::template ValueIter< MaskDenseIterator, const PointDataLeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: PointDataGrid.h:681
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
Definition: LeafNode.h:233
typename BaseLeaf::template ChildIter< MaskOffIterator, PointDataLeafNode, ChildOff > ChildOffIter
Definition: PointDataGrid.h:687
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:529
void setValueOnly(const Coord &, const ValueType &)
Definition: PointDataGrid.h:550
ValueAllCIter cendValueAll() const
Definition: PointDataGrid.h:762
void fill(const ValueType &value)
Definition: PointDataGrid.h:583
void assertNonModifiableUnlessZero(const ValueType &value)
Definition: PointDataGrid.h:543
Index32 Index
Definition: Types.h:61
typename BaseLeaf::ChildOn ChildOn
Definition: PointDataGrid.h:622
ChildOffCIter cendChildOff() const
Definition: PointDataGrid.h:779
uint64_t Index64
Definition: Types.h:60
void uninitialize()
Global deregistration of point data-related types.
void addLeaf(PointDataLeafNode *)
Definition: PointDataGrid.h:470
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:86
IndexIter< ValueOnCIter, FilterT > beginIndexOn(const FilterT &filter) const
Definition: PointDataGrid.h:728
OPENVDB_DEPRECATED Index64 groupPointCount(const PointDataTreeT &tree, const Name &name, const bool inCoreOnly=true)
Definition: PointCount.h:262
void setValueOff(const Coord &xyz)
Definition: PointDataGrid.h:553
void flush()
Manually flushes the current page to disk if non-zero.
void setValueOn(const Coord &, const ValueType &)
Definition: PointDataGrid.h:562
void setValueOn(Index offset)
Definition: PointDataGrid.h:560
Definition: RootNode.h:70
std::map< std::string, boost::any > AuxDataMap
Definition: io.h:114
IndexAllIter beginIndexAll() const
Leaf index iterator.
Definition: PointDataGrid.h:702
Definition: Exceptions.h:40
PointDataLeafNode(const PointDataLeafNode &other, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:311
Index64 memUsage() const
Definition: PointDataGrid.h:1549
void setValueOn(const Coord &xyz)
Definition: PointDataGrid.h:559
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition: PointAttribute.h:618
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:149
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:272
typename NodeMaskType::OnIterator MaskOnIterator
Definition: PointDataGrid.h:626
void setValueOff(Index offset)
Definition: PointDataGrid.h:554
ValueOnCIter endValueOn() const
Definition: PointDataGrid.h:757
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:144
PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: PointDataGrid.h:490
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
PointDataLeafNode(PartialCreate, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:340
Definition: Exceptions.h:84
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only writing size data.
Definition: StreamCompression.h:282
Definition: NodeMasks.h:272
void modifyValueAndActiveStateAndCache(const Coord &, const ModifyOp &, AccessorT &)
Definition: PointDataGrid.h:590
typename PointDataNodeChain< ChildT, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1712
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:235
PointDataLeafNode(const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Construct using supplied origin, value and active status.
Definition: PointDataGrid.h:305
void setOutputStream(std::ostream &os)
Definition: StreamCompression.h:287
ChildAllCIter cendChildAll() const
Definition: PointDataGrid.h:782
ValueOffCIter cbeginValueOff() const
Definition: PointDataGrid.h:749
AttributeSet::Descriptor Descriptor
Definition: PointDataGrid.h:274
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &, const T &, TopologyCopy)
Definition: PointDataGrid.h:335
PointDataLeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: PointDataGrid.h:478
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: PointDataGrid.h:628
void negate()
Definition: PointDataGrid.h:609
Library and file format version numbers.
PointDataLeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: PointDataGrid.h:488
typename BaseLeaf::template ChildIter< MaskOnIterator, const PointDataLeafNode, ChildOn > ChildOnCIter
Definition: PointDataGrid.h:685
void setValueOnly(Index, const ValueType &)
Definition: PointDataGrid.h:551
std::shared_ptr< PointDataLeafNode > Ptr
Definition: PointDataGrid.h:268
SharedPtr< StreamMetadata > Ptr
Definition: io.h:60
ChildOffCIter beginChildOff() const
Definition: PointDataGrid.h:770
PointDataLeafNode(const tools::PointIndexLeafNode< OtherValueType, Log2Dim > &other)
Definition: PointDataGrid.h:321
typename BaseLeaf::ValueOff ValueOff
Definition: PointDataGrid.h:614
IndexIter< ValueOffCIter, FilterT > beginIndexOff(const FilterT &filter) const
Definition: PointDataGrid.h:733
ValueOffCIter cendValueOff() const
Definition: PointDataGrid.h:759
OPENVDB_API SharedPtr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme...
typename BaseLeaf::template ValueIter< MaskOffIterator, const PointDataLeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: PointDataGrid.h:677
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:64
Definition: InternalNode.h:60
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:115
ChildOffCIter cbeginChildOff() const
Definition: PointDataGrid.h:769
const AttributeSet & attributeSet() const
Retrieve the attribute set.
Definition: PointDataGrid.h:349
ValueOnCIter cendValueOn() const
Definition: PointDataGrid.h:756
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:93
PointIndex< Index32, 1 > PointDataIndex32
Definition: Types.h:208
std::shared_ptr< PagedInputStream > Ptr
Definition: StreamCompression.h:238
virtual Index size() const =0
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:150
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &parent)
Definition: PointDataGrid.h:598
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:151
typename BaseLeaf::template ValueIter< MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll > ValueAllIter
Definition: PointDataGrid.h:679
const PointDataLeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:497
typename NodeMaskType::OffIterator MaskOffIterator
Definition: PointDataGrid.h:627
Definition: IndexIterator.h:70
ValueAllIter endValueAll()
Definition: PointDataGrid.h:764
std::pair< ValueType, ValueType > ValueTypePair
Definition: PointDataGrid.h:271
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.
Definition: Tree.h:203
ValueOnIter beginValueOn()
Definition: PointDataGrid.h:748
ChildAllIter beginChildAll()
Definition: PointDataGrid.h:774
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
typename BaseLeaf::template ValueIter< MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: PointDataGrid.h:673
typename boost::mpl::push_back< SubtreeT, InternalNodeT >::type Type
Definition: PointDataGrid.h:1714
void reorderAttributes(const Descriptor::Ptr &replacement)
Reorder attribute set.
Definition: PointDataGrid.h:855
Definition: LeafNode.h:232
Definition: LeafNode.h:232
ValueOffIter endValueOff()
Definition: PointDataGrid.h:761
Attribute array storage for string data using Descriptor Metadata.
Definition: Exceptions.h:92
ValueAllCIter cbeginValueAll() const
Definition: PointDataGrid.h:752
void modifyValueAndActiveState(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:577
const PointDataLeafNode * probeLeaf(const Coord &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:500
void appendAttribute(PointDataTreeT &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:409
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
static index::State state()
Definition: AttributeGroup.h:170
void setActiveState(const Coord &xyz, bool on)
Definition: PointDataGrid.h:547
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
void addLeafAndCache(PointDataLeafNode *, AccessorT &)
Definition: PointDataGrid.h:472
Descriptor & descriptor()
Return a reference to this attribute set&#39;s descriptor, which might be shared with other sets...
Definition: AttributeSet.h:121
typename BaseLeaf::ValueAll ValueAll
Definition: PointDataGrid.h:615
Definition: Exceptions.h:87
A forward iterator over array indices in a single voxel.
Definition: IndexIterator.h:91
int32_t Int32
Definition: Types.h:63
typename PointDataNodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1702
Definition: PointDataGrid.h:201
Definition: LeafNode.h:232
Index filtering on group membership.
Definition: AttributeGroup.h:159
ChildOnCIter cendChildOn() const
Definition: PointDataGrid.h:776
Set of Attribute Arrays which tracks metadata about each array.
PointDataLeafNode()
Default constructor.
Definition: PointDataGrid.h:293
bool operator==(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:463
void setValue(const Coord &, const ValueType &)
Definition: PointDataGrid.h:565
Definition: PointIndexGrid.h:79
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only reading size data.
Definition: StreamCompression.h:245
typename BaseLeaf::ChildAll ChildAll
Definition: PointDataGrid.h:624
const PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:499
typename boost::mpl::vector< LeafNodeT, InternalNodeT >::type Type
Definition: PointDataGrid.h:1724
Leaf nodes that require multi-pass I/O must inherit from this struct.
Definition: io.h:141
void resetBackground(const ValueType &, const ValueType &newBackground)
Definition: PointDataGrid.h:602
ValueOnCIter cbeginValueOn() const
Definition: PointDataGrid.h:746
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:56
Definition: IndexIterator.h:69
T ValueType
Definition: PointDataGrid.h:270
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:341