OpenVDB  5.2.0
LeafManager.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
41 
42 #ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
44 
45 #include <openvdb/Types.h>
46 #include "TreeIterator.h" // for CopyConstness
47 #include <tbb/blocked_range.h>
48 #include <tbb/parallel_for.h>
49 #include <tbb/parallel_reduce.h>
50 #include <functional>
51 #include <type_traits>
52 
53 
54 namespace openvdb {
56 namespace OPENVDB_VERSION_NAME {
57 namespace tree {
58 
59 namespace leafmgr {
60 
62 template<typename TreeT> struct TreeTraits {
64  static const bool IsConstTree = false;
65  using LeafIterType = typename TreeT::LeafIter;
66 };
67 template<typename TreeT> struct TreeTraits<const TreeT> {
68  static const bool IsConstTree = true;
69  using LeafIterType = typename TreeT::LeafCIter;
70 };
72 
73 } // namespace leafmgr
74 
75 
78 template<typename ManagerT>
80 {
81  using RangeT = typename ManagerT::RangeType;
82  using LeafT = typename ManagerT::LeafType;
83  using BufT = typename ManagerT::BufferType;
84 
85  static inline void doSwapLeafBuffer(const RangeT& r, size_t auxBufferIdx,
86  LeafT** leafs, BufT* bufs, size_t bufsPerLeaf)
87  {
88  for (size_t n = r.begin(), m = r.end(), N = bufsPerLeaf; n != m; ++n) {
89  leafs[n]->swap(bufs[n * N + auxBufferIdx]);
90  }
91  }
92 };
93 
94 
96 
97 
109 template<typename TreeT>
111 {
112 public:
113  using TreeType = TreeT;
114  using ValueType = typename TreeT::ValueType;
115  using RootNodeType = typename TreeT::RootNodeType;
116  using NonConstLeafType = typename TreeType::LeafNodeType;
120  using NonConstBufferType = typename LeafType::Buffer;
122  using RangeType = tbb::blocked_range<size_t>; // leaf index range
123  static const Index DEPTH = 2; // root + leaf nodes
124 
125  static const bool IsConstTree = leafmgr::TreeTraits<TreeT>::IsConstTree;
126 
127  class LeafRange
128  {
129  public:
130  class Iterator
131  {
132  public:
133  Iterator(const LeafRange& range, size_t pos): mRange(range), mPos(pos)
134  {
135  assert(this->isValid());
136  }
137  Iterator(const Iterator&) = default;
138  Iterator& operator=(const Iterator&) = default;
140  Iterator& operator++() { ++mPos; return *this; }
142  LeafType& operator*() const { return mRange.mLeafManager.leaf(mPos); }
144  LeafType* operator->() const { return &(this->operator*()); }
147  BufferType& buffer(size_t bufferIdx)
148  {
149  return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
150  }
152  size_t pos() const { return mPos; }
154  bool isValid() const { return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
156  bool test() const { return mPos < mRange.mEnd; }
158  operator bool() const { return this->test(); }
160  bool empty() const { return !this->test(); }
161  bool operator!=(const Iterator& other) const
162  {
163  return (mPos != other.mPos) || (&mRange != &other.mRange);
164  }
165  bool operator==(const Iterator& other) const { return !(*this != other); }
166  const LeafRange& leafRange() const { return mRange; }
167 
168  private:
169  const LeafRange& mRange;
170  size_t mPos;
171  };// end Iterator
172 
173  LeafRange(size_t begin, size_t end, const LeafManager& leafManager, size_t grainSize=1)
174  : mEnd(end)
175  , mBegin(begin)
176  , mGrainSize(grainSize)
177  , mLeafManager(leafManager)
178  {
179  }
180 
181  Iterator begin() const {return Iterator(*this, mBegin);}
182 
183  Iterator end() const {return Iterator(*this, mEnd);}
184 
185  size_t size() const { return mEnd - mBegin; }
186 
187  size_t grainsize() const { return mGrainSize; }
188 
189  const LeafManager& leafManager() const { return mLeafManager; }
190 
191  bool empty() const {return !(mBegin < mEnd);}
192 
193  bool is_divisible() const {return mGrainSize < this->size();}
194 
195  LeafRange(LeafRange& r, tbb::split)
196  : mEnd(r.mEnd)
197  , mBegin(doSplit(r))
198  , mGrainSize(r.mGrainSize)
199  , mLeafManager(r.mLeafManager)
200  {
201  }
202 
203  private:
204  size_t mEnd, mBegin, mGrainSize;
205  const LeafManager& mLeafManager;
206 
207  static size_t doSplit(LeafRange& r)
208  {
209  assert(r.is_divisible());
210  size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
211  r.mEnd = middle;
212  return middle;
213  }
214  };// end of LeafRange
215 
218  LeafManager(TreeType& tree, size_t auxBuffersPerLeaf=0, bool serial=false)
219  : mTree(&tree)
220  , mLeafCount(0)
221  , mAuxBufferCount(0)
222  , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
223  , mLeafs(nullptr)
224  , mAuxBuffers(nullptr)
225  , mTask(0)
226  , mIsMaster(true)
227  {
228  this->rebuild(serial);
229  }
230 
234  LeafManager(TreeType& tree, LeafType** begin, LeafType** end,
235  size_t auxBuffersPerLeaf=0, bool serial=false)
236  : mTree(&tree)
237  , mLeafCount(end-begin)
238  , mAuxBufferCount(0)
239  , mAuxBuffersPerLeaf(auxBuffersPerLeaf)
240  , mLeafs(new LeafType*[mLeafCount])
241  , mAuxBuffers(nullptr)
242  , mTask(0)
243  , mIsMaster(true)
244  {
245  size_t n = mLeafCount;
246  LeafType **target = mLeafs, **source = begin;
247  while (n--) *target++ = *source++;
248  if (auxBuffersPerLeaf) this->initAuxBuffers(serial);
249  }
250 
254  LeafManager(const LeafManager& other)
255  : mTree(other.mTree)
256  , mLeafCount(other.mLeafCount)
257  , mAuxBufferCount(other.mAuxBufferCount)
258  , mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf)
259  , mLeafs(other.mLeafs)
260  , mAuxBuffers(other.mAuxBuffers)
261  , mTask(other.mTask)
262  , mIsMaster(false)
263  {
264  }
265 
266  virtual ~LeafManager()
267  {
268  if (mIsMaster) {
269  delete [] mLeafs;
270  delete [] mAuxBuffers;
271  }
272  }
273 
279  void rebuild(bool serial=false)
280  {
281  this->initLeafArray();
282  this->initAuxBuffers(serial);
283  }
285  void rebuild(size_t auxBuffersPerLeaf, bool serial=false)
287  {
288  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
289  this->rebuild(serial);
290  }
291  void rebuild(TreeType& tree, bool serial=false)
292  {
293  mTree = &tree;
294  this->rebuild(serial);
295  }
296  void rebuild(TreeType& tree, size_t auxBuffersPerLeaf, bool serial=false)
297  {
298  mTree = &tree;
299  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
300  this->rebuild(serial);
301  }
303  void rebuildAuxBuffers(size_t auxBuffersPerLeaf, bool serial=false)
308  {
309  mAuxBuffersPerLeaf = auxBuffersPerLeaf;
310  this->initAuxBuffers(serial);
311  }
313  void removeAuxBuffers() { this->rebuildAuxBuffers(0); }
314 
317  {
318  this->removeAuxBuffers();
319  this->initLeafArray();
320  }
321 
323  size_t auxBufferCount() const { return mAuxBufferCount; }
325  size_t auxBuffersPerLeaf() const { return mAuxBuffersPerLeaf; }
326 
328  size_t leafCount() const { return mLeafCount; }
329 
333  {
334  return tbb::parallel_reduce(this->leafRange(), Index64(0),
335  [] (const LeafRange& range, Index64 sum) -> Index64 {
336  for (const auto& leaf: range) { sum += leaf.onVoxelCount(); }
337  return sum;
338  },
339  [] (Index64 n, Index64 m) -> Index64 { return n + m; });
340  }
341 
343  const TreeType& tree() const { return *mTree; }
344 
346  TreeType& tree() { return *mTree; }
347 
349  const RootNodeType& root() const { return mTree->root(); }
350 
352  RootNodeType& root() { return mTree->root(); }
353 
355  bool isConstTree() const { return this->IsConstTree; }
356 
359  LeafType& leaf(size_t leafIdx) const { assert(leafIdx<mLeafCount); return *mLeafs[leafIdx]; }
360 
371  BufferType& getBuffer(size_t leafIdx, size_t bufferIdx) const
372  {
373  assert(leafIdx < mLeafCount);
374  assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
375  return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
376  : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
377  }
378 
383  RangeType getRange(size_t grainsize = 1) const { return RangeType(0, mLeafCount, grainsize); }
384 
386  LeafRange leafRange(size_t grainsize = 1) const
387  {
388  return LeafRange(0, mLeafCount, *this, grainsize);
389  }
390 
400  bool swapLeafBuffer(size_t bufferIdx, bool serial = false)
401  {
402  namespace ph = std::placeholders;
403  if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree()) return false;
404  mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, bufferIdx - 1);
405  this->cook(serial ? 0 : 512);
406  return true;//success
407  }
412  bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial = false)
413  {
414  namespace ph = std::placeholders;
415  const size_t b1 = std::min(bufferIdx1, bufferIdx2);
416  const size_t b2 = std::max(bufferIdx1, bufferIdx2);
417  if (b1 == b2 || b2 > mAuxBuffersPerLeaf) return false;
418  if (b1 == 0) {
419  if (this->isConstTree()) return false;
420  mTask = std::bind(&LeafManager::doSwapLeafBuffer, ph::_1, ph::_2, b2-1);
421  } else {
422  mTask = std::bind(&LeafManager::doSwapAuxBuffer, ph::_1, ph::_2, b1-1, b2-1);
423  }
424  this->cook(serial ? 0 : 512);
425  return true;//success
426  }
427 
436  bool syncAuxBuffer(size_t bufferIdx, bool serial = false)
437  {
438  namespace ph = std::placeholders;
439  if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf) return false;
440  mTask = std::bind(&LeafManager::doSyncAuxBuffer, ph::_1, ph::_2, bufferIdx - 1);
441  this->cook(serial ? 0 : 64);
442  return true;//success
443  }
444 
448  bool syncAllBuffers(bool serial = false)
449  {
450  namespace ph = std::placeholders;
451  switch (mAuxBuffersPerLeaf) {
452  case 0: return false;//nothing to do
453  case 1: mTask = std::bind(&LeafManager::doSyncAllBuffers1, ph::_1, ph::_2); break;
454  case 2: mTask = std::bind(&LeafManager::doSyncAllBuffers2, ph::_1, ph::_2); break;
455  default: mTask = std::bind(&LeafManager::doSyncAllBuffersN, ph::_1, ph::_2); break;
456  }
457  this->cook(serial ? 0 : 64);
458  return true;//success
459  }
460 
523  template<typename LeafOp>
524  void foreach(const LeafOp& op, bool threaded = true, size_t grainSize=1)
525  {
526  LeafTransformer<LeafOp> transform(op);
527  transform.run(this->leafRange(grainSize), threaded);
528  }
529 
572  template<typename LeafOp>
573  void reduce(LeafOp& op, bool threaded = true, size_t grainSize=1)
574  {
575  LeafReducer<LeafOp> transform(op);
576  transform.run(this->leafRange(grainSize), threaded);
577  }
578 
579 
584  template<typename ArrayT>
585  void getNodes(ArrayT& array)
586  {
587  using T = typename ArrayT::value_type;
588  static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
589  using LeafT = typename std::conditional<std::is_const<
590  typename std::remove_pointer<T>::type>::value, const LeafType, LeafType>::type;
591 
593  if (std::is_same<T, LeafT*>::value) {
594  array.resize(mLeafCount);
595  for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
596  } else {
597  mTree->getNodes(array);
598  }
600  }
601 
606  template<typename ArrayT>
607  void getNodes(ArrayT& array) const
608  {
609  using T = typename ArrayT::value_type;
610  static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array");
611  static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
612  "argument to getNodes() must be an array of const node pointers");
613 
615  if (std::is_same<T, const LeafType*>::value) {
616  array.resize(mLeafCount);
617  for (size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
618  } else {
619  mTree->getNodes(array);
620  }
622  }
623 
635  size_t getPrefixSum(size_t*& offsets, size_t& size, size_t grainSize=1) const
636  {
637  if (offsets == nullptr || size < mLeafCount) {
638  delete [] offsets;
639  offsets = new size_t[mLeafCount];
640  size = mLeafCount;
641  }
642  size_t prefix = 0;
643  if ( grainSize > 0 ) {
644  PrefixSum tmp(this->leafRange( grainSize ), offsets, prefix);
645  } else {// serial
646  for (size_t i=0; i<mLeafCount; ++i) {
647  offsets[i] = prefix;
648  prefix += mLeafs[i]->onVoxelCount();
649  }
650  }
651  return prefix;
652  }
653 
655  // All methods below are for internal use only and should never be called directly
656 
658  void operator()(const RangeType& r) const
659  {
660  if (mTask) mTask(const_cast<LeafManager*>(this), r);
661  else OPENVDB_THROW(ValueError, "task is undefined");
662  }
663 
664 private:
665 
666  // This a simple wrapper for a c-style array so it mimics the api
667  // of a std container, e.g. std::vector or std::deque, and can be
668  // passed to Tree::getNodes().
669  struct MyArray {
670  using value_type = LeafType*;//required by Tree::getNodes
671  value_type* ptr;
672  MyArray(value_type* array) : ptr(array) {}
673  void push_back(value_type leaf) { *ptr++ = leaf; }//required by Tree::getNodes
674  };
675 
676  void initLeafArray()
677  {
678  const size_t leafCount = mTree->leafCount();
679  if (leafCount != mLeafCount) {
680  delete [] mLeafs;
681  mLeafs = (leafCount == 0) ? nullptr : new LeafType*[leafCount];
682  mLeafCount = leafCount;
683  }
684  MyArray a(mLeafs);
685  mTree->getNodes(a);
686  }
687 
688  void initAuxBuffers(bool serial)
689  {
690  const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
691  if (auxBufferCount != mAuxBufferCount) {
692  delete [] mAuxBuffers;
693  mAuxBuffers = (auxBufferCount == 0) ? nullptr : new NonConstBufferType[auxBufferCount];
694  mAuxBufferCount = auxBufferCount;
695  }
696  this->syncAllBuffers(serial);
697  }
698 
699  void cook(size_t grainsize)
700  {
701  if (grainsize>0) {
702  tbb::parallel_for(this->getRange(grainsize), *this);
703  } else {
704  (*this)(this->getRange());
705  }
706  }
707 
708  void doSwapLeafBuffer(const RangeType& r, size_t auxBufferIdx)
709  {
711  r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
712  }
713 
714  void doSwapAuxBuffer(const RangeType& r, size_t auxBufferIdx1, size_t auxBufferIdx2)
715  {
716  for (size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
717  mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
718  }
719  }
720 
721  void doSyncAuxBuffer(const RangeType& r, size_t auxBufferIdx)
722  {
723  for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
724  mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
725  }
726  }
727 
728  void doSyncAllBuffers1(const RangeType& r)
729  {
730  for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
731  mAuxBuffers[n] = mLeafs[n]->buffer();
732  }
733  }
734 
735  void doSyncAllBuffers2(const RangeType& r)
736  {
737  for (size_t n = r.begin(), m = r.end(); n != m; ++n) {
738  const BufferType& leafBuffer = mLeafs[n]->buffer();
739  mAuxBuffers[2*n ] = leafBuffer;
740  mAuxBuffers[2*n+1] = leafBuffer;
741  }
742  }
743 
744  void doSyncAllBuffersN(const RangeType& r)
745  {
746  for (size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
747  const BufferType& leafBuffer = mLeafs[n]->buffer();
748  for (size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
749  }
750  }
751 
754  template<typename LeafOp>
755  struct LeafTransformer
756  {
757  LeafTransformer(const LeafOp &leafOp) : mLeafOp(leafOp)
758  {
759  }
760  void run(const LeafRange &range, bool threaded) const
761  {
762  threaded ? tbb::parallel_for(range, *this) : (*this)(range);
763  }
764  void operator()(const LeafRange &range) const
765  {
766  for (typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
767  }
768  const LeafOp mLeafOp;
769  };// LeafTransformer
770 
773  template<typename LeafOp>
774  struct LeafReducer
775  {
776  LeafReducer(LeafOp &leafOp) : mLeafOp(&leafOp), mOwnsOp(false)
777  {
778  }
779  LeafReducer(const LeafReducer &other, tbb::split)
780  : mLeafOp(new LeafOp(*(other.mLeafOp), tbb::split())), mOwnsOp(true)
781  {
782  }
783  ~LeafReducer() { if (mOwnsOp) delete mLeafOp; }
784  void run(const LeafRange& range, bool threaded)
785  {
786  threaded ? tbb::parallel_reduce(range, *this) : (*this)(range);
787  }
788  void operator()(const LeafRange& range)
789  {
790  LeafOp &op = *mLeafOp;//local registry
791  for (typename LeafRange::Iterator it = range.begin(); it; ++it) op(*it, it.pos());
792  }
793  void join(const LeafReducer& other) { mLeafOp->join(*(other.mLeafOp)); }
794  LeafOp *mLeafOp;
795  const bool mOwnsOp;
796  };// LeafReducer
797 
798  // Helper class to compute a prefix sum of offsets to active voxels
799  struct PrefixSum
800  {
801  PrefixSum(const LeafRange& r, size_t* offsets, size_t& prefix)
802  : mOffsets(offsets)
803  {
804  tbb::parallel_for( r, *this);
805  for (size_t i=0, leafCount = r.size(); i<leafCount; ++i) {
806  size_t tmp = offsets[i];
807  offsets[i] = prefix;
808  prefix += tmp;
809  }
810  }
811  inline void operator()(const LeafRange& r) const {
812  for (typename LeafRange::Iterator i = r.begin(); i; ++i) {
813  mOffsets[i.pos()] = i->onVoxelCount();
814  }
815  }
816  size_t* mOffsets;
817  };// PrefixSum
818 
819  using FuncType = typename std::function<void (LeafManager*, const RangeType&)>;
820 
821  TreeType* mTree;
822  size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
823  LeafType** mLeafs;//array of LeafNode pointers
824  NonConstBufferType* mAuxBuffers;//array of auxiliary buffers
825  FuncType mTask;
826  const bool mIsMaster;
827 };//end of LeafManager class
828 
829 
830 // Partial specializations of LeafManager methods for const trees
831 template<typename TreeT>
832 struct LeafManagerImpl<LeafManager<const TreeT> >
833 {
835  using RangeT = typename ManagerT::RangeType;
836  using LeafT = typename ManagerT::LeafType;
837  using BufT = typename ManagerT::BufferType;
838 
839  static inline void doSwapLeafBuffer(const RangeT&, size_t /*auxBufferIdx*/,
840  LeafT**, BufT*, size_t /*bufsPerLeaf*/)
841  {
842  // Buffers can't be swapped into const trees.
843  }
844 };
845 
846 } // namespace tree
847 } // namespace OPENVDB_VERSION_NAME
848 } // namespace openvdb
849 
850 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
851 
852 // Copyright (c) 2012-2018 DreamWorks Animation LLC
853 // All rights reserved. This software is distributed under the
854 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
void removeAuxBuffers()
Remove the auxiliary buffers, but don&#39;t rebuild the leaf array.
Definition: LeafManager.h:313
void rebuildLeafArray()
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:316
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition: LeafManager.h:352
LeafType * operator->() const
Return a pointer to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:144
bool empty() const
Return true if this iterator is exhausted.
Definition: LeafManager.h:160
typename TreeT::RootNodeType RootNodeType
Definition: LeafManager.h:115
const LeafManager & leafManager() const
Definition: LeafManager.h:189
LeafType & operator*() const
Return a reference to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:142
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Repopulate the leaf array and delete and reallocate auxiliary buffers.
Definition: LeafManager.h:296
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition: LeafManager.h:448
typename TreeT::LeafCIter LeafIterType
Definition: LeafManager.h:69
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:386
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:328
LeafRange(LeafRange &r, tbb::split)
Definition: LeafManager.h:195
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
void reduce(LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager. Unlike foreach (defined above) this method performs a reduction on all the leaf nodes.
Definition: LeafManager.h:573
size_t auxBuffersPerLeaf() const
Return the number of auxiliary buffers per leaf node.
Definition: LeafManager.h:325
typename TreeT::ValueType ValueType
Definition: LeafManager.h:114
LeafType LeafNodeType
Definition: LeafManager.h:118
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition: LeafManager.h:85
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition: LeafManager.h:658
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:82
LeafManager(TreeType &tree, LeafType **begin, LeafType **end, size_t auxBuffersPerLeaf=0, bool serial=false)
Construct directly from an existing array of leafnodes.
Definition: LeafManager.h:234
BufferType & getBuffer(size_t leafIdx, size_t bufferIdx) const
Return the leaf or auxiliary buffer for the leaf node at index leafIdx. If bufferIdx is zero...
Definition: LeafManager.h:371
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition: LeafManager.h:349
BufferType & buffer(size_t bufferIdx)
Return the nth buffer for the leaf node to which this iterator is pointing, where n = bufferIdx and n...
Definition: LeafManager.h:147
bool syncAuxBuffer(size_t bufferIdx, bool serial=false)
Sync up the specified auxiliary buffer with the corresponding leaf node buffer.
Definition: LeafManager.h:436
LeafManager(TreeType &tree, size_t auxBuffersPerLeaf=0, bool serial=false)
Constructor from a tree reference and an auxiliary buffer count.
Definition: LeafManager.h:218
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition: LeafManager.h:323
bool swapLeafBuffer(size_t bufferIdx, bool serial=false)
Swap each leaf node&#39;s buffer with the nth corresponding auxiliary buffer, where n = bufferIdx...
Definition: LeafManager.h:400
size_t grainsize() const
Definition: LeafManager.h:187
void rebuild(bool serial=false)
(Re)initialize by resizing (if necessary) and repopulating the leaf array and by deleting existing au...
Definition: LeafManager.h:279
LeafManager(const LeafManager &other)
Definition: LeafManager.h:254
typename std::remove_const< ToType >::type Type
Definition: TreeIterator.h:68
typename CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition: LeafManager.h:117
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
void getNodes(ArrayT &array)
Insert pointers to nodes of the specified type into the array.
Definition: LeafManager.h:585
Useful traits for Tree types.
Definition: LeafManager.h:63
Iterator end() const
Definition: LeafManager.h:183
Definition: LeafManager.h:79
bool test() const
Return true if this iterator is not yet exhausted.
Definition: LeafManager.h:156
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition: LeafManager.h:173
Iterator & operator++()
Advance to the next leaf node.
Definition: LeafManager.h:140
Index64 activeLeafVoxelCount() const
Return the number of active voxels in the leaf nodes.
Definition: LeafManager.h:332
Definition: Exceptions.h:92
bool empty() const
Definition: LeafManager.h:191
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:359
Iterator begin() const
Definition: LeafManager.h:181
Definition: Exceptions.h:40
typename ManagerT::BufferType BufT
Definition: LeafManager.h:837
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:129
typename ManagerT::LeafType LeafT
Definition: LeafManager.h:836
typename CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:121
typename TreeT::LeafIter LeafIterType
Definition: LeafManager.h:65
bool operator==(const Iterator &other) const
Definition: LeafManager.h:165
typename TreeType::LeafNodeType NonConstLeafType
Definition: LeafManager.h:116
Index32 Index
Definition: Types.h:61
bool operator!=(const Iterator &other) const
Definition: LeafManager.h:161
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:81
typename LeafType::Buffer NonConstBufferType
Definition: LeafManager.h:120
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition: LeafManager.h:839
uint64_t Index64
Definition: Types.h:60
TreeT TreeType
Definition: LeafManager.h:113
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
size_t pos() const
Return the index into the leaf array of the current leaf node.
Definition: LeafManager.h:152
Iterator(const LeafRange &range, size_t pos)
Definition: LeafManager.h:133
typename ManagerT::BufferType BufT
Definition: LeafManager.h:83
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:130
size_t size() const
Definition: LeafManager.h:185
Definition: LeafManager.h:127
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:343
typename leafmgr::TreeTraits< TreeT >::LeafIterType LeafIterType
Definition: LeafManager.h:119
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition: LeafManager.h:355
const LeafRange & leafRange() const
Definition: LeafManager.h:166
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
bool isValid() const
Return true if the position of this iterator is in a valid range.
Definition: LeafManager.h:154
void rebuild(TreeType &tree, bool serial=false)
Repopulate the leaf array and delete and reallocate auxiliary buffers.
Definition: LeafManager.h:291
virtual ~LeafManager()
Definition: LeafManager.h:266
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:645
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
size_t getPrefixSum(size_t *&offsets, size_t &size, size_t grainSize=1) const
Generate a linear array of prefix sums of offsets into the active voxels in the leafs. So offsets[n]+m is the offset to the mth active voxel in the nth leaf node (useful for user-managed value buffers, e.g. in tools/LevelSetAdvect.h).
Definition: LeafManager.h:635
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:383
void getNodes(ArrayT &array) const
Insert node pointers of the specified type into the array.
Definition: LeafManager.h:607
bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial=false)
Swap any two buffers for each leaf node.
Definition: LeafManager.h:412
bool is_divisible() const
Definition: LeafManager.h:193
typename ManagerT::RangeType RangeT
Definition: LeafManager.h:835
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition: LeafManager.h:346
tbb::blocked_range< size_t > RangeType
Definition: LeafManager.h:122