OpenVDB  3.2.0
LeafNode.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 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 
31 #ifndef OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
33 
34 #include <iostream>
35 #include <algorithm> // for std::swap
36 #include <cstring> // for std::memcpy()
37 #include <boost/shared_ptr.hpp>
38 #include <boost/static_assert.hpp>
39 #include <boost/bind.hpp>
40 #include <tbb/blocked_range.h>
41 #include <tbb/spin_mutex.h>
42 #include <tbb/parallel_for.h>
43 #include <openvdb/Types.h>
44 #include <openvdb/util/NodeMasks.h>
45 #include <openvdb/io/Compression.h> // for io::readData(), etc.
46 #include "Iterator.h"
47 
48 
49 class TestLeaf;
50 template<typename> class TestLeafIO;
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace tree {
56 
57 template<Index, typename> struct SameLeafConfig; // forward declaration
58 
59 
64 template<typename T, Index Log2Dim>
65 class LeafNode
66 {
67 public:
68  typedef T BuildType;
69  typedef T ValueType;
71  typedef boost::shared_ptr<LeafNode> Ptr;
73 
74  static const Index
75  LOG2DIM = Log2Dim, // needed by parent nodes
76  TOTAL = Log2Dim, // needed by parent nodes
77  DIM = 1 << TOTAL, // dimension along one coordinate direction
78  NUM_VALUES = 1 << 3 * Log2Dim,
79  NUM_VOXELS = NUM_VALUES, // total number of voxels represented by this node
80  SIZE = NUM_VALUES,
81  LEVEL = 0; // level 0 = leaf
82 
85  template<typename OtherValueType>
86  struct ValueConverter {
88  };
89 
92  template<typename OtherNodeType>
95  };
96 
97 #ifndef OPENVDB_2_ABI_COMPATIBLE
98  struct FileInfo
99  {
100  FileInfo(): bufpos(0) , maskpos(0) {}
101  std::streamoff bufpos;
102  std::streamoff maskpos;
104  boost::shared_ptr<io::StreamMetadata> meta;
105  };
106 #endif
107 
110  class Buffer
111  {
112  public:
113 #ifdef OPENVDB_2_ABI_COMPATIBLE
114  Buffer(): mData(new ValueType[SIZE]) {}
117  explicit Buffer(const ValueType& val): mData(new ValueType[SIZE]) { this->fill(val); }
119  Buffer(const Buffer& other): mData(new ValueType[SIZE]) { *this = other; }
121  ~Buffer() { delete[] mData; }
122 
124  bool isOutOfCore() const { return false; }
126  bool empty() const { return (mData == NULL); }
127 #else
128  typedef ValueType WordType;
129  static const Index WORD_COUNT = SIZE;
131  Buffer(): mData(new ValueType[SIZE]), mOutOfCore(0) {}
133  explicit Buffer(const ValueType& val): mData(new ValueType[SIZE]), mOutOfCore(0)
134  {
135  this->fill(val);
136  }
138  Buffer(const Buffer& other): mData(NULL), mOutOfCore(other.mOutOfCore)
139  {
140  if (other.isOutOfCore()) {
141  mFileInfo = new FileInfo(*other.mFileInfo);
142  } else {
143  this->allocate();
144  ValueType* target = mData;
145  const ValueType* source = other.mData;
146  Index n = SIZE;
147  while (n--) *target++ = *source++;
148  }
149  }
151  Buffer(PartialCreate, const ValueType&): mData(NULL), mOutOfCore(0) {}
154  {
155  if (this->isOutOfCore()) {
156  this->detachFromFile();
157  } else {
158  this->deallocate();
159  }
160  }
161 
163  bool isOutOfCore() const { return bool(mOutOfCore); }
165  bool empty() const { return !mData || this->isOutOfCore(); }
166 #endif
167  bool allocate() { if (mData == NULL) mData = new ValueType[SIZE]; return true; }
169 
171  void fill(const ValueType& val)
172  {
173  this->detachFromFile();
174  if (mData != NULL) {
175  ValueType* target = mData;
176  Index n = SIZE;
177  while (n--) *target++ = val;
178  }
179  }
180 
182  const ValueType& getValue(Index i) const { return this->at(i); }
184  const ValueType& operator[](Index i) const { return this->at(i); }
186  void setValue(Index i, const ValueType& val)
187  {
188  assert(i < SIZE);
189 #ifdef OPENVDB_2_ABI_COMPATIBLE
190  mData[i] = val;
191 #else
192  this->loadValues();
193  if (mData) mData[i] = val;
194 #endif
195  }
196 
198  Buffer& operator=(const Buffer& other)
199  {
200  if (&other != this) {
201 #ifndef OPENVDB_2_ABI_COMPATIBLE
202  if (this->isOutOfCore()) {
203  this->detachFromFile();
204  } else {
205  if (other.isOutOfCore()) this->deallocate();
206  }
207  if (other.isOutOfCore()) {
208  mOutOfCore = other.mOutOfCore;
209  mFileInfo = new FileInfo(*other.mFileInfo);
210  } else {
211 #endif
212  this->allocate();
213  ValueType* target = mData;
214  const ValueType* source = other.mData;
215  Index n = SIZE;
216  while (n--) *target++ = *source++;
217 #ifndef OPENVDB_2_ABI_COMPATIBLE
218  }
219 #endif
220  }
221  return *this;
222  }
223 
226  bool operator==(const Buffer& other) const
227  {
228  this->loadValues();
229  other.loadValues();
230  const ValueType *target = mData, *source = other.mData;
231  if (!target && !source) return true;
232  if (!target || !source) return false;
233  Index n = SIZE;
234  while (n && math::isExactlyEqual(*target++, *source++)) --n;
235  return n == 0;
236  }
239  bool operator!=(const Buffer& other) const { return !(other == *this); }
240 
242  void swap(Buffer& other)
243  {
244  std::swap(mData, other.mData);
245 #ifndef OPENVDB_2_ABI_COMPATIBLE
246  std::swap(mOutOfCore, other.mOutOfCore);
247 #endif
248  }
249 
251  Index memUsage() const
252  {
253  size_t n = sizeof(*this);
254 #ifdef OPENVDB_2_ABI_COMPATIBLE
255  if (mData) n += SIZE * sizeof(ValueType);
256 #else
257  if (this->isOutOfCore()) n += sizeof(FileInfo);
258  else if (mData) n += SIZE * sizeof(ValueType);
259 #endif
260  return static_cast<Index>(n);
261  }
263  static Index size() { return SIZE; }
264 
268  const ValueType* data() const
269  {
270 #ifndef OPENVDB_2_ABI_COMPATIBLE
271  this->loadValues();
272  if (mData == NULL) {
273  Buffer* self = const_cast<Buffer*>(this);
274  // This lock will be contended at most once.
275  tbb::spin_mutex::scoped_lock lock(self->mMutex);
276  if (mData == NULL) self->mData = new ValueType[SIZE];
277  }
278 #endif
279  return mData;
280  }
281 
285  ValueType* data()
286  {
287 #ifndef OPENVDB_2_ABI_COMPATIBLE
288  this->loadValues();
289  if (mData == NULL) {
290  // This lock will be contended at most once.
291  tbb::spin_mutex::scoped_lock lock(mMutex);
292  if (mData == NULL) mData = new ValueType[SIZE];
293  }
294 #endif
295  return mData;
296  }
297 
298  private:
300  const ValueType& at(Index i) const
301  {
302  assert(i < SIZE);
303 #ifdef OPENVDB_2_ABI_COMPATIBLE
304  return mData[i];
305 #else
306  this->loadValues();
307  // We can't use the ternary operator here, otherwise Visual C++ returns
308  // a reference to a temporary.
309  if (mData) return mData[i]; else return sZero;
310 #endif
311  }
312 
318  ValueType& operator[](Index i) { return const_cast<ValueType&>(this->at(i)); }
319 
320  bool deallocate()
321  {
322  if (mData != NULL && !this->isOutOfCore()) {
323  delete[] mData;
324  mData = NULL;
325  return true;
326  }
327  return false;
328  }
329 
330 #ifdef OPENVDB_2_ABI_COMPATIBLE
331  void setOutOfCore(bool) {}
332  void loadValues() const {}
333  void doLoad() const {}
334  bool detachFromFile() { return false; }
335 #else
336  inline void setOutOfCore(bool b) { mOutOfCore = b; }
337  // To facilitate inlining in the common case in which the buffer is in-core,
338  // the loading logic is split into a separate function, doLoad().
339  inline void loadValues() const { if (this->isOutOfCore()) this->doLoad(); }
340  inline void doLoad() const;
341  inline bool detachFromFile()
342  {
343  if (this->isOutOfCore()) {
344  delete mFileInfo;
345  mFileInfo = NULL;
346  this->setOutOfCore(false);
347  return true;
348  }
349  return false;
350  }
351 #endif
352 
353  friend class ::TestLeaf;
354  // Allow the parent LeafNode to access this buffer's data pointer.
355  friend class LeafNode;
356 
357 #ifdef OPENVDB_2_ABI_COMPATIBLE
358  ValueType* mData;
359 #else
360  union {
361  ValueType* mData;
363  };
364  Index32 mOutOfCore; // currently interpreted as bool; extra bits reserved for future use
365  tbb::spin_mutex mMutex; // 1 byte
366  //int8_t mReserved[3]; // padding for alignment
367 
368  static const ValueType sZero;
369 #endif
370  }; // class Buffer
371 
372 
374  LeafNode();
375 
380  explicit LeafNode(const Coord& coords,
381  const ValueType& value = zeroVal<ValueType>(),
382  bool active = false);
383 
384 
385 #ifndef OPENVDB_2_ABI_COMPATIBLE
392  const Coord& coords,
393  const ValueType& value = zeroVal<ValueType>(),
394  bool active = false);
395 #endif
396 
398  LeafNode(const LeafNode&);
399 
401  template<typename OtherValueType>
402  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
403 
405  template<typename OtherValueType>
407  const ValueType& offValue, const ValueType& onValue, TopologyCopy);
408 
410  template<typename OtherValueType>
412  const ValueType& background, TopologyCopy);
413 
415  ~LeafNode();
416 
417  //
418  // Statistics
419  //
421  static Index log2dim() { return Log2Dim; }
423  static Index dim() { return DIM; }
425  static Index size() { return SIZE; }
427  static Index numValues() { return SIZE; }
429  static Index getLevel() { return LEVEL; }
431  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
433  static Index getChildDim() { return 1; }
435  static Index32 leafCount() { return 1; }
437  static Index32 nonLeafCount() { return 0; }
438 
440  Index64 onVoxelCount() const { return mValueMask.countOn(); }
442  Index64 offVoxelCount() const { return mValueMask.countOff(); }
443  Index64 onLeafVoxelCount() const { return onVoxelCount(); }
444  Index64 offLeafVoxelCount() const { return offVoxelCount(); }
445  static Index64 onTileCount() { return 0; }
446  static Index64 offTileCount() { return 0; }
448  bool isEmpty() const { return mValueMask.isOff(); }
450  bool isDense() const { return mValueMask.isOn(); }
451 
452 #ifndef OPENVDB_2_ABI_COMPATIBLE
453  bool isAllocated() const { return !mBuffer.isOutOfCore() && !mBuffer.empty(); }
456  bool allocate() { return mBuffer.allocate(); }
457 #endif
458 
460  Index64 memUsage() const;
461 
465  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
466 
469  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
470 
472  void setOrigin(const Coord& origin) { mOrigin = origin; }
474  const Coord& origin() const { return mOrigin; }
476  void getOrigin(Coord& origin) const { origin = mOrigin; }
477  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
479 
481  static Index coordToOffset(const Coord& xyz);
484  static Coord offsetToLocalCoord(Index n);
486  Coord offsetToGlobalCoord(Index n) const;
487 
489  std::string str() const;
490 
493  template<typename OtherType, Index OtherLog2Dim>
494  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
495 
497  bool operator==(const LeafNode& other) const;
498  bool operator!=(const LeafNode& other) const { return !(other == *this); }
499 
500 protected:
504 
505  // Type tags to disambiguate template instantiations
506  struct ValueOn {}; struct ValueOff {}; struct ValueAll {};
507  struct ChildOn {}; struct ChildOff {}; struct ChildAll {};
508 
509  template<typename MaskIterT, typename NodeT, typename ValueT, typename TagT>
510  struct ValueIter:
511  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
512  // if MaskIterT is a dense mask iterator type.
513  public SparseIteratorBase<
514  MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
515  {
517 
519  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
520 
521  ValueT& getItem(Index pos) const { return this->parent().getValue(pos); }
522  ValueT& getValue() const { return this->parent().getValue(this->pos()); }
523 
524  // Note: setItem() can't be called on const iterators.
525  void setItem(Index pos, const ValueT& value) const
526  {
527  this->parent().setValueOnly(pos, value);
528  }
529  // Note: setValue() can't be called on const iterators.
530  void setValue(const ValueT& value) const
531  {
532  this->parent().setValueOnly(this->pos(), value);
533  }
534 
535  // Note: modifyItem() can't be called on const iterators.
536  template<typename ModifyOp>
537  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
538  // Note: modifyValue() can't be called on const iterators.
539  template<typename ModifyOp>
540  void modifyValue(const ModifyOp& op) const { this->parent().modifyValue(this->pos(), op); }
541  };
542 
544  template<typename MaskIterT, typename NodeT, typename TagT>
545  struct ChildIter:
546  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
547  {
549  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
550  MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>(iter, parent) {}
551  };
552 
553  template<typename NodeT, typename ValueT, typename TagT>
554  struct DenseIter: public DenseIteratorBase<
555  MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, /*ChildT=*/void, ValueT>
556  {
559 
561  DenseIter(const MaskDenseIterator& iter, NodeT* parent): BaseT(iter, parent) {}
562 
563  bool getItem(Index pos, void*& child, NonConstValueT& value) const
564  {
565  value = this->parent().getValue(pos);
566  child = NULL;
567  return false; // no child
568  }
569 
570  // Note: setItem() can't be called on const iterators.
571  //void setItem(Index pos, void* child) const {}
572 
573  // Note: unsetItem() can't be called on const iterators.
574  void unsetItem(Index pos, const ValueT& value) const
575  {
576  this->parent().setValueOnly(pos, value);
577  }
578  };
579 
580 public:
593 
594  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
595  ValueOnCIter beginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
596  ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
597  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
598  ValueOffCIter beginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
599  ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
600  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
601  ValueAllCIter beginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
602  ValueAllIter beginValueAll() { return ValueAllIter(mValueMask.beginDense(), this); }
603 
604  ValueOnCIter cendValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
605  ValueOnCIter endValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
606  ValueOnIter endValueOn() { return ValueOnIter(mValueMask.endOn(), this); }
607  ValueOffCIter cendValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
608  ValueOffCIter endValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
609  ValueOffIter endValueOff() { return ValueOffIter(mValueMask.endOff(), this); }
610  ValueAllCIter cendValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
611  ValueAllCIter endValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
612  ValueAllIter endValueAll() { return ValueAllIter(mValueMask.endDense(), this); }
613 
614  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
615  // because leaf nodes have no children.
616  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
617  ChildOnCIter beginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
618  ChildOnIter beginChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
619  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
620  ChildOffCIter beginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
621  ChildOffIter beginChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
622  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
623  ChildAllCIter beginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
624  ChildAllIter beginChildAll() { return ChildAllIter(mValueMask.beginDense(), this); }
625 
626  ChildOnCIter cendChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
627  ChildOnCIter endChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
628  ChildOnIter endChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
629  ChildOffCIter cendChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
630  ChildOffCIter endChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
631  ChildOffIter endChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
632  ChildAllCIter cendChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
633  ChildAllCIter endChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
634  ChildAllIter endChildAll() { return ChildAllIter(mValueMask.endDense(), this); }
635 
636  //
637  // Buffer management
638  //
641  void swap(Buffer& other) { mBuffer.swap(other); }
642  const Buffer& buffer() const { return mBuffer; }
643  Buffer& buffer() { return mBuffer; }
644 
645  //
646  // I/O methods
647  //
651  void readTopology(std::istream& is, bool fromHalf = false);
655  void writeTopology(std::ostream& os, bool toHalf = false) const;
656 
660  void readBuffers(std::istream& is, bool fromHalf = false);
665  void readBuffers(std::istream& is, const CoordBBox& bbox, bool fromHalf = false);
669  void writeBuffers(std::ostream& os, bool toHalf = false) const;
670 
671  size_t streamingSize(bool toHalf = false) const;
672 
673  //
674  // Accessor methods
675  //
677  const ValueType& getValue(const Coord& xyz) const;
679  const ValueType& getValue(Index offset) const;
680 
684  bool probeValue(const Coord& xyz, ValueType& val) const;
688  bool probeValue(Index offset, ValueType& val) const;
689 
691  static Index getValueLevel(const Coord&) { return LEVEL; }
692 
694  void setActiveState(const Coord& xyz, bool on);
696  void setActiveState(Index offset, bool on) { assert(offset<SIZE); mValueMask.set(offset, on); }
697 
699  void setValueOnly(const Coord& xyz, const ValueType& val);
701  void setValueOnly(Index offset, const ValueType& val);
702 
704  void setValueOff(const Coord& xyz) { mValueMask.setOff(LeafNode::coordToOffset(xyz)); }
706  void setValueOff(Index offset) { assert(offset < SIZE); mValueMask.setOff(offset); }
707 
709  void setValueOff(const Coord& xyz, const ValueType& val);
711  void setValueOff(Index offset, const ValueType& val);
712 
714  void setValueOn(const Coord& xyz) { mValueMask.setOn(LeafNode::coordToOffset(xyz)); }
716  void setValueOn(Index offset) { assert(offset < SIZE); mValueMask.setOn(offset); }
718  void setValueOn(const Coord& xyz, const ValueType& val) {
719  this->setValueOn(LeafNode::coordToOffset(xyz), val);
720  }
722  void setValue(const Coord& xyz, const ValueType& val) { this->setValueOn(xyz, val); }
724  void setValueOn(Index offset, const ValueType& val) {
725  mBuffer.setValue(offset, val);
726  mValueMask.setOn(offset);
727  }
728 
731  template<typename ModifyOp>
732  void modifyValue(Index offset, const ModifyOp& op)
733  {
734  ValueType val = mBuffer[offset];
735  op(val);
736  mBuffer.setValue(offset, val);
737  mValueMask.setOn(offset);
738  }
741  template<typename ModifyOp>
742  void modifyValue(const Coord& xyz, const ModifyOp& op)
743  {
744  this->modifyValue(this->coordToOffset(xyz), op);
745  }
746 
748  template<typename ModifyOp>
749  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
750  {
751  const Index offset = this->coordToOffset(xyz);
752  bool state = mValueMask.isOn(offset);
753  ValueType val = mBuffer[offset];
754  op(val, state);
755  mBuffer.setValue(offset, val);
756  mValueMask.set(offset, state);
757  }
758 
760  void setValuesOn() { mValueMask.setOn(); }
762  void setValuesOff() { mValueMask.setOff(); }
763 
765  bool isValueOn(const Coord& xyz) const {return this->isValueOn(LeafNode::coordToOffset(xyz));}
767  bool isValueOn(Index offset) const { return mValueMask.isOn(offset); }
768 
770  static bool hasActiveTiles() { return false; }
771 
773  void clip(const CoordBBox&, const ValueType& background);
774 
776  void fill(const CoordBBox& bbox, const ValueType&, bool active = true);
777 
779  void fill(const ValueType& value);
781  void fill(const ValueType& value, bool active);
782 
794  template<typename DenseT>
795  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
796 
813  template<typename DenseT>
814  void copyFromDense(const CoordBBox& bbox, const DenseT& dense,
815  const ValueType& background, const ValueType& tolerance);
816 
819  template<typename AccessorT>
820  const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const
821  {
822  return this->getValue(xyz);
823  }
824 
827  template<typename AccessorT>
828  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
829 
832  template<typename AccessorT>
833  void setValueAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
834  {
835  this->setValueOn(xyz, val);
836  }
837 
841  template<typename AccessorT>
842  void setValueOnlyAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
843  {
844  this->setValueOnly(xyz, val);
845  }
846 
850  template<typename ModifyOp, typename AccessorT>
851  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
852  {
853  this->modifyValue(xyz, op);
854  }
855 
858  template<typename ModifyOp, typename AccessorT>
859  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
860  {
861  this->modifyValueAndActiveState(xyz, op);
862  }
863 
866  template<typename AccessorT>
867  void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&)
868  {
869  this->setValueOff(xyz, value);
870  }
871 
875  template<typename AccessorT>
876  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
877  {
878  this->setActiveState(xyz, on);
879  }
880 
884  template<typename AccessorT>
885  bool probeValueAndCache(const Coord& xyz, ValueType& val, AccessorT&) const
886  {
887  return this->probeValue(xyz, val);
888  }
889 
893  template<typename AccessorT>
894  const ValueType& getValue(const Coord& xyz, bool& state, int& level, AccessorT&) const
895  {
896  const Index offset = this->coordToOffset(xyz);
897  state = mValueMask.isOn(offset);
898  level = LEVEL;
899  return mBuffer[offset];
900  }
901 
904  template<typename AccessorT>
905  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
906 
910  const ValueType& getFirstValue() const { return mBuffer[0]; }
912  const ValueType& getLastValue() const { return mBuffer[SIZE - 1]; }
913 
916  void resetBackground(const ValueType& oldBackground, const ValueType& newBackground);
917 
918  void negate();
919 
922  void voxelizeActiveTiles(bool = true) {}
923 
924  template<MergePolicy Policy> void merge(const LeafNode&);
925  template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive);
926  template<MergePolicy Policy>
927  void merge(const LeafNode& other, const ValueType& /*bg*/, const ValueType& /*otherBG*/);
928 
935  template<typename OtherType>
936  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other);
937 
949  template<typename OtherType>
950  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
951 
963  template<typename OtherType>
964  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
965 
966  template<typename CombineOp>
967  void combine(const LeafNode& other, CombineOp& op);
968  template<typename CombineOp>
969  void combine(const ValueType& value, bool valueIsActive, CombineOp& op);
970 
971  template<typename CombineOp, typename OtherType /*= ValueType*/>
972  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
973  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
974  void combine2(const ValueType&, const OtherNodeT& other, bool valueIsActive, CombineOp&);
975  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
976  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
977 
983  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
984 
985  template<typename VisitorOp> void visit(VisitorOp&);
986  template<typename VisitorOp> void visit(VisitorOp&) const;
987 
988  template<typename OtherLeafNodeType, typename VisitorOp>
989  void visit2Node(OtherLeafNodeType& other, VisitorOp&);
990  template<typename OtherLeafNodeType, typename VisitorOp>
991  void visit2Node(OtherLeafNodeType& other, VisitorOp&) const;
992  template<typename IterT, typename VisitorOp>
993  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
994  template<typename IterT, typename VisitorOp>
995  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
996 
998  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
1000  void addLeaf(LeafNode*) {}
1001  template<typename AccessorT>
1002  void addLeafAndCache(LeafNode*, AccessorT&) {}
1003  template<typename NodeT>
1004  NodeT* stealNode(const Coord&, const ValueType&, bool) { return NULL; }
1005  template<typename NodeT>
1006  NodeT* probeNode(const Coord&) { return NULL; }
1007  template<typename NodeT>
1008  const NodeT* probeConstNode(const Coord&) const { return NULL; }
1009  template<typename ArrayT> void getNodes(ArrayT&) const {}
1010  template<typename ArrayT> void stealNodes(ArrayT&, const ValueType&, bool) {}
1012 
1013  void addTile(Index level, const Coord&, const ValueType&, bool);
1014  void addTile(Index offset, const ValueType&, bool);
1015  template<typename AccessorT>
1016  void addTileAndCache(Index, const Coord&, const ValueType&, bool, AccessorT&);
1017 
1019  LeafNode* touchLeaf(const Coord&) { return this; }
1021  template<typename AccessorT>
1022  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
1023  template<typename NodeT, typename AccessorT>
1024  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
1025  {
1027  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
1028  return reinterpret_cast<NodeT*>(this);
1030  }
1031  LeafNode* probeLeaf(const Coord&) { return this; }
1032  template<typename AccessorT>
1033  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
1035 
1036  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
1038  template<typename AccessorT>
1039  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
1040  template<typename AccessorT>
1041  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
1042  const LeafNode* probeLeaf(const Coord&) const { return this; }
1043  template<typename NodeT, typename AccessorT>
1044  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
1045  {
1047  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
1048  return reinterpret_cast<const NodeT*>(this);
1050  }
1052 
1062  bool isConstant(ValueType& firstValue, bool& state,
1063  const ValueType& tolerance = zeroVal<ValueType>()) const;
1064 
1076  bool isConstant(ValueType& minValue, ValueType& maxValue,
1077  bool& state, const ValueType& tolerance = zeroVal<ValueType>()) const;
1078 
1080  bool isInactive() const { return mValueMask.isOff(); }
1081 
1082 protected:
1083  friend class ::TestLeaf;
1084  template<typename> friend class ::TestLeafIO;
1085 
1086  // During topology-only construction, access is needed
1087  // to protected/private members of other template instances.
1088  template<typename, Index> friend class LeafNode;
1089 
1090  friend struct ValueIter<MaskOnIterator, LeafNode, ValueType, ValueOn>;
1091  friend struct ValueIter<MaskOffIterator, LeafNode, ValueType, ValueOff>;
1092  friend struct ValueIter<MaskDenseIterator, LeafNode, ValueType, ValueAll>;
1093  friend struct ValueIter<MaskOnIterator, const LeafNode, ValueType, ValueOn>;
1094  friend struct ValueIter<MaskOffIterator, const LeafNode, ValueType, ValueOff>;
1095  friend struct ValueIter<MaskDenseIterator, const LeafNode, ValueType, ValueAll>;
1096 
1097  // Allow iterators to call mask accessor methods (see below).
1099  friend class IteratorBase<MaskOnIterator, LeafNode>;
1100  friend class IteratorBase<MaskOffIterator, LeafNode>;
1101  friend class IteratorBase<MaskDenseIterator, LeafNode>;
1102 
1103  // Mask accessors
1104 public:
1105  bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
1106  bool isValueMaskOn() const { return mValueMask.isOn(); }
1107  bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
1108  bool isValueMaskOff() const { return mValueMask.isOff(); }
1109  const NodeMaskType& getValueMask() const { return mValueMask; }
1110  NodeMaskType& getValueMask() { return mValueMask; }
1111  const NodeMaskType& valueMask() const { return mValueMask; }
1112  void setValueMask(const NodeMaskType& mask) { mValueMask = mask; }
1113  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
1114  bool isChildMaskOff(Index) const { return true; }
1115  bool isChildMaskOff() const { return true; }
1116 protected:
1117  void setValueMask(Index n, bool on) { mValueMask.set(n, on); }
1118  void setValueMaskOn(Index n) { mValueMask.setOn(n); }
1119  void setValueMaskOff(Index n) { mValueMask.setOff(n); }
1120 
1122  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
1123 
1124  template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
1125  static inline void doVisit(NodeT&, VisitorOp&);
1126 
1127  template<typename NodeT, typename OtherNodeT, typename VisitorOp,
1128  typename ChildAllIterT, typename OtherChildAllIterT>
1129  static inline void doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp&);
1130 
1131  template<typename NodeT, typename VisitorOp,
1132  typename ChildAllIterT, typename OtherChildAllIterT>
1133  static inline void doVisit2(NodeT& self, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
1134 
1135 private:
1137  Buffer mBuffer;
1139  NodeMaskType mValueMask;
1141  Coord mOrigin;
1142 }; // end of LeafNode class
1143 
1144 
1145 #ifndef OPENVDB_2_ABI_COMPATIBLE
1146 template<typename T, Index Log2Dim>
1147 const T LeafNode<T, Log2Dim>::Buffer::sZero = zeroVal<T>();
1148 #endif
1149 
1150 
1152 
1153 
1155 template<Index Dim1, typename NodeT2>
1158 struct SameLeafConfig { static const bool value = false; };
1159 
1160 template<Index Dim1, typename T2>
1161 struct SameLeafConfig<Dim1, LeafNode<T2, Dim1> > { static const bool value = true; };
1163 
1164 
1166 
1167 
1168 template<typename T, Index Log2Dim>
1169 inline
1171  mValueMask(),//default is off!
1172  mOrigin(0, 0, 0)
1173 {
1174 }
1175 
1176 
1177 template<typename T, Index Log2Dim>
1178 inline
1179 LeafNode<T, Log2Dim>::LeafNode(const Coord& xyz, const ValueType& val, bool active):
1180  mBuffer(val),
1181  mValueMask(active),
1182  mOrigin(xyz & (~(DIM - 1)))
1183 {
1184 }
1185 
1186 
1187 #ifndef OPENVDB_2_ABI_COMPATIBLE
1188 template<typename T, Index Log2Dim>
1189 inline
1190 LeafNode<T, Log2Dim>::LeafNode(PartialCreate, const Coord& xyz, const ValueType& val, bool active):
1191  mBuffer(PartialCreate(), val),
1192  mValueMask(active),
1193  mOrigin(xyz & (~(DIM - 1)))
1194 {
1195 }
1196 #endif
1197 
1198 
1199 template<typename T, Index Log2Dim>
1200 inline
1202  mBuffer(other.mBuffer),
1203  mValueMask(other.valueMask()),
1204  mOrigin(other.mOrigin)
1205 {
1206 }
1207 
1208 
1209 // Copy-construct from a leaf node with the same configuration but a different ValueType.
1210 template<typename T, Index Log2Dim>
1211 template<typename OtherValueType>
1212 inline
1214  mValueMask(other.valueMask()),
1215  mOrigin(other.mOrigin)
1216 {
1217  struct Local {
1219  static inline ValueType convertValue(const OtherValueType& val) { return ValueType(val); }
1220  };
1221 
1222  for (Index i = 0; i < SIZE; ++i) {
1223  mBuffer[i] = Local::convertValue(other.mBuffer[i]);
1224  }
1225 }
1226 
1227 
1228 template<typename T, Index Log2Dim>
1229 template<typename OtherValueType>
1230 inline
1232  const ValueType& background, TopologyCopy):
1233  mBuffer(background),
1234  mValueMask(other.valueMask()),
1235  mOrigin(other.mOrigin)
1236 {
1237 }
1238 
1239 
1240 template<typename T, Index Log2Dim>
1241 template<typename OtherValueType>
1242 inline
1244  const ValueType& offValue, const ValueType& onValue, TopologyCopy):
1245  mValueMask(other.valueMask()),
1246  mOrigin(other.mOrigin)
1247 {
1248  for (Index i = 0; i < SIZE; ++i) {
1249  mBuffer[i] = (mValueMask.isOn(i) ? onValue : offValue);
1250  }
1251 }
1252 
1253 
1254 template<typename T, Index Log2Dim>
1255 inline
1257 {
1258 }
1259 
1260 
1261 template<typename T, Index Log2Dim>
1262 inline std::string
1264 {
1265  std::ostringstream ostr;
1266  ostr << "LeafNode @" << mOrigin << ": " << mBuffer;
1267  return ostr.str();
1268 }
1269 
1270 
1272 
1273 
1274 template<typename T, Index Log2Dim>
1275 inline Index
1277 {
1278  assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1279  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1280  + ((xyz[1] & (DIM-1u)) << Log2Dim)
1281  + (xyz[2] & (DIM-1u));
1282 }
1283 
1284 template<typename T, Index Log2Dim>
1285 inline Coord
1287 {
1288  assert(n<(1<< 3*Log2Dim));
1289  Coord xyz;
1290  xyz.setX(n >> 2*Log2Dim);
1291  n &= ((1<<2*Log2Dim)-1);
1292  xyz.setY(n >> Log2Dim);
1293  xyz.setZ(n & ((1<<Log2Dim)-1));
1294  return xyz;
1295 }
1296 
1297 
1298 template<typename T, Index Log2Dim>
1299 inline Coord
1301 {
1302  return (this->offsetToLocalCoord(n) + this->origin());
1303 }
1304 
1305 
1307 
1308 
1309 template<typename ValueT, Index Log2Dim>
1310 inline const ValueT&
1312 {
1313  return this->getValue(LeafNode::coordToOffset(xyz));
1314 }
1315 
1316 template<typename ValueT, Index Log2Dim>
1317 inline const ValueT&
1319 {
1320  assert(offset < SIZE);
1321  return mBuffer[offset];
1322 }
1323 
1324 
1325 template<typename T, Index Log2Dim>
1326 inline bool
1327 LeafNode<T, Log2Dim>::probeValue(const Coord& xyz, ValueType& val) const
1328 {
1329  return this->probeValue(LeafNode::coordToOffset(xyz), val);
1330 }
1331 
1332 template<typename T, Index Log2Dim>
1333 inline bool
1334 LeafNode<T, Log2Dim>::probeValue(Index offset, ValueType& val) const
1335 {
1336  assert(offset < SIZE);
1337  val = mBuffer[offset];
1338  return mValueMask.isOn(offset);
1339 }
1340 
1341 
1342 template<typename T, Index Log2Dim>
1343 inline void
1344 LeafNode<T, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& val)
1345 {
1346  this->setValueOff(LeafNode::coordToOffset(xyz), val);
1347 }
1348 
1349 template<typename T, Index Log2Dim>
1350 inline void
1351 LeafNode<T, Log2Dim>::setValueOff(Index offset, const ValueType& val)
1352 {
1353  assert(offset < SIZE);
1354  mBuffer.setValue(offset, val);
1355  mValueMask.setOff(offset);
1356 }
1357 
1358 
1359 template<typename T, Index Log2Dim>
1360 inline void
1362 {
1363  mValueMask.set(this->coordToOffset(xyz), on);
1364 }
1365 
1366 
1367 template<typename T, Index Log2Dim>
1368 inline void
1369 LeafNode<T, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& val)
1370 {
1371  this->setValueOnly(LeafNode::coordToOffset(xyz), val);
1372 }
1373 
1374 template<typename T, Index Log2Dim>
1375 inline void
1376 LeafNode<T, Log2Dim>::setValueOnly(Index offset, const ValueType& val)
1377 {
1378  assert(offset<SIZE); mBuffer.setValue(offset, val);
1379 }
1380 
1381 
1383 
1384 
1385 template<typename T, Index Log2Dim>
1386 inline void
1387 LeafNode<T, Log2Dim>::clip(const CoordBBox& clipBBox, const T& background)
1388 {
1389  CoordBBox nodeBBox = this->getNodeBoundingBox();
1390  if (!clipBBox.hasOverlap(nodeBBox)) {
1391  // This node lies completely outside the clipping region. Fill it with the background.
1392  this->fill(background, /*active=*/false);
1393  } else if (clipBBox.isInside(nodeBBox)) {
1394  // This node lies completely inside the clipping region. Leave it intact.
1395  return;
1396  }
1397 
1398  // This node isn't completely contained inside the clipping region.
1399  // Set any voxels that lie outside the region to the background value.
1400 
1401  // Construct a boolean mask that is on inside the clipping region and off outside it.
1402  NodeMaskType mask;
1403  nodeBBox.intersect(clipBBox);
1404  Coord xyz;
1405  int &x = xyz.x(), &y = xyz.y(), &z = xyz.z();
1406  for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++x) {
1407  for (y = nodeBBox.min().y(); y <= nodeBBox.max().y(); ++y) {
1408  for (z = nodeBBox.min().z(); z <= nodeBBox.max().z(); ++z) {
1409  mask.setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1410  }
1411  }
1412  }
1413 
1414  // Set voxels that lie in the inactive region of the mask (i.e., outside
1415  // the clipping region) to the background value.
1416  for (MaskOffIterator maskIter = mask.beginOff(); maskIter; ++maskIter) {
1417  this->setValueOff(maskIter.pos(), background);
1418  }
1419 }
1420 
1421 
1423 
1424 
1425 template<typename T, Index Log2Dim>
1426 inline void
1427 LeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1428 {
1429 #ifndef OPENVDB_2_ABI_COMPATIBLE
1430  if (!this->allocate()) return;
1431 #endif
1432 
1433  for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1434  const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1435  for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1436  const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1437  for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1438  const Index offset = offsetXY + (z & (DIM-1u));
1439  mBuffer[offset] = value;
1440  mValueMask.set(offset, active);
1441  }
1442  }
1443  }
1444 }
1445 
1446 template<typename T, Index Log2Dim>
1447 inline void
1448 LeafNode<T, Log2Dim>::fill(const ValueType& value)
1449 {
1450  mBuffer.fill(value);
1451 }
1452 
1453 template<typename T, Index Log2Dim>
1454 inline void
1455 LeafNode<T, Log2Dim>::fill(const ValueType& value, bool active)
1456 {
1457  mBuffer.fill(value);
1458  mValueMask.set(active);
1459 }
1460 
1461 
1463 
1464 
1465 template<typename T, Index Log2Dim>
1466 template<typename DenseT>
1467 inline void
1468 LeafNode<T, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1469 {
1470 #ifndef OPENVDB_2_ABI_COMPATIBLE
1471  if (!this->isAllocated()) return;
1472 #endif
1473 
1474  typedef typename DenseT::ValueType DenseValueType;
1475 
1476  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1477  const Coord& min = dense.bbox().min();
1478  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1479  const T* s0 = &mBuffer[bbox.min()[2] & (DIM-1u)]; // source array
1480  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1481  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1482  const T* s1 = s0 + ((x & (DIM-1u)) << 2*Log2Dim);
1483  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1484  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1485  const T* s2 = s1 + ((y & (DIM-1u)) << Log2Dim);
1486  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1487  *t2 = DenseValueType(*s2++);
1488  }
1489  }
1490  }
1491 }
1492 
1493 
1494 template<typename T, Index Log2Dim>
1495 template<typename DenseT>
1496 inline void
1497 LeafNode<T, Log2Dim>::copyFromDense(const CoordBBox& bbox, const DenseT& dense,
1498  const ValueType& background, const ValueType& tolerance)
1499 {
1500 #ifndef OPENVDB_2_ABI_COMPATIBLE
1501  if (!this->allocate()) return;
1502 #endif
1503 
1504  typedef typename DenseT::ValueType DenseValueType;
1505 
1506  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1507  const Coord& min = dense.bbox().min();
1508 
1509  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1510  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1511  for (Int32 x = bbox.min()[0], ex = bbox.max()[0]+1; x < ex; ++x) {
1512  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1513  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1514  for (Int32 y = bbox.min()[1], ey = bbox.max()[1]+1; y < ey; ++y) {
1515  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1516  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1517  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1518  if (math::isApproxEqual(background, ValueType(*s2), tolerance)) {
1519  mValueMask.setOff(n2);
1520  mBuffer[n2] = background;
1521  } else {
1522  mValueMask.setOn(n2);
1523  mBuffer[n2] = ValueType(*s2);
1524  }
1525  }
1526  }
1527  }
1528 }
1529 
1530 
1532 
1533 
1534 template<typename T, Index Log2Dim>
1535 inline void
1536 LeafNode<T, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
1537 {
1538  mValueMask.load(is);
1539 }
1540 
1541 
1542 template<typename T, Index Log2Dim>
1543 inline void
1544 LeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
1545 {
1546  mValueMask.save(os);
1547 }
1548 
1549 
1551 
1552 
1553 #ifndef OPENVDB_2_ABI_COMPATIBLE
1554 template<typename T, Index Log2Dim>
1555 inline void
1557 {
1558  if (!this->isOutOfCore()) return;
1559 
1560  Buffer* self = const_cast<Buffer*>(this);
1561 
1562  // This lock will be contended at most once, after which this buffer
1563  // will no longer be out-of-core.
1564  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1565  if (!this->isOutOfCore()) return;
1566 
1567  boost::scoped_ptr<FileInfo> info(self->mFileInfo);
1568  assert(info.get() != NULL);
1569  assert(info->mapping.get() != NULL);
1570  assert(info->meta.get() != NULL);
1571 
1573  self->mData = NULL;
1574  self->allocate();
1575 
1576  boost::shared_ptr<std::streambuf> buf = info->mapping->createBuffer();
1577  std::istream is(buf.get());
1578 
1579  io::setStreamMetadataPtr(is, info->meta, /*transfer=*/true);
1580 
1581  NodeMaskType mask;
1582  is.seekg(info->maskpos);
1583  mask.load(is);
1584 
1585  is.seekg(info->bufpos);
1586  io::readCompressedValues(is, self->mData, SIZE, mask, io::getHalfFloat(is));
1587 
1588  self->setOutOfCore(false);
1589 }
1590 #endif
1591 
1592 
1594 
1595 
1596 template<typename T, Index Log2Dim>
1597 inline void
1598 LeafNode<T,Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1599 {
1600  this->readBuffers(is, CoordBBox::inf(), fromHalf);
1601 }
1602 
1603 
1604 template<typename T, Index Log2Dim>
1605 inline void
1606 LeafNode<T,Log2Dim>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
1607 {
1608 #ifndef OPENVDB_2_ABI_COMPATIBLE
1609  std::streamoff maskpos = is.tellg();
1610 #endif
1611 
1612  // Read in the value mask.
1613  mValueMask.load(is);
1614 
1615  int8_t numBuffers = 1;
1617  // Read in the origin.
1618  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
1619 
1620  // Read in the number of buffers, which should now always be one.
1621  is.read(reinterpret_cast<char*>(&numBuffers), sizeof(int8_t));
1622  }
1623 
1624  CoordBBox nodeBBox = this->getNodeBoundingBox();
1625  if (!clipBBox.hasOverlap(nodeBBox)) {
1626  // This node lies completely outside the clipping region.
1627  // Read and discard its voxel values.
1628  Buffer temp;
1629  io::readCompressedValues(is, temp.mData, SIZE, mValueMask, fromHalf);
1630  mValueMask.setOff();
1631  mBuffer.setOutOfCore(false);
1632  } else {
1633 #ifndef OPENVDB_2_ABI_COMPATIBLE
1634  // If this node lies completely inside the clipping region and it is being read
1635  // from a memory-mapped file, delay loading of its buffer until the buffer
1636  // is actually accessed. (If this node requires clipping, its buffer
1637  // must be accessed and therefore must be loaded.)
1638  io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
1639  const bool delayLoad = ((mappedFile.get() != NULL) && clipBBox.isInside(nodeBBox));
1640 
1641  if (delayLoad) {
1642  mBuffer.setOutOfCore(true);
1643  mBuffer.mFileInfo = new FileInfo;
1644  mBuffer.mFileInfo->bufpos = is.tellg();
1645  mBuffer.mFileInfo->mapping = mappedFile;
1646  // Save the offset to the value mask, because the in-memory copy
1647  // might change before the value buffer gets read.
1648  mBuffer.mFileInfo->maskpos = maskpos;
1649 
1650  mBuffer.mFileInfo->meta = io::getStreamMetadataPtr(is);
1651 
1652  // Read and discard voxel values.
1653  Buffer temp;
1654  io::readCompressedValues(is, temp.mData, SIZE, mValueMask, fromHalf);
1655  } else {
1656 #endif
1657  mBuffer.allocate();
1658  io::readCompressedValues(is, mBuffer.mData, SIZE, mValueMask, fromHalf);
1659  mBuffer.setOutOfCore(false);
1660 
1661  // Get this tree's background value.
1662  T background = zeroVal<T>();
1663  if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
1664  background = *static_cast<const T*>(bgPtr);
1665  }
1666  this->clip(clipBBox, background);
1667 #ifndef OPENVDB_2_ABI_COMPATIBLE
1668  }
1669 #endif
1670  }
1671 
1672  if (numBuffers > 1) {
1673  // Read in and discard auxiliary buffers that were created with earlier
1674  // versions of the library. (Auxiliary buffers are not mask compressed.)
1675  const bool zipped = io::getDataCompression(is) & io::COMPRESS_ZIP;
1676  Buffer temp;
1677  for (int i = 1; i < numBuffers; ++i) {
1678  if (fromHalf) {
1679  io::HalfReader<io::RealToHalf<T>::isReal, T>::read(is, temp.mData, SIZE, zipped);
1680  } else {
1681  io::readData<T>(is, temp.mData, SIZE, zipped);
1682  }
1683  }
1684  }
1685 }
1686 
1687 
1688 template<typename T, Index Log2Dim>
1689 inline void
1690 LeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1691 {
1692  // Write out the value mask.
1693  mValueMask.save(os);
1694 
1695  mBuffer.loadValues();
1696 
1697  io::writeCompressedValues(os, mBuffer.mData, SIZE,
1698  mValueMask, /*childMask=*/NodeMaskType(), toHalf);
1699 }
1700 
1701 
1703 
1704 
1705 template<typename T, Index Log2Dim>
1706 inline bool
1708 {
1709  return mOrigin == other.mOrigin &&
1710  mValueMask == other.valueMask() &&
1711  mBuffer == other.mBuffer;
1712 }
1713 
1714 
1715 template<typename T, Index Log2Dim>
1716 inline Index64
1718 {
1719  // Use sizeof(*this) to capture alignment-related padding
1720  // (but note that sizeof(*this) includes sizeof(mBuffer)).
1721  return sizeof(*this) + mBuffer.memUsage() - sizeof(mBuffer);
1722 }
1723 
1724 
1725 template<typename T, Index Log2Dim>
1726 inline void
1728 {
1729  CoordBBox this_bbox = this->getNodeBoundingBox();
1730  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
1731  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
1732  if (visitVoxels) {//use voxel granularity?
1733  this_bbox.reset();
1734  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
1735  this_bbox.translate(this->origin());
1736  }
1737  bbox.expand(this_bbox);
1738  }
1739 }
1740 
1741 
1742 template<typename T, Index Log2Dim>
1743 template<typename OtherType, Index OtherLog2Dim>
1744 inline bool
1746 {
1747  assert(other);
1748  return (Log2Dim == OtherLog2Dim && mValueMask == other->getValueMask());
1749 }
1750 
1751 template<typename T, Index Log2Dim>
1752 inline bool
1753 LeafNode<T, Log2Dim>::isConstant(ValueType& firstValue,
1754  bool& state,
1755  const ValueType& tolerance) const
1756 {
1757  if (!mValueMask.isConstant(state)) return false;// early termination
1758  firstValue = mBuffer[0];
1759  for (Index i = 1; i < SIZE; ++i) {
1760  if ( !math::isApproxEqual(mBuffer[i], firstValue, tolerance) ) return false;// early termination
1761  }
1762  return true;
1763 }
1764 
1765 template<typename T, Index Log2Dim>
1766 inline bool
1768  ValueType& maxValue,
1769  bool& state,
1770  const ValueType& tolerance) const
1771 {
1772  if (!mValueMask.isConstant(state)) return false;// early termination
1773  minValue = maxValue = mBuffer[0];
1774  for (Index i = 1; i < SIZE; ++i) {
1775  const T& v = mBuffer[i];
1776  if (v < minValue) {
1777  if ((maxValue - v) > tolerance) return false;// early termination
1778  minValue = v;
1779  } else if (v > maxValue) {
1780  if ((v - minValue) > tolerance) return false;// early termination
1781  maxValue = v;
1782  }
1783  }
1784  return true;
1785 }
1786 
1788 
1789 
1790 template<typename T, Index Log2Dim>
1791 inline void
1792 LeafNode<T, Log2Dim>::addTile(Index /*level*/, const Coord& xyz, const ValueType& val, bool active)
1793 {
1794  this->addTile(this->coordToOffset(xyz), val, active);
1795 }
1796 
1797 template<typename T, Index Log2Dim>
1798 inline void
1799 LeafNode<T, Log2Dim>::addTile(Index offset, const ValueType& val, bool active)
1800 {
1801  assert(offset < SIZE);
1802  setValueOnly(offset, val);
1803  setActiveState(offset, active);
1804 }
1805 
1806 template<typename T, Index Log2Dim>
1807 template<typename AccessorT>
1808 inline void
1810  const ValueType& val, bool active, AccessorT&)
1811 {
1812  this->addTile(level, xyz, val, active);
1813 }
1814 
1815 
1817 
1818 
1819 template<typename T, Index Log2Dim>
1820 inline void
1821 LeafNode<T, Log2Dim>::resetBackground(const ValueType& oldBackground,
1822  const ValueType& newBackground)
1823 {
1824 #ifndef OPENVDB_2_ABI_COMPATIBLE
1825  if (!this->allocate()) return;
1826 #endif
1827 
1828  typename NodeMaskType::OffIterator iter;
1829  // For all inactive values...
1830  for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1831  ValueType &inactiveValue = mBuffer[iter.pos()];
1832  if (math::isApproxEqual(inactiveValue, oldBackground)) {
1833  inactiveValue = newBackground;
1834  } else if (math::isApproxEqual(inactiveValue, math::negative(oldBackground))) {
1835  inactiveValue = math::negative(newBackground);
1836  }
1837  }
1838 }
1839 
1840 
1841 template<typename T, Index Log2Dim>
1842 template<MergePolicy Policy>
1843 inline void
1845 {
1846 #ifndef OPENVDB_2_ABI_COMPATIBLE
1847  if (!this->allocate()) return;
1848 #endif
1849 
1851  if (Policy == MERGE_NODES) return;
1852  typename NodeMaskType::OnIterator iter = other.valueMask().beginOn();
1853  for (; iter; ++iter) {
1854  const Index n = iter.pos();
1855  if (mValueMask.isOff(n)) {
1856  mBuffer[n] = other.mBuffer[n];
1857  mValueMask.setOn(n);
1858  }
1859  }
1861 }
1862 
1863 template<typename T, Index Log2Dim>
1864 template<MergePolicy Policy>
1865 inline void
1867  const ValueType& /*bg*/, const ValueType& /*otherBG*/)
1868 {
1869  this->template merge<Policy>(other);
1870 }
1871 
1872 template<typename T, Index Log2Dim>
1873 template<MergePolicy Policy>
1874 inline void
1875 LeafNode<T, Log2Dim>::merge(const ValueType& tileValue, bool tileActive)
1876 {
1877 #ifndef OPENVDB_2_ABI_COMPATIBLE
1878  if (!this->allocate()) return;
1879 #endif
1880 
1882  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1883  if (!tileActive) return;
1884  // Replace all inactive values with the active tile value.
1885  for (typename NodeMaskType::OffIterator iter = mValueMask.beginOff(); iter; ++iter) {
1886  const Index n = iter.pos();
1887  mBuffer[n] = tileValue;
1888  mValueMask.setOn(n);
1889  }
1891 }
1892 
1893 
1894 template<typename T, Index Log2Dim>
1895 template<typename OtherType>
1896 inline void
1898 {
1899  mValueMask |= other.valueMask();
1900 }
1901 
1902 template<typename T, Index Log2Dim>
1903 template<typename OtherType>
1904 inline void
1906  const ValueType&)
1907 {
1908  mValueMask &= other.valueMask();
1909 }
1910 
1911 template<typename T, Index Log2Dim>
1912 template<typename OtherType>
1913 inline void
1915  const ValueType&)
1916 {
1917  mValueMask &= !other.valueMask();
1918 }
1919 
1920 template<typename T, Index Log2Dim>
1921 inline void
1923 {
1924 #ifndef OPENVDB_2_ABI_COMPATIBLE
1925  if (!this->allocate()) return;
1926 #endif
1927  for (Index i = 0; i < SIZE; ++i) {
1928  mBuffer[i] = -mBuffer[i];
1929  }
1930 }
1931 
1932 
1934 
1935 
1936 template<typename T, Index Log2Dim>
1937 template<typename CombineOp>
1938 inline void
1939 LeafNode<T, Log2Dim>::combine(const LeafNode& other, CombineOp& op)
1940 {
1941 #ifndef OPENVDB_2_ABI_COMPATIBLE
1942  if (!this->allocate()) return;
1943 #endif
1944  CombineArgs<T> args;
1945  for (Index i = 0; i < SIZE; ++i) {
1946  op(args.setARef(mBuffer[i])
1947  .setAIsActive(mValueMask.isOn(i))
1948  .setBRef(other.mBuffer[i])
1949  .setBIsActive(other.valueMask().isOn(i))
1950  .setResultRef(mBuffer[i]));
1951  mValueMask.set(i, args.resultIsActive());
1952  }
1953 }
1954 
1955 
1956 template<typename T, Index Log2Dim>
1957 template<typename CombineOp>
1958 inline void
1959 LeafNode<T, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op)
1960 {
1961 #ifndef OPENVDB_2_ABI_COMPATIBLE
1962  if (!this->allocate()) return;
1963 #endif
1964  CombineArgs<T> args;
1965  args.setBRef(value).setBIsActive(valueIsActive);
1966  for (Index i = 0; i < SIZE; ++i) {
1967  op(args.setARef(mBuffer[i])
1968  .setAIsActive(mValueMask.isOn(i))
1969  .setResultRef(mBuffer[i]));
1970  mValueMask.set(i, args.resultIsActive());
1971  }
1972 }
1973 
1974 
1976 
1977 
1978 template<typename T, Index Log2Dim>
1979 template<typename CombineOp, typename OtherType>
1980 inline void
1981 LeafNode<T, Log2Dim>::combine2(const LeafNode& other, const OtherType& value,
1982  bool valueIsActive, CombineOp& op)
1983 {
1984 #ifndef OPENVDB_2_ABI_COMPATIBLE
1985  if (!this->allocate()) return;
1986 #endif
1988  args.setBRef(value).setBIsActive(valueIsActive);
1989  for (Index i = 0; i < SIZE; ++i) {
1990  op(args.setARef(other.mBuffer[i])
1991  .setAIsActive(other.valueMask().isOn(i))
1992  .setResultRef(mBuffer[i]));
1993  mValueMask.set(i, args.resultIsActive());
1994  }
1995 }
1996 
1997 
1998 template<typename T, Index Log2Dim>
1999 template<typename CombineOp, typename OtherNodeT>
2000 inline void
2001 LeafNode<T, Log2Dim>::combine2(const ValueType& value, const OtherNodeT& other,
2002  bool valueIsActive, CombineOp& op)
2003 {
2004 #ifndef OPENVDB_2_ABI_COMPATIBLE
2005  if (!this->allocate()) return;
2006 #endif
2008  args.setARef(value).setAIsActive(valueIsActive);
2009  for (Index i = 0; i < SIZE; ++i) {
2010  op(args.setBRef(other.mBuffer[i])
2011  .setBIsActive(other.valueMask().isOn(i))
2012  .setResultRef(mBuffer[i]));
2013  mValueMask.set(i, args.resultIsActive());
2014  }
2015 }
2016 
2017 
2018 template<typename T, Index Log2Dim>
2019 template<typename CombineOp, typename OtherNodeT>
2020 inline void
2021 LeafNode<T, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
2022 {
2023 #ifndef OPENVDB_2_ABI_COMPATIBLE
2024  if (!this->allocate()) return;
2025 #endif
2027  for (Index i = 0; i < SIZE; ++i) {
2028  mValueMask.set(i, b0.valueMask().isOn(i) || b1.valueMask().isOn(i));
2029  op(args.setARef(b0.mBuffer[i])
2030  .setAIsActive(b0.valueMask().isOn(i))
2031  .setBRef(b1.mBuffer[i])
2032  .setBIsActive(b1.valueMask().isOn(i))
2033  .setResultRef(mBuffer[i]));
2034  mValueMask.set(i, args.resultIsActive());
2035  }
2036 }
2037 
2038 
2040 
2041 
2042 template<typename T, Index Log2Dim>
2043 template<typename BBoxOp>
2044 inline void
2046 {
2047  if (op.template descent<LEVEL>()) {
2048  for (ValueOnCIter i=this->cbeginValueOn(); i; ++i) {
2049 #ifdef _MSC_VER
2050  op.operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
2051 #else
2052  op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
2053 #endif
2054  }
2055  } else {
2056 #ifdef _MSC_VER
2057  op.operator()<LEVEL>(this->getNodeBoundingBox());
2058 #else
2059  op.template operator()<LEVEL>(this->getNodeBoundingBox());
2060 #endif
2061  }
2062 }
2063 
2064 
2065 template<typename T, Index Log2Dim>
2066 template<typename VisitorOp>
2067 inline void
2069 {
2070  doVisit<LeafNode, VisitorOp, ChildAllIter>(*this, op);
2071 }
2072 
2073 
2074 template<typename T, Index Log2Dim>
2075 template<typename VisitorOp>
2076 inline void
2077 LeafNode<T, Log2Dim>::visit(VisitorOp& op) const
2078 {
2079  doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*this, op);
2080 }
2081 
2082 
2083 template<typename T, Index Log2Dim>
2084 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
2085 inline void
2086 LeafNode<T, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
2087 {
2088  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2089  op(iter);
2090  }
2091 }
2092 
2093 
2095 
2096 
2097 template<typename T, Index Log2Dim>
2098 template<typename OtherLeafNodeType, typename VisitorOp>
2099 inline void
2100 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op)
2101 {
2102  doVisit2Node<LeafNode, OtherLeafNodeType, VisitorOp, ChildAllIter,
2103  typename OtherLeafNodeType::ChildAllIter>(*this, other, op);
2104 }
2105 
2106 
2107 template<typename T, Index Log2Dim>
2108 template<typename OtherLeafNodeType, typename VisitorOp>
2109 inline void
2110 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op) const
2111 {
2112  doVisit2Node<const LeafNode, OtherLeafNodeType, VisitorOp, ChildAllCIter,
2113  typename OtherLeafNodeType::ChildAllCIter>(*this, other, op);
2114 }
2115 
2116 
2117 template<typename T, Index Log2Dim>
2118 template<
2119  typename NodeT,
2120  typename OtherNodeT,
2121  typename VisitorOp,
2122  typename ChildAllIterT,
2123  typename OtherChildAllIterT>
2124 inline void
2125 LeafNode<T, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
2126 {
2127  // Allow the two nodes to have different ValueTypes, but not different dimensions.
2128  BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
2129  BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
2130 
2131  ChildAllIterT iter = self.beginChildAll();
2132  OtherChildAllIterT otherIter = other.beginChildAll();
2133 
2134  for ( ; iter && otherIter; ++iter, ++otherIter) {
2135  op(iter, otherIter);
2136  }
2137 }
2138 
2139 
2141 
2142 
2143 template<typename T, Index Log2Dim>
2144 template<typename IterT, typename VisitorOp>
2145 inline void
2146 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS)
2147 {
2148  doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
2149  *this, otherIter, op, otherIsLHS);
2150 }
2151 
2152 
2153 template<typename T, Index Log2Dim>
2154 template<typename IterT, typename VisitorOp>
2155 inline void
2156 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS) const
2157 {
2158  doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
2159  *this, otherIter, op, otherIsLHS);
2160 }
2161 
2162 
2163 template<typename T, Index Log2Dim>
2164 template<
2165  typename NodeT,
2166  typename VisitorOp,
2167  typename ChildAllIterT,
2168  typename OtherChildAllIterT>
2169 inline void
2170 LeafNode<T, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
2171  VisitorOp& op, bool otherIsLHS)
2172 {
2173  if (!otherIter) return;
2174 
2175  if (otherIsLHS) {
2176  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2177  op(otherIter, iter);
2178  }
2179  } else {
2180  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2181  op(iter, otherIter);
2182  }
2183  }
2184 }
2185 
2186 
2188 
2189 
2190 template<typename T, Index Log2Dim>
2191 inline std::ostream&
2192 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
2193 {
2194  for (Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] << ", ";
2195  return os;
2196 }
2197 
2198 } // namespace tree
2199 } // namespace OPENVDB_VERSION_NAME
2200 } // namespace openvdb
2201 
2202 
2204 
2205 
2206 // Specialization for LeafNodes of type bool
2207 #include "LeafNodeBool.h"
2208 
2209 // Specialization for LeafNodes with mask information only
2210 #include "LeafNodeMask.h"
2211 
2212 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
2213 
2214 // Copyright (c) 2012-2016 DreamWorks Animation LLC
2215 // All rights reserved. This software is distributed under the
2216 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
ChildOnIter beginChildOn()
Definition: LeafNode.h:618
OffIterator beginOff() const
Definition: NodeMasks.h:351
T BuildType
Definition: LeafNode.h:68
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:828
boost::shared_ptr< MappedFile > Ptr
Definition: io.h:135
std::streamoff maskpos
Definition: LeafNode.h:102
bool isValueMaskOff(Index n) const
Definition: LeafNode.h:1107
void stealNodes(ArrayT &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNode.h:1010
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1727
bool isValueMaskOn() const
Definition: LeafNode.h:1106
bool resultIsActive() const
Definition: Types.h:376
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:469
static const Index LEVEL
Definition: LeafNode.h:81
void negate()
Definition: LeafNode.h:1922
bool isOff(Index32 n) const
Return true if the nth bit is off.
Definition: NodeMasks.h:505
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1276
static Index size()
Return the number of values contained in this buffer.
Definition: LeafNode.h:263
bool isOn(Index32 n) const
Return true if the nth bit is on.
Definition: NodeMasks.h:499
DenseIteratorBase< MaskDenseIterator, DenseIter, NodeT, void, ValueT > BaseT
Definition: LeafNode.h:557
OPENVDB_API void setStreamMetadataPtr(std::ios_base &, boost::shared_ptr< StreamMetadata > &, bool transfer=true)
Associate the given stream with (a shared pointer to) an object that stores metadata (file format...
bool isValueMaskOn(Index n) const
Definition: LeafNode.h:1105
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
Definition: LeafNode.h:429
ChildIter< MaskOffIterator, const LeafNode, ChildOff > ChildOffCIter
Definition: LeafNode.h:590
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:407
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition: LeafNode.h:1745
Coord & setX(Int32 x)
Definition: Coord.h:101
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1717
const ValueType & operator[](Index i) const
Return a const reference to the i&#39;th element of this buffer.
Definition: LeafNode.h:184
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1792
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
Definition: LeafNode.h:437
void setValueMask(Index n, bool on)
Definition: LeafNode.h:1117
ChildOnCIter cendChildOn() const
Definition: LeafNode.h:626
void copyToDense(const GridOrTreeT &sparse, DenseT &dense, bool serial=false)
Populate a dense grid with the values of voxels from a sparse grid, where the sparse grid intersects ...
Definition: Dense.h:443
Definition: LeafNode.h:50
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1544
Definition: Types.h:442
ValueOnCIter endValueOn() const
Definition: LeafNode.h:605
void reset()
Definition: Coord.h:338
FileInfo()
Definition: LeafNode.h:100
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
Definition: LeafNode.h:867
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNode.h:563
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:1006
OnIterator beginOn() const
Definition: NodeMasks.h:349
void load(std::istream &is)
Definition: NodeMasks.h:566
void voxelizeActiveTiles(bool=true)
No-op.
Definition: LeafNode.h:922
BaseT::NonConstValueType NonConstValueT
Definition: LeafNode.h:558
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: LeafNode.h:714
ValueOffIter beginValueOff()
Definition: LeafNode.h:599
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a LeafNod...
Definition: LeafNode.h:93
ChildAllCIter endChildAll() const
Definition: LeafNode.h:633
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:519
void visit(VisitorOp &)
Definition: LeafNode.h:2068
io::MappedFile::Ptr mapping
Definition: LeafNode.h:103
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1286
OPENVDB_API boost::shared_ptr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme...
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:498
Buffer & buffer()
Definition: LeafNode.h:643
void setValue(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNode.h:722
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNode.h:1004
void setValueMask(const NodeMaskType &mask)
Definition: LeafNode.h:1112
ValueType * data()
Return a pointer to the array of voxel values.
Definition: LeafNode.h:285
Int32 ValueType
Definition: Coord.h:55
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:365
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Difference this node&#39;s set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this LeafNode and inactive in the other LeafNode.
Definition: LeafNode.h:1914
const ValueType & getLastValue() const
Return a const reference to the last value in the buffer.
Definition: LeafNode.h:912
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:448
LeafNode< OtherValueType, Log2Dim > Type
Definition: LeafNode.h:87
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition: LeafNode.h:1468
ValueOffCIter cendValueOff() const
Definition: LeafNode.h:607
ValueIter()
Definition: LeafNode.h:518
bool allocate()
Allocate memory for this buffer if it has not already been allocated.
Definition: LeafNode.h:168
void setValueOn(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNode.h:718
static Index dim()
Return the number of voxels in each coordinate dimension.
Definition: LeafNode.h:423
void modifyValue(Index offset, const ModifyOp &op)
Apply a functor to the value of the voxel at the given offset and mark the voxel as active...
Definition: LeafNode.h:732
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1598
Definition: PointIndexGrid.h:69
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: LeafNode.h:592
bool isDense() const
Return true if this node contains only active voxels.
Definition: LeafNode.h:450
ValueIter< MaskDenseIterator, LeafNode, const ValueType, ValueAll > ValueAllIter
Definition: LeafNode.h:585
ValueConverter<T>::Type is the type of a LeafNode having the same dimensions as this node but a diffe...
Definition: LeafNode.h:86
ValueOnIter beginValueOn()
Definition: LeafNode.h:596
ValueIter< MaskOnIterator, const LeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: LeafNode.h:582
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don&#39;t change its value. ...
Definition: LeafNode.h:696
bool allocate()
Allocate memory for this node&#39;s buffer if it has not already been allocated.
Definition: LeafNode.h:456
Int32 x() const
Definition: Coord.h:146
FileInfo * mFileInfo
Definition: LeafNode.h:362
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
ValueOnIter endValueOn()
Definition: LeafNode.h:606
Array of fixed size that stores the voxel values of a LeafNode.
Definition: LeafNode.h:110
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:1024
void setValue(Index i, const ValueType &val)
Set the i&#39;th value of this buffer to the specified value.
Definition: LeafNode.h:186
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:1263
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:477
SparseIteratorBase< MaskIterT, ValueIter, NodeT, ValueT > BaseT
Definition: LeafNode.h:516
void copyFromDense(const DenseT &dense, GridOrTreeT &sparse, const typename GridOrTreeT::ValueType &tolerance, bool serial=false)
Populate a sparse grid with the values of all of the voxels of a dense grid.
Definition: Dense.h:590
bool isChildMaskOff() const
Definition: LeafNode.h:1115
Index32 pos() const
Definition: NodeMasks.h:193
ValueType * mData
Definition: LeafNode.h:361
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:330
Coord & setY(Int32 y)
Definition: Coord.h:102
ChildAllIter beginChildAll()
Definition: LeafNode.h:624
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
Definition: LeafNode.h:588
void setValuesOn()
Mark all voxels as active but don&#39;t change their values.
Definition: LeafNode.h:760
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:370
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Replace inactive occurrences of oldBackground with newBackground, and inactive occurrences of -oldBac...
Definition: LeafNode.h:1821
OPENVDB_API bool getHalfFloat(std::ios_base &)
Return true if floating-point values should be quantized to 16 bits when writing to the given stream ...
Index32 Index
Definition: Types.h:58
bool isConstant(bool &isOn) const
Definition: NodeMasks.h:523
const ValueType & getFirstValue() const
Return a const reference to the first value in the buffer.
Definition: LeafNode.h:910
static Index64 offTileCount()
Definition: LeafNode.h:446
ValueIter< MaskOffIterator, LeafNode, const ValueType, ValueOff > ValueOffIter
Definition: LeafNode.h:583
int32_t Int32
Definition: Types.h:60
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNode.h:1008
boost::shared_ptr< io::StreamMetadata > meta
Definition: LeafNode.h:104
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1981
void modifyValue(const ModifyOp &op) const
Definition: LeafNode.h:540
uint64_t Index64
Definition: Types.h:57
const LeafNode * probeLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNode.h:1042
bool empty() const
Return true if memory for this buffer has not yet been allocated.
Definition: LeafNode.h:165
const ValueType & getValue(const Coord &xyz, bool &state, int &level, AccessorT &) const
Return the value of the voxel at the given coordinates and return its active state and level (i...
Definition: LeafNode.h:894
void fill(const ValueType &val)
Populate this buffer with a constant value.
Definition: LeafNode.h:171
ValueT & getItem(Index pos) const
Definition: LeafNode.h:521
#define OPENVDB_VERSION_NAME
Definition: version.h:43
OPENVDB_API boost::shared_ptr< MappedFile > getMappedFilePtr(std::ios_base &)
Return a shared pointer to the memory-mapped file with which the given stream is associated, or a null pointer if the stream is not associated with a memory-mapped file.
OPENVDB_STATIC_SPECIALIZATION GridType::Ptr clip(const GridType &grid, const BBoxd &)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:356
Buffer()
Default constructor.
Definition: LeafNode.h:131
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:329
const Coord & origin() const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:475
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: LeafNode.h:1387
Coord & setZ(Int32 z)
Definition: Coord.h:103
bool isOutOfCore() const
Return true if this buffer&#39;s values have not yet been read from disk.
Definition: LeafNode.h:163
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:401
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
Definition: LeafNode.h:431
void swap(Buffer &other)
Exchange this node&#39;s data buffer with the given data buffer without changing the active states of the...
Definition: LeafNode.h:641
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1707
ValueIter< MaskOnIterator, LeafNode, const ValueType, ValueOn > ValueOnIter
Definition: LeafNode.h:581
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNode.h:767
bool isChildMaskOff(Index) const
Definition: LeafNode.h:1114
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
void visit2Node(OtherLeafNodeType &other, VisitorOp &)
Definition: LeafNode.h:2100
NodeMaskType::OnIterator MaskOnIterator
Definition: LeafNode.h:501
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:476
ChildOnIter endChildOn()
Definition: LeafNode.h:628
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNode.h:905
const ValueType & getValue(Index i) const
Return a const reference to the i&#39;th element of this buffer.
Definition: LeafNode.h:182
bool isValueMaskOff() const
Definition: LeafNode.h:1108
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: LeafNode.h:742
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: LeafNode.h:1361
ChildAllCIter beginChildAll() const
Definition: LeafNode.h:623
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
ValueIter< MaskDenseIterator, const LeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: LeafNode.h:586
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNode.h:859
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:820
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:304
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1809
void translate(const Coord &t)
Translate this bounding box by .
Definition: Coord.h:440
~LeafNode()
Destructor.
Definition: LeafNode.h:1256
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:431
static Index32 leafCount()
Return the leaf count for this node, which is one.
Definition: LeafNode.h:435
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1536
const ValueType * data() const
Return a const pointer to the array of voxel values.
Definition: LeafNode.h:268
ValueOnCIter beginValueOn() const
Definition: LeafNode.h:595
Definition: Exceptions.h:39
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other)
Union this node&#39;s set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1897
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: LeafNode.h:561
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:1002
ChildOffIter endChildOff()
Definition: LeafNode.h:631
uint32_t Index32
Definition: Types.h:56
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:129
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: LeafNode.h:876
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:440
util::NodeMask< Log2Dim > NodeMaskType
Definition: LeafNode.h:72
std::streamoff bufpos
Definition: LeafNode.h:101
ValueOnCIter cendValueOn() const
Definition: LeafNode.h:604
void swap(Buffer &other)
Exchange this buffer&#39;s values with the other buffer&#39;s values.
Definition: LeafNode.h:242
const NodeMaskType & valueMask() const
Definition: LeafNode.h:1111
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNode.h:1122
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1039
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:211
Index memUsage() const
Return the memory footprint of this buffer in bytes.
Definition: LeafNode.h:251
void setValueMaskOn(Index n)
Definition: LeafNode.h:1118
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:148
ChildOnCIter endChildOn() const
Definition: LeafNode.h:627
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:217
void set(Index32 n, bool On)
Set the nth bit to the specified state.
Definition: NodeMasks.h:459
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1311
static void doVisit2(NodeT &self, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: LeafNode.h:2170
ChildOffCIter cendChildOff() const
Definition: LeafNode.h:629
ChildIter()
Definition: LeafNode.h:548
Int32 z() const
Definition: Coord.h:148
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information. An additional level argument is pro...
Definition: LeafNode.h:2045
static Index64 onTileCount()
Definition: LeafNode.h:445
ChildIter< MaskOffIterator, LeafNode, ChildOff > ChildOffIter
Definition: LeafNode.h:589
Definition: NodeMasks.h:267
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: LeafNode.h:851
static const Index SIZE
Definition: LeafNode.h:80
ValueType WordType
Definition: LeafNode.h:128
NodeMaskType::OffIterator MaskOffIterator
Definition: LeafNode.h:502
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:449
NodeMaskType & getValueMask()
Definition: LeafNode.h:1110
void setValueMaskOff(Index n)
Definition: LeafNode.h:1119
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1939
const Coord & min() const
Definition: Coord.h:332
Definition: Compression.h:211
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1044
Buffer(PartialCreate, const ValueType &)
Construct a buffer but don&#39;t allocate memory for the full array of values.
Definition: LeafNode.h:151
ChildOffIter beginChildOff()
Definition: LeafNode.h:621
ValueAllCIter beginValueAll() const
Definition: LeafNode.h:601
void setValue(const ValueT &value) const
Definition: LeafNode.h:530
ValueAllCIter cendValueAll() const
Definition: LeafNode.h:610
bool probeValueAndCache(const Coord &xyz, ValueType &val, AccessorT &) const
Return true if the voxel at the given coordinates is active and return the voxel value in val...
Definition: LeafNode.h:885
static void doVisit2Node(NodeT &self, OtherNodeT &other, VisitorOp &)
Definition: LeafNode.h:2125
void save(std::ostream &os) const
Definition: NodeMasks.h:562
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:450
LeafNode()
Default constructor.
Definition: LeafNode.h:1170
ChildAllIter endChildAll()
Definition: LeafNode.h:634
ChildOffCIter endChildOff() const
Definition: LeafNode.h:630
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:395
const Coord & max() const
Definition: Coord.h:333
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:130
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don&#39;t change its value.
Definition: LeafNode.h:706
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:367
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:1109
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
Definition: LeafNode.h:433
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
Definition: LeafNode.h:1009
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:594
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don&#39;t change its active state.
Definition: LeafNode.h:1369
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:425
Index64 offLeafVoxelCount() const
Definition: LeafNode.h:444
static const Index LOG2DIM
Definition: LeafNode.h:75
bool operator!=(const Buffer &other) const
Return true if the contents of the other buffer are not exactly equal to the contents of this buffer...
Definition: LeafNode.h:239
bool isInactive() const
Return true if all of this node&#39;s values are inactive.
Definition: LeafNode.h:1080
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:545
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:454
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1690
Buffer(const ValueType &val)
Construct a buffer populated with the specified value.
Definition: LeafNode.h:133
NodeMaskType::DenseIterator MaskDenseIterator
Definition: LeafNode.h:503
Int32 y() const
Definition: Coord.h:147
ValueOffCIter cbeginValueOff() const
Definition: LeafNode.h:597
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
Definition: LeafNode.h:591
ValueOffCIter beginValueOff() const
Definition: LeafNode.h:598
Index64 onLeafVoxelCount() const
Definition: LeafNode.h:443
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:374
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNode.h:1000
ValueAllCIter cbeginValueAll() const
Definition: LeafNode.h:600
ValueAllIter endValueAll()
Definition: LeafNode.h:612
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:427
void copyFromDense(const CoordBBox &bbox, const DenseT &dense, const ValueType &background, const ValueType &tolerance)
Copy from a dense grid into this node the values of the voxels that lie within a given bounding box...
Definition: LeafNode.h:1497
ChildAllCIter cendChildAll() const
Definition: LeafNode.h:632
void unsetItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:574
static Index getValueLevel(const Coord &)
Return the level (i.e., 0) at which leaf node values reside.
Definition: LeafNode.h:691
ChildOffCIter beginChildOff() const
Definition: LeafNode.h:620
void setItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:525
DenseIter()
Definition: LeafNode.h:560
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:427
ValueAllCIter endValueAll() const
Definition: LeafNode.h:611
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:765
Definition: NodeMasks.h:205
Definition: NodeMasks.h:236
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:116
ValueT & getValue() const
Definition: LeafNode.h:522
ValueAllIter beginValueAll()
Definition: LeafNode.h:602
void setValueAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
Definition: LeafNode.h:833
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNode.h:770
bool isAllocated() const
Return true if memory for this node&#39;s buffer has been allocated.
Definition: LeafNode.h:454
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:383
Definition: Types.h:444
ChildIter< MaskOnIterator, LeafNode, ChildOn > ChildOnIter
Definition: LeafNode.h:587
static void doVisit(NodeT &, VisitorOp &)
Definition: LeafNode.h:2086
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Definition: Compression.h:79
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:1033
ValueIter< MaskOffIterator, const LeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: LeafNode.h:584
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect this node&#39;s set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if both of the original voxels were active.
Definition: LeafNode.h:1905
ValueOffIter endValueOff()
Definition: LeafNode.h:609
static Index log2dim()
Return log2 of the dimension of this LeafNode, e.g. 3 if dimensions are 8^3.
Definition: LeafNode.h:421
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNode.h:537
boost::shared_ptr< LeafNode > Ptr
Definition: LeafNode.h:71
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1753
const Buffer & buffer() const
Definition: LeafNode.h:642
void merge(const LeafNode &)
Definition: LeafNode.h:1844
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:749
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1327
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNode.h:1031
Definition: Types.h:266
ChildOffCIter cbeginChildOff() const
Definition: LeafNode.h:619
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1041
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
Definition: LeafNode.h:2146
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:1022
void fill(const CoordBBox &bbox, const ValueType &, bool active=true)
Set all voxels within an axis-aligned box to the specified value and active state.
Definition: LeafNode.h:1427
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: LeafNode.h:704
Index64 offVoxelCount() const
Return the number of voxels marked Off.
Definition: LeafNode.h:442
void setValueOn(Index offset, const ValueType &val)
Set the value of the voxel at the given offset and mark the voxel as active.
Definition: LeafNode.h:724
T ValueType
Definition: LeafNode.h:69
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don&#39;t change its value.
Definition: LeafNode.h:716
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:549
ChildOnCIter cbeginChildOn() const
Definition: LeafNode.h:616
ValueOffCIter endValueOff() const
Definition: LeafNode.h:608
LeafNode< ValueType, Log2Dim > LeafNodeType
Definition: LeafNode.h:70
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node&#39;s local origin.
Definition: LeafNode.h:472
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:312
bool operator==(const Buffer &other) const
Return true if the contents of the other buffer exactly equal the contents of this buffer...
Definition: LeafNode.h:226
ChildOnCIter beginChildOn() const
Definition: LeafNode.h:617
void setValuesOff()
Mark all voxels as inactive but don&#39;t change their values.
Definition: LeafNode.h:762
~Buffer()
Destructor.
Definition: LeafNode.h:153
Buffer(const Buffer &other)
Copy constructor.
Definition: LeafNode.h:138
static const Index DIM
Definition: LeafNode.h:77
ChildAllCIter cbeginChildAll() const
Definition: LeafNode.h:622
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1300
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:324
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
Buffer & operator=(const Buffer &other)
Copy the other buffer&#39;s values into this buffer.
Definition: LeafNode.h:198
bool isChildMaskOn(Index) const
Definition: LeafNode.h:1113
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128
void setValueOnlyAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
Definition: LeafNode.h:842