OpenVDB: nanovdb/util/GridBuilder.h Source File

OpenVDB 11.0.0

Loading...
Searching...
No Matches
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
33namespace nanovdb {
34
35 namespace build {
36
37// ----------------------------> Froward decelerations of random access methods <--------------------------------------
38
39template <typename T> struct GetValue;
40template <typename T> struct SetValue;
41template <typename T> struct TouchLeaf;
42template <typename T> struct GetState;
43template <typename T> struct ProbeValue;
44
45// ----------------------------> RootNode <--------------------------------------
46
47template<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;
62 ValueType value;
63 bool state;
64 };
65 using MapT = std::map<Coord, Tile>;
66 MapT mTable;
67 ValueType mBackground;
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
79 class ChildIterator
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();}
94 ChildIterator& operator++() {
95 NANOVDB_ASSERT(mParent);
96 ++mIter;
97 while (mIter!=mParent->mTable.end() && mIter->second.child==nullptr) ++mIter;
98 return *this;
99 }
100 ChildIterator operator++(int) {
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
114 class ValueIterator
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();}
129 ValueIterator& operator++() {
130 NANOVDB_ASSERT(mParent);
131 ++mIter;
132 while (mIter!=mParent->mTable.end() && mIter->second.child!=nullptr) ++mIter;
133 return *this;;
134 }
135 ValueIterator operator++(int) {
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
149 class ValueOnIterator
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();}
163 ValueOnIterator& operator++() {
164 NANOVDB_ASSERT(mParent);
165 ++mIter;
166 while (mIter!=mParent->mTable.end() && (mIter->second.child!=nullptr || !mIter->second.state)) ++mIter;
167 return *this;;
168 }
169 ValueOnIterator operator++(int) {
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
183 class TileIterator
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;}
205 TileIterator& operator++() {
206 NANOVDB_ASSERT(mParent);
207 ++mIter;
208 return *this;
209 }
210 TileIterator operator++(int) {
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
576template<typename ChildT>
577template<typename T>
578inline typename std::enable_if<std::is_floating_point<T>::value>::type
579RootNode<ChildT>::signedFloodFill(T outside)
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
610template<typename ChildT>
611 struct InternalNode
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
624 using MaskT = Mask<LOG2DIM>;
625 template<bool On>
626 using MaskIterT = typename MaskT::template Iterator<On>;
627 using NanoNodeT = typename NanoNode<BuildType, LEVEL>::Type;
628
629 struct Tile {
630 Tile(ChildT* c = nullptr) : child(c) {}
631 Tile(const ValueType& v) : value(v) {}
632 union{
633 ChildT* child;
634 ValueType value;
635 };
636 };
637 Coord mOrigin;
638 MaskT mValueMask;
639 MaskT mChildMask;
640 Tile mTable[SIZE];
641
642 union {
643 NanoNodeT *mDstNode;
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
661 ChildIterator beginChild() {return ChildIterator(this);}
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
678 ValueIterator beginValue() {return ValueIterator(this);}
679 ValueIterator cbeginValueAll() const {return ValueIterator(this);}
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
694 ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
695 ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
696
697 /// @brief Visits all tile values and child nodes of this node
698 class DenseIterator : public MaskT::DenseIterator
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
720 DenseIterator beginDense() {return DenseIterator(this);}
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
735 ~InternalNode()
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 {
777 Coord ijk = InternalNode::OffsetToLocalCoord(n);
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
1057template<typename ChildT>
1058template<typename T>
1059inline typename std::enable_if<std::is_floating_point<T>::value>::type
1060InternalNode<ChildT>::signedFloodFill(T outside)
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
1092template<typename BuildT>
1093 struct LeafNode
1094{
1095 using BuildType = BuildT;
1096 using ValueType = typename BuildToValueMap<BuildT>::type;
1097 using LeafNodeType = LeafNode<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
1105 using NodeMaskType = Mask<LOG2DIM>;
1106 template<bool ON>
1107 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1108 using NanoLeafT = typename NanoNode<BuildT, 0>::Type;
1109
1110 Coord mOrigin;
1111 Mask<LOG2DIM> mValueMask;
1112 ValueType mValues[SIZE];
1113 union {
1114 NanoLeafT *mDstNode;
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
1151 class ValueIterator
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;}
1164 ValueIterator operator++(int) {
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 {
1217 Coord ijk = LeafNode::OffsetToLocalCoord(n);
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
1287template <>
1288 struct LeafNode<ValueMask>
1289{
1290 using ValueType = bool;
1291 using BuildType = ValueMask;
1292 using LeafNodeType = LeafNode<BuildType>;
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
1300 using NodeMaskType = Mask<LOG2DIM>;
1301 template<bool ON>
1302 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1303 using NanoLeafT = typename NanoNode<BuildType, 0>::Type;
1304
1305 Coord mOrigin;
1306 Mask<LOG2DIM> mValueMask;
1307 union {
1308 NanoLeafT *mDstNode;
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 {
1403 Coord ijk = LeafNode::OffsetToLocalCoord(n);
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
1459template <>
1460 struct LeafNode<bool>
1461{
1462 using ValueType = bool;
1463 using BuildType = ValueMask;
1464 using LeafNodeType = LeafNode<BuildType>;
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
1472 using NodeMaskType = Mask<LOG2DIM>;
1473 template<bool ON>
1474 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1475 using NanoLeafT = typename NanoNode<BuildType, 0>::Type;
1476
1477 Coord mOrigin;
1478 Mask<LOG2DIM> mValueMask, mValues;
1479 union {
1480 NanoLeafT *mDstNode;
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 {
1579 Coord ijk = LeafNode::OffsetToLocalCoord(n);
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
1637template<typename BuildT>
1638template<typename T>
1639inline typename std::enable_if<std::is_floating_point<T>::value>::type
1640LeafNode<BuildT>::signedFloodFill(T outside)
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
1670template<typename BuildT>
1671 struct ValueAccessor
1672{
1673 using ValueType = typename BuildToValueMap<BuildT>::type;
1674 using LeafT = build::LeafNode<BuildT>;
1675 using Node1 = build::InternalNode<LeafT>;
1676 using Node2 = build::InternalNode<Node1>;
1677 using RootNodeType = build::RootNode<Node2>;
1678 using LeafNodeType = typename RootNodeType::LeafNodeType;
1679
1680 ValueAccessor(RootNodeType& root)
1681 : mRoot(root)
1682 , mKeys{Coord(Maximum<int>::value()), Coord(Maximum<int>::value()), Coord(Maximum<int>::value())}
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 }
1801 RootNodeType& mRoot;
1802 mutable Coord mKeys[3];
1803 mutable void* mNode[3];
1804}; // build::ValueAccessor<BuildT>
1805
1806// ----------------------------> Tree <--------------------------------------
1807
1808template<typename BuildT>
1809 struct Tree
1810{
1811 using ValueType = typename BuildToValueMap<BuildT>::type;
1812 using Node0 = build::LeafNode<BuildT>;
1813 using Node1 = build::InternalNode<Node0>;
1814 using Node2 = build::InternalNode<Node1>;
1815 using RootNodeType = build::RootNode<Node2>;
1816 using LeafNodeType = typename RootNodeType::LeafNodeType;
1817 struct WriteAccessor;
1818
1819 RootNodeType mRoot;
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
1837 ValueAccessor<BuildT> getAccessor() { return ValueAccessor<BuildT>(mRoot); }
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
1844template<typename BuildT>
1845 struct Tree<BuildT>::WriteAccessor
1846{
1847 using AccT = ValueAccessor<BuildT>;
1848 using ValueType = typename AccT::ValueType;
1849 using LeafT = typename AccT::LeafT;
1850 using Node1 = typename AccT::Node1;
1851 using Node2 = typename AccT::Node2;
1852 using RootNodeType = typename AccT::RootNodeType;
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;
1874 AccT mAcc;
1875 std::mutex &mMutex;
1876}; // build::Tree<BuildT>::WriteAccessor
1877
1878// ----------------------------> Grid <--------------------------------------
1879
1880template<typename BuildT>
1881 struct Grid : public Tree<BuildT>
1882{
1883 using BuildType = BuildT;
1884 using ValueType = typename BuildToValueMap<BuildT>::type;
1885 using TreeType = Tree<BuildT>;
1886 using Node0 = build::LeafNode<BuildT>;
1887 using Node1 = build::InternalNode<Node0>;
1888 using Node2 = build::InternalNode<Node1>;
1889 using RootNodeType = build::RootNode<Node2>;
1890
1891 GridClass mGridClass;
1892 GridType mGridType;
1893 Map mMap;
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
1927template <typename BuildT>
1928template <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
2021template <typename T>
2022 using BuildLeaf = LeafNode<T>;
2023template <typename T>
2024 using BuildLower = InternalNode<BuildLeaf<T>>;
2025template <typename T>
2026 using BuildUpper = InternalNode<BuildLower<T>>;
2027template <typename T>
2028 using BuildRoot = RootNode<BuildUpper<T>>;
2029template <typename T>
2030 using BuildTile = typename BuildRoot<T>::Tile;
2031
2032 using FloatGrid = Grid<float>;
2033 using Fp4Grid = Grid<Fp4>;
2034 using Fp8Grid = Grid<Fp8>;
2035 using Fp16Grid = Grid<Fp16>;
2036 using FpNGrid = Grid<FpN>;
2037 using DoubleGrid = Grid<double>;
2038 using Int32Grid = Grid<int32_t>;
2039 using UInt32Grid = Grid<uint32_t>;
2040 using Int64Grid = Grid<int64_t>;
2041 using Vec3fGrid = Grid<Vec3f>;
2042 using Vec3dGrid = Grid<Vec3d>;
2043 using Vec4fGrid = Grid<Vec4f>;
2044 using Vec4dGrid = Grid<Vec4d>;
2045 using MaskGrid = Grid<ValueMask>;
2046 using IndexGrid = Grid<ValueIndex>;
2047 using OnIndexGrid = Grid<ValueOnIndex>;
2048 using BoolGrid = Grid<bool>;
2049
2050// ----------------------------> NodeManager <--------------------------------------
2051
2052// GridT can be openvdb::Grid and nanovdb::build::Grid
2053template <typename GridT>
2054 class NodeManager
2055{
2056public:
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
2138protected:
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
2147template <typename NodeManagerT>
2148typename enable_if<is_floating_point<typename NodeManagerT::ValueType>::value>::type
2149sdfToLevelSet(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
2166template <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
2241template <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.
2249template <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
2260template <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
2271template <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
2285template <typename T>
2286 struct ProbeValue {
2287 using ValueT = typename BuildLeaf<T>::ValueType;
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
ForEach.h
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
NanoVDB.h
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
NANOVDB_ASSERT
#define NANOVDB_ASSERT(x)
Definition NanoVDB.h:190
Range.h
Custom Range class that is compatible with the tbb::blocked_range classes.
nanovdb::Coord
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition NanoVDB.h:1302
nanovdb::Grid< uint32_t >
nanovdb::Mask::DenseIterator
Definition NanoVDB.h:2893
nanovdb::Mask
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Definition NanoVDB.h:2825
nanovdb::Mask::beginOn
OnIterator beginOn() const
Definition NanoVDB.h:2922
nanovdb::Mask::isOff
bool isOff(uint32_t n) const
Return true if the given bit is NOT set.
Definition NanoVDB.h:2986
nanovdb::Mask::set
void set(uint32_t n, bool on)
Set the specified bit on or off.
Definition NanoVDB.h:3026
nanovdb::Mask::countOn
uint32_t countOn() const
Return the total number of set bits in this Mask.
Definition NanoVDB.h:2840
nanovdb::Mask::isOn
bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition NanoVDB.h:2983
nanovdb::Mask::setOn
void setOn(uint32_t n)
Set the specified bit on.
Definition NanoVDB.h:3007
nanovdb::Range
Definition Range.h:28
nanovdb::ValueMask
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:273
nanovdb::Vec3< double >
nanovdb::build::InternalNode::ChildIterator
Visits child nodes of this node only.
Definition GridBuilder.h:649
nanovdb::build::InternalNode::ChildIterator::ChildIterator
ChildIterator()
Definition GridBuilder.h:653
nanovdb::build::InternalNode::ChildIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:658
nanovdb::build::InternalNode::ChildIterator::operator->
const ChildT * operator->() const
Definition GridBuilder.h:657
nanovdb::build::InternalNode::ChildIterator::operator=
ChildIterator & operator=(const ChildIterator &)=default
nanovdb::build::InternalNode::ChildIterator::ChildIterator
ChildIterator(const InternalNode *parent)
Definition GridBuilder.h:654
nanovdb::build::InternalNode::ChildIterator::operator*
const ChildT & operator*() const
Definition GridBuilder.h:656
nanovdb::build::InternalNode::DenseIterator
Visits all tile values and child nodes of this node.
Definition GridBuilder.h:699
nanovdb::build::InternalNode::DenseIterator::DenseIterator
DenseIterator()
Definition GridBuilder.h:703
nanovdb::build::InternalNode::DenseIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:717
nanovdb::build::InternalNode::DenseIterator::operator=
DenseIterator & operator=(const DenseIterator &)=default
nanovdb::build::InternalNode::DenseIterator::DenseIterator
DenseIterator(const InternalNode *parent)
Definition GridBuilder.h:704
nanovdb::build::InternalNode::DenseIterator::probeChild
ChildT * probeChild(ValueType &value) const
Definition GridBuilder.h:706
nanovdb::build::InternalNode::ValueIterator
Visits all tile values in this node, i.e. both inactive and active tiles.
Definition GridBuilder.h:666
nanovdb::build::InternalNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::build::InternalNode::ValueIterator::ValueIterator
ValueIterator(const InternalNode *parent)
Definition GridBuilder.h:671
nanovdb::build::InternalNode::ValueIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:674
nanovdb::build::InternalNode::ValueIterator::isActive
bool isActive() const
Definition GridBuilder.h:675
nanovdb::build::InternalNode::ValueIterator::ValueIterator
ValueIterator()
Definition GridBuilder.h:670
nanovdb::build::InternalNode::ValueIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:673
nanovdb::build::InternalNode::ValueOnIterator
Visits active tile values of this node only.
Definition GridBuilder.h:683
nanovdb::build::InternalNode::ValueOnIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:691
nanovdb::build::InternalNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const InternalNode *parent)
Definition GridBuilder.h:688
nanovdb::build::InternalNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::build::InternalNode::ValueOnIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:690
nanovdb::build::InternalNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition GridBuilder.h:687
nanovdb::build::LeafNode::ValueIterator
Visits all values in a leaf node, i.e. both active and inactive values.
Definition GridBuilder.h:1152
nanovdb::build::LeafNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::build::LeafNode::ValueIterator::operator++
ValueIterator & operator++()
Definition GridBuilder.h:1163
nanovdb::build::LeafNode::ValueIterator::operator++
ValueIterator operator++(int)
Definition GridBuilder.h:1164
nanovdb::build::LeafNode::ValueIterator::ValueIterator
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1157
nanovdb::build::LeafNode::ValueIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1160
nanovdb::build::LeafNode::ValueIterator::isActive
bool isActive() const
Definition GridBuilder.h:1161
nanovdb::build::LeafNode::ValueIterator::ValueIterator
ValueIterator()
Definition GridBuilder.h:1156
nanovdb::build::LeafNode::ValueIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:1159
nanovdb::build::LeafNode::ValueOffIterator
Visits all inactive values in a leaf node.
Definition GridBuilder.h:1136
nanovdb::build::LeafNode::ValueOffIterator::ValueOffIterator
ValueOffIterator()
Definition GridBuilder.h:1140
nanovdb::build::LeafNode::ValueOffIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1144
nanovdb::build::LeafNode::ValueOffIterator::operator=
ValueOffIterator & operator=(const ValueOffIterator &)=default
nanovdb::build::LeafNode::ValueOffIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:1143
nanovdb::build::LeafNode::ValueOffIterator::ValueOffIterator
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1141
nanovdb::build::LeafNode::ValueOnIterator
Visits all active values in a leaf node.
Definition GridBuilder.h:1120
nanovdb::build::LeafNode::ValueOnIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1128
nanovdb::build::LeafNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1125
nanovdb::build::LeafNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::build::LeafNode::ValueOnIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:1127
nanovdb::build::LeafNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition GridBuilder.h:1124
nanovdb::build::LeafNode< ValueMask >::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::build::LeafNode< ValueMask >::ValueIterator::operator++
ValueIterator & operator++()
Definition GridBuilder.h:1357
nanovdb::build::LeafNode< ValueMask >::ValueIterator::operator++
ValueIterator operator++(int)
Definition GridBuilder.h:1358
nanovdb::build::LeafNode< ValueMask >::ValueIterator::operator*
bool operator*() const
Definition GridBuilder.h:1353
nanovdb::build::LeafNode< ValueMask >::ValueIterator::ValueIterator
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1351
nanovdb::build::LeafNode< ValueMask >::ValueIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1354
nanovdb::build::LeafNode< ValueMask >::ValueIterator::isActive
bool isActive() const
Definition GridBuilder.h:1355
nanovdb::build::LeafNode< ValueMask >::ValueIterator::ValueIterator
ValueIterator()
Definition GridBuilder.h:1350
nanovdb::build::LeafNode< ValueMask >::ValueOffIterator::ValueOffIterator
ValueOffIterator()
Definition GridBuilder.h:1334
nanovdb::build::LeafNode< ValueMask >::ValueOffIterator::operator*
bool operator*() const
Definition GridBuilder.h:1337
nanovdb::build::LeafNode< ValueMask >::ValueOffIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1338
nanovdb::build::LeafNode< ValueMask >::ValueOffIterator::operator=
ValueOffIterator & operator=(const ValueOffIterator &)=default
nanovdb::build::LeafNode< ValueMask >::ValueOffIterator::ValueOffIterator
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1335
nanovdb::build::LeafNode< ValueMask >::ValueOnIterator::operator*
bool operator*() const
Definition GridBuilder.h:1321
nanovdb::build::LeafNode< ValueMask >::ValueOnIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1322
nanovdb::build::LeafNode< ValueMask >::ValueOnIterator::ValueOnIterator
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1319
nanovdb::build::LeafNode< ValueMask >::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::build::LeafNode< ValueMask >::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition GridBuilder.h:1318
nanovdb::build::LeafNode< bool >::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::build::LeafNode< bool >::ValueIterator::operator++
ValueIterator & operator++()
Definition GridBuilder.h:1529
nanovdb::build::LeafNode< bool >::ValueIterator::operator++
ValueIterator operator++(int)
Definition GridBuilder.h:1530
nanovdb::build::LeafNode< bool >::ValueIterator::operator*
bool operator*() const
Definition GridBuilder.h:1525
nanovdb::build::LeafNode< bool >::ValueIterator::ValueIterator
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1523
nanovdb::build::LeafNode< bool >::ValueIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1526
nanovdb::build::LeafNode< bool >::ValueIterator::isActive
bool isActive() const
Definition GridBuilder.h:1527
nanovdb::build::LeafNode< bool >::ValueIterator::ValueIterator
ValueIterator()
Definition GridBuilder.h:1522
nanovdb::build::LeafNode< bool >::ValueOffIterator::ValueOffIterator
ValueOffIterator()
Definition GridBuilder.h:1506
nanovdb::build::LeafNode< bool >::ValueOffIterator::operator*
bool operator*() const
Definition GridBuilder.h:1509
nanovdb::build::LeafNode< bool >::ValueOffIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1510
nanovdb::build::LeafNode< bool >::ValueOffIterator::operator=
ValueOffIterator & operator=(const ValueOffIterator &)=default
nanovdb::build::LeafNode< bool >::ValueOffIterator::ValueOffIterator
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1507
nanovdb::build::LeafNode< bool >::ValueOnIterator::operator*
bool operator*() const
Definition GridBuilder.h:1493
nanovdb::build::LeafNode< bool >::ValueOnIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:1494
nanovdb::build::LeafNode< bool >::ValueOnIterator::ValueOnIterator
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1491
nanovdb::build::LeafNode< bool >::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::build::LeafNode< bool >::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition GridBuilder.h:1490
nanovdb::build::NodeManager
Definition GridBuilder.h:2055
nanovdb::build::NodeManager::tree
const TreeType & tree() const
Definition GridBuilder.h:2133
nanovdb::build::NodeManager::init
void init()
Definition GridBuilder.h:2069
nanovdb::build::NodeManager::lower
Node1 & lower(uint32_t i)
Definition GridBuilder.h:2121
nanovdb::build::NodeManager::root
RootNodeType & root()
Definition GridBuilder.h:2129
nanovdb::build::NodeManager::tree
TreeType & tree()
Definition GridBuilder.h:2132
nanovdb::build::NodeManager::Node0
typename Node1::ChildNodeType Node0
Definition GridBuilder.h:2066
nanovdb::build::NodeManager::nodeCount
uint64_t nodeCount(int level) const
Return the number of tree nodes at the specified level.
Definition GridBuilder.h:2095
nanovdb::build::NodeManager::node
enable_if< LEVEL==0, Node0 & >::type node(int i)
Definition GridBuilder.h:2102
nanovdb::build::NodeManager::upper
const Node2 & upper(uint32_t i) const
Return the i'th upper internal node with respect to breadth-first ordering.
Definition GridBuilder.h:2125
nanovdb::build::NodeManager::leafCount
uint64_t leafCount() const
Definition GridBuilder.h:2117
nanovdb::build::NodeManager::leaf
const Node0 & leaf(uint32_t i) const
Return the i'th leaf node with respect to breadth-first ordering.
Definition GridBuilder.h:2115
nanovdb::build::NodeManager::upperCount
uint64_t upperCount() const
Definition GridBuilder.h:2127
nanovdb::build::NodeManager::upper
Node2 & upper(uint32_t i)
Definition GridBuilder.h:2126
nanovdb::build::NodeManager::node
enable_if< LEVEL==0, constNode0 & >::type node(int i) const
Definition GridBuilder.h:2104
nanovdb::build::NodeManager::RootNodeType
typename TreeType::RootNodeType RootNodeType
Definition GridBuilder.h:2062
nanovdb::build::NodeManager::grid
GridType & grid()
Definition GridBuilder.h:2135
nanovdb::build::NodeManager::leaf
Node0 & leaf(uint32_t i)
Definition GridBuilder.h:2116
nanovdb::build::NodeManager::mArray0
std::vector< Node0 * > mArray0
Definition GridBuilder.h:2141
nanovdb::build::NodeManager::Node2
typename RootNodeType::ChildNodeType Node2
Definition GridBuilder.h:2064
nanovdb::build::NodeManager::node
enable_if< LEVEL==2, Node2 & >::type node(int i)
Definition GridBuilder.h:2110
nanovdb::build::NodeManager::BuildType
typename GridT::BuildType BuildType
Definition GridBuilder.h:2059
nanovdb::build::NodeManager::mGrid
GridT & mGrid
Definition GridBuilder.h:2140
nanovdb::build::NodeManager::mArray2
std::vector< Node2 * > mArray2
Definition GridBuilder.h:2143
nanovdb::build::NodeManager::TreeType
typename GridT::TreeType TreeType
Definition GridBuilder.h:2061
nanovdb::build::NodeManager::NodeManager
NodeManager(GridT &grid)
Definition GridBuilder.h:2068
nanovdb::build::NodeManager::ValueType
typename GridT::ValueType ValueType
Definition GridBuilder.h:2058
nanovdb::build::NodeManager::grid
const GridType & grid() const
Definition GridBuilder.h:2136
nanovdb::build::NodeManager::node
enable_if< LEVEL==1, constNode1 & >::type node(int i) const
Definition GridBuilder.h:2108
nanovdb::build::NodeManager::Node1
typename Node2::ChildNodeType Node1
Definition GridBuilder.h:2065
nanovdb::build::NodeManager::lowerCount
uint64_t lowerCount() const
Definition GridBuilder.h:2122
nanovdb::build::NodeManager::node
enable_if< LEVEL==2, constNode2 & >::type node(int i) const
Definition GridBuilder.h:2112
nanovdb::build::NodeManager::GridType
GridT GridType
Definition GridBuilder.h:2060
nanovdb::build::NodeManager::node
enable_if< LEVEL==1, Node1 & >::type node(int i)
Definition GridBuilder.h:2106
nanovdb::build::NodeManager::root
const RootNodeType & root() const
Definition GridBuilder.h:2130
nanovdb::build::NodeManager::lower
const Node1 & lower(uint32_t i) const
Return the i'th lower internal node with respect to breadth-first ordering.
Definition GridBuilder.h:2120
nanovdb::build::NodeManager::mArray1
std::vector< Node1 * > mArray1
Definition GridBuilder.h:2142
nanovdb::build::RootNode::ChildIterator
Definition GridBuilder.h:80
nanovdb::build::RootNode::ChildIterator::getOrigin
Coord getOrigin() const
Definition GridBuilder.h:91
nanovdb::build::RootNode::ChildIterator::ChildIterator
ChildIterator()
Definition GridBuilder.h:84
nanovdb::build::RootNode::ChildIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:92
nanovdb::build::RootNode::ChildIterator::operator++
ChildIterator & operator++()
Definition GridBuilder.h:94
nanovdb::build::RootNode::ChildIterator::operator++
ChildIterator operator++(int)
Definition GridBuilder.h:100
nanovdb::build::RootNode::ChildIterator::operator*
ChildT & operator*() const
Definition GridBuilder.h:89
nanovdb::build::RootNode::ChildIterator::operator->
ChildT * operator->() const
Definition GridBuilder.h:90
nanovdb::build::RootNode::ChildIterator::operator=
ChildIterator & operator=(const ChildIterator &)=default
nanovdb::build::RootNode::ChildIterator::pos
uint32_t pos() const
Definition GridBuilder.h:105
nanovdb::build::RootNode::ChildIterator::ChildIterator
ChildIterator(const RootNode *parent)
Definition GridBuilder.h:85
nanovdb::build::RootNode::TileIterator
Definition GridBuilder.h:184
nanovdb::build::RootNode::TileIterator::getOrigin
Coord getOrigin() const
Definition GridBuilder.h:195
nanovdb::build::RootNode::TileIterator::TileIterator
TileIterator(const RootNode *parent)
Definition GridBuilder.h:189
nanovdb::build::RootNode::TileIterator::TileIterator
TileIterator()
Definition GridBuilder.h:188
nanovdb::build::RootNode::TileIterator::isValueOn
bool isValueOn() const
Definition GridBuilder.h:204
nanovdb::build::RootNode::TileIterator::operator++
TileIterator & operator++()
Definition GridBuilder.h:205
nanovdb::build::RootNode::TileIterator::operator*
const Tile & operator*() const
Definition GridBuilder.h:193
nanovdb::build::RootNode::TileIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:196
nanovdb::build::RootNode::TileIterator::operator++
TileIterator operator++(int)
Definition GridBuilder.h:210
nanovdb::build::RootNode::TileIterator::operator->
const Tile * operator->() const
Definition GridBuilder.h:194
nanovdb::build::RootNode::TileIterator::operator=
TileIterator & operator=(const TileIterator &)=default
nanovdb::build::RootNode::TileIterator::pos
uint32_t pos() const
Definition GridBuilder.h:215
nanovdb::build::RootNode::TileIterator::probeChild
const ChildT * probeChild(ValueType &value)
Definition GridBuilder.h:198
nanovdb::build::RootNode::ValueIterator
Definition GridBuilder.h:115
nanovdb::build::RootNode::ValueIterator::operator=
ValueIterator & operator=(const ValueIterator &)=default
nanovdb::build::RootNode::ValueIterator::getOrigin
Coord getOrigin() const
Definition GridBuilder.h:126
nanovdb::build::RootNode::ValueIterator::operator++
ValueIterator & operator++()
Definition GridBuilder.h:129
nanovdb::build::RootNode::ValueIterator::operator++
ValueIterator operator++(int)
Definition GridBuilder.h:135
nanovdb::build::RootNode::ValueIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:127
nanovdb::build::RootNode::ValueIterator::isActive
bool isActive() const
Definition GridBuilder.h:125
nanovdb::build::RootNode::ValueIterator::ValueIterator
ValueIterator()
Definition GridBuilder.h:119
nanovdb::build::RootNode::ValueIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:124
nanovdb::build::RootNode::ValueIterator::pos
uint32_t pos() const
Definition GridBuilder.h:140
nanovdb::build::RootNode::ValueIterator::ValueIterator
ValueIterator(const RootNode *parent)
Definition GridBuilder.h:120
nanovdb::build::RootNode::ValueOnIterator
Definition GridBuilder.h:150
nanovdb::build::RootNode::ValueOnIterator::getOrigin
Coord getOrigin() const
Definition GridBuilder.h:160
nanovdb::build::RootNode::ValueOnIterator::operator++
ValueOnIterator operator++(int)
Definition GridBuilder.h:169
nanovdb::build::RootNode::ValueOnIterator::getCoord
Coord getCoord() const
Definition GridBuilder.h:161
nanovdb::build::RootNode::ValueOnIterator::ValueOnIterator
ValueOnIterator(const RootNode *parent)
Definition GridBuilder.h:155
nanovdb::build::RootNode::ValueOnIterator::operator=
ValueOnIterator & operator=(const ValueOnIterator &)=default
nanovdb::build::RootNode::ValueOnIterator::operator++
ValueOnIterator & operator++()
Definition GridBuilder.h:163
nanovdb::build::RootNode::ValueOnIterator::operator*
ValueType operator*() const
Definition GridBuilder.h:159
nanovdb::build::RootNode::ValueOnIterator::pos
uint32_t pos() const
Definition GridBuilder.h:174
nanovdb::build::RootNode::ValueOnIterator::ValueOnIterator
ValueOnIterator()
Definition GridBuilder.h:154
nanovdb::build::sdfToLevelSet
enable_if< is_floating_point< typenameNodeManagerT::ValueType >::value >::type sdfToLevelSet(NodeManagerT &mgr)
Definition GridBuilder.h:2149
nanovdb::build::levelSetToFog
void levelSetToFog(NodeManagerT &mgr, bool rebuild=true)
Definition GridBuilder.h:2167
nanovdb::build::BuildTile
typename BuildRoot< T >::Tile BuildTile
Definition GridBuilder.h:2030
nanovdb
Convert a base-pointer to an openvdb grid, denoted srcGrid, to a nanovdb grid of the same type,...
Definition NanoVDB.h:247
nanovdb::GridClass
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition NanoVDB.h:362
nanovdb::GridClass::FogVolume
@ FogVolume
nanovdb::GridClass::Unknown
@ Unknown
nanovdb::GridClass::LevelSet
@ LevelSet
nanovdb::GridType
GridType
List of types that are currently supported by NanoVDB.
Definition NanoVDB.h:317
nanovdb::Vec3d
Vec3< double > Vec3d
Definition NanoVDB.h:1704
nanovdb::mapToGridType
GridType mapToGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:2050
nanovdb::forEach
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:40
nanovdb::Range1D
Range< 1, size_t > Range1D
Definition Range.h:30
openvdb::v11_0::tools::prune
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
nanovdb::BBox< Coord >
nanovdb::BuildToValueMap::type
T type
Definition NanoVDB.h:654
nanovdb::Map
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:3158
nanovdb::Map::set
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
nanovdb::Maximum
Maximum floating-point values.
Definition NanoVDB.h:1076
nanovdb::NanoNode
Trait to map from LEVEL to node type.
Definition NanoVDB.h:6453
nanovdb::build::GetState
Implements Tree::isActive(Coord)
Definition GridBuilder.h:2261
nanovdb::build::GetState::get
static bool get(const BuildRoot< T > &)
Definition GridBuilder.h:2262
nanovdb::build::GetState::get
static bool get(const BuildTile< T > &tile)
Definition GridBuilder.h:2263
nanovdb::build::GetState::get
static bool get(const BuildUpper< T > &node, uint32_t n)
Definition GridBuilder.h:2264
nanovdb::build::GetState::get
static bool get(const BuildLower< T > &node, uint32_t n)
Definition GridBuilder.h:2265
nanovdb::build::GetState::get
static bool get(const BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2266
nanovdb::build::GetValue
Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate ijk.
Definition GridBuilder.h:2250
nanovdb::build::GetValue::get
static auto get(const BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2255
nanovdb::build::GetValue::get
static auto get(const BuildLower< T > &node, uint32_t n)
Definition GridBuilder.h:2254
nanovdb::build::GetValue::get
static auto get(const BuildRoot< T > &root)
Definition GridBuilder.h:2251
nanovdb::build::GetValue::get
static auto get(const BuildTile< T > &tile)
Definition GridBuilder.h:2252
nanovdb::build::GetValue::get
static auto get(const BuildUpper< T > &node, uint32_t n)
Definition GridBuilder.h:2253
nanovdb::build::Grid
Definition GridBuilder.h:1882
nanovdb::build::Grid::gridType
const GridType & gridType() const
Definition GridBuilder.h:1905
nanovdb::build::Grid::tree
TreeType & tree()
Definition GridBuilder.h:1904
nanovdb::build::Grid::setTransform
void setTransform(double scale=1.0, const Vec3d &translation=Vec3d(0.0))
Definition GridBuilder.h:1908
nanovdb::build::Grid::Grid
Grid(const ValueType &background, const std::string &name="", GridClass gClass=GridClass::Unknown)
Definition GridBuilder.h:1896
nanovdb::build::Grid::getName
const std::string & getName() const
Definition GridBuilder.h:1910
nanovdb::build::Grid::mName
std::string mName
Definition GridBuilder.h:1894
nanovdb::build::Grid::mGridType
GridType mGridType
Definition GridBuilder.h:1892
nanovdb::build::Grid::gridClass
const GridClass & gridClass() const
Definition GridBuilder.h:1906
nanovdb::build::Grid::mGridClass
GridClass mGridClass
Definition GridBuilder.h:1891
nanovdb::build::Grid::operator()
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
nanovdb::build::Grid::setName
void setName(const std::string &name)
Definition GridBuilder.h:1911
nanovdb::build::Grid::mMap
Map mMap
Definition GridBuilder.h:1893
nanovdb::build::Grid::ValueType
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1884
nanovdb::build::Grid::gridName
const std::string & gridName() const
Definition GridBuilder.h:1909
nanovdb::build::Grid::map
const Map & map() const
Definition GridBuilder.h:1907
nanovdb::build::Grid::BuildType
BuildT BuildType
Definition GridBuilder.h:1883
nanovdb::build::InternalNode::Tile
Definition GridBuilder.h:629
nanovdb::build::InternalNode::Tile::Tile
Tile(const ValueType &v)
Definition GridBuilder.h:631
nanovdb::build::InternalNode::Tile::Tile
Tile(ChildT *c=nullptr)
Definition GridBuilder.h:630
nanovdb::build::InternalNode::Tile::child
ChildT * child
Definition GridBuilder.h:633
nanovdb::build::InternalNode::Tile::value
ValueType value
Definition GridBuilder.h:634
nanovdb::build::InternalNode
Definition GridBuilder.h:612
nanovdb::build::InternalNode::addTile
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
nanovdb::build::InternalNode::operator=
InternalNode & operator=(InternalNode &&)=delete
nanovdb::build::InternalNode::setValueAndCache
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition GridBuilder.h:882
nanovdb::build::InternalNode::valueMask
const MaskT & valueMask() const
Definition GridBuilder.h:742
nanovdb::build::InternalNode::offsetToGlobalCoord
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:775
nanovdb::build::InternalNode::getNodes
void getNodes(std::vector< NodeT * > &array)
Definition GridBuilder.h:957
nanovdb::build::InternalNode::getLastValue
ValueType getLastValue() const
Definition GridBuilder.h:783
nanovdb::build::InternalNode::mChildMask
MaskT mChildMask
Definition GridBuilder.h:639
nanovdb::build::InternalNode::getValueMask
const MaskT & getValueMask() const
Definition GridBuilder.h:741
nanovdb::build::InternalNode::beginValueOn
ValueOnIterator beginValueOn()
Definition GridBuilder.h:694
nanovdb::build::InternalNode::~InternalNode
~InternalNode()
Definition GridBuilder.h:735
nanovdb::build::InternalNode::MASK
static constexpr uint32_t MASK
Definition GridBuilder.h:621
nanovdb::build::InternalNode::MaskIterT
typename MaskT::template Iterator< On > MaskIterT
Definition GridBuilder.h:626
nanovdb::build::InternalNode::BuildType
typename ChildT::BuildType BuildType
Definition GridBuilder.h:614
nanovdb::build::InternalNode::NanoNodeT
typename NanoNode< BuildType, LEVEL >::Type NanoNodeT
Definition GridBuilder.h:627
nanovdb::build::InternalNode::LEVEL
static constexpr uint32_t LEVEL
Definition GridBuilder.h:622
nanovdb::build::InternalNode::addChild
void addChild(ChildT *&child)
Definition GridBuilder.h:970
nanovdb::build::InternalNode::nodeCount
void nodeCount(std::array< size_t, 3 > &count) const
Definition GridBuilder.h:747
nanovdb::build::InternalNode::mTable
Tile mTable[SIZE]
Definition GridBuilder.h:640
nanovdb::build::InternalNode::origin
const Coord & origin() const
Definition GridBuilder.h:745
nanovdb::build::InternalNode::CoordToOffset
static uint32_t CoordToOffset(const Coord &ijk)
Definition GridBuilder.h:755
nanovdb::build::InternalNode::setValueOnAndCache
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:898
nanovdb::build::InternalNode::DIM
static constexpr uint32_t DIM
Definition GridBuilder.h:619
nanovdb::build::InternalNode::addNode
void addNode(NodeT *&node)
Definition GridBuilder.h:1017
nanovdb::build::InternalNode::nodeCount
uint32_t nodeCount() const
Definition GridBuilder.h:941
nanovdb::build::InternalNode::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:769
nanovdb::build::InternalNode::setValue
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:856
nanovdb::build::InternalNode::mDstOffset
uint64_t mDstOffset
Definition GridBuilder.h:644
nanovdb::build::InternalNode::beginDense
DenseIterator beginDense()
Definition GridBuilder.h:720
nanovdb::build::InternalNode::ChildNodeType
ChildT ChildNodeType
Definition GridBuilder.h:615
nanovdb::build::InternalNode::setAndCache
auto setAndCache(const Coord &ijk, const AccT &acc, ArgsT &&... args)
Definition GridBuilder.h:824
nanovdb::build::InternalNode::beginValue
ValueIterator beginValue()
Definition GridBuilder.h:678
nanovdb::build::InternalNode::beginChild
ChildIterator beginChild()
Definition GridBuilder.h:661
nanovdb::build::InternalNode::cbeginChildAll
DenseIterator cbeginChildAll() const
Definition GridBuilder.h:721
nanovdb::build::InternalNode::OffsetToLocalCoord
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:762
nanovdb::build::InternalNode::signedFloodFill
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:1060
nanovdb::build::InternalNode::get
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:786
nanovdb::build::InternalNode::LeafNodeType
typename ChildT::LeafNodeType LeafNodeType
Definition GridBuilder.h:616
nanovdb::build::InternalNode::TOTAL
static constexpr uint32_t TOTAL
Definition GridBuilder.h:618
nanovdb::build::InternalNode::getFirstValue
ValueType getFirstValue() const
Definition GridBuilder.h:782
nanovdb::build::InternalNode::InternalNode
InternalNode(InternalNode &&)=delete
nanovdb::build::InternalNode::LOG2DIM
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:617
nanovdb::build::InternalNode::ValueType
typename ChildT::ValueType ValueType
Definition GridBuilder.h:613
nanovdb::build::InternalNode::InternalNode
InternalNode(const Coord &origin, const ValueType &value, bool state)
Definition GridBuilder.h:723
nanovdb::build::InternalNode::cbeginValueAll
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:679
nanovdb::build::InternalNode::cbeginValueOn
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:695
nanovdb::build::InternalNode::mValueMask
MaskT mValueMask
Definition GridBuilder.h:638
nanovdb::build::InternalNode::merge
void merge(InternalNode &other)
Definition GridBuilder.h:1035
nanovdb::build::InternalNode::getAndCache
auto getAndCache(const Coord &ijk, const AccT &acc, ArgsT &&... args) const
Definition GridBuilder.h:810
nanovdb::build::InternalNode::mDstNode
NanoNodeT * mDstNode
Definition GridBuilder.h:643
nanovdb::build::InternalNode::SIZE
static constexpr uint32_t SIZE
Definition GridBuilder.h:620
nanovdb::build::InternalNode::set
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:794
nanovdb::build::InternalNode::getValueAndCache
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:871
nanovdb::build::InternalNode::getValue
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:848
nanovdb::build::InternalNode::getChildMask
const MaskT & getChildMask() const
Definition GridBuilder.h:743
nanovdb::build::InternalNode::childMask
const MaskT & childMask() const
Definition GridBuilder.h:744
nanovdb::build::InternalNode::NUM_VALUES
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:623
nanovdb::build::InternalNode::touchLeafAndCache
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:914
nanovdb::build::InternalNode::mOrigin
Coord mOrigin
Definition GridBuilder.h:637
nanovdb::build::InternalNode::operator=
InternalNode & operator=(const InternalNode &)=delete
nanovdb::build::InternalNode::cbeginChildOn
ChildIterator cbeginChildOn() const
Definition GridBuilder.h:662
nanovdb::build::InternalNode::InternalNode
InternalNode(const InternalNode &)=delete
nanovdb::build::InternalNode::isActiveAndCache
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:929
nanovdb::build::LeafNode< ValueMask >::offsetToGlobalCoord
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1401
nanovdb::build::LeafNode< ValueMask >::MaskIterT
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1302
nanovdb::build::LeafNode< ValueMask >::getLastValue
bool getLastValue() const
Definition GridBuilder.h:1409
nanovdb::build::LeafNode< ValueMask >::operator=
LeafNode & operator=(LeafNode &&)=delete
nanovdb::build::LeafNode< ValueMask >::merge
void merge(LeafNode &other)
Definition GridBuilder.h:1450
nanovdb::build::LeafNode< ValueMask >::setValueOnAndCache
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1434
nanovdb::build::LeafNode< ValueMask >::getFirstValue
bool getFirstValue() const
Definition GridBuilder.h:1408
nanovdb::build::LeafNode< ValueMask >::beginValueOn
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1325
nanovdb::build::LeafNode< ValueMask >::setValueAndCache
void setValueAndCache(const Coord &ijk, bool, const AccT &)
Definition GridBuilder.h:1427
nanovdb::build::LeafNode< ValueMask >::NanoLeafT
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition GridBuilder.h:1303
nanovdb::build::LeafNode< ValueMask >::getValue
bool getValue(uint32_t i) const
Definition GridBuilder.h:1410
nanovdb::build::LeafNode< ValueMask >::cbeginValueOff
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1342
nanovdb::build::LeafNode< ValueMask >::operator=
LeafNode & operator=(const LeafNode &)=delete
nanovdb::build::LeafNode< ValueMask >::valueMask
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1380
nanovdb::build::LeafNode< ValueMask >::origin
const Coord & origin() const
Definition GridBuilder.h:1382
nanovdb::build::LeafNode< ValueMask >::CoordToOffset
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1385
nanovdb::build::LeafNode< ValueMask >::LeafNode
LeafNode(const Coord &ijk, const ValueType &, bool state)
Definition GridBuilder.h:1368
nanovdb::build::LeafNode< ValueMask >::mDstNode
NanoLeafT * mDstNode
Definition GridBuilder.h:1308
nanovdb::build::LeafNode< ValueMask >::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1399
nanovdb::build::LeafNode< ValueMask >::getValueAndCache
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1421
nanovdb::build::LeafNode< ValueMask >::mDstOffset
uint64_t mDstOffset
Definition GridBuilder.h:1309
nanovdb::build::LeafNode< ValueMask >::isActiveAndCache
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1441
nanovdb::build::LeafNode< ValueMask >::~LeafNode
~LeafNode()=default
nanovdb::build::LeafNode< ValueMask >::LeafNode
LeafNode(LeafNode &&)=delete
nanovdb::build::LeafNode< ValueMask >::ValueType
bool ValueType
Definition GridBuilder.h:1290
nanovdb::build::LeafNode< ValueMask >::beginValue
ValueIterator beginValue()
Definition GridBuilder.h:1365
nanovdb::build::LeafNode< ValueMask >::OffsetToLocalCoord
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1392
nanovdb::build::LeafNode< ValueMask >::mValueMask
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1306
nanovdb::build::LeafNode< ValueMask >::get
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1414
nanovdb::build::LeafNode< ValueMask >::getValueMask
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1381
nanovdb::build::LeafNode< ValueMask >::LeafNode
LeafNode(const LeafNode &)=delete
nanovdb::build::LeafNode< ValueMask >::cbeginValueAll
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1366
nanovdb::build::LeafNode< ValueMask >::cbeginValueOn
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1326
nanovdb::build::LeafNode< ValueMask >::setValue
void setValue(const Coord &ijk)
Definition GridBuilder.h:1448
nanovdb::build::LeafNode< ValueMask >::setValue
void setValue(uint32_t n, bool)
Definition GridBuilder.h:1447
nanovdb::build::LeafNode< ValueMask >::set
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:1417
nanovdb::build::LeafNode< ValueMask >::beginValueOff
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1341
nanovdb::build::LeafNode< ValueMask >::getValue
bool getValue(const Coord &ijk) const
Definition GridBuilder.h:1411
nanovdb::build::LeafNode< ValueMask >::mOrigin
Coord mOrigin
Definition GridBuilder.h:1305
nanovdb::build::LeafNode< bool >::offsetToGlobalCoord
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1577
nanovdb::build::LeafNode< bool >::MaskIterT
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1474
nanovdb::build::LeafNode< bool >::getLastValue
bool getLastValue() const
Definition GridBuilder.h:1584
nanovdb::build::LeafNode< bool >::operator=
LeafNode & operator=(LeafNode &&)=delete
nanovdb::build::LeafNode< bool >::merge
void merge(LeafNode &other)
Definition GridBuilder.h:1627
nanovdb::build::LeafNode< bool >::setValueOnAndCache
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1613
nanovdb::build::LeafNode< bool >::getFirstValue
bool getFirstValue() const
Definition GridBuilder.h:1583
nanovdb::build::LeafNode< bool >::beginValueOn
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1497
nanovdb::build::LeafNode< bool >::setValue
void setValue(uint32_t n, bool value)
Definition GridBuilder.h:1620
nanovdb::build::LeafNode< bool >::NanoLeafT
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition GridBuilder.h:1475
nanovdb::build::LeafNode< bool >::getValue
bool getValue(uint32_t i) const
Definition GridBuilder.h:1586
nanovdb::build::LeafNode< bool >::cbeginValueOff
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1514
nanovdb::build::LeafNode< bool >::operator=
LeafNode & operator=(const LeafNode &)=delete
nanovdb::build::LeafNode< bool >::valueMask
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1553
nanovdb::build::LeafNode< bool >::origin
const Coord & origin() const
Definition GridBuilder.h:1555
nanovdb::build::LeafNode< bool >::CoordToOffset
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1558
nanovdb::build::LeafNode< bool >::setValue
void setValue(const Coord &ijk, bool value)
Definition GridBuilder.h:1625
nanovdb::build::LeafNode< bool >::mDstNode
NanoLeafT * mDstNode
Definition GridBuilder.h:1480
nanovdb::build::LeafNode< bool >::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1572
nanovdb::build::LeafNode< bool >::getValueAndCache
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1599
nanovdb::build::LeafNode< bool >::mDstOffset
uint64_t mDstOffset
Definition GridBuilder.h:1481
nanovdb::build::LeafNode< bool >::isActiveAndCache
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1593
nanovdb::build::LeafNode< bool >::~LeafNode
~LeafNode()=default
nanovdb::build::LeafNode< bool >::LeafNode
LeafNode(LeafNode &&)=delete
nanovdb::build::LeafNode< bool >::ValueType
bool ValueType
Definition GridBuilder.h:1462
nanovdb::build::LeafNode< bool >::beginValue
ValueIterator beginValue()
Definition GridBuilder.h:1537
nanovdb::build::LeafNode< bool >::LeafNode
LeafNode(const Coord &ijk, bool value, bool state)
Definition GridBuilder.h:1540
nanovdb::build::LeafNode< bool >::OffsetToLocalCoord
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1565
nanovdb::build::LeafNode< bool >::mValueMask
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1478
nanovdb::build::LeafNode< bool >::getValueMask
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1554
nanovdb::build::LeafNode< bool >::LeafNode
LeafNode(const LeafNode &)=delete
nanovdb::build::LeafNode< bool >::cbeginValueAll
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1538
nanovdb::build::LeafNode< bool >::cbeginValueOn
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1498
nanovdb::build::LeafNode< bool >::beginValueOff
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1513
nanovdb::build::LeafNode< bool >::getValue
bool getValue(const Coord &ijk) const
Definition GridBuilder.h:1587
nanovdb::build::LeafNode< bool >::setValueAndCache
void setValueAndCache(const Coord &ijk, bool value, const AccT &)
Definition GridBuilder.h:1605
nanovdb::build::LeafNode< bool >::mOrigin
Coord mOrigin
Definition GridBuilder.h:1477
nanovdb::build::LeafNode
Definition GridBuilder.h:1094
nanovdb::build::LeafNode::offsetToGlobalCoord
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1215
nanovdb::build::LeafNode::mValues
ValueType mValues[SIZE]
Definition GridBuilder.h:1112
nanovdb::build::LeafNode::getLastValue
ValueType getLastValue() const
Definition GridBuilder.h:1223
nanovdb::build::LeafNode::MaskIterT
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1107
nanovdb::build::LeafNode::operator=
LeafNode & operator=(LeafNode &&)=delete
nanovdb::build::LeafNode::merge
void merge(LeafNode &other)
Definition GridBuilder.h:1269
nanovdb::build::LeafNode::setValueOnAndCache
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1249
nanovdb::build::LeafNode::beginValueOn
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1131
nanovdb::build::LeafNode::MASK
static constexpr uint32_t MASK
Definition GridBuilder.h:1102
nanovdb::build::LeafNode::LEVEL
static constexpr uint32_t LEVEL
Definition GridBuilder.h:1103
nanovdb::build::LeafNode::getValue
const ValueType & getValue(const Coord &ijk) const
Definition GridBuilder.h:1225
nanovdb::build::LeafNode::cbeginValueOff
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1148
nanovdb::build::LeafNode::operator=
LeafNode & operator=(const LeafNode &)=delete
nanovdb::build::LeafNode::valueMask
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1192
nanovdb::build::LeafNode::origin
const Coord & origin() const
Definition GridBuilder.h:1193
nanovdb::build::LeafNode::CoordToOffset
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1196
nanovdb::build::LeafNode::DIM
static constexpr uint32_t DIM
Definition GridBuilder.h:1100
nanovdb::build::LeafNode::mDstNode
NanoLeafT * mDstNode
Definition GridBuilder.h:1114
nanovdb::build::LeafNode::localToGlobalCoord
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1210
nanovdb::build::LeafNode::setValue
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1267
nanovdb::build::LeafNode::getValue
const ValueType & getValue(uint32_t i) const
Definition GridBuilder.h:1224
nanovdb::build::LeafNode::mDstOffset
uint64_t mDstOffset
Definition GridBuilder.h:1115
nanovdb::build::LeafNode::getValueAndCache
const ValueType & getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1235
nanovdb::build::LeafNode::isActiveAndCache
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1256
nanovdb::build::LeafNode::~LeafNode
~LeafNode()=default
nanovdb::build::LeafNode::LeafNode
LeafNode(LeafNode &&)=delete
nanovdb::build::LeafNode::beginValue
ValueIterator beginValue()
Definition GridBuilder.h:1171
nanovdb::build::LeafNode::OffsetToLocalCoord
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1203
nanovdb::build::LeafNode::signedFloodFill
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:1640
nanovdb::build::LeafNode::mValueMask
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1111
nanovdb::build::LeafNode::get
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1228
nanovdb::build::LeafNode::TOTAL
static constexpr uint32_t TOTAL
Definition GridBuilder.h:1099
nanovdb::build::LeafNode::getFirstValue
ValueType getFirstValue() const
Definition GridBuilder.h:1222
nanovdb::build::LeafNode::LOG2DIM
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:1098
nanovdb::build::LeafNode::getValueMask
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1191
nanovdb::build::LeafNode::LeafNode
LeafNode(const LeafNode &)=delete
nanovdb::build::LeafNode::NanoLeafT
typename NanoNode< BuildT, 0 >::Type NanoLeafT
Definition GridBuilder.h:1108
nanovdb::build::LeafNode::ValueType
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1096
nanovdb::build::LeafNode::cbeginValueAll
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1172
nanovdb::build::LeafNode::cbeginValueOn
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1132
nanovdb::build::LeafNode::setValueAndCache
void setValueAndCache(const Coord &ijk, const ValueType &value, const AccT &)
Definition GridBuilder.h:1241
nanovdb::build::LeafNode::SIZE
static constexpr uint32_t SIZE
Definition GridBuilder.h:1101
nanovdb::build::LeafNode::set
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:1231
nanovdb::build::LeafNode::beginValueOff
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1147
nanovdb::build::LeafNode::LeafNode
LeafNode(const Coord &ijk, const ValueType &value, bool state)
Definition GridBuilder.h:1174
nanovdb::build::LeafNode::setValue
void setValue(uint32_t n, const ValueType &value)
Definition GridBuilder.h:1262
nanovdb::build::LeafNode::NUM_VALUES
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:1104
nanovdb::build::LeafNode::mOrigin
Coord mOrigin
Definition GridBuilder.h:1110
nanovdb::build::LeafNode::BuildType
BuildT BuildType
Definition GridBuilder.h:1095
nanovdb::build::ProbeValue
Implements Tree::probeLeaf(Coord)
Definition GridBuilder.h:2286
nanovdb::build::ProbeValue::ValueT
typename BuildLeaf< T >::ValueType ValueT
Definition GridBuilder.h:2287
nanovdb::build::ProbeValue::get
static bool get(const BuildTile< T > &tile, ValueT &v)
Definition GridBuilder.h:2292
nanovdb::build::ProbeValue::get
static bool get(const BuildLower< T > &node, uint32_t n, ValueT &v)
Definition GridBuilder.h:2300
nanovdb::build::ProbeValue::get
static bool get(const BuildRoot< T > &root, ValueT &v)
Definition GridBuilder.h:2288
nanovdb::build::ProbeValue::get
static bool get(const BuildUpper< T > &node, uint32_t n, ValueT &v)
Definition GridBuilder.h:2296
nanovdb::build::ProbeValue::get
static bool get(const BuildLeaf< T > &leaf, uint32_t n, ValueT &v)
Definition GridBuilder.h:2304
nanovdb::build::RootNode::Tile
Definition GridBuilder.h:55
nanovdb::build::RootNode::Tile::isActive
bool isActive() const
Definition GridBuilder.h:60
nanovdb::build::RootNode::Tile::Tile
Tile(const ValueType &v, bool s)
Definition GridBuilder.h:57
nanovdb::build::RootNode::Tile::Tile
Tile(ChildT *c=nullptr)
Definition GridBuilder.h:56
nanovdb::build::RootNode::Tile::child
ChildT * child
Definition GridBuilder.h:61
nanovdb::build::RootNode::Tile::isValue
bool isValue() const
Definition GridBuilder.h:59
nanovdb::build::RootNode::Tile::state
bool state
Definition GridBuilder.h:63
nanovdb::build::RootNode::Tile::isChild
bool isChild() const
Definition GridBuilder.h:58
nanovdb::build::RootNode::Tile::value
ValueType value
Definition GridBuilder.h:62
nanovdb::build::RootNode
Definition GridBuilder.h:49
nanovdb::build::RootNode::tileCount
uint32_t tileCount() const
Definition GridBuilder.h:234
nanovdb::build::RootNode::addTile
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
nanovdb::build::RootNode::RootNode
RootNode(RootNode &&)=default
nanovdb::build::RootNode::setValueAndCache
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition GridBuilder.h:387
nanovdb::build::RootNode::getNodes
void getNodes(std::vector< NodeT * > &array)
Definition GridBuilder.h:462
nanovdb::build::RootNode::getValue
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:340
nanovdb::build::RootNode::beginValueOn
ValueOnIterator beginValueOn()
Definition GridBuilder.h:180
nanovdb::build::RootNode::BuildType
typename ChildT::BuildType BuildType
Definition GridBuilder.h:51
nanovdb::build::RootNode::probeTile
Tile * probeTile(const Coord &ijk)
Definition GridBuilder.h:69
nanovdb::build::RootNode::LEVEL
static constexpr uint32_t LEVEL
Definition GridBuilder.h:54
nanovdb::build::RootNode::addChild
void addChild(ChildT *&child)
Definition GridBuilder.h:477
nanovdb::build::RootNode::nodeCount
void nodeCount(std::array< size_t, 3 > &count) const
Definition GridBuilder.h:238
nanovdb::build::RootNode::getTableSize
uint32_t getTableSize() const
Definition GridBuilder.h:235
nanovdb::build::RootNode::merge
void merge(RootNode &other)
Definition GridBuilder.h:553
nanovdb::build::RootNode::operator=
RootNode & operator=(const RootNode &)=delete
nanovdb::build::RootNode::operator=
RootNode & operator=(RootNode &&)=default
nanovdb::build::RootNode::setValueOnAndCache
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:406
nanovdb::build::RootNode::empty
bool empty() const
Definition GridBuilder.h:246
nanovdb::build::RootNode::addNode
void addNode(NodeT *&node)
Definition GridBuilder.h:532
nanovdb::build::RootNode::nodeCount
uint32_t nodeCount() const
Definition GridBuilder.h:445
nanovdb::build::RootNode::setValue
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:342
nanovdb::build::RootNode::RootNode
RootNode(const RootNode &)=delete
nanovdb::build::RootNode::ChildNodeType
ChildT ChildNodeType
Definition GridBuilder.h:52
nanovdb::build::RootNode::cbeginChild
ChildIterator cbeginChild() const
Definition GridBuilder.h:111
nanovdb::build::RootNode::beginValue
ValueIterator beginValue()
Definition GridBuilder.h:146
nanovdb::build::RootNode::RootNode
RootNode(const ValueType &background)
Definition GridBuilder.h:226
nanovdb::build::RootNode::cbeginChildAll
TileIterator cbeginChildAll() const
Definition GridBuilder.h:222
nanovdb::build::RootNode::signedFloodFill
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:579
nanovdb::build::RootNode::LeafNodeType
typename ChildT::LeafNodeType LeafNodeType
Definition GridBuilder.h:53
nanovdb::build::RootNode::mBackground
ValueType mBackground
Definition GridBuilder.h:67
nanovdb::build::RootNode::~RootNode
~RootNode()
Definition GridBuilder.h:232
nanovdb::build::RootNode::MapT
std::map< Coord, Tile > MapT
Definition GridBuilder.h:65
nanovdb::build::RootNode::ValueType
typename ChildT::ValueType ValueType
Definition GridBuilder.h:50
nanovdb::build::RootNode::clear
void clear()
Definition GridBuilder.h:248
nanovdb::build::RootNode::beginTile
TileIterator beginTile()
Definition GridBuilder.h:221
nanovdb::build::RootNode::cbeginValueAll
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:147
nanovdb::build::RootNode::cbeginValueOn
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:181
nanovdb::build::RootNode::background
const ValueType & background() const
Definition GridBuilder.h:236
nanovdb::build::RootNode::getValueAndCache
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:374
nanovdb::build::RootNode::getValue
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:324
nanovdb::build::RootNode::probeTile
const Tile * probeTile(const Coord &ijk) const
Definition GridBuilder.h:74
nanovdb::build::RootNode::mTable
MapT mTable
Definition GridBuilder.h:66
nanovdb::build::RootNode::CoordToKey
static Coord CoordToKey(const Coord &ijk)
Definition GridBuilder.h:254
nanovdb::build::RootNode::touchLeafAndCache
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:425
nanovdb::build::RootNode::cbeginChildOn
ChildIterator cbeginChildOn() const
Definition GridBuilder.h:112
nanovdb::build::RootNode::isActiveAndCache
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:361
nanovdb::build::SetValue
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:2272
nanovdb::build::SetValue::set
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2273
nanovdb::build::SetValue::set
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n, const typename BuildLeaf< T >::ValueType &v)
Definition GridBuilder.h:2277
nanovdb::build::TouchLeaf
Definition GridBuilder.h:2242
nanovdb::build::TouchLeaf::set
static BuildLeaf< T > & set(BuildLeaf< T > &leaf, uint32_t)
Definition GridBuilder.h:2243
nanovdb::build::Tree::WriteAccessor
Definition GridBuilder.h:1846
nanovdb::build::Tree::WriteAccessor::Node2
typename AccT::Node2 Node2
Definition GridBuilder.h:1851
nanovdb::build::Tree::WriteAccessor::~WriteAccessor
~WriteAccessor()
Definition GridBuilder.h:1863
nanovdb::build::Tree::WriteAccessor::WriteAccessor
WriteAccessor(const WriteAccessor &)=delete
nanovdb::build::Tree::WriteAccessor::setValue
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1871
nanovdb::build::Tree::WriteAccessor::mMutex
std::mutex & mMutex
Definition GridBuilder.h:1875
nanovdb::build::Tree::WriteAccessor::WriteAccessor
WriteAccessor(WriteAccessor &&)=default
nanovdb::build::Tree::WriteAccessor::mParent
RootNodeType & mParent
Definition GridBuilder.h:1873
nanovdb::build::Tree::WriteAccessor::Node1
typename AccT::Node1 Node1
Definition GridBuilder.h:1850
nanovdb::build::Tree::WriteAccessor::WriteAccessor
WriteAccessor(RootNodeType &parent, std::mutex &mx)
Definition GridBuilder.h:1854
nanovdb::build::Tree::WriteAccessor::setValueOn
void setValueOn(const Coord &ijk)
Definition GridBuilder.h:1870
nanovdb::build::Tree::WriteAccessor::mAcc
AccT mAcc
Definition GridBuilder.h:1874
nanovdb::build::Tree::WriteAccessor::LeafT
typename AccT::LeafT LeafT
Definition GridBuilder.h:1849
nanovdb::build::Tree::WriteAccessor::merge
void merge()
Definition GridBuilder.h:1864
nanovdb::build::Tree::WriteAccessor::RootNodeType
typename AccT::RootNodeType RootNodeType
Definition GridBuilder.h:1852
nanovdb::build::Tree::WriteAccessor::ValueType
typename AccT::ValueType ValueType
Definition GridBuilder.h:1848
nanovdb::build::Tree
Definition GridBuilder.h:1810
nanovdb::build::Tree::getAccessor
ValueAccessor< BuildT > getAccessor()
regular accessor for thread-safe reading and non-thread-safe writing
Definition GridBuilder.h:1837
nanovdb::build::Tree::root
RootNodeType & root()
Definition GridBuilder.h:1826
nanovdb::build::Tree::nodeCount
std::array< size_t, 3 > nodeCount() const
Definition GridBuilder.h:1830
nanovdb::build::Tree::getValue
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:1828
nanovdb::build::Tree::tree
Tree & tree()
Definition GridBuilder.h:1825
nanovdb::build::Tree::mRoot
RootNodeType mRoot
Definition GridBuilder.h:1819
nanovdb::build::Tree::setValue
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1829
nanovdb::build::Tree::mMutex
std::mutex mMutex
Definition GridBuilder.h:1820
nanovdb::build::Tree::Tree
Tree(Tree &&)=delete
nanovdb::build::Tree::Tree
Tree(const Tree &)=delete
nanovdb::build::Tree::ValueType
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1811
nanovdb::build::Tree::getWriteAccessor
WriteAccessor getWriteAccessor()
special accessor for thread-safe writing only
Definition GridBuilder.h:1839
nanovdb::build::Tree::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition GridBuilder.h:1816
nanovdb::build::Tree::getValue
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:1827
nanovdb::build::Tree::Tree
Tree(const ValueType &background)
Definition GridBuilder.h:1822
nanovdb::build::ValueAccessor
Definition GridBuilder.h:1672
nanovdb::build::ValueAccessor::mRoot
RootNodeType & mRoot
Definition GridBuilder.h:1801
nanovdb::build::ValueAccessor::mNode
void * mNode[3]
Definition GridBuilder.h:1803
nanovdb::build::ValueAccessor::getValue
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:1688
nanovdb::build::ValueAccessor::ValueAccessor
ValueAccessor(const ValueAccessor &)=delete
nanovdb::build::ValueAccessor::mKeys
Coord mKeys[3]
Definition GridBuilder.h:1802
nanovdb::build::ValueAccessor::touchLeaf
void touchLeaf(const Coord &ijk) const
Definition GridBuilder.h:1769
nanovdb::build::ValueAccessor::isActive
bool isActive(const Coord &ijk) const
Definition GridBuilder.h:1781
nanovdb::build::ValueAccessor::insert
void insert(const Coord &ijk, NodeT *node) const
Definition GridBuilder.h:1796
nanovdb::build::ValueAccessor::isValueOn
bool isValueOn(const Coord &ijk) const
Definition GridBuilder.h:1794
nanovdb::build::ValueAccessor::setValue
LeafT * setValue(const Coord &ijk, const ValueType &value)
Sets value in a leaf node and returns it.
Definition GridBuilder.h:1743
nanovdb::build::ValueAccessor::get
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1698
nanovdb::build::ValueAccessor::ValueAccessor
ValueAccessor(ValueAccessor &&)=default
nanovdb::build::ValueAccessor::setValueOn
void setValueOn(const Coord &ijk)
Definition GridBuilder.h:1757
nanovdb::build::ValueAccessor::ValueType
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1673
nanovdb::build::ValueAccessor::LeafT
build::LeafNode< BuildT > LeafT
Definition GridBuilder.h:1674
nanovdb::build::ValueAccessor::set
auto set(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1711
nanovdb::build::ValueAccessor::ValueAccessor
ValueAccessor(RootNodeType &root)
Definition GridBuilder.h:1680
nanovdb::build::ValueAccessor::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition GridBuilder.h:1678
nanovdb::build::ValueAccessor::getValue
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:1730
nanovdb::build::ValueAccessor::isCached
bool isCached(const Coord &ijk) const
Definition GridBuilder.h:1690
nanovdb::enable_if
C++11 implementation of std::enable_if.
Definition NanoVDB.h:493
nanovdb::is_same
C++11 implementation of std::is_same.
Definition NanoVDB.h:442