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