OpenVDB  11.0.0
GridBuilder.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /*!
5  \file GridBuilder.h
6 
7  \author Ken Museth
8 
9  \date June 26, 2020
10 
11  \brief This file defines a minimum set of tree nodes and tools that
12  can be used (instead of OpenVDB) to build nanovdb grids on the CPU.
13 */
14 
15 #ifndef NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
16 #define NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
17 
18 #include <iostream>
19 
20 #include <map>
21 #include <limits>
22 #include <sstream> // for stringstream
23 #include <vector>
24 #include <cstring> // for memcpy
25 #include <mutex>
26 #include <array>
27 #include <atomic>
28 
29 #include <nanovdb/NanoVDB.h>
30 #include "Range.h"
31 #include "ForEach.h"
32 
33 namespace nanovdb {
34 
35 namespace build {
36 
37 // ----------------------------> Froward decelerations of random access methods <--------------------------------------
38 
39 template <typename T> struct GetValue;
40 template <typename T> struct SetValue;
41 template <typename T> struct TouchLeaf;
42 template <typename T> struct GetState;
43 template <typename T> struct ProbeValue;
44 
45 // ----------------------------> RootNode <--------------------------------------
46 
47 template<typename ChildT>
48 struct RootNode
49 {
50  using ValueType = typename ChildT::ValueType;
51  using BuildType = typename ChildT::BuildType;
52  using ChildNodeType = ChildT;
53  using LeafNodeType = typename ChildT::LeafNodeType;
54  static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
55  struct Tile {
56  Tile(ChildT* c = nullptr) : child(c) {}
57  Tile(const ValueType& v, bool s) : child(nullptr), value(v), state(s) {}
58  bool isChild() const { return child!=nullptr; }
59  bool isValue() const { return child==nullptr; }
60  bool isActive() const { return child==nullptr && state; }
61  ChildT* child;
63  bool state;
64  };
65  using MapT = std::map<Coord, Tile>;
68 
69  Tile* probeTile(const Coord &ijk) {
70  auto iter = mTable.find(CoordToKey(ijk));
71  return iter == mTable.end() ? nullptr : &(iter->second);
72  }
73 
74  const Tile* probeTile(const Coord &ijk) const {
75  auto iter = mTable.find(CoordToKey(ijk));
76  return iter == mTable.end() ? nullptr : &(iter->second);
77  }
78 
80  {
81  const RootNode *mParent;
82  typename MapT::const_iterator mIter;
83  public:
84  ChildIterator() : mParent(nullptr), mIter() {}
85  ChildIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
86  while (mIter!=parent->mTable.end() && mIter->second.child==nullptr) ++mIter;
87  }
88  ChildIterator& operator=(const ChildIterator&) = default;
89  ChildT& operator*() const {NANOVDB_ASSERT(*this); return *mIter->second.child;}
90  ChildT* operator->() const {NANOVDB_ASSERT(*this); return mIter->second.child;}
91  Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
92  Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
93  operator bool() const {return mParent && mIter!=mParent->mTable.end();}
95  NANOVDB_ASSERT(mParent);
96  ++mIter;
97  while (mIter!=mParent->mTable.end() && mIter->second.child==nullptr) ++mIter;
98  return *this;
99  }
101  auto tmp = *this;
102  ++(*this);
103  return tmp;
104  }
105  uint32_t pos() const {
106  NANOVDB_ASSERT(mParent);
107  return uint32_t(std::distance(mParent->mTable.begin(), mIter));
108  }
109  }; // Member class ChildIterator
110 
111  ChildIterator cbeginChild() const {return ChildIterator(this);}
112  ChildIterator cbeginChildOn() const {return ChildIterator(this);}// match openvdb
113 
115  {
116  const RootNode *mParent;
117  typename MapT::const_iterator mIter;
118  public:
119  ValueIterator() : mParent(nullptr), mIter() {}
120  ValueIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
121  while (mIter!=parent->mTable.end() && mIter->second.child!=nullptr) ++mIter;
122  }
123  ValueIterator& operator=(const ValueIterator&) = default;
124  ValueType operator*() const {NANOVDB_ASSERT(*this); return mIter->second.value;}
125  bool isActive() const {NANOVDB_ASSERT(*this); return mIter->second.state;}
126  Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
127  Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
128  operator bool() const {return mParent && mIter!=mParent->mTable.end();}
130  NANOVDB_ASSERT(mParent);
131  ++mIter;
132  while (mIter!=mParent->mTable.end() && mIter->second.child!=nullptr) ++mIter;
133  return *this;;
134  }
136  auto tmp = *this;
137  ++(*this);
138  return tmp;
139  }
140  uint32_t pos() const {
141  NANOVDB_ASSERT(mParent);
142  return uint32_t(std::distance(mParent->mTable.begin(), mIter));
143  }
144  }; // Member class ValueIterator
145 
146  ValueIterator beginValue() {return ValueIterator(this);}
147  ValueIterator cbeginValueAll() const {return ValueIterator(this);}
148 
150  {
151  const RootNode *mParent;
152  typename MapT::const_iterator mIter;
153  public:
154  ValueOnIterator() : mParent(nullptr), mIter() {}
155  ValueOnIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
156  while (mIter!=parent->mTable.end() && (mIter->second.child!=nullptr || !mIter->second.state)) ++mIter;
157  }
158  ValueOnIterator& operator=(const ValueOnIterator&) = default;
159  ValueType operator*() const {NANOVDB_ASSERT(*this); return mIter->second.value;}
160  Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
161  Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
162  operator bool() const {return mParent && mIter!=mParent->mTable.end();}
164  NANOVDB_ASSERT(mParent);
165  ++mIter;
166  while (mIter!=mParent->mTable.end() && (mIter->second.child!=nullptr || !mIter->second.state)) ++mIter;
167  return *this;;
168  }
170  auto tmp = *this;
171  ++(*this);
172  return tmp;
173  }
174  uint32_t pos() const {
175  NANOVDB_ASSERT(mParent);
176  return uint32_t(std::distance(mParent->mTable.begin(), mIter));
177  }
178  }; // Member class ValueOnIterator
179 
180  ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
181  ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
182 
184  {
185  const RootNode *mParent;
186  typename MapT::const_iterator mIter;
187  public:
188  TileIterator() : mParent(nullptr), mIter() {}
189  TileIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
190  NANOVDB_ASSERT(mParent);
191  }
192  TileIterator& operator=(const TileIterator&) = default;
193  const Tile& operator*() const {NANOVDB_ASSERT(*this); return mIter->second;}
194  const Tile* operator->() const {NANOVDB_ASSERT(*this); return &(mIter->second);}
195  Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
196  Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
197  operator bool() const {return mParent && mIter!=mParent->mTable.end();}
198  const ChildT* probeChild(ValueType &value) {
199  NANOVDB_ASSERT(*this);
200  const ChildT *child = mIter->second.child;
201  if (child==nullptr) value = mIter->second.value;
202  return child;
203  }
204  bool isValueOn() const {return mIter->second.child==nullptr && mIter->second.state;}
206  NANOVDB_ASSERT(mParent);
207  ++mIter;
208  return *this;
209  }
211  auto tmp = *this;
212  ++(*this);
213  return tmp;
214  }
215  uint32_t pos() const {
216  NANOVDB_ASSERT(mParent);
217  return uint32_t(std::distance(mParent->mTable.begin(), mIter));
218  }
219  }; // Member class TileIterator
220 
221  TileIterator beginTile() {return TileIterator(this);}
222  TileIterator cbeginChildAll() const {return TileIterator(this);}
223 
224  //class DenseIterator : public TileIterator
225 
226  RootNode(const ValueType& background) : mBackground(background) {}
227  RootNode(const RootNode&) = delete; // disallow copy-construction
228  RootNode(RootNode&&) = default; // allow move construction
229  RootNode& operator=(const RootNode&) = delete; // disallow copy assignment
230  RootNode& operator=(RootNode&&) = default; // allow move assignment
231 
232  ~RootNode() { this->clear(); }
233 
234  uint32_t tileCount() const { return uint32_t(mTable.size()); }
235  uint32_t getTableSize() const { return uint32_t(mTable.size()); }// match openvdb
236  const ValueType& background() const {return mBackground;}
237 
238  void nodeCount(std::array<size_t,3> &count) const
239  {
240  for (auto it = this->cbeginChild(); it; ++it) {
241  count[ChildT::LEVEL] += 1;
242  it->nodeCount(count);
243  }
244  }
245 
246  bool empty() const { return mTable.empty(); }
247 
248  void clear()
249  {
250  for (auto iter = mTable.begin(); iter != mTable.end(); ++iter) delete iter->second.child;
251  mTable.clear();
252  }
253 
254  static Coord CoordToKey(const Coord& ijk) { return ijk & ~ChildT::MASK; }
255 
256 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
257  template<typename OpT, typename... ArgsT>
258  auto get(const Coord& ijk, ArgsT&&... args) const
259  {
260  if (const Tile *tile = this->probeTile(ijk)) {
261  if (auto *child = tile->child) return child->template get<OpT>(ijk, args...);
262  return OpT::get(*tile, args...);
263  }
264  return OpT::get(*this, args...);
265  }
266  template<typename OpT, typename... ArgsT>
267  auto set(const Coord& ijk, ArgsT&&... args)
268  {
269  ChildT* child = nullptr;
270  const Coord key = CoordToKey(ijk);
271  auto iter = mTable.find(key);
272  if (iter == mTable.end()) {
273  child = new ChildT(ijk, mBackground, false);
274  mTable[key] = Tile(child);
275  } else if (iter->second.child != nullptr) {
276  child = iter->second.child;
277  } else {
278  child = new ChildT(ijk, iter->second.value, iter->second.state);
279  iter->second.child = child;
280  }
281  NANOVDB_ASSERT(child);
282  return child->template set<OpT>(ijk, args...);
283  }
284  template<typename OpT, typename AccT, typename... ArgsT>
285  auto getAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args) const
286  {
287  if (const Tile *tile = this->probeTile(ijk)) {
288  if (auto *child = tile->child) {
289  acc.insert(ijk, child);
290  return child->template get<OpT>(ijk, args...);
291  }
292  return OpT::get(*tile, args...);
293  }
294  return OpT::get(*this, args...);
295  }
296 
297  template<typename OpT, typename AccT, typename... ArgsT>
298  auto setAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args)
299  {
300  ChildT* child = nullptr;
301  const Coord key = CoordToKey(ijk);
302  auto iter = mTable.find(key);
303  if (iter == mTable.end()) {
304  child = new ChildT(ijk, mBackground, false);
305  mTable[key] = Tile(child);
306  } else if (iter->second.child != nullptr) {
307  child = iter->second.child;
308  } else {
309  child = new ChildT(ijk, iter->second.value, iter->second.state);
310  iter->second.child = child;
311  }
312  NANOVDB_ASSERT(child);
313  acc.insert(ijk, child);
314  return child->template setAndCache<OpT>(ijk, acc, args...);
315  }
316  ValueType getValue(const Coord& ijk) const {return this->template get<GetValue<BuildType>>(ijk);}
317  ValueType getValue(int i, int j, int k) const {return this->template get<GetValue<BuildType>>(Coord(i,j,k));}
318  ValueType operator()(const Coord& ijk) const {return this->template get<GetValue<BuildType>>(ijk);}
319  ValueType operator()(int i, int j, int k) const {return this->template get<GetValue<BuildType>>(Coord(i,j,k));}
320  void setValue(const Coord& ijk, const ValueType& value) {this->template set<SetValue<BuildType>>(ijk, value);}
321  bool probeValue(const Coord& ijk, ValueType& value) const {return this->template get<ProbeValue<BuildType>>(ijk, value);}
322  bool isActive(const Coord& ijk) const {return this->template get<GetState<BuildType>>(ijk);}
323 #else
324  ValueType getValue(const Coord& ijk) const
325  {
326 #if 1
327  if (auto *tile = this->probeTile(ijk)) return tile->child ? tile->child->getValue(ijk) : tile->value;
328  return mBackground;
329 #else
330  auto iter = mTable.find(CoordToKey(ijk));
331  if (iter == mTable.end()) {
332  return mBackground;
333  } else if (iter->second.child) {
334  return iter->second.child->getValue(ijk);
335  } else {
336  return iter->second.value;
337  }
338 #endif
339  }
340  ValueType getValue(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
341 
342  void setValue(const Coord& ijk, const ValueType& value)
343  {
344  ChildT* child = nullptr;
345  const Coord key = CoordToKey(ijk);
346  auto iter = mTable.find(key);
347  if (iter == mTable.end()) {
348  child = new ChildT(ijk, mBackground, false);
349  mTable[key] = Tile(child);
350  } else if (iter->second.child != nullptr) {
351  child = iter->second.child;
352  } else {
353  child = new ChildT(ijk, iter->second.value, iter->second.state);
354  iter->second.child = child;
355  }
356  NANOVDB_ASSERT(child);
357  child->setValue(ijk, value);
358  }
359 
360  template<typename AccT>
361  bool isActiveAndCache(const Coord& ijk, AccT& acc) const
362  {
363  auto iter = mTable.find(CoordToKey(ijk));
364  if (iter == mTable.end())
365  return false;
366  if (iter->second.child) {
367  acc.insert(ijk, iter->second.child);
368  return iter->second.child->isActiveAndCache(ijk, acc);
369  }
370  return iter->second.state;
371  }
372 
373  template<typename AccT>
374  ValueType getValueAndCache(const Coord& ijk, AccT& acc) const
375  {
376  auto iter = mTable.find(CoordToKey(ijk));
377  if (iter == mTable.end())
378  return mBackground;
379  if (iter->second.child) {
380  acc.insert(ijk, iter->second.child);
381  return iter->second.child->getValueAndCache(ijk, acc);
382  }
383  return iter->second.value;
384  }
385 
386  template<typename AccT>
387  void setValueAndCache(const Coord& ijk, const ValueType& value, AccT& acc)
388  {
389  ChildT* child = nullptr;
390  const Coord key = CoordToKey(ijk);
391  auto iter = mTable.find(key);
392  if (iter == mTable.end()) {
393  child = new ChildT(ijk, mBackground, false);
394  mTable[key] = Tile(child);
395  } else if (iter->second.child != nullptr) {
396  child = iter->second.child;
397  } else {
398  child = new ChildT(ijk, iter->second.value, iter->second.state);
399  iter->second.child = child;
400  }
401  NANOVDB_ASSERT(child);
402  acc.insert(ijk, child);
403  child->setValueAndCache(ijk, value, acc);
404  }
405  template<typename AccT>
406  void setValueOnAndCache(const Coord& ijk, AccT& acc)
407  {
408  ChildT* child = nullptr;
409  const Coord key = CoordToKey(ijk);
410  auto iter = mTable.find(key);
411  if (iter == mTable.end()) {
412  child = new ChildT(ijk, mBackground, false);
413  mTable[key] = Tile(child);
414  } else if (iter->second.child != nullptr) {
415  child = iter->second.child;
416  } else {
417  child = new ChildT(ijk, iter->second.value, iter->second.state);
418  iter->second.child = child;
419  }
420  NANOVDB_ASSERT(child);
421  acc.insert(ijk, child);
422  child->setValueOnAndCache(ijk, acc);
423  }
424  template<typename AccT>
425  void touchLeafAndCache(const Coord &ijk, AccT& acc)
426  {
427  ChildT* child = nullptr;
428  const Coord key = CoordToKey(ijk);
429  auto iter = mTable.find(key);
430  if (iter == mTable.end()) {
431  child = new ChildT(ijk, mBackground, false);
432  mTable[key] = Tile(child);
433  } else if (iter->second.child != nullptr) {
434  child = iter->second.child;
435  } else {
436  child = new ChildT(ijk, iter->second.value, iter->second.state);
437  iter->second.child = child;
438  }
439  acc.insert(ijk, child);
440  child->touchLeafAndCache(ijk, acc);
441  }
442 #endif// NANOVDB_NEW_ACCESSOR_METHODS
443 
444  template<typename NodeT>
445  uint32_t nodeCount() const
446  {
447  static_assert(is_same<ValueType, typename NodeT::ValueType>::value, "Root::getNodes: Invalid type");
448  static_assert(NodeT::LEVEL < LEVEL, "Root::getNodes: LEVEL error");
449  uint32_t sum = 0;
450  for (auto iter = mTable.begin(); iter != mTable.end(); ++iter) {
451  if (iter->second.child == nullptr) continue; // skip tiles
452  if constexpr(is_same<NodeT, ChildT>::value) { //resolved at compile-time
453  ++sum;
454  } else {
455  sum += iter->second.child->template nodeCount<NodeT>();
456  }
457  }
458  return sum;
459  }
460 
461  template<typename NodeT>
462  void getNodes(std::vector<NodeT*>& array)
463  {
464  static_assert(is_same<ValueType, typename NodeT::ValueType>::value, "Root::getNodes: Invalid type");
465  static_assert(NodeT::LEVEL < LEVEL, "Root::getNodes: LEVEL error");
466  for (auto iter = mTable.begin(); iter != mTable.end(); ++iter) {
467  if (iter->second.child == nullptr)
468  continue;
469  if constexpr(is_same<NodeT, ChildT>::value) { //resolved at compile-time
470  array.push_back(reinterpret_cast<NodeT*>(iter->second.child));
471  } else {
472  iter->second.child->getNodes(array);
473  }
474  }
475  }
476 
477  void addChild(ChildT*& child)
478  {
479  NANOVDB_ASSERT(child);
480  const Coord key = CoordToKey(child->mOrigin);
481  auto iter = mTable.find(key);
482  if (iter != mTable.end() && iter->second.child != nullptr) { // existing child node
483  delete iter->second.child;
484  iter->second.child = child;
485  } else {
486  mTable[key] = Tile(child);
487  }
488  child = nullptr;
489  }
490 
491  /// @brief Add a tile containing voxel (i, j, k) at the specified tree level,
492  /// creating a new branch if necessary. Delete any existing lower-level nodes
493  /// that contain (x, y, z).
494  /// @tparam level tree level at which the tile is inserted. Must be 1, 2 or 3.
495  /// @param ijk Index coordinate that map to the tile being inserted
496  /// @param value Value of the tile
497  /// @param state Binary state of the tile
498  template <uint32_t level>
499  void addTile(const Coord& ijk, const ValueType& value, bool state)
500  {
501  static_assert(level > 0 && level <= LEVEL, "invalid template value of level");
502  const Coord key = CoordToKey(ijk);
503  auto iter = mTable.find(key);
504  if constexpr(level == LEVEL) {
505  if (iter == mTable.end()) {
506  mTable[key] = Tile(value, state);
507  } else if (iter->second.child == nullptr) {
508  iter->second.value = value;
509  iter->second.state = state;
510  } else {
511  delete iter->second.child;
512  iter->second.child = nullptr;
513  iter->second.value = value;
514  iter->second.state = state;
515  }
516  } else if constexpr(level < LEVEL) {
517  ChildT* child = nullptr;
518  if (iter == mTable.end()) {
519  child = new ChildT(ijk, mBackground, false);
520  mTable[key] = Tile(child);
521  } else if (iter->second.child != nullptr) {
522  child = iter->second.child;
523  } else {
524  child = new ChildT(ijk, iter->second.value, iter->second.state);
525  iter->second.child = child;
526  }
527  child->template addTile<level>(ijk, value, state);
528  }
529  }
530 
531  template<typename NodeT>
532  void addNode(NodeT*& node)
533  {
534  if constexpr(is_same<NodeT, ChildT>::value) { //resolved at compile-time
535  this->addChild(reinterpret_cast<ChildT*&>(node));
536  } else {
537  ChildT* child = nullptr;
538  const Coord key = CoordToKey(node->mOrigin);
539  auto iter = mTable.find(key);
540  if (iter == mTable.end()) {
541  child = new ChildT(node->mOrigin, mBackground, false);
542  mTable[key] = Tile(child);
543  } else if (iter->second.child != nullptr) {
544  child = iter->second.child;
545  } else {
546  child = new ChildT(node->mOrigin, iter->second.value, iter->second.state);
547  iter->second.child = child;
548  }
549  child->addNode(node);
550  }
551  }
552 
553  void merge(RootNode &other)
554  {
555  for (auto iter1 = other.mTable.begin(); iter1 != other.mTable.end(); ++iter1) {
556  if (iter1->second.child == nullptr) continue;// ignore input tiles
557  auto iter2 = mTable.find(iter1->first);
558  if (iter2 == mTable.end() || iter2->second.child == nullptr) {
559  mTable[iter1->first] = Tile(iter1->second.child);
560  iter1->second.child = nullptr;
561  } else {
562  iter2->second.child->merge(*iter1->second.child);
563  }
564  }
565  other.clear();
566  }
567 
568  template<typename T>
569  typename std::enable_if<std::is_floating_point<T>::value>::type
570  signedFloodFill(T outside);
571 
572 }; // build::RootNode
573 
574 //================================================================================================
575 
576 template<typename ChildT>
577 template<typename T>
578 inline typename std::enable_if<std::is_floating_point<T>::value>::type
580 {
581  std::map<Coord, ChildT*> nodeKeys;
582  for (auto iter = mTable.begin(); iter != mTable.end(); ++iter) {
583  if (iter->second.child == nullptr)
584  continue;
585  nodeKeys.insert(std::pair<Coord, ChildT*>(iter->first, iter->second.child));
586  }
587 
588  // We employ a simple z-scanline algorithm that inserts inactive tiles with
589  // the inside value if they are sandwiched between inside child nodes only!
590  auto b = nodeKeys.begin(), e = nodeKeys.end();
591  if (b == e)
592  return;
593  for (auto a = b++; b != e; ++a, ++b) {
594  Coord d = b->first - a->first; // delta of neighboring coordinates
595  if (d[0] != 0 || d[1] != 0 || d[2] == int(ChildT::DIM))
596  continue; // not same z-scanline or neighbors
597  const ValueType fill[] = {a->second->getLastValue(), b->second->getFirstValue()};
598  if (!(fill[0] < 0) || !(fill[1] < 0))
599  continue; // scanline isn't inside
600  Coord c = a->first + Coord(0u, 0u, ChildT::DIM);
601  for (; c[2] != b->first[2]; c[2] += ChildT::DIM) {
602  const Coord key = RootNode<ChildT>::CoordToKey(c);
603  mTable[key] = typename RootNode<ChildT>::Tile(-outside, false); // inactive tile
604  }
605  }
606 } // build::RootNode::signedFloodFill
607 
608 // ----------------------------> InternalNode <--------------------------------------
609 
610 template<typename ChildT>
612 {
613  using ValueType = typename ChildT::ValueType;
614  using BuildType = typename ChildT::BuildType;
615  using ChildNodeType = ChildT;
616  using LeafNodeType = typename ChildT::LeafNodeType;
617  static constexpr uint32_t LOG2DIM = ChildT::LOG2DIM + 1;
618  static constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL; //dimension in index space
619  static constexpr uint32_t DIM = 1u << TOTAL;
620  static constexpr uint32_t SIZE = 1u << (3 * LOG2DIM); //number of tile values (or child pointers)
621  static constexpr uint32_t MASK = DIM - 1;
622  static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
623  static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
625  template<bool On>
626  using MaskIterT = typename MaskT::template Iterator<On>;
628 
629  struct Tile {
630  Tile(ChildT* c = nullptr) : child(c) {}
631  Tile(const ValueType& v) : value(v) {}
632  union{
633  ChildT* child;
635  };
636  };
640  Tile mTable[SIZE];
641 
642  union {
644  uint64_t mDstOffset;
645  };
646 
647  /// @brief Visits child nodes of this node only
648  class ChildIterator : public MaskIterT<true>
649  {
650  using BaseT = MaskIterT<true>;
651  const InternalNode *mParent;
652  public:
653  ChildIterator() : BaseT(), mParent(nullptr) {}
654  ChildIterator(const InternalNode* parent) : BaseT(parent->mChildMask.beginOn()), mParent(parent) {}
655  ChildIterator& operator=(const ChildIterator&) = default;
656  const ChildT& operator*() const {NANOVDB_ASSERT(*this); return *mParent->mTable[BaseT::pos()].child;}
657  const ChildT* operator->() const {NANOVDB_ASSERT(*this); return mParent->mTable[BaseT::pos()].child;}
658  Coord getCoord() const { NANOVDB_ASSERT(*this); return (*this)->origin();}
659  }; // Member class ChildIterator
660 
662  ChildIterator cbeginChildOn() const {return ChildIterator(this);}// match openvdb
663 
664  /// @brief Visits all tile values in this node, i.e. both inactive and active tiles
665  class ValueIterator : public MaskIterT<false>
666  {
667  using BaseT = MaskIterT<false>;
668  const InternalNode *mParent;
669  public:
670  ValueIterator() : BaseT(), mParent(nullptr) {}
671  ValueIterator(const InternalNode* parent) : BaseT(parent->mChildMask.beginOff()), mParent(parent) {}
672  ValueIterator& operator=(const ValueIterator&) = default;
673  ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->mTable[BaseT::pos()].value;}
674  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
675  bool isActive() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(BaseT::pos());}
676  }; // Member class ValueIterator
677 
680 
681  /// @brief Visits active tile values of this node only
682  class ValueOnIterator : public MaskIterT<true>
683  {
684  using BaseT = MaskIterT<true>;
685  const InternalNode *mParent;
686  public:
687  ValueOnIterator() : BaseT(), mParent(nullptr) {}
688  ValueOnIterator(const InternalNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
689  ValueOnIterator& operator=(const ValueOnIterator&) = default;
690  ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->mTable[BaseT::pos()].value;}
691  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
692  }; // Member class ValueOnIterator
693 
696 
697  /// @brief Visits all tile values and child nodes of this node
699  {
700  using BaseT = typename MaskT::DenseIterator;
701  const InternalNode *mParent;
702  public:
703  DenseIterator() : BaseT(), mParent(nullptr) {}
704  DenseIterator(const InternalNode* parent) : BaseT(0), mParent(parent) {}
705  DenseIterator& operator=(const DenseIterator&) = default;
706  ChildT* probeChild(ValueType& value) const
707  {
708  NANOVDB_ASSERT(mParent && bool(*this));
709  ChildT *child = nullptr;
710  if (mParent->mChildMask.isOn(BaseT::pos())) {
711  child = mParent->mTable[BaseT::pos()].child;
712  } else {
713  value = mParent->mTable[BaseT::pos()].value;
714  }
715  return child;
716  }
717  Coord getCoord() const { NANOVDB_ASSERT(mParent && bool(*this)); return mParent->offsetToGlobalCoord(BaseT::pos());}
718  }; // Member class DenseIterator
719 
721  DenseIterator cbeginChildAll() const {return DenseIterator(this);}// matches openvdb
722 
723  InternalNode(const Coord& origin, const ValueType& value, bool state)
724  : mOrigin(origin & ~MASK)
725  , mValueMask(state)
726  , mChildMask()
727  , mDstOffset(0)
728  {
729  for (uint32_t i = 0; i < SIZE; ++i) mTable[i].value = value;
730  }
731  InternalNode(const InternalNode&) = delete; // disallow copy-construction
732  InternalNode(InternalNode&&) = delete; // disallow move construction
733  InternalNode& operator=(const InternalNode&) = delete; // disallow copy assignment
734  InternalNode& operator=(InternalNode&&) = delete; // disallow move assignment
736  {
737  for (auto iter = mChildMask.beginOn(); iter; ++iter) {
738  delete mTable[*iter].child;
739  }
740  }
741  const MaskT& getValueMask() const {return mValueMask;}
742  const MaskT& valueMask() const {return mValueMask;}
743  const MaskT& getChildMask() const {return mChildMask;}
744  const MaskT& childMask() const {return mChildMask;}
745  const Coord& origin() const {return mOrigin;}
746 
747  void nodeCount(std::array<size_t,3> &count) const
748  {
749  count[ChildT::LEVEL] += mChildMask.countOn();
750  if constexpr(ChildT::LEVEL>0) {
751  for (auto it = const_cast<InternalNode*>(this)->beginChild(); it; ++it) it->nodeCount(count);
752  }
753  }
754 
755  static uint32_t CoordToOffset(const Coord& ijk)
756  {
757  return (((ijk[0] & int32_t(MASK)) >> ChildT::TOTAL) << (2 * LOG2DIM)) +
758  (((ijk[1] & int32_t(MASK)) >> ChildT::TOTAL) << (LOG2DIM)) +
759  ((ijk[2] & int32_t(MASK)) >> ChildT::TOTAL);
760  }
761 
762  static Coord OffsetToLocalCoord(uint32_t n)
763  {
764  NANOVDB_ASSERT(n < SIZE);
765  const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
766  return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & ((1 << LOG2DIM) - 1));
767  }
768 
769  void localToGlobalCoord(Coord& ijk) const
770  {
771  ijk <<= ChildT::TOTAL;
772  ijk += mOrigin;
773  }
774 
775  Coord offsetToGlobalCoord(uint32_t n) const
776  {
778  this->localToGlobalCoord(ijk);
779  return ijk;
780  }
781 
782  ValueType getFirstValue() const { return mChildMask.isOn(0) ? mTable[0].child->getFirstValue() : mTable[0].value; }
783  ValueType getLastValue() const { return mChildMask.isOn(SIZE - 1) ? mTable[SIZE - 1].child->getLastValue() : mTable[SIZE - 1].value; }
784 
785  template<typename OpT, typename... ArgsT>
786  auto get(const Coord& ijk, ArgsT&&... args) const
787  {
788  const uint32_t n = CoordToOffset(ijk);
789  if (mChildMask.isOn(n)) return mTable[n].child->template get<OpT>(ijk, args...);
790  return OpT::get(*this, n, args...);
791  }
792 
793  template<typename OpT, typename... ArgsT>
794  auto set(const Coord& ijk, ArgsT&&... args)
795  {
796  const uint32_t n = CoordToOffset(ijk);
797  ChildT* child = nullptr;
798  if (mChildMask.isOn(n)) {
799  child = mTable[n].child;
800  } else {
801  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
802  mTable[n].child = child;
803  mChildMask.setOn(n);
804  }
805  NANOVDB_ASSERT(child);
806  return child->template set<OpT>(ijk, args...);
807  }
808 
809  template<typename OpT, typename AccT, typename... ArgsT>
810  auto getAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args) const
811  {
812  const uint32_t n = CoordToOffset(ijk);
813  if (mChildMask.isOff(n)) return OpT::get(*this, n, args...);
814  ChildT* child = mTable[n].child;
815  acc.insert(ijk, child);
816  if constexpr(ChildT::LEVEL == 0) {
817  return child->template get<OpT>(ijk, args...);
818  } else {
819  return child->template getAndCache<OpT>(ijk, acc, args...);
820  }
821  }
822 
823  template<typename OpT, typename AccT, typename... ArgsT>
824  auto setAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args)
825  {
826  const uint32_t n = CoordToOffset(ijk);
827  ChildT* child = nullptr;
828  if (mChildMask.isOn(n)) {
829  child = mTable[n].child;
830  } else {
831  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
832  mTable[n].child = child;
833  mChildMask.setOn(n);
834  }
835  NANOVDB_ASSERT(child);
836  acc.insert(ijk, child);
837  if constexpr(ChildT::LEVEL == 0) {
838  return child->template set<OpT>(ijk, args...);
839  } else {
840  return child->template setAndCache<OpT>(ijk, acc, args...);
841  }
842  }
843 
844 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
845  ValueType getValue(const Coord& ijk) const {return this->template get<GetValue<BuildType>>(ijk);}
846  LeafNodeType& setValue(const Coord& ijk, const ValueType& value){return this->template set<SetValue<BuildType>>(ijk, value);}
847 #else
848  ValueType getValue(const Coord& ijk) const
849  {
850  const uint32_t n = CoordToOffset(ijk);
851  if (mChildMask.isOn(n)) {
852  return mTable[n].child->getValue(ijk);
853  }
854  return mTable[n].value;
855  }
856  void setValue(const Coord& ijk, const ValueType& value)
857  {
858  const uint32_t n = CoordToOffset(ijk);
859  ChildT* child = nullptr;
860  if (mChildMask.isOn(n)) {
861  child = mTable[n].child;
862  } else {
863  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
864  mTable[n].child = child;
865  mChildMask.setOn(n);
866  }
867  child->setValue(ijk, value);
868  }
869 
870  template<typename AccT>
871  ValueType getValueAndCache(const Coord& ijk, AccT& acc) const
872  {
873  const uint32_t n = CoordToOffset(ijk);
874  if (mChildMask.isOn(n)) {
875  acc.insert(ijk, const_cast<ChildT*>(mTable[n].child));
876  return mTable[n].child->getValueAndCache(ijk, acc);
877  }
878  return mTable[n].value;
879  }
880 
881  template<typename AccT>
882  void setValueAndCache(const Coord& ijk, const ValueType& value, AccT& acc)
883  {
884  const uint32_t n = CoordToOffset(ijk);
885  ChildT* child = nullptr;
886  if (mChildMask.isOn(n)) {
887  child = mTable[n].child;
888  } else {
889  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
890  mTable[n].child = child;
891  mChildMask.setOn(n);
892  }
893  acc.insert(ijk, child);
894  child->setValueAndCache(ijk, value, acc);
895  }
896 
897  template<typename AccT>
898  void setValueOnAndCache(const Coord& ijk, AccT& acc)
899  {
900  const uint32_t n = CoordToOffset(ijk);
901  ChildT* child = nullptr;
902  if (mChildMask.isOn(n)) {
903  child = mTable[n].child;
904  } else {
905  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
906  mTable[n].child = child;
907  mChildMask.setOn(n);
908  }
909  acc.insert(ijk, child);
910  child->setValueOnAndCache(ijk, acc);
911  }
912 
913  template<typename AccT>
914  void touchLeafAndCache(const Coord &ijk, AccT& acc)
915  {
916  const uint32_t n = CoordToOffset(ijk);
917  ChildT* child = nullptr;
918  if (mChildMask.isOn(n)) {
919  child = mTable[n].child;
920  } else {
921  child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
922  mTable[n].child = child;
923  mChildMask.setOn(n);
924  }
925  acc.insert(ijk, child);
926  if constexpr(LEVEL>1) child->touchLeafAndCache(ijk, acc);
927  }
928  template<typename AccT>
929  bool isActiveAndCache(const Coord& ijk, AccT& acc) const
930  {
931  const uint32_t n = CoordToOffset(ijk);
932  if (mChildMask.isOn(n)) {
933  acc.insert(ijk, const_cast<ChildT*>(mTable[n].child));
934  return mTable[n].child->isActiveAndCache(ijk, acc);
935  }
936  return mValueMask.isOn(n);
937  }
938 #endif
939 
940  template<typename NodeT>
941  uint32_t nodeCount() const
942  {
943  static_assert(is_same<ValueType, typename NodeT::ValueType>::value, "Node::getNodes: Invalid type");
944  NANOVDB_ASSERT(NodeT::LEVEL < LEVEL);
945  uint32_t sum = 0;
946  if constexpr(is_same<NodeT, ChildT>::value) { // resolved at compile-time
947  sum += mChildMask.countOn();
948  } else if constexpr(LEVEL>1) {
949  for (auto iter = mChildMask.beginOn(); iter; ++iter) {
950  sum += mTable[*iter].child->template nodeCount<NodeT>();
951  }
952  }
953  return sum;
954  }
955 
956  template<typename NodeT>
957  void getNodes(std::vector<NodeT*>& array)
958  {
959  static_assert(is_same<ValueType, typename NodeT::ValueType>::value, "Node::getNodes: Invalid type");
960  NANOVDB_ASSERT(NodeT::LEVEL < LEVEL);
961  for (auto iter = mChildMask.beginOn(); iter; ++iter) {
962  if constexpr(is_same<NodeT, ChildT>::value) { // resolved at compile-time
963  array.push_back(reinterpret_cast<NodeT*>(mTable[*iter].child));
964  } else if constexpr(LEVEL>1) {
965  mTable[*iter].child->getNodes(array);
966  }
967  }
968  }
969 
970  void addChild(ChildT*& child)
971  {
972  NANOVDB_ASSERT(child && (child->mOrigin & ~MASK) == this->mOrigin);
973  const uint32_t n = CoordToOffset(child->mOrigin);
974  if (mChildMask.isOn(n)) {
975  delete mTable[n].child;
976  } else {
977  mChildMask.setOn(n);
978  }
979  mTable[n].child = child;
980  child = nullptr;
981  }
982 
983  /// @brief Add a tile containing voxel (i, j, k) at the specified tree level,
984  /// creating a new branch if necessary. Delete any existing lower-level nodes
985  /// that contain (x, y, z).
986  /// @tparam level tree level at which the tile is inserted. Must be 1 or 2.
987  /// @param ijk Index coordinate that map to the tile being inserted
988  /// @param value Value of the tile
989  /// @param state Binary state of the tile
990  template <uint32_t level>
991  void addTile(const Coord& ijk, const ValueType& value, bool state)
992  {
993  static_assert(level > 0 && level <= LEVEL, "invalid template value of level");
994  const uint32_t n = CoordToOffset(ijk);
995  if constexpr(level == LEVEL) {
996  if (mChildMask.isOn(n)) {
997  delete mTable[n].child;
998  mTable[n] = Tile(value);
999  } else {
1000  mValueMask.set(n, state);
1001  mTable[n].value = value;
1002  }
1003  } else if constexpr(level < LEVEL) {
1004  ChildT* child = nullptr;
1005  if (mChildMask.isOn(n)) {
1006  child = mTable[n].child;
1007  } else {
1008  child = new ChildT(ijk, value, state);
1009  mTable[n].child = child;
1010  mChildMask.setOn(n);
1011  }
1012  child->template addTile<level>(ijk, value, state);
1013  }
1014  }
1015 
1016  template<typename NodeT>
1017  void addNode(NodeT*& node)
1018  {
1019  if constexpr(is_same<NodeT, ChildT>::value) { //resolved at compile-time
1020  this->addChild(reinterpret_cast<ChildT*&>(node));
1021  } else if constexpr(LEVEL>1) {
1022  const uint32_t n = CoordToOffset(node->mOrigin);
1023  ChildT* child = nullptr;
1024  if (mChildMask.isOn(n)) {
1025  child = mTable[n].child;
1026  } else {
1027  child = new ChildT(node->mOrigin, mTable[n].value, mValueMask.isOn(n));
1028  mTable[n].child = child;
1029  mChildMask.setOn(n);
1030  }
1031  child->addNode(node);
1032  }
1033  }
1034 
1035  void merge(InternalNode &other)
1036  {
1037  for (auto iter = other.mChildMask.beginOn(); iter; ++iter) {
1038  const uint32_t n = *iter;
1039  if (mChildMask.isOn(n)) {
1040  mTable[n].child->merge(*other.mTable[n].child);
1041  } else {
1042  mTable[n].child = other.mTable[n].child;
1043  other.mChildMask.setOff(n);
1044  mChildMask.setOn(n);
1045  }
1046  }
1047  }
1048 
1049  template<typename T>
1050  typename std::enable_if<std::is_floating_point<T>::value>::type
1051  signedFloodFill(T outside);
1052 
1053 }; // build::InternalNode
1054 
1055 //================================================================================================
1056 
1057 template<typename ChildT>
1058 template<typename T>
1059 inline typename std::enable_if<std::is_floating_point<T>::value>::type
1061 {
1062  const uint32_t first = *mChildMask.beginOn();
1063  if (first < NUM_VALUES) {
1064  bool xInside = mTable[first].child->getFirstValue() < 0;
1065  bool yInside = xInside, zInside = xInside;
1066  for (uint32_t x = 0; x != (1 << LOG2DIM); ++x) {
1067  const uint32_t x00 = x << (2 * LOG2DIM); // offset for block(x, 0, 0)
1068  if (mChildMask.isOn(x00)) {
1069  xInside = mTable[x00].child->getLastValue() < 0;
1070  }
1071  yInside = xInside;
1072  for (uint32_t y = 0; y != (1u << LOG2DIM); ++y) {
1073  const uint32_t xy0 = x00 + (y << LOG2DIM); // offset for block(x, y, 0)
1074  if (mChildMask.isOn(xy0))
1075  yInside = mTable[xy0].child->getLastValue() < 0;
1076  zInside = yInside;
1077  for (uint32_t z = 0; z != (1 << LOG2DIM); ++z) {
1078  const uint32_t xyz = xy0 + z; // offset for block(x, y, z)
1079  if (mChildMask.isOn(xyz)) {
1080  zInside = mTable[xyz].child->getLastValue() < 0;
1081  } else {
1082  mTable[xyz].value = zInside ? -outside : outside;
1083  }
1084  }
1085  }
1086  }
1087  }
1088 } // build::InternalNode::signedFloodFill
1089 
1090 // ----------------------------> LeafNode <--------------------------------------
1091 
1092 template<typename BuildT>
1093 struct LeafNode
1094 {
1095  using BuildType = BuildT;
1098  static constexpr uint32_t LOG2DIM = 3;
1099  static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1100  static constexpr uint32_t DIM = 1u << TOTAL;
1101  static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1102  static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1103  static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1104  static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1106  template<bool ON>
1107  using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1109 
1112  ValueType mValues[SIZE];
1113  union {
1115  uint64_t mDstOffset;
1116  };
1117 
1118  /// @brief Visits all active values in a leaf node
1119  class ValueOnIterator : public MaskIterT<true>
1120  {
1121  using BaseT = MaskIterT<true>;
1122  const LeafNode *mParent;
1123  public:
1124  ValueOnIterator() : BaseT(), mParent(nullptr) {}
1125  ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
1126  ValueOnIterator& operator=(const ValueOnIterator&) = default;
1127  ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues[BaseT::pos()];}
1128  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1129  }; // Member class ValueOnIterator
1130 
1131  ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
1132  ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
1133 
1134  /// @brief Visits all inactive values in a leaf node
1135  class ValueOffIterator : public MaskIterT<false>
1136  {
1137  using BaseT = MaskIterT<false>;
1138  const LeafNode *mParent;
1139  public:
1140  ValueOffIterator() : BaseT(), mParent(nullptr) {}
1141  ValueOffIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOff()), mParent(parent) {}
1142  ValueOffIterator& operator=(const ValueOffIterator&) = default;
1143  ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues[BaseT::pos()];}
1144  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1145  }; // Member class ValueOffIterator
1146 
1147  ValueOffIterator beginValueOff() {return ValueOffIterator(this);}
1148  ValueOffIterator cbeginValueOff() const {return ValueOffIterator(this);}
1149 
1150  /// @brief Visits all values in a leaf node, i.e. both active and inactive values
1152  {
1153  const LeafNode *mParent;
1154  uint32_t mPos;
1155  public:
1156  ValueIterator() : mParent(nullptr), mPos(1u << 3 * LOG2DIM) {}
1157  ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
1158  ValueIterator& operator=(const ValueIterator&) = default;
1159  ValueType operator*() const { NANOVDB_ASSERT(*this); return mParent->mValues[mPos];}
1160  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
1161  bool isActive() const { NANOVDB_ASSERT(*this); return mParent->isActive(mPos);}
1162  operator bool() const {return mPos < SIZE;}
1163  ValueIterator& operator++() {++mPos; return *this;}
1165  auto tmp = *this;
1166  ++(*this);
1167  return tmp;
1168  }
1169  }; // Member class ValueIterator
1170 
1171  ValueIterator beginValue() {return ValueIterator(this);}
1172  ValueIterator cbeginValueAll() const {return ValueIterator(this);}
1173 
1174  LeafNode(const Coord& ijk, const ValueType& value, bool state)
1175  : mOrigin(ijk & ~MASK)
1176  , mValueMask(state) //invalid
1177  , mDstOffset(0)
1178  {
1179  ValueType* target = mValues;
1180  uint32_t n = SIZE;
1181  while (n--) {
1182  *target++ = value;
1183  }
1184  }
1185  LeafNode(const LeafNode&) = delete; // disallow copy-construction
1186  LeafNode(LeafNode&&) = delete; // disallow move construction
1187  LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1188  LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1189  ~LeafNode() = default;
1190 
1191  const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1192  const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1193  const Coord& origin() const {return mOrigin;}
1194 
1195  /// @brief Return the linear offset corresponding to the given coordinate
1196  static uint32_t CoordToOffset(const Coord& ijk)
1197  {
1198  return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1199  ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1200  (ijk[2] & int32_t(MASK));
1201  }
1202 
1203  static Coord OffsetToLocalCoord(uint32_t n)
1204  {
1205  NANOVDB_ASSERT(n < SIZE);
1206  const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1207  return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1208  }
1209 
1210  void localToGlobalCoord(Coord& ijk) const
1211  {
1212  ijk += mOrigin;
1213  }
1214 
1215  Coord offsetToGlobalCoord(uint32_t n) const
1216  {
1218  this->localToGlobalCoord(ijk);
1219  return ijk;
1220  }
1221 
1222  ValueType getFirstValue() const { return mValues[0]; }
1223  ValueType getLastValue() const { return mValues[SIZE - 1]; }
1224  const ValueType& getValue(uint32_t i) const {return mValues[i];}
1225  const ValueType& getValue(const Coord& ijk) const {return mValues[CoordToOffset(ijk)];}
1226 
1227  template<typename OpT, typename... ArgsT>
1228  auto get(const Coord& ijk, ArgsT&&... args) const {return OpT::get(*this, CoordToOffset(ijk), args...);}
1229 
1230  template<typename OpT, typename... ArgsT>
1231  auto set(const Coord& ijk, ArgsT&&... args) {return OpT::set(*this, CoordToOffset(ijk), args...);}
1232 
1233 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1234  template<typename AccT>
1235  const ValueType& getValueAndCache(const Coord& ijk, const AccT&) const
1236  {
1237  return mValues[CoordToOffset(ijk)];
1238  }
1239 
1240  template<typename AccT>
1241  void setValueAndCache(const Coord& ijk, const ValueType& value, const AccT&)
1242  {
1243  const uint32_t n = CoordToOffset(ijk);
1244  mValueMask.setOn(n);
1245  mValues[n] = value;
1246  }
1247 
1248  template<typename AccT>
1249  void setValueOnAndCache(const Coord& ijk, const AccT&)
1250  {
1251  const uint32_t n = CoordToOffset(ijk);
1252  mValueMask.setOn(n);
1253  }
1254 
1255  template<typename AccT>
1256  bool isActiveAndCache(const Coord& ijk, const AccT&) const
1257  {
1258  return mValueMask.isOn(CoordToOffset(ijk));
1259  }
1260 #endif
1261 
1262  void setValue(uint32_t n, const ValueType& value)
1263  {
1264  mValueMask.setOn(n);
1265  mValues[n] = value;
1266  }
1267  void setValue(const Coord& ijk, const ValueType& value){this->setValue(CoordToOffset(ijk), value);}
1268 
1269  void merge(LeafNode &other)
1270  {
1271  other.mValueMask -= mValueMask;
1272  for (auto iter = other.mValueMask.beginOn(); iter; ++iter) {
1273  const uint32_t n = *iter;
1274  mValues[n] = other.mValues[n];
1275  }
1276  mValueMask |= other.mValueMask;
1277  }
1278 
1279  template<typename T>
1280  typename std::enable_if<std::is_floating_point<T>::value>::type
1281  signedFloodFill(T outside);
1282 
1283 }; // build::LeafNode<T>
1284 
1285 //================================================================================================
1286 
1287 template <>
1289 {
1290  using ValueType = bool;
1293  static constexpr uint32_t LOG2DIM = 3;
1294  static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1295  static constexpr uint32_t DIM = 1u << TOTAL;
1296  static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1297  static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1298  static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1299  static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1301  template<bool ON>
1302  using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1304 
1307  union {
1309  uint64_t mDstOffset;
1310  };
1311 
1312  /// @brief Visits all active values in a leaf node
1313  class ValueOnIterator : public MaskIterT<true>
1314  {
1315  using BaseT = MaskIterT<true>;
1316  const LeafNode *mParent;
1317  public:
1318  ValueOnIterator() : BaseT(), mParent(nullptr) {}
1319  ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
1320  ValueOnIterator& operator=(const ValueOnIterator&) = default;
1321  bool operator*() const {NANOVDB_ASSERT(*this); return true;}
1322  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1323  }; // Member class ValueOnIterator
1324 
1325  ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
1326  ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
1327 
1328  /// @brief Visits all inactive values in a leaf node
1329  class ValueOffIterator : public MaskIterT<false>
1330  {
1331  using BaseT = MaskIterT<false>;
1332  const LeafNode *mParent;
1333  public:
1334  ValueOffIterator() : BaseT(), mParent(nullptr) {}
1335  ValueOffIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOff()), mParent(parent) {}
1336  ValueOffIterator& operator=(const ValueOffIterator&) = default;
1337  bool operator*() const {NANOVDB_ASSERT(*this); return false;}
1338  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1339  }; // Member class ValueOffIterator
1340 
1341  ValueOffIterator beginValueOff() {return ValueOffIterator(this);}
1342  ValueOffIterator cbeginValueOff() const {return ValueOffIterator(this);}
1343 
1344  /// @brief Visits all values in a leaf node, i.e. both active and inactive values
1345  class ValueIterator
1346  {
1347  const LeafNode *mParent;
1348  uint32_t mPos;
1349  public:
1350  ValueIterator() : mParent(nullptr), mPos(1u << 3 * LOG2DIM) {}
1351  ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
1352  ValueIterator& operator=(const ValueIterator&) = default;
1353  bool operator*() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1354  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
1355  bool isActive() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1356  operator bool() const {return mPos < SIZE;}
1357  ValueIterator& operator++() {++mPos; return *this;}
1358  ValueIterator operator++(int) {
1359  auto tmp = *this;
1360  ++(*this);
1361  return tmp;
1362  }
1363  }; // Member class ValueIterator
1364 
1365  ValueIterator beginValue() {return ValueIterator(this);}
1366  ValueIterator cbeginValueAll() const {return ValueIterator(this);}
1367 
1368  LeafNode(const Coord& ijk, const ValueType&, bool state)
1369  : mOrigin(ijk & ~MASK)
1370  , mValueMask(state) //invalid
1371  , mDstOffset(0)
1372  {
1373  }
1374  LeafNode(const LeafNode&) = delete; // disallow copy-construction
1375  LeafNode(LeafNode&&) = delete; // disallow move construction
1376  LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1377  LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1378  ~LeafNode() = default;
1379 
1380  const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1381  const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1382  const Coord& origin() const {return mOrigin;}
1383 
1384  /// @brief Return the linear offset corresponding to the given coordinate
1385  static uint32_t CoordToOffset(const Coord& ijk)
1386  {
1387  return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1388  ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1389  (ijk[2] & int32_t(MASK));
1390  }
1391 
1392  static Coord OffsetToLocalCoord(uint32_t n)
1393  {
1394  NANOVDB_ASSERT(n < SIZE);
1395  const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1396  return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1397  }
1398 
1399  void localToGlobalCoord(Coord& ijk) const {ijk += mOrigin;}
1400 
1401  Coord offsetToGlobalCoord(uint32_t n) const
1402  {
1404  this->localToGlobalCoord(ijk);
1405  return ijk;
1406  }
1407 
1408  bool getFirstValue() const { return mValueMask.isOn(0); }
1409  bool getLastValue() const { return mValueMask.isOn(SIZE - 1); }
1410  bool getValue(uint32_t i) const {return mValueMask.isOn(i);}
1411  bool getValue(const Coord& ijk) const {return mValueMask.isOn(CoordToOffset(ijk));}
1412 
1413  template<typename OpT, typename... ArgsT>
1414  auto get(const Coord& ijk, ArgsT&&... args) const {return OpT::get(*this, CoordToOffset(ijk), args...);}
1415 
1416  template<typename OpT, typename... ArgsT>
1417  auto set(const Coord& ijk, ArgsT&&... args) {return OpT::set(*this, CoordToOffset(ijk), args...);}
1418 
1419 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1420  template<typename AccT>
1421  bool getValueAndCache(const Coord& ijk, const AccT&) const
1422  {
1423  return mValueMask.isOn(CoordToOffset(ijk));
1424  }
1425 
1426  template<typename AccT>
1427  void setValueAndCache(const Coord& ijk, bool, const AccT&)
1428  {
1429  const uint32_t n = CoordToOffset(ijk);
1430  mValueMask.setOn(n);
1431  }
1432 
1433  template<typename AccT>
1434  void setValueOnAndCache(const Coord& ijk, const AccT&)
1435  {
1436  const uint32_t n = CoordToOffset(ijk);
1437  mValueMask.setOn(n);
1438  }
1439 
1440  template<typename AccT>
1441  bool isActiveAndCache(const Coord& ijk, const AccT&) const
1442  {
1443  return mValueMask.isOn(CoordToOffset(ijk));
1444  }
1445 #endif
1446 
1447  void setValue(uint32_t n, bool) {mValueMask.setOn(n);}
1448  void setValue(const Coord& ijk) {mValueMask.setOn(CoordToOffset(ijk));}
1449 
1450  void merge(LeafNode &other)
1451  {
1452  mValueMask |= other.mValueMask;
1453  }
1454 
1455 }; // build::LeafNode<ValueMask>
1456 
1457 //================================================================================================
1458 
1459 template <>
1460 struct LeafNode<bool>
1461 {
1462  using ValueType = bool;
1465  static constexpr uint32_t LOG2DIM = 3;
1466  static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1467  static constexpr uint32_t DIM = 1u << TOTAL;
1468  static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1469  static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1470  static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1471  static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1473  template<bool ON>
1474  using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1476 
1478  Mask<LOG2DIM> mValueMask, mValues;
1479  union {
1481  uint64_t mDstOffset;
1482  };
1483 
1484  /// @brief Visits all active values in a leaf node
1485  class ValueOnIterator : public MaskIterT<true>
1486  {
1487  using BaseT = MaskIterT<true>;
1488  const LeafNode *mParent;
1489  public:
1490  ValueOnIterator() : BaseT(), mParent(nullptr) {}
1491  ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
1492  ValueOnIterator& operator=(const ValueOnIterator&) = default;
1493  bool operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues.isOn(BaseT::pos());}
1494  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1495  }; // Member class ValueOnIterator
1496 
1497  ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
1498  ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
1499 
1500  /// @brief Visits all inactive values in a leaf node
1501  class ValueOffIterator : public MaskIterT<false>
1502  {
1503  using BaseT = MaskIterT<false>;
1504  const LeafNode *mParent;
1505  public:
1506  ValueOffIterator() : BaseT(), mParent(nullptr) {}
1507  ValueOffIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOff()), mParent(parent) {}
1508  ValueOffIterator& operator=(const ValueOffIterator&) = default;
1509  bool operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues.isOn(BaseT::pos());}
1510  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1511  }; // Member class ValueOffIterator
1512 
1513  ValueOffIterator beginValueOff() {return ValueOffIterator(this);}
1514  ValueOffIterator cbeginValueOff() const {return ValueOffIterator(this);}
1515 
1516  /// @brief Visits all values in a leaf node, i.e. both active and inactive values
1517  class ValueIterator
1518  {
1519  const LeafNode *mParent;
1520  uint32_t mPos;
1521  public:
1522  ValueIterator() : mParent(nullptr), mPos(1u << 3 * LOG2DIM) {}
1523  ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
1524  ValueIterator& operator=(const ValueIterator&) = default;
1525  bool operator*() const { NANOVDB_ASSERT(*this); return mParent->mValues.isOn(mPos);}
1526  Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
1527  bool isActive() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1528  operator bool() const {return mPos < SIZE;}
1529  ValueIterator& operator++() {++mPos; return *this;}
1530  ValueIterator operator++(int) {
1531  auto tmp = *this;
1532  ++(*this);
1533  return tmp;
1534  }
1535  }; // Member class ValueIterator
1536 
1537  ValueIterator beginValue() {return ValueIterator(this);}
1538  ValueIterator cbeginValueAll() const {return ValueIterator(this);}
1539 
1540  LeafNode(const Coord& ijk, bool value, bool state)
1541  : mOrigin(ijk & ~MASK)
1542  , mValueMask(state)
1543  , mValues(value)
1544  , mDstOffset(0)
1545  {
1546  }
1547  LeafNode(const LeafNode&) = delete; // disallow copy-construction
1548  LeafNode(LeafNode&&) = delete; // disallow move construction
1549  LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1550  LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1551  ~LeafNode() = default;
1552 
1553  const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1554  const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1555  const Coord& origin() const {return mOrigin;}
1556 
1557  /// @brief Return the linear offset corresponding to the given coordinate
1558  static uint32_t CoordToOffset(const Coord& ijk)
1559  {
1560  return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1561  ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1562  (ijk[2] & int32_t(MASK));
1563  }
1564 
1565  static Coord OffsetToLocalCoord(uint32_t n)
1566  {
1567  NANOVDB_ASSERT(n < SIZE);
1568  const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1569  return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1570  }
1571 
1572  void localToGlobalCoord(Coord& ijk) const
1573  {
1574  ijk += mOrigin;
1575  }
1576 
1577  Coord offsetToGlobalCoord(uint32_t n) const
1578  {
1580  this->localToGlobalCoord(ijk);
1581  return ijk;
1582  }
1583  bool getFirstValue() const { return mValues.isOn(0); }
1584  bool getLastValue() const { return mValues.isOn(SIZE - 1); }
1585 
1586  bool getValue(uint32_t i) const {return mValues.isOn(i);}
1587  bool getValue(const Coord& ijk) const
1588  {
1589  return mValues.isOn(CoordToOffset(ijk));
1590  }
1591 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1592  template<typename AccT>
1593  bool isActiveAndCache(const Coord& ijk, const AccT&) const
1594  {
1595  return mValueMask.isOn(CoordToOffset(ijk));
1596  }
1597 
1598  template<typename AccT>
1599  bool getValueAndCache(const Coord& ijk, const AccT&) const
1600  {
1601  return mValues.isOn(CoordToOffset(ijk));
1602  }
1603 
1604  template<typename AccT>
1605  void setValueAndCache(const Coord& ijk, bool value, const AccT&)
1606  {
1607  const uint32_t n = CoordToOffset(ijk);
1608  mValueMask.setOn(n);
1609  mValues.setOn(n);
1610  }
1611 
1612  template<typename AccT>
1613  void setValueOnAndCache(const Coord& ijk, const AccT&)
1614  {
1615  const uint32_t n = CoordToOffset(ijk);
1616  mValueMask.setOn(n);
1617  }
1618 #endif
1619 
1620  void setValue(uint32_t n, bool value)
1621  {
1622  mValueMask.setOn(n);
1623  mValues.set(n, value);
1624  }
1625  void setValue(const Coord& ijk, bool value) {return this->setValue(CoordToOffset(ijk), value);}
1626 
1627  void merge(LeafNode &other)
1628  {
1629  mValues |= other.mValues;
1630  mValueMask |= other.mValueMask;
1631  }
1632 
1633 }; // build::LeafNode<bool>
1634 
1635 //================================================================================================
1636 
1637 template<typename BuildT>
1638 template<typename T>
1639 inline typename std::enable_if<std::is_floating_point<T>::value>::type
1641 {
1642  const uint32_t first = *mValueMask.beginOn();
1643  if (first < SIZE) {
1644  bool xInside = mValues[first] < 0, yInside = xInside, zInside = xInside;
1645  for (uint32_t x = 0; x != DIM; ++x) {
1646  const uint32_t x00 = x << (2 * LOG2DIM);
1647  if (mValueMask.isOn(x00))
1648  xInside = mValues[x00] < 0; // element(x, 0, 0)
1649  yInside = xInside;
1650  for (uint32_t y = 0; y != DIM; ++y) {
1651  const uint32_t xy0 = x00 + (y << LOG2DIM);
1652  if (mValueMask.isOn(xy0))
1653  yInside = mValues[xy0] < 0; // element(x, y, 0)
1654  zInside = yInside;
1655  for (uint32_t z = 0; z != (1 << LOG2DIM); ++z) {
1656  const uint32_t xyz = xy0 + z; // element(x, y, z)
1657  if (mValueMask.isOn(xyz)) {
1658  zInside = mValues[xyz] < 0;
1659  } else {
1660  mValues[xyz] = zInside ? -outside : outside;
1661  }
1662  }
1663  }
1664  }
1665  }
1666 } // build::LeafNode<T>::signedFloodFill
1667 
1668 // ----------------------------> ValueAccessor <--------------------------------------
1669 
1670 template<typename BuildT>
1672 {
1679 
1681  : mRoot(root)
1683  , mNode{nullptr, nullptr, nullptr}
1684  {
1685  }
1686  ValueAccessor(ValueAccessor&&) = default; // allow move construction
1687  ValueAccessor(const ValueAccessor&) = delete; // disallow copy construction
1688  ValueType getValue(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
1689  template<typename NodeT>
1690  bool isCached(const Coord& ijk) const
1691  {
1692  return (ijk[0] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][0] &&
1693  (ijk[1] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][1] &&
1694  (ijk[2] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][2];
1695  }
1696 
1697  template <typename OpT, typename... ArgsT>
1698  auto get(const Coord& ijk, ArgsT&&... args) const
1699  {
1700  if (this->template isCached<LeafT>(ijk)) {
1701  return ((const LeafT*)mNode[0])->template get<OpT>(ijk, args...);
1702  } else if (this->template isCached<Node1>(ijk)) {
1703  return ((const Node1*)mNode[1])->template getAndCache<OpT>(ijk, *this, args...);
1704  } else if (this->template isCached<Node2>(ijk)) {
1705  return ((const Node2*)mNode[2])->template getAndCache<OpT>(ijk, *this, args...);
1706  }
1707  return mRoot.template getAndCache<OpT>(ijk, *this, args...);
1708  }
1709 
1710  template <typename OpT, typename... ArgsT>
1711  auto set(const Coord& ijk, ArgsT&&... args) const
1712  {
1713  if (this->template isCached<LeafT>(ijk)) {
1714  return ((LeafT*)mNode[0])->template set<OpT>(ijk, args...);
1715  } else if (this->template isCached<Node1>(ijk)) {
1716  return ((Node1*)mNode[1])->template setAndCache<OpT>(ijk, *this, args...);
1717  } else if (this->template isCached<Node2>(ijk)) {
1718  return ((Node2*)mNode[2])->template setAndCache<OpT>(ijk, *this, args...);
1719  }
1720  return mRoot.template setAndCache<OpT>(ijk, *this, args...);
1721  }
1722 
1723 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
1724  ValueType getValue(const Coord& ijk) const {return this->template get<GetValue<BuildT>>(ijk);}
1725  LeafT* setValue(const Coord& ijk, const ValueType& value) {return this->template set<SetValue<BuildT>>(ijk, value);}
1726  LeafT* setValueOn(const Coord& ijk) {return this->template set<SetValue<BuildT>>(ijk);}
1727  LeafT& touchLeaf(const Coord& ijk) {return this->template set<TouchLeaf<BuildT>>(ijk);}
1728  bool isActive(const Coord& ijk) const {return this->template get<GetState<BuildT>>(ijk);}
1729 #else
1730  ValueType getValue(const Coord& ijk) const
1731  {
1732  if (this->template isCached<LeafT>(ijk)) {
1733  return ((LeafT*)mNode[0])->getValueAndCache(ijk, *this);
1734  } else if (this->template isCached<Node1>(ijk)) {
1735  return ((Node1*)mNode[1])->getValueAndCache(ijk, *this);
1736  } else if (this->template isCached<Node2>(ijk)) {
1737  return ((Node2*)mNode[2])->getValueAndCache(ijk, *this);
1738  }
1739  return mRoot.getValueAndCache(ijk, *this);
1740  }
1741 
1742  /// @brief Sets value in a leaf node and returns it.
1743  LeafT* setValue(const Coord& ijk, const ValueType& value)
1744  {
1745  if (this->template isCached<LeafT>(ijk)) {
1746  ((LeafT*)mNode[0])->setValueAndCache(ijk, value, *this);
1747  } else if (this->template isCached<Node1>(ijk)) {
1748  ((Node1*)mNode[1])->setValueAndCache(ijk, value, *this);
1749  } else if (this->template isCached<Node2>(ijk)) {
1750  ((Node2*)mNode[2])->setValueAndCache(ijk, value, *this);
1751  } else {
1752  mRoot.setValueAndCache(ijk, value, *this);
1753  }
1754  NANOVDB_ASSERT(this->isCached<LeafT>(ijk));
1755  return (LeafT*)mNode[0];
1756  }
1757  void setValueOn(const Coord& ijk)
1758  {
1759  if (this->template isCached<LeafT>(ijk)) {
1760  ((LeafT*)mNode[0])->setValueOnAndCache(ijk, *this);
1761  } else if (this->template isCached<Node1>(ijk)) {
1762  ((Node1*)mNode[1])->setValueOnAndCache(ijk, *this);
1763  } else if (this->template isCached<Node2>(ijk)) {
1764  ((Node2*)mNode[2])->setValueOnAndCache(ijk, *this);
1765  } else {
1766  mRoot.setValueOnAndCache(ijk, *this);
1767  }
1768  }
1769  void touchLeaf(const Coord& ijk) const
1770  {
1771  if (this->template isCached<LeafT>(ijk)) {
1772  return;
1773  } else if (this->template isCached<Node1>(ijk)) {
1774  ((Node1*)mNode[1])->touchLeafAndCache(ijk, *this);
1775  } else if (this->template isCached<Node2>(ijk)) {
1776  ((Node2*)mNode[2])->touchLeafAndCache(ijk, *this);
1777  } else {
1778  mRoot.touchLeafAndCache(ijk, *this);
1779  }
1780  }
1781  bool isActive(const Coord& ijk) const
1782  {
1783  if (this->template isCached<LeafT>(ijk)) {
1784  return ((LeafT*)mNode[0])->isActiveAndCache(ijk, *this);
1785  } else if (this->template isCached<Node1>(ijk)) {
1786  return ((Node1*)mNode[1])->isActiveAndCache(ijk, *this);
1787  } else if (this->template isCached<Node2>(ijk)) {
1788  return ((Node2*)mNode[2])->isActiveAndCache(ijk, *this);
1789  }
1790  return mRoot.isActiveAndCache(ijk, *this);
1791  }
1792 #endif
1793 
1794  bool isValueOn(const Coord& ijk) const { return this->isActive(ijk); }
1795  template<typename NodeT>
1796  void insert(const Coord& ijk, NodeT* node) const
1797  {
1798  mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
1799  mNode[NodeT::LEVEL] = node;
1800  }
1802  mutable Coord mKeys[3];
1803  mutable void* mNode[3];
1804 }; // build::ValueAccessor<BuildT>
1805 
1806 // ----------------------------> Tree <--------------------------------------
1807 
1808 template<typename BuildT>
1809 struct Tree
1810 {
1818 
1820  std::mutex mMutex;
1821 
1822  Tree(const ValueType &background) : mRoot(background) {}
1823  Tree(const Tree&) = delete; // disallow copy construction
1824  Tree(Tree&&) = delete; // disallow move construction
1825  Tree& tree() {return *this;}
1826  RootNodeType& root() {return mRoot;}
1827  ValueType getValue(const Coord& ijk) const {return mRoot.getValue(ijk);}
1828  ValueType getValue(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
1829  void setValue(const Coord& ijk, const ValueType &value) {mRoot.setValue(ijk, value);}
1830  std::array<size_t,3> nodeCount() const
1831  {
1832  std::array<size_t, 3> count{0,0,0};
1833  mRoot.nodeCount(count);
1834  return count;
1835  }
1836  /// @brief regular accessor for thread-safe reading and non-thread-safe writing
1838  /// @brief special accessor for thread-safe writing only
1839  WriteAccessor getWriteAccessor() { return WriteAccessor(mRoot, mMutex); }
1840 };// build::Tree<BuildT>
1841 
1842 // ----------------------------> Tree::WriteAccessor <--------------------------------------
1843 
1844 template<typename BuildT>
1845 struct Tree<BuildT>::WriteAccessor
1846 {
1848  using ValueType = typename AccT::ValueType;
1849  using LeafT = typename AccT::LeafT;
1850  using Node1 = typename AccT::Node1;
1851  using Node2 = typename AccT::Node2;
1853 
1854  WriteAccessor(RootNodeType& parent, std::mutex &mx)
1855  : mParent(parent)
1856  , mRoot(parent.mBackground)
1857  , mAcc(mRoot)
1858  , mMutex(mx)
1859  {
1860  }
1861  WriteAccessor(const WriteAccessor&) = delete; // disallow copy construction
1862  WriteAccessor(WriteAccessor&&) = default; // allow move construction
1863  ~WriteAccessor() { this->merge(); }
1864  void merge()
1865  {
1866  mMutex.lock();
1867  mParent.merge(mRoot);
1868  mMutex.unlock();
1869  }
1870  inline void setValueOn(const Coord& ijk) {mAcc.setValueOn(ijk);}
1871  inline void setValue(const Coord& ijk, const ValueType &value) {mAcc.setValue(ijk, value);}
1872 
1873  RootNodeType &mParent, mRoot;
1875  std::mutex &mMutex;
1876 }; // build::Tree<BuildT>::WriteAccessor
1877 
1878 // ----------------------------> Grid <--------------------------------------
1879 
1880 template<typename BuildT>
1881 struct Grid : public Tree<BuildT>
1882 {
1883  using BuildType = BuildT;
1890 
1894  std::string mName;
1895 
1896  Grid(const ValueType &background, const std::string &name = "", GridClass gClass = GridClass::Unknown)
1897  : TreeType(background)
1898  , mGridClass(gClass)
1899  , mGridType(mapToGridType<BuildT>())
1900  , mName(name)
1901  {
1902  mMap.set(1.0, Vec3d(0.0), 1.0);
1903  }
1904  TreeType& tree() {return *this;}
1905  const GridType& gridType() const { return mGridType; }
1906  const GridClass& gridClass() const { return mGridClass; }
1907  const Map& map() const { return mMap; }
1908  void setTransform(double scale=1.0, const Vec3d &translation = Vec3d(0.0)) {mMap.set(scale, translation, 1.0);}
1909  const std::string& gridName() const { return mName; }
1910  const std::string& getName() const { return mName; }
1911  void setName(const std::string &name) { mName = name; }
1912  /// @brief Sets grids values in domain of the @a bbox to those returned by the specified @a func with the
1913  /// expected signature [](const Coord&)->ValueType.
1914  ///
1915  /// @note If @a func returns a value equal to the background value of the input grid at a
1916  /// specific voxel coordinate, then the active state of that coordinate is off! Else the value
1917  /// value is set and the active state is on. This is done to allow for sparse grids to be generated.
1918  ///
1919  /// @param func Functor used to evaluate the grid values in the @a bbox
1920  /// @param bbox Coordinate bounding-box over which the grid values will be set.
1921  /// @param delta Specifies a lower threshold value for rendering (optional). Typically equals the voxel size
1922  /// for level sets and otherwise it's zero.
1923  template <typename Func>
1924  void operator()(const Func& func, const CoordBBox& bbox, ValueType delta = ValueType(0));
1925 };// build::Grid
1926 
1927 template <typename BuildT>
1928 template <typename Func>
1929 void Grid<BuildT>::operator()(const Func& func, const CoordBBox& bbox, ValueType delta)
1930 {
1931  auto &root = this->tree().root();
1932 #if __cplusplus >= 201703L
1933  static_assert(is_same<ValueType, typename std::invoke_result<Func,const Coord&>::type>::value, "GridBuilder: mismatched ValueType");
1934 #else// invoke_result was introduced in C++17 and result_of was removed in C++20
1935  static_assert(is_same<ValueType, typename std::result_of<Func(const Coord&)>::type>::value, "GridBuilder: mismatched ValueType");
1936 #endif
1937  const CoordBBox leafBBox(bbox[0] >> Node0::TOTAL, bbox[1] >> Node0::TOTAL);
1938  std::mutex mutex;
1939  forEach(leafBBox, [&](const CoordBBox& b) {
1940  Node0* leaf = nullptr;
1941  for (auto it = b.begin(); it; ++it) {
1942  Coord min(*it << Node0::TOTAL), max(min + Coord(Node0::DIM - 1));
1943  const CoordBBox b(min.maxComponent(bbox.min()),
1944  max.minComponent(bbox.max()));// crop
1945  if (leaf == nullptr) {
1946  leaf = new Node0(b[0], root.mBackground, false);
1947  } else {
1948  leaf->mOrigin = b[0] & ~Node0::MASK;
1949  NANOVDB_ASSERT(leaf->mValueMask.isOff());
1950  }
1951  leaf->mDstOffset = 0;// no prune
1952  for (auto ijk = b.begin(); ijk; ++ijk) {
1953  const auto v = func(*ijk);// call functor
1954  if (v != root.mBackground) leaf->setValue(*ijk, v);// don't insert background values
1955  }
1956  if (!leaf->mValueMask.isOff()) {// has active values
1957  if (leaf->mValueMask.isOn()) {// only active values
1958  const auto first = leaf->getFirstValue();
1959  int n=1;
1960  while (n<512) {// 8^3 = 512
1961  if (leaf->mValues[n++] != first) break;
1962  }
1963  if (n == 512) leaf->mDstOffset = 1;// prune below
1964  }
1965  std::lock_guard<std::mutex> guard(mutex);
1966  NANOVDB_ASSERT(leaf != nullptr);
1967  root.addNode(leaf);
1968  NANOVDB_ASSERT(leaf == nullptr);
1969  }
1970  }// loop over sub-part of leafBBox
1971  if (leaf) delete leaf;
1972  });
1973 
1974  // Prune leaf and tile nodes
1975  for (auto it2 = root.mTable.begin(); it2 != root.mTable.end(); ++it2) {
1976  if (auto *upper = it2->second.child) {//upper level internal node
1977  for (auto it1 = upper->mChildMask.beginOn(); it1; ++it1) {
1978  auto *lower = upper->mTable[*it1].child;// lower level internal node
1979  for (auto it0 = lower->mChildMask.beginOn(); it0; ++it0) {
1980  auto *leaf = lower->mTable[*it0].child;// leaf nodes
1981  if (leaf->mDstOffset) {
1982  lower->mTable[*it0].value = leaf->getFirstValue();
1983  lower->mChildMask.setOff(*it0);
1984  lower->mValueMask.setOn(*it0);
1985  delete leaf;
1986  }
1987  }// loop over leaf nodes
1988  if (lower->mChildMask.isOff()) {//only tiles
1989  const auto first = lower->getFirstValue();
1990  int n=1;
1991  while (n < 4096) {// 16^3 = 4096
1992  if (lower->mTable[n++].value != first) break;
1993  }
1994  if (n == 4096) {// identical tile values so prune
1995  upper->mTable[*it1].value = first;
1996  upper->mChildMask.setOff(*it1);
1997  upper->mValueMask.setOn(*it1);
1998  delete lower;
1999  }
2000  }
2001  }// loop over lower internal nodes
2002  if (upper->mChildMask.isOff()) {//only tiles
2003  const auto first = upper->getFirstValue();
2004  int n=1;
2005  while (n < 32768) {// 32^3 = 32768
2006  if (upper->mTable[n++].value != first) break;
2007  }
2008  if (n == 32768) {// identical tile values so prune
2009  it2->second.value = first;
2010  it2->second.state = upper->mValueMask.isOn();
2011  it2->second.child = nullptr;
2012  delete upper;
2013  }
2014  }
2015  }// is child node of the root
2016  }// loop over root table
2017 }// build::Grid::operator()
2018 
2019 //================================================================================================
2020 
2021 template <typename T>
2023 template <typename T>
2025 template <typename T>
2027 template <typename T>
2029 template <typename T>
2031 
2049 
2050 // ----------------------------> NodeManager <--------------------------------------
2051 
2052 // GridT can be openvdb::Grid and nanovdb::build::Grid
2053 template <typename GridT>
2055 {
2056 public:
2057 
2058  using ValueType = typename GridT::ValueType;
2059  using BuildType = typename GridT::BuildType;
2060  using GridType = GridT;
2061  using TreeType = typename GridT::TreeType;
2062  using RootNodeType = typename TreeType::RootNodeType;
2063  static_assert(RootNodeType::LEVEL == 3, "NodeManager expected LEVEL=3");
2064  using Node2 = typename RootNodeType::ChildNodeType;
2065  using Node1 = typename Node2::ChildNodeType;
2066  using Node0 = typename Node1::ChildNodeType;
2067 
2068  NodeManager(GridT &grid) : mGrid(grid) {this->init();}
2069  void init()
2070  {
2071  mArray0.clear();
2072  mArray1.clear();
2073  mArray2.clear();
2074  auto counts = mGrid.tree().nodeCount();
2075  mArray0.reserve(counts[0]);
2076  mArray1.reserve(counts[1]);
2077  mArray2.reserve(counts[2]);
2078 
2079  for (auto it2 = mGrid.tree().root().cbeginChildOn(); it2; ++it2) {
2080  Node2 &upper = const_cast<Node2&>(*it2);
2081  mArray2.emplace_back(&upper);
2082  for (auto it1 = upper.cbeginChildOn(); it1; ++it1) {
2083  Node1 &lower = const_cast<Node1&>(*it1);
2084  mArray1.emplace_back(&lower);
2085  for (auto it0 = lower.cbeginChildOn(); it0; ++it0) {
2086  Node0 &leaf = const_cast<Node0&>(*it0);
2087  mArray0.emplace_back(&leaf);
2088  }// loop over leaf nodes
2089  }// loop over lower internal nodes
2090  }// loop over root node
2091  }
2092 
2093  /// @brief Return the number of tree nodes at the specified level
2094  /// @details 0 is leaf, 1 is lower internal, and 2 is upper internal level
2095  uint64_t nodeCount(int level) const
2096  {
2097  NANOVDB_ASSERT(level==0 || level==1 || level==2);
2098  return level==0 ? mArray0.size() : level==1 ? mArray1.size() : mArray2.size();
2099  }
2100 
2101  template <int LEVEL>
2102  typename enable_if<LEVEL==0, Node0&>::type node(int i) {return *mArray0[i];}
2103  template <int LEVEL>
2104  typename enable_if<LEVEL==0, const Node0&>::type node(int i) const {return *mArray0[i];}
2105  template <int LEVEL>
2106  typename enable_if<LEVEL==1, Node1&>::type node(int i) {return *mArray1[i];}
2107  template <int LEVEL>
2108  typename enable_if<LEVEL==1, const Node1&>::type node(int i) const {return *mArray1[i];}
2109  template <int LEVEL>
2110  typename enable_if<LEVEL==2, Node2&>::type node(int i) {return *mArray2[i];}
2111  template <int LEVEL>
2112  typename enable_if<LEVEL==2, const Node2&>::type node(int i) const {return *mArray2[i];}
2113 
2114  /// @brief Return the i'th leaf node with respect to breadth-first ordering
2115  const Node0& leaf(uint32_t i) const { return *mArray0[i]; }
2116  Node0& leaf(uint32_t i) { return *mArray0[i]; }
2117  uint64_t leafCount() const {return mArray0.size();}
2118 
2119  /// @brief Return the i'th lower internal node with respect to breadth-first ordering
2120  const Node1& lower(uint32_t i) const { return *mArray1[i]; }
2121  Node1& lower(uint32_t i) { return *mArray1[i]; }
2122  uint64_t lowerCount() const {return mArray1.size();}
2123 
2124  /// @brief Return the i'th upper internal node with respect to breadth-first ordering
2125  const Node2& upper(uint32_t i) const { return *mArray2[i]; }
2126  Node2& upper(uint32_t i) { return *mArray2[i]; }
2127  uint64_t upperCount() const {return mArray2.size();}
2128 
2129  RootNodeType& root() {return mGrid.tree().root();}
2130  const RootNodeType& root() const {return mGrid.tree().root();}
2131 
2132  TreeType& tree() {return mGrid.tree();}
2133  const TreeType& tree() const {return mGrid.tree();}
2134 
2135  GridType& grid() {return mGrid;}
2136  const GridType& grid() const {return mGrid;}
2137 
2138 protected:
2139 
2140  GridT &mGrid;
2141  std::vector<Node0*> mArray0; // leaf nodes
2142  std::vector<Node1*> mArray1; // lower internal nodes
2143  std::vector<Node2*> mArray2; // upper internal nodes
2144 
2145 };// NodeManager
2146 
2147 template <typename NodeManagerT>
2149 sdfToLevelSet(NodeManagerT &mgr)
2150 {
2151  mgr.grid().mGridClass = GridClass::LevelSet;
2152  // Note that the bottom-up flood filling is essential
2153  const auto outside = mgr.root().mBackground;
2154  forEach(0, mgr.leafCount(), 8, [&](const Range1D& r) {
2155  for (auto i = r.begin(); i != r.end(); ++i) mgr.leaf(i).signedFloodFill(outside);
2156  });
2157  forEach(0, mgr.lowerCount(), 1, [&](const Range1D& r) {
2158  for (auto i = r.begin(); i != r.end(); ++i) mgr.lower(i).signedFloodFill(outside);
2159  });
2160  forEach(0, mgr.upperCount(), 1, [&](const Range1D& r) {
2161  for (auto i = r.begin(); i != r.end(); ++i) mgr.upper(i).signedFloodFill(outside);
2162  });
2163  mgr.root().signedFloodFill(outside);
2164 }// sdfToLevelSet
2165 
2166 template <typename NodeManagerT>
2167 void levelSetToFog(NodeManagerT &mgr, bool rebuild = true)
2168 {
2169  using ValueType = typename NodeManagerT::ValueType;
2170  mgr.grid().mGridClass = GridClass::FogVolume;
2171  const ValueType d = -mgr.root().mBackground, w = 1.0f / d;
2172  std::atomic_bool prune{false};
2173  auto op = [&](ValueType& v) -> bool {
2174  if (v > ValueType(0)) {
2175  v = ValueType(0);
2176  return false;
2177  }
2178  v = v > d ? v * w : ValueType(1);
2179  return true;
2180  };
2181  forEach(0, mgr.leafCount(), 8, [&](const Range1D& r) {
2182  for (auto i = r.begin(); i != r.end(); ++i) {
2183  auto& leaf = mgr.leaf(i);
2184  for (uint32_t i = 0; i < 512u; ++i) leaf.mValueMask.set(i, op(leaf.mValues[i]));
2185  }
2186  });
2187  forEach(0, mgr.lowerCount(), 1, [&](const Range1D& r) {
2188  for (auto i = r.begin(); i != r.end(); ++i) {
2189  auto& node = mgr.lower(i);
2190  for (uint32_t i = 0; i < 4096u; ++i) {
2191  if (node.mChildMask.isOn(i)) {
2192  auto* leaf = node.mTable[i].child;
2193  if (leaf->mValueMask.isOff()) {// prune leaf node
2194  node.mTable[i].value = leaf->getFirstValue();
2195  node.mChildMask.setOff(i);
2196  delete leaf;
2197  prune = true;
2198  }
2199  } else {
2200  node.mValueMask.set(i, op(node.mTable[i].value));
2201  }
2202  }
2203  }
2204  });
2205  forEach(0, mgr.upperCount(), 1, [&](const Range1D& r) {
2206  for (auto i = r.begin(); i != r.end(); ++i) {
2207  auto& node = mgr.upper(i);
2208  for (uint32_t i = 0; i < 32768u; ++i) {
2209  if (node.mChildMask.isOn(i)) {// prune lower internal node
2210  auto* child = node.mTable[i].child;
2211  if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2212  node.mTable[i].value = child->getFirstValue();
2213  node.mChildMask.setOff(i);
2214  delete child;
2215  prune = true;
2216  }
2217  } else {
2218  node.mValueMask.set(i, op(node.mTable[i].value));
2219  }
2220  }
2221  }
2222  });
2223 
2224  for (auto it = mgr.root().mTable.begin(); it != mgr.root().mTable.end(); ++it) {
2225  auto* child = it->second.child;
2226  if (child == nullptr) {
2227  it->second.state = op(it->second.value);
2228  } else if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2229  it->second.value = child->getFirstValue();
2230  it->second.state = false;
2231  it->second.child = nullptr;
2232  delete child;
2233  prune = true;
2234  }
2235  }
2236  if (rebuild && prune) mgr.init();
2237 }// levelSetToFog
2238 
2239 // ----------------------------> Implementations of random access methods <--------------------------------------
2240 
2241 template <typename T>
2242 struct TouchLeaf {
2243  static BuildLeaf<T>& set(BuildLeaf<T> &leaf, uint32_t) {return leaf;}
2244 };// TouchLeaf<BuildT>
2245 
2246 /// @brief Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate @c ijk.
2247 /// @tparam BuildT Build type of the grid being called
2248 /// @details The value at a coordinate maps to the background, a tile value or a leaf value.
2249 template <typename T>
2250 struct GetValue {
2251  static auto get(const BuildRoot<T> &root) {return root.mBackground;}
2252  static auto get(const BuildTile<T> &tile) {return tile.value;}
2253  static auto get(const BuildUpper<T> &node, uint32_t n) {return node.mTable[n].value;}
2254  static auto get(const BuildLower<T> &node, uint32_t n) {return node.mTable[n].value;}
2255  static auto get(const BuildLeaf<T> &leaf, uint32_t n) {return leaf.getValue(n);}
2256 };// GetValue<T>
2257 
2258 /// @brief Implements Tree::isActive(Coord)
2259 /// @tparam T Build type of the grid being called
2260 template <typename T>
2261 struct GetState {
2262  static bool get(const BuildRoot<T>&) {return false;}
2263  static bool get(const BuildTile<T> &tile) {return tile.state;}
2264  static bool get(const BuildUpper<T> &node, uint32_t n) {return node.mValueMask.isOn(n);}
2265  static bool get(const BuildLower<T> &node, uint32_t n) {return node.mValueMask.isOn(n);}
2266  static bool get(const BuildLeaf<T> &leaf, uint32_t n) {return leaf.mValueMask.isOn(n);}
2267 };// GetState<T>
2268 
2269 /// @brief Set the value and its state at the leaf level mapped to by ijk, and create the leaf node and branch if needed.
2270 /// @tparam T BuildType of the corresponding tree
2271 template <typename T>
2272 struct SetValue {
2273  static BuildLeaf<T>* set(BuildLeaf<T> &leaf, uint32_t n) {
2274  leaf.mValueMask.setOn(n);// always set the active bit
2275  return &leaf;
2276  }
2277  static BuildLeaf<T>* set(BuildLeaf<T> &leaf, uint32_t n, const typename BuildLeaf<T>::ValueType &v) {
2278  leaf.setValue(n, v);
2279  return &leaf;
2280  }
2281 };// SetValue<T>
2282 
2283 /// @brief Implements Tree::probeLeaf(Coord)
2284 /// @tparam T Build type of the grid being called
2285 template <typename T>
2286 struct ProbeValue {
2288  static bool get(const BuildRoot<T> &root, ValueT &v) {
2289  v = root.mBackground;
2290  return false;
2291  }
2292  static bool get(const BuildTile<T> &tile, ValueT &v) {
2293  v = tile.value;
2294  return tile.state;
2295  }
2296  static bool get(const BuildUpper<T> &node, uint32_t n, ValueT &v) {
2297  v = node.mTable[n].value;
2298  return node.mValueMask.isOn(n);
2299  }
2300  static bool get(const BuildLower<T> &node, uint32_t n, ValueT &v) {
2301  v = node.mTable[n].value;
2302  return node.mValueMask.isOn(n);
2303  }
2304  static bool get(const BuildLeaf<T> &leaf, uint32_t n, ValueT &v) {
2305  v = leaf.getValue(n);
2306  return leaf.isActive(n);
2307  }
2308 };// ProbeValue<T>
2309 
2310 } // namespace build
2311 
2312 } // namespace nanovdb
2313 
2314 #endif // NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
enable_if< LEVEL==1, const Node1 & >::type node(int i) const
Definition: GridBuilder.h:2108
ChildIterator(const InternalNode *parent)
Definition: GridBuilder.h:654
uint64_t upperCount() const
Definition: GridBuilder.h:2127
ValueIterator beginValue()
Definition: GridBuilder.h:1171
ValueType mBackground
Definition: GridBuilder.h:67
std::mutex mMutex
Definition: GridBuilder.h:1820
const Mask< LOG2DIM > & valueMask() const
Definition: GridBuilder.h:1380
uint64_t mDstOffset
Definition: GridBuilder.h:1481
ValueOffIterator cbeginValueOff() const
Definition: GridBuilder.h:1148
ValueOffIterator beginValueOff()
Definition: GridBuilder.h:1341
DenseIterator()
Definition: GridBuilder.h:703
typename Node2::ChildNodeType Node1
Definition: GridBuilder.h:2065
void addChild(ChildT *&child)
Definition: GridBuilder.h:477
bool empty() const
Definition: GridBuilder.h:246
ChildT * probeChild(ValueType &value) const
Definition: GridBuilder.h:706
ValueIterator operator++(int)
Definition: GridBuilder.h:1164
Definition: GridBuilder.h:1093
ValueOnIterator cbeginValueOn() const
Definition: GridBuilder.h:1326
ValueIterator(const LeafNode *parent)
Definition: GridBuilder.h:1351
static constexpr uint32_t LEVEL
Definition: GridBuilder.h:54
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition: GridBuilder.h:1303
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition: GridBuilder.h:1302
const MaskT & getChildMask() const
Definition: GridBuilder.h:743
ValueIterator cbeginValueAll() const
Definition: GridBuilder.h:147
Coord getCoord() const
Definition: GridBuilder.h:1128
const RootNodeType & root() const
Definition: GridBuilder.h:2130
Coord getCoord() const
Definition: GridBuilder.h:1338
bool operator*() const
Definition: GridBuilder.h:1321
const TreeType & tree() const
Definition: GridBuilder.h:2133
Coord getCoord() const
Definition: GridBuilder.h:196
bool getFirstValue() const
Definition: GridBuilder.h:1583
GridT GridType
Definition: GridBuilder.h:2060
DenseIterator(const InternalNode *parent)
Definition: GridBuilder.h:704
Coord getCoord() const
Definition: GridBuilder.h:127
ChildT ChildNodeType
Definition: GridBuilder.h:615
uint32_t getTableSize() const
Definition: GridBuilder.h:235
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition: GridBuilder.h:425
Visits all values in a leaf node, i.e. both active and inactive values.
Definition: GridBuilder.h:1151
~InternalNode()
Definition: GridBuilder.h:735
Definition: GridBuilder.h:183
~RootNode()
Definition: GridBuilder.h:232
Coord getCoord() const
Definition: GridBuilder.h:658
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition: GridBuilder.h:914
void setValueAndCache(const Coord &ijk, bool, const AccT &)
Definition: GridBuilder.h:1427
Coord getCoord() const
Definition: GridBuilder.h:1510
typename GridT::BuildType BuildType
Definition: GridBuilder.h:2059
TileIterator operator++(int)
Definition: GridBuilder.h:210
uint64_t mDstOffset
Definition: GridBuilder.h:1115
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition: NanoVDB.h:362
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
const Node2 & upper(uint32_t i) const
Return the i&#39;th upper internal node with respect to breadth-first ordering.
Definition: GridBuilder.h:2125
std::vector< Node1 * > mArray1
Definition: GridBuilder.h:2142
bool operator*() const
Definition: GridBuilder.h:1337
ValueIterator()
Definition: GridBuilder.h:1522
ValueOnIterator cbeginValueOn() const
Definition: GridBuilder.h:1498
Mask< LOG2DIM > mValueMask
Definition: GridBuilder.h:1306
ValueIterator()
Definition: GridBuilder.h:670
RootNodeType mRoot
Definition: GridBuilder.h:1817
ChildIterator operator++(int)
Definition: GridBuilder.h:100
auto getAndCache(const Coord &ijk, const AccT &acc, ArgsT &&...args) const
Definition: GridBuilder.h:810
ChildIterator()
Definition: GridBuilder.h:653
ValueIterator cbeginValueAll() const
Definition: GridBuilder.h:679
void set(const MatT &mat, const MatT &invMat, const Vec3T &translate, double taper=1.0)
Initialize the member data from 3x3 or 4x4 matrices.
Definition: NanoVDB.h:3296
bool isActive() const
Definition: GridBuilder.h:1355
ValueType getValue(const Coord &ijk) const
Definition: GridBuilder.h:324
LeafNode(const Coord &ijk, const ValueType &value, bool state)
Definition: GridBuilder.h:1174
typename GridT::TreeType TreeType
Definition: GridBuilder.h:2061
NanoLeafT * mDstNode
Definition: GridBuilder.h:1308
Trait to map from LEVEL to node type.
Definition: NanoVDB.h:6453
Implements Tree::probeLeaf(Coord)
Definition: GridBuilder.h:43
const Mask< LOG2DIM > & getValueMask() const
Definition: GridBuilder.h:1191
Coord getCoord() const
Definition: GridBuilder.h:1144
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition: GridBuilder.h:1613
uint64_t leafCount() const
Definition: GridBuilder.h:2117
uint32_t pos() const
Definition: GridBuilder.h:174
ValueType operator*() const
Definition: GridBuilder.h:159
void setOn(uint32_t n)
Set the specified bit on.
Definition: NanoVDB.h:3007
ValueType operator*() const
Definition: GridBuilder.h:124
Definition: GridBuilder.h:79
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:615
TileIterator beginTile()
Definition: GridBuilder.h:221
Mask< LOG2DIM > mValueMask
Definition: GridBuilder.h:1111
Implements Tree::isActive(Coord)
Definition: GridBuilder.h:42
ValueType getValue(int i, int j, int k) const
Definition: GridBuilder.h:1688
void setValueAndCache(const Coord &ijk, bool value, const AccT &)
Definition: GridBuilder.h:1605
void merge(LeafNode &other)
Definition: GridBuilder.h:1269
bool isActive(const Coord &ijk) const
Definition: GridBuilder.h:1781
Visits all tile values in this node, i.e. both inactive and active tiles.
Definition: GridBuilder.h:665
bool getFirstValue() const
Definition: GridBuilder.h:1408
enable_if< LEVEL==2, const Node2 & >::type node(int i) const
Definition: GridBuilder.h:2112
ValueOffIterator cbeginValueOff() const
Definition: GridBuilder.h:1342
MaskT mChildMask
Definition: GridBuilder.h:639
bool isActive() const
Definition: GridBuilder.h:1161
void set(uint32_t n, bool on)
Set the specified bit on or off.
Definition: NanoVDB.h:3026
GridType mapToGridType()
Maps from a templated build type to a GridType enum.
Definition: NanoVDB.h:2050
const std::string & gridName() const
Definition: GridBuilder.h:1909
void merge()
Definition: GridBuilder.h:1864
static Coord OffsetToLocalCoord(uint32_t n)
Definition: GridBuilder.h:1203
void merge(RootNode &other)
Definition: GridBuilder.h:553
typename GridT::ValueType ValueType
Definition: GridBuilder.h:2058
void merge(LeafNode &other)
Definition: GridBuilder.h:1627
const Mask< LOG2DIM > & getValueMask() const
Definition: GridBuilder.h:1554
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition: GridBuilder.h:1640
ValueOnIterator(const InternalNode *parent)
Definition: GridBuilder.h:688
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition: GridBuilder.h:1107
std::map< Coord, Tile > MapT
Definition: GridBuilder.h:65
ValueOnIterator()
Definition: GridBuilder.h:1124
ValueOnIterator cbeginValueOn() const
Definition: GridBuilder.h:695
std::mutex & mMutex
Definition: GridBuilder.h:1875
Definition: GridBuilder.h:611
bool isValueOn() const
Definition: GridBuilder.h:204
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition: ForEach.h:40
TreeType & tree()
Definition: GridBuilder.h:1904
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition: GridBuilder.h:882
bool operator*() const
Definition: GridBuilder.h:1525
typename Node2::BuildType BuildType
Definition: GridBuilder.h:51
ValueOnIterator(const LeafNode *parent)
Definition: GridBuilder.h:1125
Coord getOrigin() const
Definition: GridBuilder.h:160
ValueOnIterator()
Definition: GridBuilder.h:1490
bool getLastValue() const
Definition: GridBuilder.h:1409
typename DataType::Tile Tile
Definition: NanoVDB.h:4346
void setValueAndCache(const Coord &ijk, const ValueType &value, const AccT &)
Definition: GridBuilder.h:1241
ValueOnIterator & operator++()
Definition: GridBuilder.h:163
bool getValue(uint32_t i) const
Definition: GridBuilder.h:1586
ValueOffIterator()
Definition: GridBuilder.h:1506
Set the value and its state at the leaf level mapped to by ijk, and create the leaf node and branch i...
Definition: GridBuilder.h:40
ValueType value
Definition: GridBuilder.h:634
GridT & mGrid
Definition: GridBuilder.h:2140
void setName(const std::string &name)
Definition: GridBuilder.h:1911
ValueOffIterator(const LeafNode *parent)
Definition: GridBuilder.h:1507
ValueType getValue(const Coord &ijk) const
Definition: GridBuilder.h:1827
ValueOnIterator()
Definition: GridBuilder.h:687
Coord offsetToGlobalCoord(uint32_t n) const
Definition: GridBuilder.h:775
typename AccT::Node1 Node1
Definition: GridBuilder.h:1850
const ChildT & operator*() const
Definition: GridBuilder.h:656
ValueIterator & operator++()
Definition: GridBuilder.h:1529
Tree(const ValueType &background)
Definition: GridBuilder.h:1822
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
Visits active tile values of this node only.
Definition: GridBuilder.h:682
ValueOnIterator(const LeafNode *parent)
Definition: GridBuilder.h:1319
void setValue(const Coord &ijk, const ValueType &value)
Definition: GridBuilder.h:1267
typename RootNodeType::LeafNodeType LeafNodeType
Definition: GridBuilder.h:1816
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition: GridBuilder.h:1249
ValueIterator(const RootNode *parent)
Definition: GridBuilder.h:120
Visits all inactive values in a leaf node.
Definition: GridBuilder.h:1135
uint64_t lowerCount() const
Definition: GridBuilder.h:2122
void setValue(uint32_t n, bool)
Definition: GridBuilder.h:1447
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition: GridBuilder.h:579
Definition: NanoVDB.h:247
ChildIterator()
Definition: GridBuilder.h:84
ValueIterator()
Definition: GridBuilder.h:1156
void localToGlobalCoord(Coord &ijk) const
Definition: GridBuilder.h:769
GridClass mGridClass
Definition: GridBuilder.h:1891
LeafNode(const Coord &ijk, const ValueType &, bool state)
Definition: GridBuilder.h:1368
Coord getCoord() const
Definition: GridBuilder.h:1354
static Coord OffsetToLocalCoord(uint32_t n)
Definition: GridBuilder.h:1565
Coord getCoord() const
Definition: GridBuilder.h:674
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Definition: NanoVDB.h:2824
ValueIterator beginValue()
Definition: GridBuilder.h:1365
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1441
ValueIterator cbeginValueAll() const
Definition: GridBuilder.h:1538
Tile(ChildT *c=nullptr)
Definition: GridBuilder.h:630
const Mask< LOG2DIM > & valueMask() const
Definition: GridBuilder.h:1553
static uint32_t CoordToOffset(const Coord &ijk)
Definition: GridBuilder.h:755
bool isValueOn(const Coord &ijk) const
Definition: GridBuilder.h:1794
ChildT & operator*() const
Definition: GridBuilder.h:89
const Tile & operator*() const
Definition: GridBuilder.h:193
Tile(ChildT *c=nullptr)
Definition: GridBuilder.h:56
const GridType & grid() const
Definition: GridBuilder.h:2136
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1593
const Node1 & lower(uint32_t i) const
Return the i&#39;th lower internal node with respect to breadth-first ordering.
Definition: GridBuilder.h:2120
void merge(LeafNode &other)
Definition: GridBuilder.h:1450
void localToGlobalCoord(Coord &ijk) const
Definition: GridBuilder.h:1399
ValueOnIterator operator++(int)
Definition: GridBuilder.h:169
Map mMap
Definition: GridBuilder.h:1893
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition: GridBuilder.h:929
ValueType operator*() const
Definition: GridBuilder.h:1159
Coord getCoord() const
Definition: GridBuilder.h:1494
ValueOnIterator beginValueOn()
Definition: GridBuilder.h:1497
void setValueOn(const Coord &ijk)
Definition: GridBuilder.h:1757
ValueType operator*() const
Definition: GridBuilder.h:1127
AccT mAcc
Definition: GridBuilder.h:1874
Visits all tile values and child nodes of this node.
Definition: GridBuilder.h:698
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition: GridBuilder.h:1475
ValueIterator operator++(int)
Definition: GridBuilder.h:1530
void setValue(const Coord &ijk, const ValueType &value)
Definition: GridBuilder.h:1829
ValueType operator*() const
Definition: GridBuilder.h:690
void touchLeaf(const Coord &ijk) const
Definition: GridBuilder.h:1769
uint32_t pos() const
Definition: GridBuilder.h:215
bool getLastValue() const
Definition: GridBuilder.h:1584
void localToGlobalCoord(Coord &ijk) const
Definition: GridBuilder.h:1572
bool isActive() const
Definition: GridBuilder.h:675
void setTransform(double scale=1.0, const Vec3d &translation=Vec3d(0.0))
Definition: GridBuilder.h:1908
Custom Range class that is compatible with the tbb::blocked_range classes.
ValueOnIterator beginValueOn()
Definition: GridBuilder.h:1131
ValueOnIterator cbeginValueOn() const
Definition: GridBuilder.h:181
enable_if< LEVEL==0, Node0 & >::type node(int i)
Definition: GridBuilder.h:2102
ChildIterator cbeginChildOn() const
Definition: GridBuilder.h:112
uint32_t nodeCount() const
Definition: GridBuilder.h:941
ChildIterator cbeginChild() const
Definition: GridBuilder.h:111
ValueType getFirstValue() const
Definition: GridBuilder.h:1222
ChildT * operator->() const
Definition: GridBuilder.h:90
uint32_t nodeCount() const
Definition: GridBuilder.h:445
static Coord OffsetToLocalCoord(uint32_t n)
Definition: GridBuilder.h:1392
typename BuildToValueMap< BuildT >::type ValueType
Definition: GridBuilder.h:1673
void nodeCount(std::array< size_t, 3 > &count) const
Definition: GridBuilder.h:747
void merge(InternalNode &other)
Definition: GridBuilder.h:1035
typename BuildToValueMap< nanovdb::ValueMask >::type ValueType
Definition: GridBuilder.h:1096
void clear()
Definition: GridBuilder.h:248
ValueIterator operator++(int)
Definition: GridBuilder.h:1358
bool state
Definition: GridBuilder.h:63
Maps one type (e.g. the build types above) to other (actual) types.
Definition: NanoVDB.h:651
ValueType operator*() const
Definition: GridBuilder.h:1143
void addTile(const Coord &ijk, const ValueType &value, bool state)
Add a tile containing voxel (i, j, k) at the specified tree level, creating a new branch if necessary...
Definition: GridBuilder.h:991
Definition: GridBuilder.h:149
ValueType getValue(int i, int j, int k) const
Definition: GridBuilder.h:340
Tile * probeTile(const Coord &ijk)
Definition: GridBuilder.h:69
Definition: GridBuilder.h:2054
Grid(const ValueType &background, const std::string &name="", GridClass gClass=GridClass::Unknown)
Definition: GridBuilder.h:1896
ValueIterator beginValue()
Definition: GridBuilder.h:678
Coord mOrigin
Definition: GridBuilder.h:1110
ValueType mValues[SIZE]
Definition: GridBuilder.h:1112
Coord getOrigin() const
Definition: GridBuilder.h:126
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition: GridBuilder.h:898
ValueIterator & operator++()
Definition: GridBuilder.h:1163
const Map & map() const
Definition: GridBuilder.h:1907
Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate ijk...
Definition: GridBuilder.h:39
typename RootNodeType::LeafNodeType LeafNodeType
Definition: GridBuilder.h:1678
ValueType getLastValue() const
Definition: GridBuilder.h:1223
bool isActive() const
Definition: GridBuilder.h:125
ChildT * child
Definition: GridBuilder.h:633
Definition: GridBuilder.h:114
void setValue(const Coord &ijk, const ValueType &value)
Definition: GridBuilder.h:1871
bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition: NanoVDB.h:2983
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition: GridBuilder.h:871
TreeType & tree()
Definition: GridBuilder.h:2132
typename Node2::ValueType ValueType
Definition: GridBuilder.h:50
bool getValue(const Coord &ijk) const
Definition: GridBuilder.h:1587
WriteAccessor getWriteAccessor()
special accessor for thread-safe writing only
Definition: GridBuilder.h:1839
ValueAccessor(RootNodeType &root)
Definition: GridBuilder.h:1680
Coord mOrigin
Definition: GridBuilder.h:1477
ValueAccessor< BuildT > getAccessor()
regular accessor for thread-safe reading and non-thread-safe writing
Definition: GridBuilder.h:1837
void addNode(NodeT *&node)
Definition: GridBuilder.h:532
void insert(const Coord &ijk, NodeT *node) const
Definition: GridBuilder.h:1796
uint32_t pos() const
Definition: GridBuilder.h:105
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1599
Definition: GridBuilder.h:1881
void levelSetToFog(NodeManagerT &mgr, bool rebuild=true)
Definition: GridBuilder.h:2167
ChildIterator cbeginChildOn() const
Definition: GridBuilder.h:662
MaskT mValueMask
Definition: GridBuilder.h:638
TileIterator(const RootNode *parent)
Definition: GridBuilder.h:189
MapT mTable
Definition: GridBuilder.h:66
OnIterator beginOn() const
Definition: NanoVDB.h:2922
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1421
bool operator*() const
Definition: GridBuilder.h:1353
ValueIterator cbeginValueAll() const
Definition: GridBuilder.h:1172
const Tile * probeTile(const Coord &ijk) const
Definition: GridBuilder.h:74
const ValueType & getValue(uint32_t i) const
Definition: GridBuilder.h:1224
Coord getCoord() const
Definition: GridBuilder.h:1526
DenseIterator beginDense()
Definition: GridBuilder.h:720
typename ChildT::BuildType BuildType
Definition: GridBuilder.h:614
typename AccT::Node2 Node2
Definition: GridBuilder.h:1851
NanoNodeT * mDstNode
Definition: GridBuilder.h:643
void operator()(const Func &func, const CoordBBox &bbox, ValueType delta=ValueType(0))
Sets grids values in domain of the bbox to those returned by the specified func with the expected sig...
Definition: GridBuilder.h:1929
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition: GridBuilder.h:387
ValueType getValue(const Coord &ijk) const
Definition: GridBuilder.h:848
Definition: Range.h:28
uint32_t pos() const
Definition: GridBuilder.h:140
void setValue(uint32_t n, bool value)
Definition: GridBuilder.h:1620
Tile mTable[SIZE]
Definition: GridBuilder.h:640
bool ValueType
Definition: GridBuilder.h:1290
typename ChildT::LeafNodeType LeafNodeType
Definition: GridBuilder.h:616
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition: GridBuilder.h:1196
const Coord & origin() const
Definition: GridBuilder.h:1193
ValueOnIterator(const LeafNode *parent)
Definition: GridBuilder.h:1491
ValueIterator(const InternalNode *parent)
Definition: GridBuilder.h:671
ValueIterator & operator++()
Definition: GridBuilder.h:1357
ValueIterator(const LeafNode *parent)
Definition: GridBuilder.h:1523
static Coord CoordToKey(const Coord &ijk)
Definition: GridBuilder.h:254
LeafNode(const Coord &ijk, bool value, bool state)
Definition: GridBuilder.h:1540
bool isActive() const
Definition: GridBuilder.h:60
ValueType getValue(int i, int j, int k) const
Definition: GridBuilder.h:1828
Coord getOrigin() const
Definition: GridBuilder.h:195
bool isOff(uint32_t n) const
Return true if the given bit is NOT set.
Definition: NanoVDB.h:2986
typename BuildLeaf< T >::ValueType ValueT
Definition: GridBuilder.h:2287
const GridType & gridType() const
Definition: GridBuilder.h:1905
Coord mOrigin
Definition: GridBuilder.h:1305
Definition: GridBuilder.h:55
void setValue(const Coord &ijk, const ValueType &value)
Definition: GridBuilder.h:856
Node2 & upper(uint32_t i)
Definition: GridBuilder.h:2126
Coord mOrigin
Definition: GridBuilder.h:637
ValueIterator beginValue()
Definition: GridBuilder.h:1537
Definition: GridBuilder.h:41
bool isChild() const
Definition: GridBuilder.h:58
Node2 ChildNodeType
Definition: GridBuilder.h:52
bool isActive() const
Definition: GridBuilder.h:1527
RootNode(const ValueType &background)
Definition: GridBuilder.h:226
Maximum floating-point values.
Definition: NanoVDB.h:1051
const MaskT & childMask() const
Definition: GridBuilder.h:744
ValueIterator operator++(int)
Definition: GridBuilder.h:135
DenseIterator cbeginChildAll() const
Definition: GridBuilder.h:721
Dummy type for a voxel whose value equals its binary active state.
Definition: NanoVDB.h:272
bool isCached(const Coord &ijk) const
Definition: GridBuilder.h:1690
ValueOffIterator(const LeafNode *parent)
Definition: GridBuilder.h:1141
ChildIterator beginChild()
Definition: GridBuilder.h:661
uint64_t nodeCount(int level) const
Return the number of tree nodes at the specified level.
Definition: GridBuilder.h:2095
ChildIterator(const RootNode *parent)
Definition: GridBuilder.h:85
WriteAccessor(RootNodeType &parent, std::mutex &mx)
Definition: GridBuilder.h:1854
const ValueType & background() const
Definition: GridBuilder.h:236
ValueIterator()
Definition: GridBuilder.h:119
ValueIterator cbeginValueAll() const
Definition: GridBuilder.h:1366
NanoLeafT * mDstNode
Definition: GridBuilder.h:1480
NanoLeafT * mDstNode
Definition: GridBuilder.h:1114
const Node0 & leaf(uint32_t i) const
Return the i&#39;th leaf node with respect to breadth-first ordering.
Definition: GridBuilder.h:2115
Coord getCoord() const
Definition: GridBuilder.h:1322
RootNodeType & root()
Definition: GridBuilder.h:1826
void addNode(NodeT *&node)
Definition: GridBuilder.h:1017
Tile(const ValueType &v, bool s)
Definition: GridBuilder.h:57
typename Node2::LeafNodeType LeafNodeType
Definition: GridBuilder.h:53
Definition: GridBuilder.h:48
#define NANOVDB_ASSERT(x)
Definition: NanoVDB.h:190
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition: GridBuilder.h:406
ValueType operator*() const
Definition: GridBuilder.h:673
enable_if< is_floating_point< typename NodeManagerT::ValueType >::value >::type sdfToLevelSet(NodeManagerT &mgr)
Definition: GridBuilder.h:2149
Tile(const ValueType &v)
Definition: GridBuilder.h:631
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1256
TileIterator()
Definition: GridBuilder.h:188
Coord getOrigin() const
Definition: GridBuilder.h:91
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation...
Definition: NanoVDB.h:3157
typename NanoNode< BuildType, LEVEL >::Type NanoNodeT
Definition: GridBuilder.h:627
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:317
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition: GridBuilder.h:1385
const Coord & origin() const
Definition: GridBuilder.h:1382
~WriteAccessor()
Definition: GridBuilder.h:1863
Definition: GridBuilder.h:1671
const Mask< LOG2DIM > & valueMask() const
Definition: GridBuilder.h:1192
const ChildT * operator->() const
Definition: GridBuilder.h:657
const ValueType & getValue(const Coord &ijk) const
Definition: GridBuilder.h:1225
void getNodes(std::vector< NodeT * > &array)
Definition: GridBuilder.h:462
typename TreeType::RootNodeType RootNodeType
Definition: GridBuilder.h:2062
GridType & grid()
Definition: GridBuilder.h:2135
void setValueOn(const Coord &ijk)
Definition: GridBuilder.h:1870
TileIterator & operator++()
Definition: GridBuilder.h:205
enable_if< LEVEL==2, Node2 & >::type node(int i)
Definition: GridBuilder.h:2110
ChildT * child
Definition: GridBuilder.h:61
typename MaskT::template Iterator< On > MaskIterT
Definition: GridBuilder.h:626
const Mask< LOG2DIM > & getValueMask() const
Definition: GridBuilder.h:1381
bool getValue(uint32_t i) const
Definition: GridBuilder.h:1410
typename AccT::RootNodeType RootNodeType
Definition: GridBuilder.h:1852
typename NanoNode< nanovdb::ValueMask, 0 >::Type NanoLeafT
Definition: GridBuilder.h:1108
std::array< size_t, 3 > nodeCount() const
Definition: GridBuilder.h:1830
std::vector< Node2 * > mArray2
Definition: GridBuilder.h:2143
bool isValue() const
Definition: GridBuilder.h:59
void setValue(const Coord &ijk, bool value)
Definition: GridBuilder.h:1625
enable_if< LEVEL==0, const Node0 & >::type node(int i) const
Definition: GridBuilder.h:2104
Definition: GridBuilder.h:1809
RootNodeType & mRoot
Definition: GridBuilder.h:1801
ValueType value
Definition: GridBuilder.h:62
Coord getCoord() const
Definition: GridBuilder.h:691
Node0 & leaf(uint32_t i)
Definition: GridBuilder.h:2116
const std::string & getName() const
Definition: GridBuilder.h:1910
ValueOnIterator()
Definition: GridBuilder.h:154
uint64_t mDstOffset
Definition: GridBuilder.h:644
Visits all active values in a leaf node.
Definition: GridBuilder.h:1119
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:335
enable_if< LEVEL==1, Node1 & >::type node(int i)
Definition: GridBuilder.h:2106
void setValue(const Coord &ijk)
Definition: GridBuilder.h:1448
Coord getCoord() const
Definition: GridBuilder.h:92
TileIterator cbeginChildAll() const
Definition: GridBuilder.h:222
void nodeCount(std::array< size_t, 3 > &count) const
Definition: GridBuilder.h:238
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition: GridBuilder.h:1060
RootNodeType & root()
Definition: GridBuilder.h:2129
typename Node1::ChildNodeType Node0
Definition: GridBuilder.h:2066
Coord getCoord() const
Definition: GridBuilder.h:161
uint32_t tileCount() const
Definition: GridBuilder.h:234
ChildIterator & operator++()
Definition: GridBuilder.h:94
const ValueType & getValueAndCache(const Coord &ijk, const AccT &) const
Definition: GridBuilder.h:1235
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition: GridBuilder.h:1434
void setValue(const Coord &ijk, const ValueType &value)
Definition: GridBuilder.h:342
const GridClass & gridClass() const
Definition: GridBuilder.h:1906
Coord getCoord() const
Definition: GridBuilder.h:1160
bool ValueType
Definition: GridBuilder.h:1462
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels >> ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition: ValueAccessor.h:88
uint64_t mDstOffset
Definition: GridBuilder.h:1309
void localToGlobalCoord(Coord &ijk) const
Definition: GridBuilder.h:1210
const MaskT & valueMask() const
Definition: GridBuilder.h:742
ValueOffIterator(const LeafNode *parent)
Definition: GridBuilder.h:1335
Coord offsetToGlobalCoord(uint32_t n) const
Definition: GridBuilder.h:1401
ValueType getFirstValue() const
Definition: GridBuilder.h:782
GridType mGridType
Definition: GridBuilder.h:1892
Node1 & lower(uint32_t i)
Definition: GridBuilder.h:2121
Definition: NanoVDB.h:2892
bool operator*() const
Definition: GridBuilder.h:1509
ValueIterator()
Definition: GridBuilder.h:1350
ValueIterator & operator++()
Definition: GridBuilder.h:129
ValueType getLastValue() const
Definition: GridBuilder.h:783
bool getValue(const Coord &ijk) const
Definition: GridBuilder.h:1411
NodeManager(GridT &grid)
Definition: GridBuilder.h:2068
Definition: GridBuilder.h:1845
void setValue(uint32_t n, const ValueType &value)
Definition: GridBuilder.h:1262
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:110
void addTile(const Coord &ijk, const ValueType &value, bool state)
Add a tile containing voxel (i, j, k) at the specified tree level, creating a new branch if necessary...
Definition: GridBuilder.h:499
uint32_t countOn() const
Return the total number of set bits in this Mask.
Definition: NanoVDB.h:2840
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition: GridBuilder.h:374
Coord offsetToGlobalCoord(uint32_t n) const
Definition: GridBuilder.h:1577
Definition: GridBuilder.h:629
LeafT * setValue(const Coord &ijk, const ValueType &value)
Sets value in a leaf node and returns it.
Definition: GridBuilder.h:1743
void setOff(uint32_t n)
Set the specified bit off.
Definition: NanoVDB.h:3009
void init()
Definition: GridBuilder.h:2069
ValueOnIterator beginValueOn()
Definition: GridBuilder.h:694
std::vector< Node0 * > mArray0
Definition: GridBuilder.h:2141
Coord offsetToGlobalCoord(uint32_t n) const
Definition: GridBuilder.h:1215
ValueOffIterator beginValueOff()
Definition: GridBuilder.h:1147
const Tile * operator->() const
Definition: GridBuilder.h:194
ValueIterator(const LeafNode *parent)
Definition: GridBuilder.h:1157
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition: NanoVDB.h:1301
ValueType getValue(const Coord &ijk) const
Definition: GridBuilder.h:1730
Mask< LOG2DIM > mValues
Definition: GridBuilder.h:1478
ValueOnIterator beginValueOn()
Definition: GridBuilder.h:1325
Coord getCoord() const
Definition: GridBuilder.h:717
ValueOffIterator beginValueOff()
Definition: GridBuilder.h:1513
void getNodes(std::vector< NodeT * > &array)
Definition: GridBuilder.h:957
ValueOnIterator(const RootNode *parent)
Definition: GridBuilder.h:155
BuildT BuildType
Definition: GridBuilder.h:1883
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:106
RootNodeType mRoot
Definition: GridBuilder.h:1873
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition: GridBuilder.h:1558
RootNode & operator=(const RootNode &)=delete
C++11 implementation of std::enable_if.
Definition: NanoVDB.h:492
typename BuildToValueMap< BuildT >::type ValueType
Definition: GridBuilder.h:1811
void addChild(ChildT *&child)
Definition: GridBuilder.h:970
ValueOffIterator()
Definition: GridBuilder.h:1140
const ChildT * probeChild(ValueType &value)
Definition: GridBuilder.h:198
static Coord OffsetToLocalCoord(uint32_t n)
Definition: GridBuilder.h:762
auto setAndCache(const Coord &ijk, const AccT &acc, ArgsT &&...args)
Definition: GridBuilder.h:824
typename ChildT::ValueType ValueType
Definition: GridBuilder.h:613
typename BuildRoot< T >::Tile BuildTile
Definition: GridBuilder.h:2030
Tree & tree()
Definition: GridBuilder.h:1825
C++11 implementation of std::is_same.
Definition: NanoVDB.h:441
typename AccT::LeafT LeafT
Definition: GridBuilder.h:1849
const Coord & origin() const
Definition: GridBuilder.h:1555
ValueOffIterator cbeginValueOff() const
Definition: GridBuilder.h:1514
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition: GridBuilder.h:361
bool operator*() const
Definition: GridBuilder.h:1493
ValueOnIterator cbeginValueOn() const
Definition: GridBuilder.h:1132
Coord & minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: NanoVDB.h:1443
ValueIterator beginValue()
Definition: GridBuilder.h:146
typename AccT::ValueType ValueType
Definition: GridBuilder.h:1848
const MaskT & getValueMask() const
Definition: GridBuilder.h:741
std::string mName
Definition: GridBuilder.h:1894
Visits child nodes of this node only.
Definition: GridBuilder.h:648
const Coord & origin() const
Definition: GridBuilder.h:745
InternalNode(const Coord &origin, const ValueType &value, bool state)
Definition: GridBuilder.h:723
ValueOnIterator beginValueOn()
Definition: GridBuilder.h:180
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition: GridBuilder.h:1474
typename RootNodeType::ChildNodeType Node2
Definition: GridBuilder.h:2064