OpenVDB  3.0.0
LeafNode.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2014 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 ValueType;
70  typedef boost::shared_ptr<LeafNode> Ptr;
72 
73  static const Index
74  LOG2DIM = Log2Dim, // needed by parent nodes
75  TOTAL = Log2Dim, // needed by parent nodes
76  DIM = 1 << TOTAL, // dimension along one coordinate direction
77  NUM_VALUES = 1 << 3 * Log2Dim,
78  NUM_VOXELS = NUM_VALUES, // total number of voxels represented by this node
79  SIZE = NUM_VALUES,
80  LEVEL = 0; // level 0 = leaf
81 
84  template<typename OtherValueType>
85  struct ValueConverter {
87  };
88 
91  template<typename OtherNodeType>
94  };
95 
96 #ifndef OPENVDB_2_ABI_COMPATIBLE
97  struct FileInfo
98  {
99  FileInfo(): bufpos(0) , maskpos(0) {}
100  std::streamoff bufpos;
101  std::streamoff maskpos;
103  boost::shared_ptr<io::StreamMetadata> meta;
104  };
105 #endif
106 
109  class Buffer
110  {
111  public:
112 #ifdef OPENVDB_2_ABI_COMPATIBLE
113  Buffer(): mData(new ValueType[SIZE]) {}
116  explicit Buffer(const ValueType& val): mData(new ValueType[SIZE]) { this->fill(val); }
118  Buffer(const Buffer& other): mData(new ValueType[SIZE]) { *this = other; }
120  ~Buffer() { delete[] mData; }
121 
123  bool isOutOfCore() const { return false; }
125  bool empty() const { return (mData == NULL); }
127  bool allocate() { if (mData == NULL) mData = new ValueType[SIZE]; return !this->empty(); }
128 #else
129  Buffer(): mData(new ValueType[SIZE]), mOutOfCore(0) {}
132  explicit Buffer(const ValueType& val): mData(new ValueType[SIZE]), mOutOfCore(0)
133  {
134  this->fill(val);
135  }
137  Buffer(const Buffer& other): mData(NULL), mOutOfCore(other.mOutOfCore)
138  {
139  if (other.isOutOfCore()) {
140  mFileInfo = new FileInfo(*other.mFileInfo);
141  } else {
142  this->allocate();
143  ValueType* target = mData;
144  const ValueType* source = other.mData;
145  Index n = SIZE;
146  while (n--) *target++ = *source++;
147  }
148  }
150  Buffer(PartialCreate, const ValueType&): mData(NULL), mOutOfCore(0) {}
153  {
154  if (this->isOutOfCore()) {
155  this->detachFromFile();
156  } else {
157  this->deallocate();
158  }
159  }
160 
162  bool isOutOfCore() const { return bool(mOutOfCore); }
164  bool empty() const { return !mData || this->isOutOfCore(); }
166  bool allocate() { if (mData == NULL) mData = new ValueType[SIZE]; return !this->empty(); }
167 #endif
168 
170  void fill(const ValueType& val)
171  {
172  this->detachFromFile();
173  if (mData != NULL) {
174  ValueType* target = mData;
175  Index n = SIZE;
176  while (n--) *target++ = val;
177  }
178  }
179 
181  const ValueType& getValue(Index i) const { return this->at(i); }
183  const ValueType& operator[](Index i) const { return this->at(i); }
185  void setValue(Index i, const ValueType& val)
186  {
187  assert(i < SIZE);
188 #ifdef OPENVDB_2_ABI_COMPATIBLE
189  mData[i] = val;
190 #else
191  this->loadValues();
192  if (mData) mData[i] = val;
193 #endif
194  }
195 
197  Buffer& operator=(const Buffer& other)
198  {
199  if (&other != this) {
200 #ifndef OPENVDB_2_ABI_COMPATIBLE
201  if (this->isOutOfCore()) {
202  this->detachFromFile();
203  } else {
204  if (other.isOutOfCore()) this->deallocate();
205  }
206  if (other.isOutOfCore()) {
207  mOutOfCore = other.mOutOfCore;
208  mFileInfo = new FileInfo(*other.mFileInfo);
209  } else {
210 #endif
211  this->allocate();
212  ValueType* target = mData;
213  const ValueType* source = other.mData;
214  Index n = SIZE;
215  while (n--) *target++ = *source++;
216 #ifndef OPENVDB_2_ABI_COMPATIBLE
217  }
218 #endif
219  }
220  return *this;
221  }
222 
225  bool operator==(const Buffer& other) const
226  {
227  this->loadValues();
228  other.loadValues();
229  const ValueType *target = mData, *source = other.mData;
230  if (!target && !source) return true;
231  if (!target || !source) return false;
232  Index n = SIZE;
233  while (n && math::isExactlyEqual(*target++, *source++)) --n;
234  return n == 0;
235  }
238  bool operator!=(const Buffer& other) const { return !(other == *this); }
239 
241  void swap(Buffer& other)
242  {
243  std::swap(mData, other.mData);
244 #ifndef OPENVDB_2_ABI_COMPATIBLE
245  std::swap(mOutOfCore, other.mOutOfCore);
246 #endif
247  }
248 
250  Index memUsage() const
251  {
252  size_t n = sizeof(*this);
253 #ifdef OPENVDB_2_ABI_COMPATIBLE
254  if (mData) n += SIZE * sizeof(ValueType);
255 #else
256  if (this->isOutOfCore()) n += sizeof(FileInfo);
257  else if (mData) n += SIZE * sizeof(ValueType);
258 #endif
259  return static_cast<Index>(n);
260  }
262  static Index size() { return SIZE; }
263 
264  private:
266  const ValueType& at(Index i) const
267  {
268  assert(i < SIZE);
269 #ifdef OPENVDB_2_ABI_COMPATIBLE
270  return mData[i];
271 #else
272  this->loadValues();
273  // We can't use the ternary operator here, otherwise Visual C++ returns
274  // a reference to a temporary.
275  if (mData) return mData[i]; else return sZero;
276 #endif
277  }
278 
284  ValueType& operator[](Index i) { return const_cast<ValueType&>(this->at(i)); }
285 
286  bool deallocate()
287  {
288  if (mData != NULL && !this->isOutOfCore()) {
289  delete[] mData;
290  mData = NULL;
291  return true;
292  }
293  return false;
294  }
295 
296 #ifdef OPENVDB_2_ABI_COMPATIBLE
297  void setOutOfCore(bool) {}
298  void loadValues() const {}
299  void doLoad() const {}
300  bool detachFromFile() { return false; }
301 #else
302  inline void setOutOfCore(bool b) { mOutOfCore = b; }
303  // To facilitate inlining in the common case in which the buffer is in-core,
304  // the loading logic is split into a separate function, doLoad().
305  inline void loadValues() const { if (this->isOutOfCore()) this->doLoad(); }
306  inline void doLoad() const;
307  inline bool detachFromFile()
308  {
309  if (this->isOutOfCore()) {
310  delete mFileInfo;
311  mFileInfo = NULL;
312  this->setOutOfCore(false);
313  return true;
314  }
315  return false;
316  }
317 #endif
318 
319  friend class ::TestLeaf;
320  // Allow the parent LeafNode to access this buffer's data pointer.
321  friend class LeafNode;
322 
323 #ifdef OPENVDB_2_ABI_COMPATIBLE
324  ValueType* mData;
325 #else
326  union {
327  ValueType* mData;
329  };
330  Index32 mOutOfCore; // currently interpreted as bool; extra bits reserved for future use
331  tbb::spin_mutex mMutex; // 1 byte
332  //int8_t mReserved[3]; // padding for alignment
333 
334  static const ValueType sZero;
335 #endif
336  }; // class Buffer
337 
338 
340  LeafNode();
341 
346  explicit LeafNode(const Coord& coords,
347  const ValueType& value = zeroVal<ValueType>(),
348  bool active = false);
349 
350 
351 #ifndef OPENVDB_2_ABI_COMPATIBLE
358  const Coord& coords,
359  const ValueType& value = zeroVal<ValueType>(),
360  bool active = false);
361 #endif
362 
364  LeafNode(const LeafNode&);
365 
367  template<typename OtherValueType>
368  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
369 
371  template<typename OtherValueType>
373  const ValueType& offValue, const ValueType& onValue, TopologyCopy);
374 
376  template<typename OtherValueType>
378  const ValueType& background, TopologyCopy);
379 
381  ~LeafNode();
382 
383  //
384  // Statistics
385  //
387  static Index log2dim() { return Log2Dim; }
389  static Index dim() { return DIM; }
391  static Index size() { return SIZE; }
393  static Index numValues() { return SIZE; }
395  static Index getLevel() { return LEVEL; }
397  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
399  static Index getChildDim() { return 1; }
401  static Index32 leafCount() { return 1; }
403  static Index32 nonLeafCount() { return 0; }
404 
406  Index64 onVoxelCount() const { return mValueMask.countOn(); }
408  Index64 offVoxelCount() const { return mValueMask.countOff(); }
409  Index64 onLeafVoxelCount() const { return onVoxelCount(); }
410  Index64 offLeafVoxelCount() const { return offVoxelCount(); }
411  static Index64 onTileCount() { return 0; }
412  static Index64 offTileCount() { return 0; }
414  bool isEmpty() const { return mValueMask.isOff(); }
416  bool isDense() const { return mValueMask.isOn(); }
417 
418 #ifndef OPENVDB_2_ABI_COMPATIBLE
419  bool isAllocated() const { return !mBuffer.isOutOfCore() && !mBuffer.empty(); }
422  bool allocate() { return mBuffer.allocate(); }
423 #endif
424 
426  Index64 memUsage() const;
427 
431  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
432 
435  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
436 
438  void setOrigin(const Coord& origin) { mOrigin = origin; }
440  const Coord& origin() const { return mOrigin; }
442  void getOrigin(Coord& origin) const { origin = mOrigin; }
443  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
445 
447  static Index coordToOffset(const Coord& xyz);
450  static Coord offsetToLocalCoord(Index n);
452  Coord offsetToGlobalCoord(Index n) const;
453 
455  std::string str() const;
456 
459  template<typename OtherType, Index OtherLog2Dim>
460  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
461 
463  bool operator==(const LeafNode& other) const;
464  bool operator!=(const LeafNode& other) const { return !(other == *this); }
465 
466 protected:
470 
471  // Type tags to disambiguate template instantiations
472  struct ValueOn {}; struct ValueOff {}; struct ValueAll {};
473  struct ChildOn {}; struct ChildOff {}; struct ChildAll {};
474 
475  template<typename MaskIterT, typename NodeT, typename ValueT, typename TagT>
476  struct ValueIter:
477  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
478  // if MaskIterT is a dense mask iterator type.
479  public SparseIteratorBase<
480  MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
481  {
483 
485  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
486 
487  ValueT& getItem(Index pos) const { return this->parent().getValue(pos); }
488  ValueT& getValue() const { return this->parent().getValue(this->pos()); }
489 
490  // Note: setItem() can't be called on const iterators.
491  void setItem(Index pos, const ValueT& value) const
492  {
493  this->parent().setValueOnly(pos, value);
494  }
495  // Note: setValue() can't be called on const iterators.
496  void setValue(const ValueT& value) const
497  {
498  this->parent().setValueOnly(this->pos(), value);
499  }
500 
501  // Note: modifyItem() can't be called on const iterators.
502  template<typename ModifyOp>
503  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
504  // Note: modifyValue() can't be called on const iterators.
505  template<typename ModifyOp>
506  void modifyValue(const ModifyOp& op) const { this->parent().modifyValue(this->pos(), op); }
507  };
508 
510  template<typename MaskIterT, typename NodeT, typename TagT>
511  struct ChildIter:
512  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
513  {
515  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
516  MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>(iter, parent) {}
517  };
518 
519  template<typename NodeT, typename ValueT, typename TagT>
520  struct DenseIter: public DenseIteratorBase<
521  MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, /*ChildT=*/void, ValueT>
522  {
525 
527  DenseIter(const MaskDenseIterator& iter, NodeT* parent): BaseT(iter, parent) {}
528 
529  bool getItem(Index pos, void*& child, NonConstValueT& value) const
530  {
531  value = this->parent().getValue(pos);
532  child = NULL;
533  return false; // no child
534  }
535 
536  // Note: setItem() can't be called on const iterators.
537  //void setItem(Index pos, void* child) const {}
538 
539  // Note: unsetItem() can't be called on const iterators.
540  void unsetItem(Index pos, const ValueT& value) const
541  {
542  this->parent().setValueOnly(pos, value);
543  }
544  };
545 
546 public:
559 
560  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
561  ValueOnCIter beginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
562  ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
563  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
564  ValueOffCIter beginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
565  ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
566  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
567  ValueAllCIter beginValueAll() const { return ValueAllCIter(mValueMask.beginDense(), this); }
568  ValueAllIter beginValueAll() { return ValueAllIter(mValueMask.beginDense(), this); }
569 
570  ValueOnCIter cendValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
571  ValueOnCIter endValueOn() const { return ValueOnCIter(mValueMask.endOn(), this); }
572  ValueOnIter endValueOn() { return ValueOnIter(mValueMask.endOn(), this); }
573  ValueOffCIter cendValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
574  ValueOffCIter endValueOff() const { return ValueOffCIter(mValueMask.endOff(), this); }
575  ValueOffIter endValueOff() { return ValueOffIter(mValueMask.endOff(), this); }
576  ValueAllCIter cendValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
577  ValueAllCIter endValueAll() const { return ValueAllCIter(mValueMask.endDense(), this); }
578  ValueAllIter endValueAll() { return ValueAllIter(mValueMask.endDense(), this); }
579 
580  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
581  // because leaf nodes have no children.
582  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
583  ChildOnCIter beginChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
584  ChildOnIter beginChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
585  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
586  ChildOffCIter beginChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
587  ChildOffIter beginChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
588  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
589  ChildAllCIter beginChildAll() const { return ChildAllCIter(mValueMask.beginDense(), this); }
590  ChildAllIter beginChildAll() { return ChildAllIter(mValueMask.beginDense(), this); }
591 
592  ChildOnCIter cendChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
593  ChildOnCIter endChildOn() const { return ChildOnCIter(mValueMask.endOn(), this); }
594  ChildOnIter endChildOn() { return ChildOnIter(mValueMask.endOn(), this); }
595  ChildOffCIter cendChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
596  ChildOffCIter endChildOff() const { return ChildOffCIter(mValueMask.endOff(), this); }
597  ChildOffIter endChildOff() { return ChildOffIter(mValueMask.endOff(), this); }
598  ChildAllCIter cendChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
599  ChildAllCIter endChildAll() const { return ChildAllCIter(mValueMask.endDense(), this); }
600  ChildAllIter endChildAll() { return ChildAllIter(mValueMask.endDense(), this); }
601 
602  //
603  // Buffer management
604  //
607  void swap(Buffer& other) { mBuffer.swap(other); }
608  const Buffer& buffer() const { return mBuffer; }
609  Buffer& buffer() { return mBuffer; }
610 
611  //
612  // I/O methods
613  //
617  void readTopology(std::istream& is, bool fromHalf = false);
621  void writeTopology(std::ostream& os, bool toHalf = false) const;
622 
626  void readBuffers(std::istream& is, bool fromHalf = false);
631  void readBuffers(std::istream& is, const CoordBBox& bbox, bool fromHalf = false);
635  void writeBuffers(std::ostream& os, bool toHalf = false) const;
636 
637  size_t streamingSize(bool toHalf = false) const;
638 
639  //
640  // Accessor methods
641  //
643  const ValueType& getValue(const Coord& xyz) const;
645  const ValueType& getValue(Index offset) const;
646 
650  bool probeValue(const Coord& xyz, ValueType& val) const;
654  bool probeValue(Index offset, ValueType& val) const;
655 
657  static Index getValueLevel(const Coord&) { return LEVEL; }
658 
660  void setActiveState(const Coord& xyz, bool on);
662  void setActiveState(Index offset, bool on) { assert(offset<SIZE); mValueMask.set(offset, on); }
663 
665  void setValueOnly(const Coord& xyz, const ValueType& val);
667  void setValueOnly(Index offset, const ValueType& val);
668 
670  void setValueOff(const Coord& xyz) { mValueMask.setOff(LeafNode::coordToOffset(xyz)); }
672  void setValueOff(Index offset) { assert(offset < SIZE); mValueMask.setOff(offset); }
673 
675  void setValueOff(const Coord& xyz, const ValueType& val);
677  void setValueOff(Index offset, const ValueType& val);
678 
680  void setValueOn(const Coord& xyz) { mValueMask.setOn(LeafNode::coordToOffset(xyz)); }
682  void setValueOn(Index offset) { assert(offset < SIZE); mValueMask.setOn(offset); }
684  void setValueOn(const Coord& xyz, const ValueType& val) {
685  this->setValueOn(LeafNode::coordToOffset(xyz), val);
686  }
688  void setValue(const Coord& xyz, const ValueType& val) { this->setValueOn(xyz, val); }
690  void setValueOn(Index offset, const ValueType& val) {
691  mBuffer.setValue(offset, val);
692  mValueMask.setOn(offset);
693  }
694 
697  template<typename ModifyOp>
698  void modifyValue(Index offset, const ModifyOp& op)
699  {
700  ValueType val = mBuffer[offset];
701  op(val);
702  mBuffer.setValue(offset, val);
703  mValueMask.setOn(offset);
704  }
707  template<typename ModifyOp>
708  void modifyValue(const Coord& xyz, const ModifyOp& op)
709  {
710  this->modifyValue(this->coordToOffset(xyz), op);
711  }
712 
714  template<typename ModifyOp>
715  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
716  {
717  const Index offset = this->coordToOffset(xyz);
718  bool state = mValueMask.isOn(offset);
719  ValueType val = mBuffer[offset];
720  op(val, state);
721  mBuffer.setValue(offset, val);
722  mValueMask.set(offset, state);
723  }
724 
726  void setValuesOn() { mValueMask.setOn(); }
728  void setValuesOff() { mValueMask.setOff(); }
729 
731  bool isValueOn(const Coord& xyz) const {return this->isValueOn(LeafNode::coordToOffset(xyz));}
733  bool isValueOn(Index offset) const { return mValueMask.isOn(offset); }
734 
736  static bool hasActiveTiles() { return false; }
737 
739  void clip(const CoordBBox&, const ValueType& background);
740 
742  void fill(const CoordBBox& bbox, const ValueType&, bool active = true);
743 
745  void fill(const ValueType& value);
747  void fill(const ValueType& value, bool active);
748 
760  template<typename DenseT>
761  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
762 
779  template<typename DenseT>
780  void copyFromDense(const CoordBBox& bbox, const DenseT& dense,
781  const ValueType& background, const ValueType& tolerance);
782 
785  template<typename AccessorT>
786  const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const
787  {
788  return this->getValue(xyz);
789  }
790 
793  template<typename AccessorT>
794  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
795 
798  template<typename AccessorT>
799  void setValueAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
800  {
801  this->setValueOn(xyz, val);
802  }
803 
807  template<typename AccessorT>
808  void setValueOnlyAndCache(const Coord& xyz, const ValueType& val, AccessorT&)
809  {
810  this->setValueOnly(xyz, val);
811  }
812 
816  template<typename ModifyOp, typename AccessorT>
817  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
818  {
819  this->modifyValue(xyz, op);
820  }
821 
824  template<typename ModifyOp, typename AccessorT>
825  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
826  {
827  this->modifyValueAndActiveState(xyz, op);
828  }
829 
832  template<typename AccessorT>
833  void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&)
834  {
835  this->setValueOff(xyz, value);
836  }
837 
841  template<typename AccessorT>
842  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
843  {
844  this->setActiveState(xyz, on);
845  }
846 
850  template<typename AccessorT>
851  bool probeValueAndCache(const Coord& xyz, ValueType& val, AccessorT&) const
852  {
853  return this->probeValue(xyz, val);
854  }
855 
859  template<typename AccessorT>
860  const ValueType& getValue(const Coord& xyz, bool& state, int& level, AccessorT&) const
861  {
862  const Index offset = this->coordToOffset(xyz);
863  state = mValueMask.isOn(offset);
864  level = LEVEL;
865  return mBuffer[offset];
866  }
867 
870  template<typename AccessorT>
871  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
872 
876  const ValueType& getFirstValue() const { return mBuffer[0]; }
878  const ValueType& getLastValue() const { return mBuffer[SIZE - 1]; }
879 
882  void resetBackground(const ValueType& oldBackground, const ValueType& newBackground);
883 
884  void negate();
885 
887 
888  template<MergePolicy Policy> void merge(const LeafNode&);
889  template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive);
890  template<MergePolicy Policy>
891  void merge(const LeafNode& other, const ValueType& /*bg*/, const ValueType& /*otherBG*/);
892 
899  template<typename OtherType>
900  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other);
901 
913  template<typename OtherType>
914  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
915 
927  template<typename OtherType>
928  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const ValueType&);
929 
930  template<typename CombineOp>
931  void combine(const LeafNode& other, CombineOp& op);
932  template<typename CombineOp>
933  void combine(const ValueType& value, bool valueIsActive, CombineOp& op);
934 
935  template<typename CombineOp, typename OtherType /*= ValueType*/>
936  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
937  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
938  void combine2(const ValueType&, const OtherNodeT& other, bool valueIsActive, CombineOp&);
939  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
940  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
941 
947  template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
948 
949  template<typename VisitorOp> void visit(VisitorOp&);
950  template<typename VisitorOp> void visit(VisitorOp&) const;
951 
952  template<typename OtherLeafNodeType, typename VisitorOp>
953  void visit2Node(OtherLeafNodeType& other, VisitorOp&);
954  template<typename OtherLeafNodeType, typename VisitorOp>
955  void visit2Node(OtherLeafNodeType& other, VisitorOp&) const;
956  template<typename IterT, typename VisitorOp>
957  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
958  template<typename IterT, typename VisitorOp>
959  void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
960 
962  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
964  void addLeaf(LeafNode*) {}
965  template<typename AccessorT>
966  void addLeafAndCache(LeafNode*, AccessorT&) {}
967  template<typename NodeT>
968  NodeT* stealNode(const Coord&, const ValueType&, bool) { return NULL; }
969  template<typename NodeT>
970  NodeT* probeNode(const Coord&) { return NULL; }
971  template<typename NodeT>
972  const NodeT* probeConstNode(const Coord&) const { return NULL; }
973  template<typename ArrayT> void getNodes(ArrayT&) const {}
975 
976  void addTile(Index level, const Coord&, const ValueType&, bool);
977  void addTile(Index offset, const ValueType&, bool);
978  template<typename AccessorT>
979  void addTileAndCache(Index, const Coord&, const ValueType&, bool, AccessorT&);
980 
982  LeafNode* touchLeaf(const Coord&) { return this; }
984  template<typename AccessorT>
985  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
986  template<typename NodeT, typename AccessorT>
987  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
988  {
990  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
991  return reinterpret_cast<NodeT*>(this);
993  }
994  LeafNode* probeLeaf(const Coord&) { return this; }
995  template<typename AccessorT>
996  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
998 
999  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
1001  template<typename AccessorT>
1002  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
1003  template<typename AccessorT>
1004  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
1005  const LeafNode* probeLeaf(const Coord&) const { return this; }
1006  template<typename NodeT, typename AccessorT>
1007  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
1008  {
1010  if (!(boost::is_same<NodeT,LeafNode>::value)) return NULL;
1011  return reinterpret_cast<const NodeT*>(this);
1013  }
1015 
1019  bool isConstant(ValueType& constValue, bool& state,
1020  const ValueType& tolerance = zeroVal<ValueType>()) const;
1022  bool isInactive() const { return mValueMask.isOff(); }
1023 
1024 protected:
1025  friend class ::TestLeaf;
1026  template<typename> friend class ::TestLeafIO;
1027 
1028  // During topology-only construction, access is needed
1029  // to protected/private members of other template instances.
1030  template<typename, Index> friend class LeafNode;
1031 
1032  friend struct ValueIter<MaskOnIterator, LeafNode, ValueType, ValueOn>;
1033  friend struct ValueIter<MaskOffIterator, LeafNode, ValueType, ValueOff>;
1034  friend struct ValueIter<MaskDenseIterator, LeafNode, ValueType, ValueAll>;
1035  friend struct ValueIter<MaskOnIterator, const LeafNode, ValueType, ValueOn>;
1036  friend struct ValueIter<MaskOffIterator, const LeafNode, ValueType, ValueOff>;
1037  friend struct ValueIter<MaskDenseIterator, const LeafNode, ValueType, ValueAll>;
1038 
1039  // Allow iterators to call mask accessor methods (see below).
1041  friend class IteratorBase<MaskOnIterator, LeafNode>;
1042  friend class IteratorBase<MaskOffIterator, LeafNode>;
1043  friend class IteratorBase<MaskDenseIterator, LeafNode>;
1044 
1045  // Mask accessors
1046 public:
1047  bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
1048  bool isValueMaskOn() const { return mValueMask.isOn(); }
1049  bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
1050  bool isValueMaskOff() const { return mValueMask.isOff(); }
1051  const NodeMaskType& getValueMask() const { return mValueMask; }
1052  NodeMaskType& getValueMask() { return mValueMask; }
1053  void setValueMask(const NodeMaskType& mask) { mValueMask = mask; }
1054  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
1055  bool isChildMaskOff(Index) const { return true; }
1056  bool isChildMaskOff() const { return true; }
1057 protected:
1058  void setValueMask(Index n, bool on) { mValueMask.set(n, on); }
1059  void setValueMaskOn(Index n) { mValueMask.setOn(n); }
1060  void setValueMaskOff(Index n) { mValueMask.setOff(n); }
1061 
1063  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
1064 
1065  template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
1066  static inline void doVisit(NodeT&, VisitorOp&);
1067 
1068  template<typename NodeT, typename OtherNodeT, typename VisitorOp,
1069  typename ChildAllIterT, typename OtherChildAllIterT>
1070  static inline void doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp&);
1071 
1072  template<typename NodeT, typename VisitorOp,
1073  typename ChildAllIterT, typename OtherChildAllIterT>
1074  static inline void doVisit2(NodeT& self, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
1075 
1076 private:
1078  Buffer mBuffer;
1080  NodeMaskType mValueMask;
1082  Coord mOrigin;
1083 }; // end of LeafNode class
1084 
1085 
1086 #ifndef OPENVDB_2_ABI_COMPATIBLE
1087 template<typename T, Index Log2Dim>
1088 const T LeafNode<T, Log2Dim>::Buffer::sZero = zeroVal<T>();
1089 #endif
1090 
1091 
1093 
1094 
1096 template<Index Dim1, typename NodeT2>
1099 struct SameLeafConfig { static const bool value = false; };
1100 
1101 template<Index Dim1, typename T2>
1102 struct SameLeafConfig<Dim1, LeafNode<T2, Dim1> > { static const bool value = true; };
1104 
1105 
1107 
1108 
1109 template<typename T, Index Log2Dim>
1110 inline
1112  mValueMask(),//default is off!
1113  mOrigin(0, 0, 0)
1114 {
1115 }
1116 
1117 
1118 template<typename T, Index Log2Dim>
1119 inline
1120 LeafNode<T, Log2Dim>::LeafNode(const Coord& xyz, const ValueType& val, bool active):
1121  mBuffer(val),
1122  mValueMask(active),
1123  mOrigin(xyz & (~(DIM - 1)))
1124 {
1125 }
1126 
1127 
1128 #ifndef OPENVDB_2_ABI_COMPATIBLE
1129 template<typename T, Index Log2Dim>
1130 inline
1131 LeafNode<T, Log2Dim>::LeafNode(PartialCreate, const Coord& xyz, const ValueType& val, bool active):
1132  mBuffer(PartialCreate(), val),
1133  mValueMask(active),
1134  mOrigin(xyz & (~(DIM - 1)))
1135 {
1136 }
1137 #endif
1138 
1139 
1140 template<typename T, Index Log2Dim>
1141 inline
1143  mBuffer(other.mBuffer),
1144  mValueMask(other.mValueMask),
1145  mOrigin(other.mOrigin)
1146 {
1147 }
1148 
1149 
1150 // Copy-construct from a leaf node with the same configuration but a different ValueType.
1151 template<typename T, Index Log2Dim>
1152 template<typename OtherValueType>
1153 inline
1155  mValueMask(other.mValueMask),
1156  mOrigin(other.mOrigin)
1157 {
1158  struct Local {
1160  static inline ValueType convertValue(const OtherValueType& val) { return ValueType(val); }
1161  };
1162 
1163  for (Index i = 0; i < SIZE; ++i) {
1164  mBuffer[i] = Local::convertValue(other.mBuffer[i]);
1165  }
1166 }
1167 
1168 
1169 template<typename T, Index Log2Dim>
1170 template<typename OtherValueType>
1171 inline
1173  const ValueType& background, TopologyCopy):
1174  mBuffer(background),
1175  mValueMask(other.mValueMask),
1176  mOrigin(other.mOrigin)
1177 {
1178 }
1179 
1180 
1181 template<typename T, Index Log2Dim>
1182 template<typename OtherValueType>
1183 inline
1185  const ValueType& offValue, const ValueType& onValue, TopologyCopy):
1186  mValueMask(other.mValueMask),
1187  mOrigin(other.mOrigin)
1188 {
1189  for (Index i = 0; i < SIZE; ++i) {
1190  mBuffer[i] = (mValueMask.isOn(i) ? onValue : offValue);
1191  }
1192 }
1193 
1194 
1195 template<typename T, Index Log2Dim>
1196 inline
1198 {
1199 }
1200 
1201 
1202 template<typename T, Index Log2Dim>
1203 inline std::string
1205 {
1206  std::ostringstream ostr;
1207  ostr << "LeafNode @" << mOrigin << ": " << mBuffer;
1208  return ostr.str();
1209 }
1210 
1211 
1213 
1214 
1215 template<typename T, Index Log2Dim>
1216 inline Index
1218 {
1219  assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1220  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1221  + ((xyz[1] & (DIM-1u)) << Log2Dim)
1222  + (xyz[2] & (DIM-1u));
1223 }
1224 
1225 template<typename T, Index Log2Dim>
1226 inline Coord
1228 {
1229  assert(n<(1<< 3*Log2Dim));
1230  Coord xyz;
1231  xyz.setX(n >> 2*Log2Dim);
1232  n &= ((1<<2*Log2Dim)-1);
1233  xyz.setY(n >> Log2Dim);
1234  xyz.setZ(n & ((1<<Log2Dim)-1));
1235  return xyz;
1236 }
1237 
1238 
1239 template<typename T, Index Log2Dim>
1240 inline Coord
1242 {
1243  return (this->offsetToLocalCoord(n) + this->origin());
1244 }
1245 
1246 
1248 
1249 
1250 template<typename ValueT, Index Log2Dim>
1251 inline const ValueT&
1253 {
1254  return this->getValue(LeafNode::coordToOffset(xyz));
1255 }
1256 
1257 template<typename ValueT, Index Log2Dim>
1258 inline const ValueT&
1260 {
1261  assert(offset < SIZE);
1262  return mBuffer[offset];
1263 }
1264 
1265 
1266 template<typename T, Index Log2Dim>
1267 inline bool
1268 LeafNode<T, Log2Dim>::probeValue(const Coord& xyz, ValueType& val) const
1269 {
1270  return this->probeValue(LeafNode::coordToOffset(xyz), val);
1271 }
1272 
1273 template<typename T, Index Log2Dim>
1274 inline bool
1275 LeafNode<T, Log2Dim>::probeValue(Index offset, ValueType& val) const
1276 {
1277  assert(offset < SIZE);
1278  val = mBuffer[offset];
1279  return mValueMask.isOn(offset);
1280 }
1281 
1282 
1283 template<typename T, Index Log2Dim>
1284 inline void
1285 LeafNode<T, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& val)
1286 {
1287  this->setValueOff(LeafNode::coordToOffset(xyz), val);
1288 }
1289 
1290 template<typename T, Index Log2Dim>
1291 inline void
1292 LeafNode<T, Log2Dim>::setValueOff(Index offset, const ValueType& val)
1293 {
1294  assert(offset < SIZE);
1295  mBuffer.setValue(offset, val);
1296  mValueMask.setOff(offset);
1297 }
1298 
1299 
1300 template<typename T, Index Log2Dim>
1301 inline void
1302 LeafNode<T, Log2Dim>::setActiveState(const Coord& xyz, bool on)
1303 {
1304  mValueMask.set(this->coordToOffset(xyz), on);
1305 }
1306 
1307 
1308 template<typename T, Index Log2Dim>
1309 inline void
1310 LeafNode<T, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& val)
1311 {
1312  this->setValueOnly(LeafNode::coordToOffset(xyz), val);
1313 }
1314 
1315 template<typename T, Index Log2Dim>
1316 inline void
1317 LeafNode<T, Log2Dim>::setValueOnly(Index offset, const ValueType& val)
1318 {
1319  assert(offset<SIZE); mBuffer.setValue(offset, val);
1320 }
1321 
1322 
1324 
1325 
1326 template<typename T, Index Log2Dim>
1327 inline void
1328 LeafNode<T, Log2Dim>::clip(const CoordBBox& clipBBox, const T& background)
1329 {
1330  CoordBBox nodeBBox = this->getNodeBoundingBox();
1331  if (!clipBBox.hasOverlap(nodeBBox)) {
1332  // This node lies completely outside the clipping region. Fill it with the background.
1333  this->fill(background, /*active=*/false);
1334  } else if (clipBBox.isInside(nodeBBox)) {
1335  // This node lies completely inside the clipping region. Leave it intact.
1336  return;
1337  }
1338 
1339  // This node isn't completely contained inside the clipping region.
1340  // Set any voxels that lie outside the region to the background value.
1341 
1342  // Construct a boolean mask that is on inside the clipping region and off outside it.
1343  NodeMaskType mask;
1344  nodeBBox.intersect(clipBBox);
1345  Coord xyz;
1346  int &x = xyz.x(), &y = xyz.y(), &z = xyz.z();
1347  for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++x) {
1348  for (y = nodeBBox.min().y(); y <= nodeBBox.max().y(); ++y) {
1349  for (z = nodeBBox.min().z(); z <= nodeBBox.max().z(); ++z) {
1350  mask.setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1351  }
1352  }
1353  }
1354 
1355  // Set voxels that lie in the inactive region of the mask (i.e., outside
1356  // the clipping region) to the background value.
1357  for (MaskOffIterator maskIter = mask.beginOff(); maskIter; ++maskIter) {
1358  this->setValueOff(maskIter.pos(), background);
1359  }
1360 }
1361 
1362 
1364 
1365 
1366 template<typename T, Index Log2Dim>
1367 inline void
1368 LeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1369 {
1370 #ifndef OPENVDB_2_ABI_COMPATIBLE
1371  if (!this->allocate()) return;
1372 #endif
1373 
1374  for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1375  const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1376  for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1377  const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1378  for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1379  const Index offset = offsetXY + (z & (DIM-1u));
1380  mBuffer[offset] = value;
1381  mValueMask.set(offset, active);
1382  }
1383  }
1384  }
1385 }
1386 
1387 template<typename T, Index Log2Dim>
1388 inline void
1389 LeafNode<T, Log2Dim>::fill(const ValueType& value)
1390 {
1391  mBuffer.fill(value);
1392 }
1393 
1394 template<typename T, Index Log2Dim>
1395 inline void
1396 LeafNode<T, Log2Dim>::fill(const ValueType& value, bool active)
1397 {
1398  mBuffer.fill(value);
1399  mValueMask.set(active);
1400 }
1401 
1402 
1404 
1405 
1406 template<typename T, Index Log2Dim>
1407 template<typename DenseT>
1408 inline void
1409 LeafNode<T, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1410 {
1411 #ifndef OPENVDB_2_ABI_COMPATIBLE
1412  if (!this->isAllocated()) return;
1413 #endif
1414 
1415  typedef typename DenseT::ValueType DenseValueType;
1416 
1417  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1418  const Coord& min = dense.bbox().min();
1419  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1420  const T* s0 = &mBuffer[bbox.min()[2] & (DIM-1u)]; // source array
1421  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1422  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1423  const T* s1 = s0 + ((x & (DIM-1u)) << 2*Log2Dim);
1424  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1425  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1426  const T* s2 = s1 + ((y & (DIM-1u)) << Log2Dim);
1427  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1428  *t2 = DenseValueType(*s2++);
1429  }
1430  }
1431  }
1432 }
1433 
1434 
1435 template<typename T, Index Log2Dim>
1436 template<typename DenseT>
1437 inline void
1438 LeafNode<T, Log2Dim>::copyFromDense(const CoordBBox& bbox, const DenseT& dense,
1439  const ValueType& background, const ValueType& tolerance)
1440 {
1441 #ifndef OPENVDB_2_ABI_COMPATIBLE
1442  if (!this->allocate()) return;
1443 #endif
1444 
1445  typedef typename DenseT::ValueType DenseValueType;
1446 
1447  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1448  const Coord& min = dense.bbox().min();
1449 
1450  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1451  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1452  for (Int32 x = bbox.min()[0], ex = bbox.max()[0]+1; x < ex; ++x) {
1453  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1454  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1455  for (Int32 y = bbox.min()[1], ey = bbox.max()[1]+1; y < ey; ++y) {
1456  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1457  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1458  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1459  if (math::isApproxEqual(background, ValueType(*s2), tolerance)) {
1460  mValueMask.setOff(n2);
1461  mBuffer[n2] = background;
1462  } else {
1463  mValueMask.setOn(n2);
1464  mBuffer[n2] = ValueType(*s2);
1465  }
1466  }
1467  }
1468  }
1469 }
1470 
1471 
1473 
1474 
1475 template<typename T, Index Log2Dim>
1476 inline void
1477 LeafNode<T, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
1478 {
1479  mValueMask.load(is);
1480 }
1481 
1482 
1483 template<typename T, Index Log2Dim>
1484 inline void
1485 LeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
1486 {
1487  mValueMask.save(os);
1488 }
1489 
1490 
1492 
1493 
1494 #ifndef OPENVDB_2_ABI_COMPATIBLE
1495 template<typename T, Index Log2Dim>
1496 inline void
1498 {
1499  if (!this->isOutOfCore()) return;
1500 
1501  Buffer* self = const_cast<Buffer*>(this);
1502 
1503  // This lock will be contended at most once, after which this buffer
1504  // will no longer be out-of-core.
1505  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1506  if (!this->isOutOfCore()) return;
1507 
1508  boost::scoped_ptr<FileInfo> info(self->mFileInfo);
1509  assert(info.get() != NULL);
1510  assert(info->mapping.get() != NULL);
1511  assert(info->meta.get() != NULL);
1512 
1514  self->mData = NULL;
1515  self->allocate();
1516 
1517  boost::shared_ptr<std::streambuf> buf = info->mapping->createBuffer();
1518  std::istream is(buf.get());
1519 
1520  io::setStreamMetadataPtr(is, info->meta, /*transfer=*/true);
1521 
1522  NodeMaskType mask;
1523  is.seekg(info->maskpos);
1524  mask.load(is);
1525 
1526  is.seekg(info->bufpos);
1527  io::readCompressedValues(is, self->mData, SIZE, mask, io::getHalfFloat(is));
1528 
1529  self->setOutOfCore(false);
1530 }
1531 #endif
1532 
1533 
1535 
1536 
1537 template<typename T, Index Log2Dim>
1538 inline void
1539 LeafNode<T,Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1540 {
1541  this->readBuffers(is, CoordBBox::inf(), fromHalf);
1542 }
1543 
1544 
1545 template<typename T, Index Log2Dim>
1546 inline void
1547 LeafNode<T,Log2Dim>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
1548 {
1549 #ifndef OPENVDB_2_ABI_COMPATIBLE
1550  std::streamoff maskpos = is.tellg();
1551 #endif
1552 
1553  // Read in the value mask.
1554  mValueMask.load(is);
1555 
1556  int8_t numBuffers = 1;
1558  // Read in the origin.
1559  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
1560 
1561  // Read in the number of buffers, which should now always be one.
1562  is.read(reinterpret_cast<char*>(&numBuffers), sizeof(int8_t));
1563  }
1564 
1565  CoordBBox nodeBBox = this->getNodeBoundingBox();
1566  if (!clipBBox.hasOverlap(nodeBBox)) {
1567  // This node lies completely outside the clipping region.
1568  // Read and discard its voxel values.
1569  Buffer temp;
1570  io::readCompressedValues(is, temp.mData, SIZE, mValueMask, fromHalf);
1571  mValueMask.setOff();
1572  mBuffer.setOutOfCore(false);
1573  } else {
1574 #ifndef OPENVDB_2_ABI_COMPATIBLE
1575  // If this node lies completely inside the clipping region and it is being read
1576  // from a memory-mapped file, delay loading of its buffer until the buffer
1577  // is actually accessed. (If this node requires clipping, its buffer
1578  // must be accessed and therefore must be loaded.)
1579  io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
1580  const bool delayLoad = ((mappedFile.get() != NULL) && clipBBox.isInside(nodeBBox));
1581 
1582  if (delayLoad) {
1583  mBuffer.setOutOfCore(true);
1584  mBuffer.mFileInfo = new FileInfo;
1585  mBuffer.mFileInfo->bufpos = is.tellg();
1586  mBuffer.mFileInfo->mapping = mappedFile;
1587  // Save the offset to the value mask, because the in-memory copy
1588  // might change before the value buffer gets read.
1589  mBuffer.mFileInfo->maskpos = maskpos;
1590 
1591  mBuffer.mFileInfo->meta = io::getStreamMetadataPtr(is);
1592 
1593  // Read and discard voxel values.
1594  Buffer temp;
1595  io::readCompressedValues(is, temp.mData, SIZE, mValueMask, fromHalf);
1596  } else {
1597 #endif
1598  mBuffer.allocate();
1599  io::readCompressedValues(is, mBuffer.mData, SIZE, mValueMask, fromHalf);
1600  mBuffer.setOutOfCore(false);
1601 
1602  // Get this tree's background value.
1603  T background = zeroVal<T>();
1604  if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
1605  background = *static_cast<const T*>(bgPtr);
1606  }
1607  this->clip(clipBBox, background);
1608 #ifndef OPENVDB_2_ABI_COMPATIBLE
1609  }
1610 #endif
1611  }
1612 
1613  if (numBuffers > 1) {
1614  // Read in and discard auxiliary buffers that were created with earlier
1615  // versions of the library. (Auxiliary buffers are not mask compressed.)
1616  const bool zipped = io::getDataCompression(is) & io::COMPRESS_ZIP;
1617  Buffer temp;
1618  for (int i = 1; i < numBuffers; ++i) {
1619  if (fromHalf) {
1620  io::HalfReader<io::RealToHalf<T>::isReal, T>::read(is, temp.mData, SIZE, zipped);
1621  } else {
1622  io::readData<T>(is, temp.mData, SIZE, zipped);
1623  }
1624  }
1625  }
1626 }
1627 
1628 
1629 template<typename T, Index Log2Dim>
1630 inline void
1631 LeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1632 {
1633  // Write out the value mask.
1634  mValueMask.save(os);
1635 
1636  mBuffer.loadValues();
1637 
1638  io::writeCompressedValues(os, mBuffer.mData, SIZE,
1639  mValueMask, /*childMask=*/NodeMaskType(), toHalf);
1640 }
1641 
1642 
1644 
1645 
1646 template<typename T, Index Log2Dim>
1647 inline bool
1649 {
1650  return mOrigin == other.mOrigin &&
1651  mValueMask == other.mValueMask &&
1652  mBuffer == other.mBuffer;
1653 }
1654 
1655 
1656 template<typename T, Index Log2Dim>
1657 inline Index64
1659 {
1660  // Use sizeof(*this) to capture alignment-related padding
1661  // (but note that sizeof(*this) includes sizeof(mBuffer)).
1662  return sizeof(*this) + mBuffer.memUsage() - sizeof(mBuffer);
1663 }
1664 
1665 
1666 template<typename T, Index Log2Dim>
1667 inline void
1668 LeafNode<T, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1669 {
1670  CoordBBox this_bbox = this->getNodeBoundingBox();
1671  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
1672  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
1673  if (visitVoxels) {//use voxel granularity?
1674  this_bbox.reset();
1675  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
1676  this_bbox.translate(this->origin());
1677  }
1678  bbox.expand(this_bbox);
1679  }
1680 }
1681 
1682 
1683 template<typename T, Index Log2Dim>
1684 template<typename OtherType, Index OtherLog2Dim>
1685 inline bool
1687 {
1688  assert(other);
1689  return (Log2Dim == OtherLog2Dim && mValueMask == other->getValueMask());
1690 }
1691 
1692 
1693 template<typename T, Index Log2Dim>
1694 inline bool
1695 LeafNode<T, Log2Dim>::isConstant(ValueType& constValue,
1696  bool& state, const ValueType& tolerance) const
1697 {
1698  state = mValueMask.isOn();
1699 
1700  if (!(state || mValueMask.isOff())) return false;
1701 
1702  bool allEqual = true;
1703  const T value = mBuffer[0];
1704  for (Index i = 1; allEqual && i < SIZE; ++i) {
1706  allEqual = math::isApproxEqual(mBuffer[i], value, tolerance);
1707  }
1708  if (allEqual) constValue = value;
1709  return allEqual;
1710 }
1711 
1712 
1714 
1715 
1716 template<typename T, Index Log2Dim>
1717 inline void
1718 LeafNode<T, Log2Dim>::addTile(Index /*level*/, const Coord& xyz, const ValueType& val, bool active)
1719 {
1720  this->addTile(this->coordToOffset(xyz), val, active);
1721 }
1722 
1723 template<typename T, Index Log2Dim>
1724 inline void
1725 LeafNode<T, Log2Dim>::addTile(Index offset, const ValueType& val, bool active)
1726 {
1727  assert(offset < SIZE);
1728  setValueOnly(offset, val);
1729  setActiveState(offset, active);
1730 }
1731 
1732 template<typename T, Index Log2Dim>
1733 template<typename AccessorT>
1734 inline void
1736  const ValueType& val, bool active, AccessorT&)
1737 {
1738  this->addTile(level, xyz, val, active);
1739 }
1740 
1741 
1743 
1744 
1745 template<typename T, Index Log2Dim>
1746 inline void
1747 LeafNode<T, Log2Dim>::resetBackground(const ValueType& oldBackground,
1748  const ValueType& newBackground)
1749 {
1750 #ifndef OPENVDB_2_ABI_COMPATIBLE
1751  if (!this->allocate()) return;
1752 #endif
1753 
1754  typename NodeMaskType::OffIterator iter;
1755  // For all inactive values...
1756  for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1757  ValueType &inactiveValue = mBuffer[iter.pos()];
1758  if (math::isApproxEqual(inactiveValue, oldBackground)) {
1759  inactiveValue = newBackground;
1760  } else if (math::isApproxEqual(inactiveValue, math::negative(oldBackground))) {
1761  inactiveValue = math::negative(newBackground);
1762  }
1763  }
1764 }
1765 
1766 
1767 template<typename T, Index Log2Dim>
1768 template<MergePolicy Policy>
1769 inline void
1771 {
1772 #ifndef OPENVDB_2_ABI_COMPATIBLE
1773  if (!this->allocate()) return;
1774 #endif
1775 
1777  if (Policy == MERGE_NODES) return;
1778  typename NodeMaskType::OnIterator iter = other.mValueMask.beginOn();
1779  for (; iter; ++iter) {
1780  const Index n = iter.pos();
1781  if (mValueMask.isOff(n)) {
1782  mBuffer[n] = other.mBuffer[n];
1783  mValueMask.setOn(n);
1784  }
1785  }
1787 }
1788 
1789 template<typename T, Index Log2Dim>
1790 template<MergePolicy Policy>
1791 inline void
1793  const ValueType& /*bg*/, const ValueType& /*otherBG*/)
1794 {
1795  this->template merge<Policy>(other);
1796 }
1797 
1798 template<typename T, Index Log2Dim>
1799 template<MergePolicy Policy>
1800 inline void
1801 LeafNode<T, Log2Dim>::merge(const ValueType& tileValue, bool tileActive)
1802 {
1803 #ifndef OPENVDB_2_ABI_COMPATIBLE
1804  if (!this->allocate()) return;
1805 #endif
1806 
1808  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1809  if (!tileActive) return;
1810  // Replace all inactive values with the active tile value.
1811  for (typename NodeMaskType::OffIterator iter = mValueMask.beginOff(); iter; ++iter) {
1812  const Index n = iter.pos();
1813  mBuffer[n] = tileValue;
1814  mValueMask.setOn(n);
1815  }
1817 }
1818 
1819 
1820 template<typename T, Index Log2Dim>
1821 template<typename OtherType>
1822 inline void
1824 {
1825  mValueMask |= other.getValueMask();
1826 }
1827 
1828 template<typename T, Index Log2Dim>
1829 template<typename OtherType>
1830 inline void
1832  const ValueType&)
1833 {
1834  mValueMask &= other.getValueMask();
1835 }
1836 
1837 template<typename T, Index Log2Dim>
1838 template<typename OtherType>
1839 inline void
1841  const ValueType&)
1842 {
1843  mValueMask &= !other.getValueMask();
1844 }
1845 
1846 template<typename T, Index Log2Dim>
1847 inline void
1849 {
1850 #ifndef OPENVDB_2_ABI_COMPATIBLE
1851  if (!this->allocate()) return;
1852 #endif
1853  for (Index i = 0; i < SIZE; ++i) {
1854  mBuffer[i] = -mBuffer[i];
1855  }
1856 }
1857 
1858 
1860 
1861 
1862 template<typename T, Index Log2Dim>
1863 template<typename CombineOp>
1864 inline void
1865 LeafNode<T, Log2Dim>::combine(const LeafNode& other, CombineOp& op)
1866 {
1867 #ifndef OPENVDB_2_ABI_COMPATIBLE
1868  if (!this->allocate()) return;
1869 #endif
1870  CombineArgs<T> args;
1871  for (Index i = 0; i < SIZE; ++i) {
1872  op(args.setARef(mBuffer[i])
1873  .setAIsActive(mValueMask.isOn(i))
1874  .setBRef(other.mBuffer[i])
1875  .setBIsActive(other.mValueMask.isOn(i))
1876  .setResultRef(mBuffer[i]));
1877  mValueMask.set(i, args.resultIsActive());
1878  }
1879 }
1880 
1881 
1882 template<typename T, Index Log2Dim>
1883 template<typename CombineOp>
1884 inline void
1885 LeafNode<T, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op)
1886 {
1887 #ifndef OPENVDB_2_ABI_COMPATIBLE
1888  if (!this->allocate()) return;
1889 #endif
1890  CombineArgs<T> args;
1891  args.setBRef(value).setBIsActive(valueIsActive);
1892  for (Index i = 0; i < SIZE; ++i) {
1893  op(args.setARef(mBuffer[i])
1894  .setAIsActive(mValueMask.isOn(i))
1895  .setResultRef(mBuffer[i]));
1896  mValueMask.set(i, args.resultIsActive());
1897  }
1898 }
1899 
1900 
1902 
1903 
1904 template<typename T, Index Log2Dim>
1905 template<typename CombineOp, typename OtherType>
1906 inline void
1907 LeafNode<T, Log2Dim>::combine2(const LeafNode& other, const OtherType& value,
1908  bool valueIsActive, CombineOp& op)
1909 {
1910 #ifndef OPENVDB_2_ABI_COMPATIBLE
1911  if (!this->allocate()) return;
1912 #endif
1914  args.setBRef(value).setBIsActive(valueIsActive);
1915  for (Index i = 0; i < SIZE; ++i) {
1916  op(args.setARef(other.mBuffer[i])
1917  .setAIsActive(other.mValueMask.isOn(i))
1918  .setResultRef(mBuffer[i]));
1919  mValueMask.set(i, args.resultIsActive());
1920  }
1921 }
1922 
1923 
1924 template<typename T, Index Log2Dim>
1925 template<typename CombineOp, typename OtherNodeT>
1926 inline void
1927 LeafNode<T, Log2Dim>::combine2(const ValueType& value, const OtherNodeT& other,
1928  bool valueIsActive, CombineOp& op)
1929 {
1930 #ifndef OPENVDB_2_ABI_COMPATIBLE
1931  if (!this->allocate()) return;
1932 #endif
1934  args.setARef(value).setAIsActive(valueIsActive);
1935  for (Index i = 0; i < SIZE; ++i) {
1936  op(args.setBRef(other.mBuffer[i])
1937  .setBIsActive(other.mValueMask.isOn(i))
1938  .setResultRef(mBuffer[i]));
1939  mValueMask.set(i, args.resultIsActive());
1940  }
1941 }
1942 
1943 
1944 template<typename T, Index Log2Dim>
1945 template<typename CombineOp, typename OtherNodeT>
1946 inline void
1947 LeafNode<T, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
1948 {
1949 #ifndef OPENVDB_2_ABI_COMPATIBLE
1950  if (!this->allocate()) return;
1951 #endif
1953  for (Index i = 0; i < SIZE; ++i) {
1954  mValueMask.set(i, b0.mValueMask.isOn(i) || b1.mValueMask.isOn(i));
1955  op(args.setARef(b0.mBuffer[i])
1956  .setAIsActive(b0.mValueMask.isOn(i))
1957  .setBRef(b1.mBuffer[i])
1958  .setBIsActive(b1.mValueMask.isOn(i))
1959  .setResultRef(mBuffer[i]));
1960  mValueMask.set(i, args.resultIsActive());
1961  }
1962 }
1963 
1964 
1966 
1967 
1968 template<typename T, Index Log2Dim>
1969 template<typename BBoxOp>
1970 inline void
1972 {
1973  if (op.template descent<LEVEL>()) {
1974  for (ValueOnCIter i=this->cbeginValueOn(); i; ++i) {
1975 #ifdef _MSC_VER
1976  op.operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1977 #else
1978  op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1979 #endif
1980  }
1981  } else {
1982 #ifdef _MSC_VER
1983  op.operator()<LEVEL>(this->getNodeBoundingBox());
1984 #else
1985  op.template operator()<LEVEL>(this->getNodeBoundingBox());
1986 #endif
1987  }
1988 }
1989 
1990 
1991 template<typename T, Index Log2Dim>
1992 template<typename VisitorOp>
1993 inline void
1995 {
1996  doVisit<LeafNode, VisitorOp, ChildAllIter>(*this, op);
1997 }
1998 
1999 
2000 template<typename T, Index Log2Dim>
2001 template<typename VisitorOp>
2002 inline void
2003 LeafNode<T, Log2Dim>::visit(VisitorOp& op) const
2004 {
2005  doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*this, op);
2006 }
2007 
2008 
2009 template<typename T, Index Log2Dim>
2010 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
2011 inline void
2012 LeafNode<T, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
2013 {
2014  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2015  op(iter);
2016  }
2017 }
2018 
2019 
2021 
2022 
2023 template<typename T, Index Log2Dim>
2024 template<typename OtherLeafNodeType, typename VisitorOp>
2025 inline void
2026 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op)
2027 {
2028  doVisit2Node<LeafNode, OtherLeafNodeType, VisitorOp, ChildAllIter,
2029  typename OtherLeafNodeType::ChildAllIter>(*this, other, op);
2030 }
2031 
2032 
2033 template<typename T, Index Log2Dim>
2034 template<typename OtherLeafNodeType, typename VisitorOp>
2035 inline void
2036 LeafNode<T, Log2Dim>::visit2Node(OtherLeafNodeType& other, VisitorOp& op) const
2037 {
2038  doVisit2Node<const LeafNode, OtherLeafNodeType, VisitorOp, ChildAllCIter,
2039  typename OtherLeafNodeType::ChildAllCIter>(*this, other, op);
2040 }
2041 
2042 
2043 template<typename T, Index Log2Dim>
2044 template<
2045  typename NodeT,
2046  typename OtherNodeT,
2047  typename VisitorOp,
2048  typename ChildAllIterT,
2049  typename OtherChildAllIterT>
2050 inline void
2051 LeafNode<T, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
2052 {
2053  // Allow the two nodes to have different ValueTypes, but not different dimensions.
2054  BOOST_STATIC_ASSERT(OtherNodeT::SIZE == NodeT::SIZE);
2055  BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
2056 
2057  ChildAllIterT iter = self.beginChildAll();
2058  OtherChildAllIterT otherIter = other.beginChildAll();
2059 
2060  for ( ; iter && otherIter; ++iter, ++otherIter) {
2061  op(iter, otherIter);
2062  }
2063 }
2064 
2065 
2067 
2068 
2069 template<typename T, Index Log2Dim>
2070 template<typename IterT, typename VisitorOp>
2071 inline void
2072 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS)
2073 {
2074  doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
2075  *this, otherIter, op, otherIsLHS);
2076 }
2077 
2078 
2079 template<typename T, Index Log2Dim>
2080 template<typename IterT, typename VisitorOp>
2081 inline void
2082 LeafNode<T, Log2Dim>::visit2(IterT& otherIter, VisitorOp& op, bool otherIsLHS) const
2083 {
2084  doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
2085  *this, otherIter, op, otherIsLHS);
2086 }
2087 
2088 
2089 template<typename T, Index Log2Dim>
2090 template<
2091  typename NodeT,
2092  typename VisitorOp,
2093  typename ChildAllIterT,
2094  typename OtherChildAllIterT>
2095 inline void
2096 LeafNode<T, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
2097  VisitorOp& op, bool otherIsLHS)
2098 {
2099  if (!otherIter) return;
2100 
2101  if (otherIsLHS) {
2102  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2103  op(otherIter, iter);
2104  }
2105  } else {
2106  for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2107  op(iter, otherIter);
2108  }
2109  }
2110 }
2111 
2112 
2114 
2115 
2116 template<typename T, Index Log2Dim>
2117 inline std::ostream&
2118 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer& buf)
2119 {
2120  for (Index32 i = 0, N = buf.size(); i < N; ++i) os << buf.mData[i] << ", ";
2121  return os;
2122 }
2123 
2124 } // namespace tree
2125 } // namespace OPENVDB_VERSION_NAME
2126 } // namespace openvdb
2127 
2128 
2130 
2131 
2132 // Specialization for LeafNodes of type bool
2133 #include "LeafNodeBool.h"
2134 
2135 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
2136 
2137 // Copyright (c) 2012-2014 DreamWorks Animation LLC
2138 // All rights reserved. This software is distributed under the
2139 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1631
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:349
void setValuesOff()
Mark all voxels as inactive but don't change their values.
Definition: LeafNode.h:728
ValueOffCIter cendValueOff() const
Definition: LeafNode.h:573
DenseIter()
Definition: LeafNode.h:526
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1217
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:441
ChildOffCIter cendChildOff() const
Definition: LeafNode.h:595
Definition: Types.h:424
ValueAllCIter cendValueAll() const
Definition: LeafNode.h:576
const ValueType & getFirstValue() const
Return a const reference to the first value in the buffer.
Definition: LeafNode.h:876
void save(std::ostream &os) const
Definition: NodeMasks.h:507
ChildOnIter beginChildOn()
Definition: LeafNode.h:584
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1718
LeafNode< OtherValueType, Log2Dim > Type
Definition: LeafNode.h:86
void setValue(const ValueT &value) const
Definition: LeafNode.h:496
boost::shared_ptr< MappedFile > Ptr
Definition: io.h:135
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:1051
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1648
ValueT & getValue() const
Definition: LeafNode.h:488
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1241
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:833
Buffer & operator=(const Buffer &other)
Copy the other buffer's values into this buffer.
Definition: LeafNode.h:197
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:970
ChildIter()
Definition: LeafNode.h:514
void load(std::istream &is)
Definition: NodeMasks.h:511
ValueAllCIter endValueAll() const
Definition: LeafNode.h:577
static const Index LEVEL
Definition: LeafNode.h:80
ValueOffIter beginValueOff()
Definition: LeafNode.h:565
void negate()
Definition: LeafNode.h:1848
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:515
Definition: LeafNode.h:50
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1227
ChildOffCIter beginChildOff() const
Definition: LeafNode.h:586
const ValueType & getLastValue() const
Return a const reference to the last value in the buffer.
Definition: LeafNode.h:878
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:688
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNode.h:968
void setValueMask(const NodeMaskType &mask)
Definition: LeafNode.h:1053
uint64_t Index64
Definition: Types.h:58
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:435
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
Definition: LeafNode.h:395
ChildIter< MaskOffIterator, const LeafNode, ChildOff > ChildOffCIter
Definition: LeafNode.h:556
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:414
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
Definition: LeafNode.h:403
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 setValueMask(Index n, bool on)
Definition: LeafNode.h:1058
SameConfiguration::value is true if and only if OtherNodeType is the type of a LeafNod...
Definition: LeafNode.h:92
ChildAllCIter cbeginChildAll() const
Definition: LeafNode.h:588
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:517
static Index dim()
Return the number of voxels in each coordinate dimension.
Definition: LeafNode.h:389
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:851
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:443
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:731
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:698
ChildOnCIter cendChildOn() const
Definition: LeafNode.h:592
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:680
FileInfo * mFileInfo
Definition: LeafNode.h:328
bool resultIsActive() const
Definition: Types.h:358
void visit(VisitorOp &)
Definition: LeafNode.h:1994
io::MappedFile::Ptr mapping
Definition: LeafNode.h:102
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:860
Buffer & buffer()
Definition: LeafNode.h:609
ValueOnIter beginValueOn()
Definition: LeafNode.h:562
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 ...
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don't change its value. ...
Definition: LeafNode.h:662
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:238
ValueOnCIter endValueOn() const
Definition: LeafNode.h:571
ValueOnCIter cendValueOn() const
Definition: LeafNode.h:570
DenseIteratorBase< MaskDenseIterator, DenseIter, NodeT, void, ValueT > BaseT
Definition: LeafNode.h:523
void setValue(Index i, const ValueType &val)
Set the i'th value of this buffer to the specified value.
Definition: LeafNode.h:185
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Difference this node'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:1840
ValueAllCIter beginValueAll() const
Definition: LeafNode.h:567
ValueOnCIter beginValueOn() const
Definition: LeafNode.h:561
ValueOnIter endValueOn()
Definition: LeafNode.h:572
const Buffer & buffer() const
Definition: LeafNode.h:608
Array of fixed size that stores the voxel values of a LeafNode.
Definition: LeafNode.h:109
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:347
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:684
FileInfo()
Definition: LeafNode.h:99
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:369
bool isValueMaskOff(Index n) const
Definition: LeafNode.h:1049
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1539
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: LeafNode.h:558
int32_t Int32
Definition: Types.h:61
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:464
ValueIter< MaskDenseIterator, LeafNode, const ValueType, ValueAll > ValueAllIter
Definition: LeafNode.h:551
Index64 onLeafVoxelCount() const
Definition: LeafNode.h:409
ChildAllIter beginChildAll()
Definition: LeafNode.h:590
Index64 offLeafVoxelCount() const
Definition: LeafNode.h:410
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Replace inactive occurrences of oldBackground with newBackground, and inactive occurrences of -oldBac...
Definition: LeafNode.h:1747
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNode.h:529
bool allocate()
Allocate memory for this buffer if it has not already been allocated.
Definition: LeafNode.h:166
ChildAllCIter beginChildAll() const
Definition: LeafNode.h:589
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information. An additional level argument is pro...
Definition: LeafNode.h:1971
bool isChildMaskOn(Index) const
Definition: LeafNode.h:1054
ValueIter< MaskOnIterator, const LeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: LeafNode.h:548
void fill(const ValueType &val)
Populate this buffer with a constant value.
Definition: LeafNode.h:170
const LeafNode * probeLeaf(const Coord &) const
Return a const pointer to this node.
Definition: LeafNode.h:1005
bool allocate()
Allocate memory for this node's buffer if it has not already been allocated.
Definition: LeafNode.h:422
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:1686
Buffer()
Default constructor.
Definition: LeafNode.h:130
ValueOffCIter endValueOff() const
Definition: LeafNode.h:574
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1907
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:786
ValueConverter::Type is the type of a LeafNode having the same dimensions as this node but a diffe...
Definition: LeafNode.h:85
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1007
ValueAllCIter cbeginValueAll() const
Definition: LeafNode.h:566
void combine(FloatTreeT &lhsDist, IntTreeT &lhsIndex, FloatTreeT &rhsDist, IntTreeT &rhsIndex)
Definition: MeshToVolume.h:403
ChildAllCIter cendChildAll() const
Definition: LeafNode.h:598
ChildOffCIter endChildOff() const
Definition: LeafNode.h:596
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:987
bool isOn(Index32 n) const
Return true if the nth bit is on.
Definition: NodeMasks.h:455
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
ValueIter()
Definition: LeafNode.h:484
Index memUsage() const
Return the memory footprint of this buffer in bytes.
Definition: LeafNode.h:250
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.
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
Definition: LeafNode.h:554
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:411
void setValuesOn()
Mark all voxels as active but don't change their values.
Definition: LeafNode.h:726
bool isChildMaskOff() const
Definition: LeafNode.h:1056
#define OPENVDB_VERSION_NAME
Definition: version.h:43
void setItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:491
Definition: Types.h:263
static Index64 offTileCount()
Definition: LeafNode.h:412
NodeMaskType::OnIterator MaskOnIterator
Definition: LeafNode.h:467
ValueIter< MaskOffIterator, LeafNode, const ValueType, ValueOff > ValueOffIter
Definition: LeafNode.h:549
ChildOnIter endChildOn()
Definition: LeafNode.h:594
ValueType * mData
Definition: LeafNode.h:327
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNode.h:871
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:708
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition: LeafNode.h:1302
boost::shared_ptr< io::StreamMetadata > meta
Definition: LeafNode.h:103
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:511
ChildOffCIter cbeginChildOff() const
Definition: LeafNode.h:585
Index32 Index
Definition: Types.h:59
ChildOnCIter beginChildOn() const
Definition: LeafNode.h:583
~LeafNode()
Destructor.
Definition: LeafNode.h:1197
bool isOff(Index32 n) const
Return true if the nth bit is off.
Definition: NodeMasks.h:461
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNode.h:503
const ValueType & getValue(Index i) const
Return a const reference to the i'th element of this buffer.
Definition: LeafNode.h:181
bool isInactive() const
Return true if all of this node's values are inactive.
Definition: LeafNode.h:1022
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:309
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNode.h:966
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: LeafNode.h:1328
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:1204
OffIterator beginOff() const
Definition: NodeMasks.h:351
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
Definition: LeafNode.h:397
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:842
void swap(Buffer &other)
Exchange this node's data buffer with the given data buffer without changing the active states of the...
Definition: LeafNode.h:607
std::streamoff bufpos
Definition: LeafNode.h:100
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1004
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:309
SparseIteratorBase< MaskIterT, ValueIter, NodeT, ValueT > BaseT
Definition: LeafNode.h:482
ValueIter< MaskOnIterator, LeafNode, const ValueType, ValueOn > ValueOnIter
Definition: LeafNode.h:547
Definition: NodeMasks.h:236
Definition: Exceptions.h:39
void visit2Node(OtherLeafNodeType &other, VisitorOp &)
Definition: LeafNode.h:2026
Definition: Compression.h:79
ValueOffCIter beginValueOff() const
Definition: LeafNode.h:564
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:121
ValueIter< MaskDenseIterator, const LeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: LeafNode.h:552
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1252
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNode.h:825
void set(Index32 n, bool On)
Set the nth bit to the specified state.
Definition: NodeMasks.h:415
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1735
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:560
static Index32 leafCount()
Return the leaf count for this node, which is one.
Definition: LeafNode.h:401
bool isApproxEqual(const Hermite &lhs, const Hermite &rhs)
Definition: Hermite.h:470
ChildIter< MaskOffIterator, LeafNode, ChildOff > ChildOffIter
Definition: LeafNode.h:555
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1477
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other)
Union this node's set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1823
ChildOffIter endChildOff()
Definition: LeafNode.h:597
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:211
void setValueMaskOff(Index n)
Definition: LeafNode.h:1060
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1865
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:107
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:364
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:406
util::NodeMask< Log2Dim > NodeMaskType
Definition: LeafNode.h:71
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:794
bool isValueMaskOn(Index n) const
Definition: LeafNode.h:1047
Index32 pos() const
Definition: NodeMasks.h:193
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNode.h:733
ChildOnCIter cbeginChildOn() const
Definition: LeafNode.h:582
Definition: NodeMasks.h:267
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNode.h:1063
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:1409
void setValueMaskOn(Index n)
Definition: LeafNode.h:1059
OPENVDB_API boost::shared_ptr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme...
void modifyValue(const ModifyOp &op) const
Definition: LeafNode.h:506
bool isChildMaskOff(Index) const
Definition: LeafNode.h:1055
ChildAllIter endChildAll()
Definition: LeafNode.h:600
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:148
bool isOutOfCore() const
Return true if this buffer's values have not yet been read from disk.
Definition: LeafNode.h:162
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:442
static void doVisit2(NodeT &self, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: LeafNode.h:2096
void swap(Buffer &other)
Exchange this buffer's values with the other buffer's values.
Definition: LeafNode.h:241
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...
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
Definition: LeafNode.h:399
bool isDense() const
Return true if this node contains only active voxels.
Definition: LeafNode.h:416
static Index64 onTileCount()
Definition: LeafNode.h:411
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:391
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:817
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1268
static const Index SIZE
Definition: LeafNode.h:79
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:450
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:410
NodeMaskType::OffIterator MaskOffIterator
Definition: LeafNode.h:468
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:122
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
Definition: LeafNode.h:973
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:405
NodeMaskType & getValueMask()
Definition: LeafNode.h:1052
Definition: NodeMasks.h:205
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: LeafNode.h:527
ChildOffIter beginChildOff()
Definition: LeafNode.h:587
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...
ValueAllIter endValueAll()
Definition: LeafNode.h:578
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1658
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNode.h:972
static void doVisit2Node(NodeT &self, OtherNodeT &other, VisitorOp &)
Definition: LeafNode.h:2051
static Index getValueLevel(const Coord &)
Return the level (i.e., 0) at which leaf node values reside.
Definition: LeafNode.h:657
void voxelizeActiveTiles()
Definition: LeafNode.h:886
ChildAllCIter endChildAll() const
Definition: LeafNode.h:599
LeafNode()
Default constructor.
Definition: LeafNode.h:1111
bool isValueMaskOn() const
Definition: LeafNode.h:1048
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:393
Definition: PointIndexGrid.h:68
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don't change its value.
Definition: LeafNode.h:672
Buffer(PartialCreate, const ValueType &)
Construct a buffer but don't allocate memory for the full array of values.
Definition: LeafNode.h:150
OnIterator beginOn() const
Definition: NodeMasks.h:349
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:391
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:799
ValueOffCIter cbeginValueOff() const
Definition: LeafNode.h:563
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNode.h:736
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: LeafNode.h:1310
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:996
ValueIter< MaskOffIterator, const LeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: LeafNode.h:550
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1668
NodeMaskType::DenseIterator MaskDenseIterator
Definition: LeafNode.h:469
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:304
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
Definition: LeafNode.h:557
static Index log2dim()
Return log2 of the dimension of this LeafNode, e.g. 3 if dimensions are 8^3.
Definition: LeafNode.h:387
bool empty() const
Return true if memory for this buffer has not yet been allocated.
Definition: LeafNode.h:164
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNode.h:964
ChildOnCIter endChildOn() const
Definition: LeafNode.h:593
bool isValueMaskOff() const
Definition: LeafNode.h:1050
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:1438
uint32_t Index32
Definition: Types.h:57
Definition: Types.h:426
void unsetItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:540
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
ValueT & getItem(Index pos) const
Definition: LeafNode.h:487
~Buffer()
Destructor.
Definition: LeafNode.h:152
Buffer(const Buffer &other)
Copy constructor.
Definition: LeafNode.h:137
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
Definition: LeafNode.h:2072
Buffer(const ValueType &val)
Construct a buffer populated with the specified value.
Definition: LeafNode.h:132
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: LeafNode.h:670
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don't change its value.
Definition: LeafNode.h:682
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:217
LeafNode< ValueType, Log2Dim > LeafNodeType
Definition: LeafNode.h:69
ValueAllIter beginValueAll()
Definition: LeafNode.h:568
const ValueType & operator[](Index i) const
Return a const reference to the i'th element of this buffer.
Definition: LeafNode.h:183
ChildIter< MaskOnIterator, LeafNode, ChildOn > ChildOnIter
Definition: LeafNode.h:553
static void doVisit(NodeT &, VisitorOp &)
Definition: LeafNode.h:2012
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:225
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect this node'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:1831
ValueOffIter endValueOff()
Definition: LeafNode.h:575
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
boost::shared_ptr< LeafNode > Ptr
Definition: LeafNode.h:70
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:808
void merge(const LeafNode &)
Definition: LeafNode.h:1770
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:715
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a const pointer to this node.
Definition: LeafNode.h:1002
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNode.h:994
bool isConstant(ValueType &constValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1695
BaseT::NonConstValueType NonConstValueT
Definition: LeafNode.h:524
static Index size()
Return the number of values contained in this buffer.
Definition: LeafNode.h:262
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNode.h:985
std::streamoff maskpos
Definition: LeafNode.h:101
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:1368
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:690
T ValueType
Definition: LeafNode.h:68
Definition: Compression.h:187
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: LeafNode.h:485
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:314
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1485
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNode.h:438
Index64 offVoxelCount() const
Return the number of voxels marked Off.
Definition: LeafNode.h:408