OpenVDB 14.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: Apache-2.0
3
4/*!
5 \file nanovdb/tools/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_TOOLS_BUILD_GRIDBUILDER_H_HAS_BEEN_INCLUDED
16#define NANOVDB_TOOLS_BUILD_GRIDBUILDER_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 <nanovdb/util/Range.h>
32
33namespace nanovdb {
34
35namespace tools::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>
49{
50 using ValueType = typename ChildT::ValueType;
51 using BuildType = typename ChildT::BuildType;
52 using ChildNodeType = ChildT;
53 using LeafNodeType = typename ChildT::LeafNodeType;
54 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
55 struct Tile {
56 Tile(ChildT* c = nullptr) : child(c) {}
57 Tile(const ValueType& v, bool s) : child(nullptr), value(v), state(s) {}
58 bool isChild() const { return child!=nullptr; }
59 bool isValue() const { return child==nullptr; }
60 bool isActive() const { return child==nullptr && state; }
61 ChildT* child;
63 bool state;
64 };
65 using MapT = std::map<Coord, Tile>;
68
69 Tile* probeTile(const Coord &ijk) {
70 auto iter = mTable.find(CoordToKey(ijk));
71 return iter == mTable.end() ? nullptr : &(iter->second);
72 }
73
74 const Tile* probeTile(const Coord &ijk) const {
75 auto iter = mTable.find(CoordToKey(ijk));
76 return iter == mTable.end() ? nullptr : &(iter->second);
77 }
78
80 {
81 const RootNode *mParent;
82 typename MapT::const_iterator mIter;
83 public:
84 ChildIterator() : mParent(nullptr), mIter() {}
85 ChildIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
86 while (mIter!=parent->mTable.end() && mIter->second.child==nullptr) ++mIter;
87 }
89 ChildT& operator*() const {NANOVDB_ASSERT(*this); return *mIter->second.child;}
90 ChildT* operator->() const {NANOVDB_ASSERT(*this); return mIter->second.child;}
91 Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
92 Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
93 operator bool() const {return mParent && mIter!=mParent->mTable.end();}
95 NANOVDB_ASSERT(mParent);
96 ++mIter;
97 while (mIter!=mParent->mTable.end() && mIter->second.child==nullptr) ++mIter;
98 return *this;
99 }
101 auto tmp = *this;
102 ++(*this);
103 return tmp;
104 }
105 uint32_t pos() const {
106 NANOVDB_ASSERT(mParent);
107 return uint32_t(std::distance(mParent->mTable.begin(), mIter));
108 }
109 }; // Member class ChildIterator
110
111 ChildIterator cbeginChild() const {return ChildIterator(this);}
112 ChildIterator cbeginChildOn() const {return ChildIterator(this);}// match openvdb
113
115 {
116 const RootNode *mParent;
117 typename MapT::const_iterator mIter;
118 public:
119 ValueIterator() : mParent(nullptr), mIter() {}
120 ValueIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
121 while (mIter!=parent->mTable.end() && mIter->second.child!=nullptr) ++mIter;
122 }
124 ValueType operator*() const {NANOVDB_ASSERT(*this); return mIter->second.value;}
125 bool isActive() const {NANOVDB_ASSERT(*this); return mIter->second.state;}
126 Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
127 Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
128 operator bool() const {return mParent && mIter!=mParent->mTable.end();}
130 NANOVDB_ASSERT(mParent);
131 ++mIter;
132 while (mIter!=mParent->mTable.end() && mIter->second.child!=nullptr) ++mIter;
133 return *this;;
134 }
136 auto tmp = *this;
137 ++(*this);
138 return tmp;
139 }
140 uint32_t pos() const {
141 NANOVDB_ASSERT(mParent);
142 return uint32_t(std::distance(mParent->mTable.begin(), mIter));
143 }
144 }; // Member class ValueIterator
145
146 ValueIterator beginValue() {return ValueIterator(this);}
147 ValueIterator cbeginValueAll() const {return ValueIterator(this);}
148
150 {
151 const RootNode *mParent;
152 typename MapT::const_iterator mIter;
153 public:
154 ValueOnIterator() : mParent(nullptr), mIter() {}
155 ValueOnIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
156 while (mIter!=parent->mTable.end() && (mIter->second.child!=nullptr || !mIter->second.state)) ++mIter;
157 }
159 ValueType operator*() const {NANOVDB_ASSERT(*this); return mIter->second.value;}
160 Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
161 Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
162 operator bool() const {return mParent && mIter!=mParent->mTable.end();}
164 NANOVDB_ASSERT(mParent);
165 ++mIter;
166 while (mIter!=mParent->mTable.end() && (mIter->second.child!=nullptr || !mIter->second.state)) ++mIter;
167 return *this;;
168 }
170 auto tmp = *this;
171 ++(*this);
172 return tmp;
173 }
174 uint32_t pos() const {
175 NANOVDB_ASSERT(mParent);
176 return uint32_t(std::distance(mParent->mTable.begin(), mIter));
177 }
178 }; // Member class ValueOnIterator
179
180 ValueOnIterator beginValueOn() {return ValueOnIterator(this);}
181 ValueOnIterator cbeginValueOn() const {return ValueOnIterator(this);}
182
184 {
185 const RootNode *mParent;
186 typename MapT::const_iterator mIter;
187 public:
188 TileIterator() : mParent(nullptr), mIter() {}
189 TileIterator(const RootNode *parent) : mParent(parent), mIter(parent->mTable.begin()) {
190 NANOVDB_ASSERT(mParent);
191 }
193 const Tile& operator*() const {NANOVDB_ASSERT(*this); return mIter->second;}
194 const Tile* operator->() const {NANOVDB_ASSERT(*this); return &(mIter->second);}
195 Coord getOrigin() const { NANOVDB_ASSERT(*this); return mIter->first;}
196 Coord getCoord() const { NANOVDB_ASSERT(*this); return mIter->first;}
197 operator bool() const {return mParent && mIter!=mParent->mTable.end();}
198 const ChildT* probeChild(ValueType &value) {
199 NANOVDB_ASSERT(*this);
200 const ChildT *child = mIter->second.child;
201 if (child==nullptr) value = mIter->second.value;
202 return child;
203 }
204 bool isValueOn() const {return mIter->second.child==nullptr && mIter->second.state;}
206 NANOVDB_ASSERT(mParent);
207 ++mIter;
208 return *this;
209 }
211 auto tmp = *this;
212 ++(*this);
213 return tmp;
214 }
215 uint32_t pos() const {
216 NANOVDB_ASSERT(mParent);
217 return uint32_t(std::distance(mParent->mTable.begin(), mIter));
218 }
219 }; // Member class TileIterator
220
221 TileIterator beginTile() {return TileIterator(this);}
222 TileIterator cbeginChildAll() const {return TileIterator(this);}
223
224 //class DenseIterator : public TileIterator
225
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(util::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(util::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(util::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(util::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(util::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>
570 signedFloodFill(T outside);
571
572}; // tools::build::RootNode
573
574//================================================================================================
575
576template<typename ChildT>
577template<typename T>
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} // tools::build::RootNode::signedFloodFill
607
608// ----------------------------> InternalNode <--------------------------------------
609
610template<typename ChildT>
612{
613 using ValueType = typename ChildT::ValueType;
614 using BuildType = typename ChildT::BuildType;
615 using ChildNodeType = ChildT;
616 using LeafNodeType = typename ChildT::LeafNodeType;
617 static constexpr uint32_t LOG2DIM = ChildT::LOG2DIM + 1;
618 static constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL; //dimension in index space
619 static constexpr uint32_t DIM = 1u << TOTAL;
620 static constexpr uint32_t SIZE = 1u << (3 * LOG2DIM); //number of tile values (or child pointers)
621 static constexpr uint32_t MASK = DIM - 1;
622 static constexpr uint32_t LEVEL = 1 + ChildT::LEVEL; // level 0 = leaf
623 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
625 template<bool On>
626 using MaskIterT = typename MaskT::template Iterator<On>;
628
629 struct Tile {
630 Tile(ChildT* c = nullptr) : child(c) {}
631 Tile(const ValueType& v) : value(v) {}
632 union{
633 ChildT* child;
635 };
636 };
641
642 union {
644 uint64_t mDstOffset;
645 };
646
647 /// @brief Visits child nodes of this node only
648 class ChildIterator : public MaskIterT<true>
649 {
650 using BaseT = MaskIterT<true>;
651 const InternalNode *mParent;
652 public:
653 ChildIterator() : BaseT(), mParent(nullptr) {}
654 ChildIterator(const InternalNode* parent) : BaseT(parent->mChildMask.beginOn()), mParent(parent) {}
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) {}
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) {}
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
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) {}
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
736 {
737 for (auto iter = mChildMask.beginOn(); iter; ++iter) {
738 delete mTable[*iter].child;
739 }
740 }
741 const MaskT& getValueMask() const {return mValueMask;}
742 const MaskT& valueMask() const {return mValueMask;}
743 const MaskT& getChildMask() const {return mChildMask;}
744 const MaskT& childMask() const {return mChildMask;}
745 const Coord& origin() const {return mOrigin;}
746
747 void nodeCount(std::array<size_t,3> &count) const
748 {
749 count[ChildT::LEVEL] += mChildMask.countOn();
750 if constexpr(ChildT::LEVEL>0) {
751 for (auto it = const_cast<InternalNode*>(this)->beginChild(); it; ++it) it->nodeCount(count);
752 }
753 }
754
755 static uint32_t CoordToOffset(const Coord& ijk)
756 {
757 return (((ijk[0] & int32_t(MASK)) >> ChildT::TOTAL) << (2 * LOG2DIM)) +
758 (((ijk[1] & int32_t(MASK)) >> ChildT::TOTAL) << (LOG2DIM)) +
759 ((ijk[2] & int32_t(MASK)) >> ChildT::TOTAL);
760 }
761
762 static Coord OffsetToLocalCoord(uint32_t n)
763 {
764 NANOVDB_ASSERT(n < SIZE);
765 const uint32_t m = n & ((1 << 2 * LOG2DIM) - 1);
766 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & ((1 << LOG2DIM) - 1));
767 }
768
769 void localToGlobalCoord(Coord& ijk) const
770 {
771 ijk <<= ChildT::TOTAL;
772 ijk += mOrigin;
773 }
774
775 Coord offsetToGlobalCoord(uint32_t n) const
776 {
778 this->localToGlobalCoord(ijk);
779 return ijk;
780 }
781
782 ValueType getFirstValue() const { return mChildMask.isOn(0) ? mTable[0].child->getFirstValue() : mTable[0].value; }
783 ValueType getLastValue() const { return mChildMask.isOn(SIZE - 1) ? mTable[SIZE - 1].child->getLastValue() : mTable[SIZE - 1].value; }
784
785 template<typename OpT, typename... ArgsT>
786 auto get(const Coord& ijk, ArgsT&&... args) const
787 {
788 const uint32_t n = CoordToOffset(ijk);
789 if (mChildMask.isOn(n)) return mTable[n].child->template get<OpT>(ijk, args...);
790 return OpT::get(*this, n, args...);
791 }
792
793 template<typename OpT, typename... ArgsT>
794 auto set(const Coord& ijk, ArgsT&&... args)
795 {
796 const uint32_t n = CoordToOffset(ijk);
797 ChildT* child = nullptr;
798 if (mChildMask.isOn(n)) {
799 child = mTable[n].child;
800 } else {
801 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
802 mTable[n].child = child;
803 mChildMask.setOn(n);
804 }
805 NANOVDB_ASSERT(child);
806 return child->template set<OpT>(ijk, args...);
807 }
808
809 template<typename OpT, typename AccT, typename... ArgsT>
810 auto getAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args) const
811 {
812 const uint32_t n = CoordToOffset(ijk);
813 if (mChildMask.isOff(n)) return OpT::get(*this, n, args...);
814 ChildT* child = mTable[n].child;
815 acc.insert(ijk, child);
816 if constexpr(ChildT::LEVEL == 0) {
817 return child->template get<OpT>(ijk, args...);
818 } else {
819 return child->template getAndCache<OpT>(ijk, acc, args...);
820 }
821 }
822
823 template<typename OpT, typename AccT, typename... ArgsT>
824 auto setAndCache(const Coord& ijk, const AccT& acc, ArgsT&&... args)
825 {
826 const uint32_t n = CoordToOffset(ijk);
827 ChildT* child = nullptr;
828 if (mChildMask.isOn(n)) {
829 child = mTable[n].child;
830 } else {
831 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
832 mTable[n].child = child;
833 mChildMask.setOn(n);
834 }
835 NANOVDB_ASSERT(child);
836 acc.insert(ijk, child);
837 if constexpr(ChildT::LEVEL == 0) {
838 return child->template set<OpT>(ijk, args...);
839 } else {
840 return child->template setAndCache<OpT>(ijk, acc, args...);
841 }
842 }
843
844#ifdef NANOVDB_NEW_ACCESSOR_METHODS
845 ValueType getValue(const Coord& ijk) const {return this->template get<GetValue<BuildType>>(ijk);}
846 LeafNodeType& setValue(const Coord& ijk, const ValueType& value){return this->template set<SetValue<BuildType>>(ijk, value);}
847#else
848 ValueType getValue(const Coord& ijk) const
849 {
850 const uint32_t n = CoordToOffset(ijk);
851 if (mChildMask.isOn(n)) {
852 return mTable[n].child->getValue(ijk);
853 }
854 return mTable[n].value;
855 }
856 void setValue(const Coord& ijk, const ValueType& value)
857 {
858 const uint32_t n = CoordToOffset(ijk);
859 ChildT* child = nullptr;
860 if (mChildMask.isOn(n)) {
861 child = mTable[n].child;
862 } else {
863 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
864 mTable[n].child = child;
865 mChildMask.setOn(n);
866 }
867 child->setValue(ijk, value);
868 }
869
870 template<typename AccT>
871 ValueType getValueAndCache(const Coord& ijk, AccT& acc) const
872 {
873 const uint32_t n = CoordToOffset(ijk);
874 if (mChildMask.isOn(n)) {
875 acc.insert(ijk, const_cast<ChildT*>(mTable[n].child));
876 return mTable[n].child->getValueAndCache(ijk, acc);
877 }
878 return mTable[n].value;
879 }
880
881 template<typename AccT>
882 void setValueAndCache(const Coord& ijk, const ValueType& value, AccT& acc)
883 {
884 const uint32_t n = CoordToOffset(ijk);
885 ChildT* child = nullptr;
886 if (mChildMask.isOn(n)) {
887 child = mTable[n].child;
888 } else {
889 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
890 mTable[n].child = child;
891 mChildMask.setOn(n);
892 }
893 acc.insert(ijk, child);
894 child->setValueAndCache(ijk, value, acc);
895 }
896
897 template<typename AccT>
898 void setValueOnAndCache(const Coord& ijk, AccT& acc)
899 {
900 const uint32_t n = CoordToOffset(ijk);
901 ChildT* child = nullptr;
902 if (mChildMask.isOn(n)) {
903 child = mTable[n].child;
904 } else {
905 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
906 mTable[n].child = child;
907 mChildMask.setOn(n);
908 }
909 acc.insert(ijk, child);
910 child->setValueOnAndCache(ijk, acc);
911 }
912
913 template<typename AccT>
914 void touchLeafAndCache(const Coord &ijk, AccT& acc)
915 {
916 const uint32_t n = CoordToOffset(ijk);
917 ChildT* child = nullptr;
918 if (mChildMask.isOn(n)) {
919 child = mTable[n].child;
920 } else {
921 child = new ChildT(ijk, mTable[n].value, mValueMask.isOn(n));
922 mTable[n].child = child;
923 mChildMask.setOn(n);
924 }
925 acc.insert(ijk, child);
926 if constexpr(LEVEL>1) child->touchLeafAndCache(ijk, acc);
927 }
928 template<typename AccT>
929 bool isActiveAndCache(const Coord& ijk, AccT& acc) const
930 {
931 const uint32_t n = CoordToOffset(ijk);
932 if (mChildMask.isOn(n)) {
933 acc.insert(ijk, const_cast<ChildT*>(mTable[n].child));
934 return mTable[n].child->isActiveAndCache(ijk, acc);
935 }
936 return mValueMask.isOn(n);
937 }
938#endif
939
940 template<typename NodeT>
941 uint32_t nodeCount() const
942 {
943 static_assert(util::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(util::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(util::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(util::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(util::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>
1052
1053}; // tools::build::InternalNode
1054
1055//================================================================================================
1056
1057template<typename ChildT>
1058template<typename T>
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} // tools::build::InternalNode::signedFloodFill
1089
1090// ----------------------------> LeafNode <--------------------------------------
1091
1092template<typename BuildT>
1094{
1095 using BuildType = BuildT;
1098 static constexpr uint32_t LOG2DIM = 3;
1099 static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1100 static constexpr uint32_t DIM = 1u << TOTAL;
1101 static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1102 static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1103 static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1104 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1106 template<bool ON>
1107 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1109
1113 union {
1115 uint64_t mDstOffset;
1116 };
1117
1118 /// @brief Visits all active values in a leaf node
1119 class ValueOnIterator : public MaskIterT<true>
1120 {
1121 using BaseT = MaskIterT<true>;
1122 const LeafNode *mParent;
1123 public:
1124 ValueOnIterator() : BaseT(), mParent(nullptr) {}
1125 ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
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) {}
1143 ValueType operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues[BaseT::pos()];}
1144 Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1145 }; // Member class ValueOffIterator
1146
1147 ValueOffIterator beginValueOff() {return ValueOffIterator(this);}
1148 ValueOffIterator cbeginValueOff() const {return ValueOffIterator(this);}
1149
1150 /// @brief Visits all values in a leaf node, i.e. both active and inactive values
1152 {
1153 const LeafNode *mParent;
1154 uint32_t mPos;
1155 public:
1156 ValueIterator() : mParent(nullptr), mPos(1u << 3 * LOG2DIM) {}
1157 ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
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->mValueMask.isOn(mPos);}
1162 operator bool() const {return mPos < SIZE;}
1163 ValueIterator& operator++() {++mPos; return *this;}
1165 auto tmp = *this;
1166 ++(*this);
1167 return tmp;
1168 }
1169 }; // Member class ValueIterator
1170
1171 ValueIterator beginValue() {return ValueIterator(this);}
1172 ValueIterator cbeginValueAll() const {return ValueIterator(this);}
1173
1174 LeafNode(const Coord& ijk, const ValueType& value, bool state)
1175 : mOrigin(ijk & ~MASK)
1176 , mValueMask(state) //invalid
1177 , mDstOffset(0)
1178 {
1179 ValueType* target = mValues;
1180 uint32_t n = SIZE;
1181 while (n--) {
1182 *target++ = value;
1183 }
1184 }
1185 LeafNode(const LeafNode&) = delete; // disallow copy-construction
1186 LeafNode(LeafNode&&) = delete; // disallow move construction
1187 LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1188 LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1189 ~LeafNode() = default;
1190
1191 const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1192 const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1193 const Coord& origin() const {return mOrigin;}
1194
1195 /// @brief Return the linear offset corresponding to the given coordinate
1196 static uint32_t CoordToOffset(const Coord& ijk)
1197 {
1198 return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1199 ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1200 (ijk[2] & int32_t(MASK));
1201 }
1202
1203 static Coord OffsetToLocalCoord(uint32_t n)
1204 {
1205 NANOVDB_ASSERT(n < SIZE);
1206 const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1207 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1208 }
1209
1210 void localToGlobalCoord(Coord& ijk) const
1211 {
1212 ijk += mOrigin;
1213 }
1214
1215 Coord offsetToGlobalCoord(uint32_t n) const
1216 {
1218 this->localToGlobalCoord(ijk);
1219 return ijk;
1220 }
1221
1222 ValueType getFirstValue() const { return mValues[0]; }
1223 ValueType getLastValue() const { return mValues[SIZE - 1]; }
1224 const ValueType& getValue(uint32_t i) const {return mValues[i];}
1225 const ValueType& getValue(const Coord& ijk) const {return mValues[CoordToOffset(ijk)];}
1226
1227 template<typename OpT, typename... ArgsT>
1228 auto get(const Coord& ijk, ArgsT&&... args) const {return OpT::get(*this, CoordToOffset(ijk), args...);}
1229
1230 template<typename OpT, typename... ArgsT>
1231 auto set(const Coord& ijk, ArgsT&&... args) {return OpT::set(*this, CoordToOffset(ijk), args...);}
1232
1233#ifndef NANOVDB_NEW_ACCESSOR_METHODS
1234 template<typename AccT>
1235 const ValueType& getValueAndCache(const Coord& ijk, const AccT&) const
1236 {
1237 return mValues[CoordToOffset(ijk)];
1238 }
1239
1240 template<typename AccT>
1241 void setValueAndCache(const Coord& ijk, const ValueType& value, const AccT&)
1242 {
1243 const uint32_t n = CoordToOffset(ijk);
1244 mValueMask.setOn(n);
1245 mValues[n] = value;
1246 }
1247
1248 template<typename AccT>
1249 void setValueOnAndCache(const Coord& ijk, const AccT&)
1250 {
1251 const uint32_t n = CoordToOffset(ijk);
1252 mValueMask.setOn(n);
1253 }
1254
1255 template<typename AccT>
1256 bool isActiveAndCache(const Coord& ijk, const AccT&) const
1257 {
1258 return mValueMask.isOn(CoordToOffset(ijk));
1259 }
1260#endif
1261
1262 void setValue(uint32_t n, const ValueType& value)
1263 {
1264 mValueMask.setOn(n);
1265 mValues[n] = value;
1266 }
1267 void setValue(const Coord& ijk, const ValueType& value){this->setValue(CoordToOffset(ijk), value);}
1268
1269 void merge(LeafNode &other)
1270 {
1271 other.mValueMask -= mValueMask;
1272 for (auto iter = other.mValueMask.beginOn(); iter; ++iter) {
1273 const uint32_t n = *iter;
1274 mValues[n] = other.mValues[n];
1275 }
1276 mValueMask |= other.mValueMask;
1277 }
1278
1279 template<typename T>
1282
1283}; // tools::build::LeafNode<T>
1284
1285//================================================================================================
1286
1287template <>
1289{
1290 using ValueType = bool;
1293 static constexpr uint32_t LOG2DIM = 3;
1294 static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1295 static constexpr uint32_t DIM = 1u << TOTAL;
1296 static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1297 static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1298 static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1299 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1301 template<bool ON>
1302 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1304
1307 union {
1309 uint64_t mDstOffset;
1310 };
1311
1312 /// @brief Visits all active values in a leaf node
1313 class ValueOnIterator : public MaskIterT<true>
1314 {
1315 using BaseT = MaskIterT<true>;
1316 const LeafNode *mParent;
1317 public:
1318 ValueOnIterator() : BaseT(), mParent(nullptr) {}
1319 ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
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
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) {}
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
1343
1344 /// @brief Visits all values in a leaf node, i.e. both active and inactive values
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 bool operator*() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1353 Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
1354 bool isActive() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1355 operator bool() const {return mPos < SIZE;}
1356 ValueIterator& operator++() {++mPos; return *this;}
1358 auto tmp = *this;
1359 ++(*this);
1360 return tmp;
1361 }
1362 }; // Member class ValueIterator
1363
1366
1367 LeafNode(const Coord& ijk, const ValueType&, bool state)
1368 : mOrigin(ijk & ~MASK)
1369 , mValueMask(state) //invalid
1370 , mDstOffset(0)
1371 {
1372 }
1373 LeafNode(const LeafNode&) = delete; // disallow copy-construction
1374 LeafNode(LeafNode&&) = delete; // disallow move construction
1375 LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1376 LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1377 ~LeafNode() = default;
1378
1379 const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1380 const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1381 const Coord& origin() const {return mOrigin;}
1382
1383 /// @brief Return the linear offset corresponding to the given coordinate
1384 static uint32_t CoordToOffset(const Coord& ijk)
1385 {
1386 return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1387 ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1388 (ijk[2] & int32_t(MASK));
1389 }
1390
1391 static Coord OffsetToLocalCoord(uint32_t n)
1392 {
1393 NANOVDB_ASSERT(n < SIZE);
1394 const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1395 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1396 }
1397
1398 void localToGlobalCoord(Coord& ijk) const {ijk += mOrigin;}
1399
1400 Coord offsetToGlobalCoord(uint32_t n) const
1401 {
1403 this->localToGlobalCoord(ijk);
1404 return ijk;
1405 }
1406
1407 bool getFirstValue() const { return mValueMask.isOn(0); }
1408 bool getLastValue() const { return mValueMask.isOn(SIZE - 1); }
1409 bool getValue(uint32_t i) const {return mValueMask.isOn(i);}
1410 bool getValue(const Coord& ijk) const {return mValueMask.isOn(CoordToOffset(ijk));}
1411
1412 template<typename OpT, typename... ArgsT>
1413 auto get(const Coord& ijk, ArgsT&&... args) const {return OpT::get(*this, CoordToOffset(ijk), args...);}
1414
1415 template<typename OpT, typename... ArgsT>
1416 auto set(const Coord& ijk, ArgsT&&... args) {return OpT::set(*this, CoordToOffset(ijk), args...);}
1417
1418#ifndef NANOVDB_NEW_ACCESSOR_METHODS
1419 template<typename AccT>
1420 bool getValueAndCache(const Coord& ijk, const AccT&) const
1421 {
1422 return mValueMask.isOn(CoordToOffset(ijk));
1423 }
1424
1425 template<typename AccT>
1426 void setValueAndCache(const Coord& ijk, bool, const AccT&)
1427 {
1428 const uint32_t n = CoordToOffset(ijk);
1429 mValueMask.setOn(n);
1430 }
1431
1432 template<typename AccT>
1433 void setValueOnAndCache(const Coord& ijk, const AccT&)
1434 {
1435 const uint32_t n = CoordToOffset(ijk);
1436 mValueMask.setOn(n);
1437 }
1438
1439 template<typename AccT>
1440 bool isActiveAndCache(const Coord& ijk, const AccT&) const
1441 {
1442 return mValueMask.isOn(CoordToOffset(ijk));
1443 }
1444#endif
1445
1446 void setValue(uint32_t n, bool) {mValueMask.setOn(n);}
1447 void setValue(const Coord& ijk) {mValueMask.setOn(CoordToOffset(ijk));}
1448
1449 void merge(LeafNode &other)
1450 {
1451 mValueMask |= other.mValueMask;
1452 }
1453
1454}; // tools::build::LeafNode<ValueMask>
1455
1456//================================================================================================
1457
1458template <>
1459struct LeafNode<bool>
1460{
1461 using ValueType = bool;
1464 static constexpr uint32_t LOG2DIM = 3;
1465 static constexpr uint32_t TOTAL = LOG2DIM; // needed by parent nodes
1466 static constexpr uint32_t DIM = 1u << TOTAL;
1467 static constexpr uint32_t SIZE = 1u << 3 * LOG2DIM; // total number of voxels represented by this node
1468 static constexpr uint32_t MASK = DIM - 1; // mask for bit operations
1469 static constexpr uint32_t LEVEL = 0; // level 0 = leaf
1470 static constexpr uint64_t NUM_VALUES = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
1472 template<bool ON>
1473 using MaskIterT = typename Mask<LOG2DIM>::template Iterator<ON>;
1475
1478 union {
1480 uint64_t mDstOffset;
1481 };
1482
1483 /// @brief Visits all active values in a leaf node
1484 class ValueOnIterator : public MaskIterT<true>
1485 {
1486 using BaseT = MaskIterT<true>;
1487 const LeafNode *mParent;
1488 public:
1489 ValueOnIterator() : BaseT(), mParent(nullptr) {}
1490 ValueOnIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOn()), mParent(parent) {}
1492 bool operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues.isOn(BaseT::pos());}
1493 Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1494 }; // Member class ValueOnIterator
1495
1498
1499 /// @brief Visits all inactive values in a leaf node
1500 class ValueOffIterator : public MaskIterT<false>
1501 {
1502 using BaseT = MaskIterT<false>;
1503 const LeafNode *mParent;
1504 public:
1505 ValueOffIterator() : BaseT(), mParent(nullptr) {}
1506 ValueOffIterator(const LeafNode* parent) : BaseT(parent->mValueMask.beginOff()), mParent(parent) {}
1508 bool operator*() const {NANOVDB_ASSERT(*this); return mParent->mValues.isOn(BaseT::pos());}
1509 Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(BaseT::pos());}
1510 }; // Member class ValueOffIterator
1511
1514
1515 /// @brief Visits all values in a leaf node, i.e. both active and inactive values
1517 {
1518 const LeafNode *mParent;
1519 uint32_t mPos;
1520 public:
1521 ValueIterator() : mParent(nullptr), mPos(1u << 3 * LOG2DIM) {}
1522 ValueIterator(const LeafNode* parent) : mParent(parent), mPos(0) {NANOVDB_ASSERT(parent);}
1523 bool operator*() const { NANOVDB_ASSERT(*this); return mParent->mValues.isOn(mPos);}
1524 Coord getCoord() const { NANOVDB_ASSERT(*this); return mParent->offsetToGlobalCoord(mPos);}
1525 bool isActive() const { NANOVDB_ASSERT(*this); return mParent->mValueMask.isOn(mPos);}
1526 operator bool() const {return mPos < SIZE;}
1527 ValueIterator& operator++() {++mPos; return *this;}
1529 auto tmp = *this;
1530 ++(*this);
1531 return tmp;
1532 }
1533 }; // Member class ValueIterator
1534
1537
1538 LeafNode(const Coord& ijk, bool value, bool state)
1539 : mOrigin(ijk & ~MASK)
1540 , mValueMask(state)
1541 , mValues(value)
1542 , mDstOffset(0)
1543 {
1544 }
1545 LeafNode(const LeafNode&) = delete; // disallow copy-construction
1546 LeafNode(LeafNode&&) = delete; // disallow move construction
1547 LeafNode& operator=(const LeafNode&) = delete; // disallow copy assignment
1548 LeafNode& operator=(LeafNode&&) = delete; // disallow move assignment
1549 ~LeafNode() = default;
1550
1551 const Mask<LOG2DIM>& valueMask() const {return mValueMask;}
1552 const Mask<LOG2DIM>& getValueMask() const {return mValueMask;}
1553 const Coord& origin() const {return mOrigin;}
1554
1555 /// @brief Return the linear offset corresponding to the given coordinate
1556 static uint32_t CoordToOffset(const Coord& ijk)
1557 {
1558 return ((ijk[0] & int32_t(MASK)) << (2 * LOG2DIM)) +
1559 ((ijk[1] & int32_t(MASK)) << LOG2DIM) +
1560 (ijk[2] & int32_t(MASK));
1561 }
1562
1563 static Coord OffsetToLocalCoord(uint32_t n)
1564 {
1565 NANOVDB_ASSERT(n < SIZE);
1566 const int32_t m = n & ((1 << 2 * LOG2DIM) - 1);
1567 return Coord(n >> 2 * LOG2DIM, m >> LOG2DIM, m & int32_t(MASK));
1568 }
1569
1570 void localToGlobalCoord(Coord& ijk) const
1571 {
1572 ijk += mOrigin;
1573 }
1574
1575 Coord offsetToGlobalCoord(uint32_t n) const
1576 {
1578 this->localToGlobalCoord(ijk);
1579 return ijk;
1580 }
1581 bool getFirstValue() const { return mValues.isOn(0); }
1582 bool getLastValue() const { return mValues.isOn(SIZE - 1); }
1583
1584 bool getValue(uint32_t i) const {return mValues.isOn(i);}
1585 bool getValue(const Coord& ijk) const
1586 {
1587 return mValues.isOn(CoordToOffset(ijk));
1588 }
1589#ifndef NANOVDB_NEW_ACCESSOR_METHODS
1590 template<typename AccT>
1591 bool isActiveAndCache(const Coord& ijk, const AccT&) const
1592 {
1593 return mValueMask.isOn(CoordToOffset(ijk));
1594 }
1595
1596 template<typename AccT>
1597 bool getValueAndCache(const Coord& ijk, const AccT&) const
1598 {
1599 return mValues.isOn(CoordToOffset(ijk));
1600 }
1601
1602 template<typename AccT>
1603 void setValueAndCache(const Coord& ijk, bool value, const AccT&)
1604 {
1605 const uint32_t n = CoordToOffset(ijk);
1606 mValueMask.setOn(n);
1607 mValues.set(n, value);
1608 }
1609
1610 template<typename AccT>
1611 void setValueOnAndCache(const Coord& ijk, const AccT&)
1612 {
1613 const uint32_t n = CoordToOffset(ijk);
1614 mValueMask.setOn(n);
1615 }
1616#endif
1617
1618 void setValue(uint32_t n, bool value)
1619 {
1620 mValueMask.setOn(n);
1621 mValues.set(n, value);
1622 }
1623 void setValue(const Coord& ijk, bool value) {return this->setValue(CoordToOffset(ijk), value);}
1624
1625 void merge(LeafNode &other)
1626 {
1627 mValues |= other.mValues;
1628 mValueMask |= other.mValueMask;
1629 }
1630
1631}; // tools::build::LeafNode<bool>
1632
1633//================================================================================================
1634
1635template<typename BuildT>
1636template<typename T>
1639{
1640 const uint32_t first = *mValueMask.beginOn();
1641 if (first < SIZE) {
1642 bool xInside = mValues[first] < 0, yInside = xInside, zInside = xInside;
1643 for (uint32_t x = 0; x != DIM; ++x) {
1644 const uint32_t x00 = x << (2 * LOG2DIM);
1645 if (mValueMask.isOn(x00))
1646 xInside = mValues[x00] < 0; // element(x, 0, 0)
1647 yInside = xInside;
1648 for (uint32_t y = 0; y != DIM; ++y) {
1649 const uint32_t xy0 = x00 + (y << LOG2DIM);
1650 if (mValueMask.isOn(xy0))
1651 yInside = mValues[xy0] < 0; // element(x, y, 0)
1652 zInside = yInside;
1653 for (uint32_t z = 0; z != (1 << LOG2DIM); ++z) {
1654 const uint32_t xyz = xy0 + z; // element(x, y, z)
1655 if (mValueMask.isOn(xyz)) {
1656 zInside = mValues[xyz] < 0;
1657 } else {
1658 mValues[xyz] = zInside ? -outside : outside;
1659 }
1660 }
1661 }
1662 }
1663 }
1664} // tools::build::LeafNode<T>::signedFloodFill
1665
1666// ----------------------------> ValueAccessor <--------------------------------------
1667
1668template<typename BuildT>
1670{
1677
1679 : mRoot(root)
1680 , mKeys{Coord(math::Maximum<int>::value()), Coord(math::Maximum<int>::value()), Coord(math::Maximum<int>::value())}
1681 , mNode{nullptr, nullptr, nullptr}
1682 {
1683 }
1684 ValueAccessor(ValueAccessor&&) = default; // allow move construction
1685 ValueAccessor(const ValueAccessor&) = delete; // disallow copy construction
1686 ValueType getValue(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
1687 template<typename NodeT>
1688 bool isCached(const Coord& ijk) const
1689 {
1690 return (ijk[0] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][0] &&
1691 (ijk[1] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][1] &&
1692 (ijk[2] & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL][2];
1693 }
1694
1695 template <typename OpT, typename... ArgsT>
1696 auto get(const Coord& ijk, ArgsT&&... args) const
1697 {
1698 if (this->template isCached<LeafT>(ijk)) {
1699 return ((const LeafT*)mNode[0])->template get<OpT>(ijk, args...);
1700 } else if (this->template isCached<Node1>(ijk)) {
1701 return ((const Node1*)mNode[1])->template getAndCache<OpT>(ijk, *this, args...);
1702 } else if (this->template isCached<Node2>(ijk)) {
1703 return ((const Node2*)mNode[2])->template getAndCache<OpT>(ijk, *this, args...);
1704 }
1705 return mRoot.template getAndCache<OpT>(ijk, *this, args...);
1706 }
1707
1708 template <typename OpT, typename... ArgsT>
1709 auto set(const Coord& ijk, ArgsT&&... args) const
1710 {
1711 if (this->template isCached<LeafT>(ijk)) {
1712 return ((LeafT*)mNode[0])->template set<OpT>(ijk, args...);
1713 } else if (this->template isCached<Node1>(ijk)) {
1714 return ((Node1*)mNode[1])->template setAndCache<OpT>(ijk, *this, args...);
1715 } else if (this->template isCached<Node2>(ijk)) {
1716 return ((Node2*)mNode[2])->template setAndCache<OpT>(ijk, *this, args...);
1717 }
1718 return mRoot.template setAndCache<OpT>(ijk, *this, args...);
1719 }
1720
1721#ifdef NANOVDB_NEW_ACCESSOR_METHODS
1722 ValueType getValue(const Coord& ijk) const {return this->template get<GetValue<BuildT>>(ijk);}
1723 LeafT* setValue(const Coord& ijk, const ValueType& value) {return this->template set<SetValue<BuildT>>(ijk, value);}
1724 LeafT* setValueOn(const Coord& ijk) {return this->template set<SetValue<BuildT>>(ijk);}
1725 LeafT& touchLeaf(const Coord& ijk) {return this->template set<TouchLeaf<BuildT>>(ijk);}
1726 bool isActive(const Coord& ijk) const {return this->template get<GetState<BuildT>>(ijk);}
1727#else
1728 ValueType getValue(const Coord& ijk) const
1729 {
1730 if (this->template isCached<LeafT>(ijk)) {
1731 return ((LeafT*)mNode[0])->getValueAndCache(ijk, *this);
1732 } else if (this->template isCached<Node1>(ijk)) {
1733 return ((Node1*)mNode[1])->getValueAndCache(ijk, *this);
1734 } else if (this->template isCached<Node2>(ijk)) {
1735 return ((Node2*)mNode[2])->getValueAndCache(ijk, *this);
1736 }
1737 return mRoot.getValueAndCache(ijk, *this);
1738 }
1739
1740 /// @brief Sets value in a leaf node and returns it.
1741 LeafT* setValue(const Coord& ijk, const ValueType& value)
1742 {
1743 if (this->template isCached<LeafT>(ijk)) {
1744 ((LeafT*)mNode[0])->setValueAndCache(ijk, value, *this);
1745 } else if (this->template isCached<Node1>(ijk)) {
1746 ((Node1*)mNode[1])->setValueAndCache(ijk, value, *this);
1747 } else if (this->template isCached<Node2>(ijk)) {
1748 ((Node2*)mNode[2])->setValueAndCache(ijk, value, *this);
1749 } else {
1750 mRoot.setValueAndCache(ijk, value, *this);
1751 }
1752 NANOVDB_ASSERT(this->isCached<LeafT>(ijk));
1753 return (LeafT*)mNode[0];
1754 }
1755 void setValueOn(const Coord& ijk)
1756 {
1757 if (this->template isCached<LeafT>(ijk)) {
1758 ((LeafT*)mNode[0])->setValueOnAndCache(ijk, *this);
1759 } else if (this->template isCached<Node1>(ijk)) {
1760 ((Node1*)mNode[1])->setValueOnAndCache(ijk, *this);
1761 } else if (this->template isCached<Node2>(ijk)) {
1762 ((Node2*)mNode[2])->setValueOnAndCache(ijk, *this);
1763 } else {
1764 mRoot.setValueOnAndCache(ijk, *this);
1765 }
1766 }
1767 void touchLeaf(const Coord& ijk) const
1768 {
1769 if (this->template isCached<LeafT>(ijk)) {
1770 return;
1771 } else if (this->template isCached<Node1>(ijk)) {
1772 ((Node1*)mNode[1])->touchLeafAndCache(ijk, *this);
1773 } else if (this->template isCached<Node2>(ijk)) {
1774 ((Node2*)mNode[2])->touchLeafAndCache(ijk, *this);
1775 } else {
1776 mRoot.touchLeafAndCache(ijk, *this);
1777 }
1778 }
1779 bool isActive(const Coord& ijk) const
1780 {
1781 if (this->template isCached<LeafT>(ijk)) {
1782 return ((LeafT*)mNode[0])->isActiveAndCache(ijk, *this);
1783 } else if (this->template isCached<Node1>(ijk)) {
1784 return ((Node1*)mNode[1])->isActiveAndCache(ijk, *this);
1785 } else if (this->template isCached<Node2>(ijk)) {
1786 return ((Node2*)mNode[2])->isActiveAndCache(ijk, *this);
1787 }
1788 return mRoot.isActiveAndCache(ijk, *this);
1789 }
1790#endif
1791
1792 bool isValueOn(const Coord& ijk) const { return this->isActive(ijk); }
1793 template<typename NodeT>
1794 void insert(const Coord& ijk, NodeT* node) const
1795 {
1796 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
1797 mNode[NodeT::LEVEL] = node;
1798 }
1800 mutable Coord mKeys[3];
1801 mutable void* mNode[3];
1802}; // tools::build::ValueAccessor<BuildT>
1803
1804// ----------------------------> Tree <--------------------------------------
1805
1806template<typename BuildT>
1807struct Tree
1808{
1815 struct WriteAccessor;
1816
1818 std::mutex mMutex;
1819
1820 Tree(const ValueType &background) : mRoot(background) {}
1821 Tree(const Tree&) = delete; // disallow copy construction
1822 Tree(Tree&&) = delete; // disallow move construction
1823 Tree& tree() {return *this;}
1825 ValueType getValue(const Coord& ijk) const {return mRoot.getValue(ijk);}
1826 ValueType getValue(int i, int j, int k) const {return this->getValue(Coord(i,j,k));}
1827 void setValue(const Coord& ijk, const ValueType &value) {mRoot.setValue(ijk, value);}
1828 std::array<size_t,3> nodeCount() const
1829 {
1830 std::array<size_t, 3> count{0,0,0};
1831 mRoot.nodeCount(count);
1832 return count;
1833 }
1834 /// @brief regular accessor for thread-safe reading and non-thread-safe writing
1836 /// @brief special accessor for thread-safe writing only
1838};// tools::build::Tree<BuildT>
1839
1840// ----------------------------> Tree::WriteAccessor <--------------------------------------
1841
1842template<typename BuildT>
1843struct Tree<BuildT>::WriteAccessor
1844{
1846 using ValueType = typename AccT::ValueType;
1847 using LeafT = typename AccT::LeafT;
1848 using Node1 = typename AccT::Node1;
1849 using Node2 = typename AccT::Node2;
1851
1852 WriteAccessor(RootNodeType& parent, std::mutex &mx)
1853 : mParent(parent)
1854 , mRoot(parent.mBackground)
1855 , mAcc(mRoot)
1856 , mMutex(mx)
1857 {
1858 }
1859 WriteAccessor(const WriteAccessor&) = delete; // disallow copy construction
1860 WriteAccessor(WriteAccessor&&) = default; // allow move construction
1861 ~WriteAccessor() { this->merge(); }
1862 void merge()
1863 {
1864 mMutex.lock();
1865 mParent.merge(mRoot);
1866 mMutex.unlock();
1867 }
1868 inline void setValueOn(const Coord& ijk) {mAcc.setValueOn(ijk);}
1869 inline void setValue(const Coord& ijk, const ValueType &value) {mAcc.setValue(ijk, value);}
1870
1873 std::mutex &mMutex;
1874}; // tools::build::Tree<BuildT>::WriteAccessor
1875
1876// ----------------------------> Grid <--------------------------------------
1877
1878template<typename BuildT>
1879struct Grid : public Tree<BuildT>
1880{
1881 using BuildType = BuildT;
1888
1892 std::string mName;
1893
1894 Grid(const ValueType &background, const std::string &name = "", GridClass gClass = GridClass::Unknown)
1895 : TreeType(background)
1896 , mGridClass(gClass)
1897 , mGridType(toGridType<BuildT>())
1898 , mName(name)
1899 {
1900 mMap.set(1.0, Vec3d(0.0), 1.0);
1901 }
1902 TreeType& tree() {return *this;}
1903 const GridType& gridType() const { return mGridType; }
1904 const GridClass& gridClass() const { return mGridClass; }
1905 const Map& map() const { return mMap; }
1906 void setTransform(double scale=1.0, const Vec3d &translation = Vec3d(0.0)) {mMap.set(scale, translation, 1.0);}
1907 const std::string& gridName() const { return mName; }
1908 const std::string& getName() const { return mName; }
1909 void setName(const std::string &name) { mName = name; }
1910 /// @brief Sets grids values in domain of the @a bbox to those returned by the specified @a func with the
1911 /// expected signature [](const Coord&)->ValueType.
1912 ///
1913 /// @note If @a func returns a value equal to the background value of the input grid at a
1914 /// specific voxel coordinate, then the active state of that coordinate is off! Else the value
1915 /// value is set and the active state is on. This is done to allow for sparse grids to be generated.
1916 ///
1917 /// @param func Functor used to evaluate the grid values in the @a bbox
1918 /// @param bbox Coordinate bounding-box over which the grid values will be set.
1919 /// @param delta Specifies a lower threshold value for rendering (optional). Typically equals the voxel size
1920 /// for level sets and otherwise it's zero.
1921 template <typename Func>
1922 void operator()(const Func& func, const CoordBBox& bbox, ValueType delta = ValueType(0));
1923};// tools::build::Grid
1924
1925template <typename BuildT>
1926template <typename Func>
1927void Grid<BuildT>::operator()(const Func& func, const CoordBBox& bbox, ValueType /*delta*/)
1928{
1929 auto &root = this->tree().root();
1930#if __cplusplus >= 201703L
1931 static_assert(util::is_same<ValueType, typename std::invoke_result<Func,const Coord&>::type>::value, "GridBuilder: mismatched ValueType");
1932#else// invoke_result was introduced in C++17 and result_of was removed in C++20
1933 static_assert(util::is_same<ValueType, typename std::result_of<Func(const Coord&)>::type>::value, "GridBuilder: mismatched ValueType");
1934#endif
1935 const CoordBBox leafBBox(bbox[0] >> Node0::TOTAL, bbox[1] >> Node0::TOTAL);
1936 std::mutex mutex;
1937 util::forEach(leafBBox, [&](const CoordBBox& b) {
1938 Node0* leaf = nullptr;
1939 for (auto it = b.begin(); it; ++it) {
1940 Coord min(*it << Node0::TOTAL), max(min + Coord(Node0::DIM - 1));
1941 const CoordBBox b(min.maxComponent(bbox.min()),
1942 max.minComponent(bbox.max()));// crop
1943 if (leaf == nullptr) {
1944 leaf = new Node0(b[0], root.mBackground, false);
1945 } else {
1946 leaf->mOrigin = b[0] & ~Node0::MASK;
1947 NANOVDB_ASSERT(leaf->mValueMask.isOff());
1948 }
1949 leaf->mDstOffset = 0;// no prune
1950 for (auto ijk = b.begin(); ijk; ++ijk) {
1951 const auto v = func(*ijk);// call functor
1952 if (v != root.mBackground) leaf->setValue(*ijk, v);// don't insert background values
1953 }
1954 if (!leaf->mValueMask.isOff()) {// has active values
1955 if (leaf->mValueMask.isOn()) {// only active values
1956 const auto first = leaf->getFirstValue();
1957 int n=1;
1958 while (n<512) {// 8^3 = 512
1959 if (leaf->mValues[n++] != first) break;
1960 }
1961 if (n == 512) leaf->mDstOffset = 1;// prune below
1962 }
1963 std::lock_guard<std::mutex> guard(mutex);
1964 NANOVDB_ASSERT(leaf != nullptr);
1965 root.addNode(leaf);
1966 NANOVDB_ASSERT(leaf == nullptr);
1967 }
1968 }// loop over sub-part of leafBBox
1969 delete leaf;
1970 });
1971
1972 // Prune leaf and tile nodes
1973 for (auto it2 = root.mTable.begin(); it2 != root.mTable.end(); ++it2) {
1974 if (auto *upper = it2->second.child) {//upper level internal node
1975 for (auto it1 = upper->mChildMask.beginOn(); it1; ++it1) {
1976 auto *lower = upper->mTable[*it1].child;// lower level internal node
1977 for (auto it0 = lower->mChildMask.beginOn(); it0; ++it0) {
1978 auto *leaf = lower->mTable[*it0].child;// leaf nodes
1979 if (leaf->mDstOffset) {
1980 lower->mTable[*it0].value = leaf->getFirstValue();
1981 lower->mChildMask.setOff(*it0);
1982 lower->mValueMask.setOn(*it0);
1983 delete leaf;
1984 }
1985 }// loop over leaf nodes
1986 if (lower->mChildMask.isOff()) {//only tiles
1987 const auto first = lower->getFirstValue();
1988 int n=1;
1989 while (n < 4096) {// 16^3 = 4096
1990 if (lower->mTable[n++].value != first) break;
1991 }
1992 if (n == 4096) {// identical tile values so prune
1993 upper->mTable[*it1].value = first;
1994 upper->mChildMask.setOff(*it1);
1995 upper->mValueMask.setOn(*it1);
1996 delete lower;
1997 }
1998 }
1999 }// loop over lower internal nodes
2000 if (upper->mChildMask.isOff()) {//only tiles
2001 const auto first = upper->getFirstValue();
2002 int n=1;
2003 while (n < 32768) {// 32^3 = 32768
2004 if (upper->mTable[n++].value != first) break;
2005 }
2006 if (n == 32768) {// identical tile values so prune
2007 it2->second.value = first;
2008 it2->second.state = upper->mValueMask.isOn();
2009 it2->second.child = nullptr;
2010 delete upper;
2011 }
2012 }
2013 }// is child node of the root
2014 }// loop over root table
2015}// tools::build::Grid::operator()
2016
2017//================================================================================================
2018
2019template <typename T>
2021template <typename T>
2023template <typename T>
2025template <typename T>
2027template <typename T>
2028using BuildTile = typename BuildRoot<T>::Tile;
2029
2047
2048// ----------------------------> NodeManager <--------------------------------------
2049
2050// GridT can be openvdb::Grid and nanovdb::tools::build::Grid
2051template <typename GridT>
2053{
2054public:
2055
2056 using ValueType = typename GridT::ValueType;
2057 using BuildType = typename GridT::BuildType;
2058 using GridType = GridT;
2059 using TreeType = typename GridT::TreeType;
2060 using RootNodeType = typename TreeType::RootNodeType;
2061 static_assert(RootNodeType::LEVEL == 3, "NodeManager expected LEVEL=3");
2062 using Node2 = typename RootNodeType::ChildNodeType;
2063 using Node1 = typename Node2::ChildNodeType;
2064 using Node0 = typename Node1::ChildNodeType;
2065
2066 NodeManager(GridT &grid) : mGrid(grid) {this->init();}
2067 void init()
2068 {
2069 mArray0.clear();
2070 mArray1.clear();
2071 mArray2.clear();
2072 auto counts = mGrid.tree().nodeCount();
2073 mArray0.reserve(counts[0]);
2074 mArray1.reserve(counts[1]);
2075 mArray2.reserve(counts[2]);
2076
2077 for (auto it2 = mGrid.tree().root().cbeginChildOn(); it2; ++it2) {
2078 Node2 &upper = const_cast<Node2&>(*it2);
2079 mArray2.emplace_back(&upper);
2080 for (auto it1 = upper.cbeginChildOn(); it1; ++it1) {
2081 Node1 &lower = const_cast<Node1&>(*it1);
2082 mArray1.emplace_back(&lower);
2083 for (auto it0 = lower.cbeginChildOn(); it0; ++it0) {
2084 Node0 &leaf = const_cast<Node0&>(*it0);
2085 mArray0.emplace_back(&leaf);
2086 }// loop over leaf nodes
2087 }// loop over lower internal nodes
2088 }// loop over root node
2089 }
2090
2091 /// @brief Return the number of tree nodes at the specified level
2092 /// @details 0 is leaf, 1 is lower internal, and 2 is upper internal level
2093 uint64_t nodeCount(int level) const
2094 {
2095 NANOVDB_ASSERT(level==0 || level==1 || level==2);
2096 return level==0 ? mArray0.size() : level==1 ? mArray1.size() : mArray2.size();
2097 }
2098
2099 template <int LEVEL>
2101 template <int LEVEL>
2103 template <int LEVEL>
2105 template <int LEVEL>
2107 template <int LEVEL>
2109 template <int LEVEL>
2111
2112 /// @brief Return the i'th leaf node with respect to breadth-first ordering
2113 const Node0& leaf(uint32_t i) const { return *mArray0[i]; }
2114 Node0& leaf(uint32_t i) { return *mArray0[i]; }
2115 uint64_t leafCount() const {return mArray0.size();}
2116
2117 /// @brief Return the i'th lower internal node with respect to breadth-first ordering
2118 const Node1& lower(uint32_t i) const { return *mArray1[i]; }
2119 Node1& lower(uint32_t i) { return *mArray1[i]; }
2120 uint64_t lowerCount() const {return mArray1.size();}
2121
2122 /// @brief Return the i'th upper internal node with respect to breadth-first ordering
2123 const Node2& upper(uint32_t i) const { return *mArray2[i]; }
2124 Node2& upper(uint32_t i) { return *mArray2[i]; }
2125 uint64_t upperCount() const {return mArray2.size();}
2126
2127 RootNodeType& root() {return mGrid.tree().root();}
2128 const RootNodeType& root() const {return mGrid.tree().root();}
2129
2130 TreeType& tree() {return mGrid.tree();}
2131 const TreeType& tree() const {return mGrid.tree();}
2132
2133 GridType& grid() {return mGrid;}
2134 const GridType& grid() const {return mGrid;}
2135
2136protected:
2137
2138 GridT &mGrid;
2139 std::vector<Node0*> mArray0; // leaf nodes
2140 std::vector<Node1*> mArray1; // lower internal nodes
2141 std::vector<Node2*> mArray2; // upper internal nodes
2142
2143};// NodeManager
2144
2145template <typename NodeManagerT>
2147sdfToLevelSet(NodeManagerT &mgr)
2148{
2149 mgr.grid().mGridClass = GridClass::LevelSet;
2150 // Note that the bottom-up flood filling is essential
2151 const auto outside = mgr.root().mBackground;
2152 util::forEach(0, mgr.leafCount(), 8, [&](const util::Range1D& r) {
2153 for (auto i = r.begin(); i != r.end(); ++i) mgr.leaf(static_cast<uint32_t>(i)).signedFloodFill(outside);
2154 });
2155 util::forEach(0, mgr.lowerCount(), 1, [&](const util::Range1D& r) {
2156 for (auto i = r.begin(); i != r.end(); ++i) mgr.lower(static_cast<uint32_t>(i)).signedFloodFill(outside);
2157 });
2158 util::forEach(0, mgr.upperCount(), 1, [&](const util::Range1D& r) {
2159 for (auto i = r.begin(); i != r.end(); ++i) mgr.upper(static_cast<uint32_t>(i)).signedFloodFill(outside);
2160 });
2161 mgr.root().signedFloodFill(outside);
2162}// sdfToLevelSet
2163
2164template <typename NodeManagerT>
2165void levelSetToFog(NodeManagerT &mgr, bool rebuild = true)
2166{
2167 using ValueType = typename NodeManagerT::ValueType;
2168 mgr.grid().mGridClass = GridClass::FogVolume;
2169 const ValueType d = -mgr.root().mBackground, w = 1.0f / d;
2170 //std::atomic_bool prune{false};
2171 std::atomic<bool> prune{false};
2172 auto op = [&](ValueType& v) -> bool {
2173 if (v > ValueType(0)) {
2174 v = ValueType(0);
2175 return false;
2176 }
2177 v = v > d ? v * w : ValueType(1);
2178 return true;
2179 };
2180 util::forEach(0, mgr.leafCount(), 8, [&](const util::Range1D& r) {
2181 for (auto i = r.begin(); i != r.end(); ++i) {
2182 auto& leaf = mgr.leaf(static_cast<uint32_t>(i));
2183 for (uint32_t i = 0; i < 512u; ++i) leaf.mValueMask.set(i, op(leaf.mValues[i]));
2184 }
2185 });
2186 util::forEach(0, mgr.lowerCount(), 1, [&](const util::Range1D& r) {
2187 for (auto i = r.begin(); i != r.end(); ++i) {
2188 auto& node = mgr.lower(static_cast<uint32_t>(i));
2189 for (uint32_t i = 0; i < 4096u; ++i) {
2190 if (node.mChildMask.isOn(i)) {
2191 auto* leaf = node.mTable[i].child;
2192 if (leaf->mValueMask.isOff()) {// prune leaf node
2193 node.mTable[i].value = leaf->getFirstValue();
2194 node.mChildMask.setOff(i);
2195 delete leaf;
2196 prune = true;
2197 }
2198 } else {
2199 node.mValueMask.set(i, op(node.mTable[i].value));
2200 }
2201 }
2202 }
2203 });
2204 util::forEach(0, mgr.upperCount(), 1, [&](const util::Range1D& r) {
2205 for (auto i = r.begin(); i != r.end(); ++i) {
2206 auto& node = mgr.upper(static_cast<uint32_t>(i));
2207 for (uint32_t i = 0; i < 32768u; ++i) {
2208 if (node.mChildMask.isOn(i)) {// prune lower internal node
2209 auto* child = node.mTable[i].child;
2210 if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2211 node.mTable[i].value = child->getFirstValue();
2212 node.mChildMask.setOff(i);
2213 delete child;
2214 prune = true;
2215 }
2216 } else {
2217 node.mValueMask.set(i, op(node.mTable[i].value));
2218 }
2219 }
2220 }
2221 });
2222
2223 for (auto it = mgr.root().mTable.begin(); it != mgr.root().mTable.end(); ++it) {
2224 auto* child = it->second.child;
2225 if (child == nullptr) {
2226 it->second.state = op(it->second.value);
2227 } else if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2228 it->second.value = child->getFirstValue();
2229 it->second.state = false;
2230 it->second.child = nullptr;
2231 delete child;
2232 prune = true;
2233 }
2234 }
2235 if (rebuild && prune) mgr.init();
2236}// levelSetToFog
2237
2238// ----------------------------> Implementations of random access methods <--------------------------------------
2239
2240template <typename T>
2242 static BuildLeaf<T>& set(BuildLeaf<T> &leaf, uint32_t) {return leaf;}
2243};// TouchLeaf<BuildT>
2244
2245/// @brief Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate @c ijk.
2246/// @tparam BuildT Build type of the grid being called
2247/// @details The value at a coordinate maps to the background, a tile value or a leaf value.
2248template <typename T>
2249struct GetValue {
2250 static auto get(const BuildRoot<T> &root) {return root.mBackground;}
2251 static auto get(const BuildTile<T> &tile) {return tile.value;}
2252 static auto get(const BuildUpper<T> &node, uint32_t n) {return node.mTable[n].value;}
2253 static auto get(const BuildLower<T> &node, uint32_t n) {return node.mTable[n].value;}
2254 static auto get(const BuildLeaf<T> &leaf, uint32_t n) {return leaf.getValue(n);}
2255};// GetValue<T>
2256
2257/// @brief Implements Tree::isActive(Coord)
2258/// @tparam T Build type of the grid being called
2259template <typename T>
2260struct GetState {
2261 static bool get(const BuildRoot<T>&) {return false;}
2262 static bool get(const BuildTile<T> &tile) {return tile.state;}
2263 static bool get(const BuildUpper<T> &node, uint32_t n) {return node.mValueMask.isOn(n);}
2264 static bool get(const BuildLower<T> &node, uint32_t n) {return node.mValueMask.isOn(n);}
2265 static bool get(const BuildLeaf<T> &leaf, uint32_t n) {return leaf.mValueMask.isOn(n);}
2266};// GetState<T>
2267
2268/// @brief Set the value and its state at the leaf level mapped to by ijk, and create the leaf node and branch if needed.
2269/// @tparam T BuildType of the corresponding tree
2270template <typename T>
2271struct SetValue {
2272 static BuildLeaf<T>* set(BuildLeaf<T> &leaf, uint32_t n) {
2273 leaf.mValueMask.setOn(n);// always set the active bit
2274 return &leaf;
2275 }
2276 static BuildLeaf<T>* set(BuildLeaf<T> &leaf, uint32_t n, const typename BuildLeaf<T>::ValueType &v) {
2277 leaf.setValue(n, v);
2278 return &leaf;
2279 }
2280};// SetValue<T>
2281
2282/// @brief Implements Tree::probeLeaf(Coord)
2283/// @tparam T Build type of the grid being called
2284template <typename T>
2287 static bool get(const BuildRoot<T> &root, ValueT &v) {
2288 v = root.mBackground;
2289 return false;
2290 }
2291 static bool get(const BuildTile<T> &tile, ValueT &v) {
2292 v = tile.value;
2293 return tile.state;
2294 }
2295 static bool get(const BuildUpper<T> &node, uint32_t n, ValueT &v) {
2296 v = node.mTable[n].value;
2297 return node.mValueMask.isOn(n);
2298 }
2299 static bool get(const BuildLower<T> &node, uint32_t n, ValueT &v) {
2300 v = node.mTable[n].value;
2301 return node.mValueMask.isOn(n);
2302 }
2303 static bool get(const BuildLeaf<T> &leaf, uint32_t n, ValueT &v) {
2304 v = leaf.getValue(n);
2305 return leaf.isActive(n);
2306 }
2307};// ProbeValue<T>
2308
2309} // namespace tools::build
2310
2311} // namespace nanovdb
2312
2313#endif // NANOVDB_TOOLS_BUILD_GRIDBUILDER_H_HAS_BEEN_INCLUDED
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
Custom Range class that is compatible with the tbb::blocked_range classes.
Definition NanoVDB.h:1121
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Definition NanoVDB.h:1054
OnIterator beginOn() const
Definition NanoVDB.h:1149
void setOff(uint32_t n)
Set the specified bit off.
Definition NanoVDB.h:1244
bool isOn(uint32_t n) const
Return true if the given bit is set.
Definition NanoVDB.h:1218
typename DataType::Tile Tile
Definition NanoVDB.h:2871
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:183
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition Math.h:425
Coord getCoord() const
Definition GridBuilder.h:658
const ChildT * operator->() const
Definition GridBuilder.h:657
ChildIterator & operator=(const ChildIterator &)=default
ChildIterator(const InternalNode *parent)
Definition GridBuilder.h:654
const ChildT & operator*() const
Definition GridBuilder.h:656
Coord getCoord() const
Definition GridBuilder.h:717
DenseIterator & operator=(const DenseIterator &)=default
DenseIterator(const InternalNode *parent)
Definition GridBuilder.h:704
ChildT * probeChild(ValueType &value) const
Definition GridBuilder.h:706
ValueIterator & operator=(const ValueIterator &)=default
ValueIterator(const InternalNode *parent)
Definition GridBuilder.h:671
Coord getCoord() const
Definition GridBuilder.h:674
bool isActive() const
Definition GridBuilder.h:675
ValueType operator*() const
Definition GridBuilder.h:673
Coord getCoord() const
Definition GridBuilder.h:691
ValueOnIterator(const InternalNode *parent)
Definition GridBuilder.h:688
ValueOnIterator & operator=(const ValueOnIterator &)=default
ValueType operator*() const
Definition GridBuilder.h:690
ValueIterator & operator=(const ValueIterator &)=default
ValueIterator & operator++()
Definition GridBuilder.h:1163
ValueIterator operator++(int)
Definition GridBuilder.h:1164
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1157
Coord getCoord() const
Definition GridBuilder.h:1160
bool isActive() const
Definition GridBuilder.h:1161
ValueIterator()
Definition GridBuilder.h:1156
ValueType operator*() const
Definition GridBuilder.h:1159
ValueOffIterator()
Definition GridBuilder.h:1140
Coord getCoord() const
Definition GridBuilder.h:1144
ValueOffIterator & operator=(const ValueOffIterator &)=default
ValueType operator*() const
Definition GridBuilder.h:1143
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1141
Coord getCoord() const
Definition GridBuilder.h:1128
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1125
ValueOnIterator & operator=(const ValueOnIterator &)=default
ValueType operator*() const
Definition GridBuilder.h:1127
ValueOnIterator()
Definition GridBuilder.h:1124
Visits all values in a leaf node, i.e. both active and inactive values.
Definition GridBuilder.h:1346
ValueIterator & operator++()
Definition GridBuilder.h:1356
ValueIterator operator++(int)
Definition GridBuilder.h:1357
bool operator*() const
Definition GridBuilder.h:1352
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1351
Coord getCoord() const
Definition GridBuilder.h:1353
bool isActive() const
Definition GridBuilder.h:1354
Visits all inactive values in a leaf node.
Definition GridBuilder.h:1330
bool operator*() const
Definition GridBuilder.h:1337
Coord getCoord() const
Definition GridBuilder.h:1338
ValueOffIterator & operator=(const ValueOffIterator &)=default
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1335
Visits all active values in a leaf node.
Definition GridBuilder.h:1314
bool operator*() const
Definition GridBuilder.h:1321
Coord getCoord() const
Definition GridBuilder.h:1322
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1319
ValueOnIterator & operator=(const ValueOnIterator &)=default
Visits all values in a leaf node, i.e. both active and inactive values.
Definition GridBuilder.h:1517
ValueIterator & operator++()
Definition GridBuilder.h:1527
ValueIterator operator++(int)
Definition GridBuilder.h:1528
bool operator*() const
Definition GridBuilder.h:1523
ValueIterator(const LeafNode *parent)
Definition GridBuilder.h:1522
Coord getCoord() const
Definition GridBuilder.h:1524
bool isActive() const
Definition GridBuilder.h:1525
Visits all inactive values in a leaf node.
Definition GridBuilder.h:1501
bool operator*() const
Definition GridBuilder.h:1508
Coord getCoord() const
Definition GridBuilder.h:1509
ValueOffIterator & operator=(const ValueOffIterator &)=default
ValueOffIterator(const LeafNode *parent)
Definition GridBuilder.h:1506
Visits all active values in a leaf node.
Definition GridBuilder.h:1485
bool operator*() const
Definition GridBuilder.h:1492
Coord getCoord() const
Definition GridBuilder.h:1493
ValueOnIterator(const LeafNode *parent)
Definition GridBuilder.h:1490
ValueOnIterator & operator=(const ValueOnIterator &)=default
const TreeType & tree() const
Definition GridBuilder.h:2131
void init()
Definition GridBuilder.h:2067
Node1 & lower(uint32_t i)
Definition GridBuilder.h:2119
RootNodeType & root()
Definition GridBuilder.h:2127
TreeType & tree()
Definition GridBuilder.h:2130
typename Node1::ChildNodeType Node0
Definition GridBuilder.h:2064
uint64_t nodeCount(int level) const
Return the number of tree nodes at the specified level.
Definition GridBuilder.h:2093
const Node2 & upper(uint32_t i) const
Return the i'th upper internal node with respect to breadth-first ordering.
Definition GridBuilder.h:2123
util::enable_if< LEVEL==0, Node0 & >::type node(int i)
Definition GridBuilder.h:2100
uint64_t leafCount() const
Definition GridBuilder.h:2115
const Node0 & leaf(uint32_t i) const
Return the i'th leaf node with respect to breadth-first ordering.
Definition GridBuilder.h:2113
uint64_t upperCount() const
Definition GridBuilder.h:2125
Node2 & upper(uint32_t i)
Definition GridBuilder.h:2124
util::enable_if< LEVEL==2, constNode2 & >::type node(int i) const
Definition GridBuilder.h:2110
typename TreeType::RootNodeType RootNodeType
Definition GridBuilder.h:2060
util::enable_if< LEVEL==1, constNode1 & >::type node(int i) const
Definition GridBuilder.h:2106
GridType & grid()
Definition GridBuilder.h:2133
Node0 & leaf(uint32_t i)
Definition GridBuilder.h:2114
std::vector< Node0 * > mArray0
Definition GridBuilder.h:2139
typename RootNodeType::ChildNodeType Node2
Definition GridBuilder.h:2062
typename GridT::BuildType BuildType
Definition GridBuilder.h:2057
util::enable_if< LEVEL==2, Node2 & >::type node(int i)
Definition GridBuilder.h:2108
GridT & mGrid
Definition GridBuilder.h:2138
std::vector< Node2 * > mArray2
Definition GridBuilder.h:2141
typename GridT::TreeType TreeType
Definition GridBuilder.h:2059
NodeManager(GridT &grid)
Definition GridBuilder.h:2066
typename GridT::ValueType ValueType
Definition GridBuilder.h:2056
const GridType & grid() const
Definition GridBuilder.h:2134
typename Node2::ChildNodeType Node1
Definition GridBuilder.h:2063
uint64_t lowerCount() const
Definition GridBuilder.h:2120
GridT GridType
Definition GridBuilder.h:2058
util::enable_if< LEVEL==0, constNode0 & >::type node(int i) const
Definition GridBuilder.h:2102
util::enable_if< LEVEL==1, Node1 & >::type node(int i)
Definition GridBuilder.h:2104
const RootNodeType & root() const
Definition GridBuilder.h:2128
const Node1 & lower(uint32_t i) const
Return the i'th lower internal node with respect to breadth-first ordering.
Definition GridBuilder.h:2118
std::vector< Node1 * > mArray1
Definition GridBuilder.h:2140
Coord getOrigin() const
Definition GridBuilder.h:91
ChildIterator()
Definition GridBuilder.h:84
Coord getCoord() const
Definition GridBuilder.h:92
ChildIterator & operator++()
Definition GridBuilder.h:94
ChildIterator operator++(int)
Definition GridBuilder.h:100
ChildT & operator*() const
Definition GridBuilder.h:89
ChildT * operator->() const
Definition GridBuilder.h:90
ChildIterator & operator=(const ChildIterator &)=default
uint32_t pos() const
Definition GridBuilder.h:105
ChildIterator(const RootNode *parent)
Definition GridBuilder.h:85
Coord getOrigin() const
Definition GridBuilder.h:195
TileIterator(const RootNode *parent)
Definition GridBuilder.h:189
TileIterator()
Definition GridBuilder.h:188
bool isValueOn() const
Definition GridBuilder.h:204
TileIterator & operator++()
Definition GridBuilder.h:205
const Tile & operator*() const
Definition GridBuilder.h:193
Coord getCoord() const
Definition GridBuilder.h:196
TileIterator operator++(int)
Definition GridBuilder.h:210
const Tile * operator->() const
Definition GridBuilder.h:194
TileIterator & operator=(const TileIterator &)=default
uint32_t pos() const
Definition GridBuilder.h:215
const ChildT * probeChild(ValueType &value)
Definition GridBuilder.h:198
ValueIterator & operator=(const ValueIterator &)=default
Coord getOrigin() const
Definition GridBuilder.h:126
ValueIterator & operator++()
Definition GridBuilder.h:129
ValueIterator operator++(int)
Definition GridBuilder.h:135
Coord getCoord() const
Definition GridBuilder.h:127
bool isActive() const
Definition GridBuilder.h:125
ValueIterator()
Definition GridBuilder.h:119
ValueType operator*() const
Definition GridBuilder.h:124
uint32_t pos() const
Definition GridBuilder.h:140
ValueIterator(const RootNode *parent)
Definition GridBuilder.h:120
Coord getOrigin() const
Definition GridBuilder.h:160
ValueOnIterator operator++(int)
Definition GridBuilder.h:169
Coord getCoord() const
Definition GridBuilder.h:161
ValueOnIterator(const RootNode *parent)
Definition GridBuilder.h:155
ValueOnIterator & operator=(const ValueOnIterator &)=default
ValueOnIterator & operator++()
Definition GridBuilder.h:163
ValueType operator*() const
Definition GridBuilder.h:159
uint32_t pos() const
Definition GridBuilder.h:174
ValueOnIterator()
Definition GridBuilder.h:154
Definition DitherLUT.h:19
Definition GridBuilder.h:35
Grid< Vec3f > Vec3fGrid
Definition GridBuilder.h:2039
Grid< float > FloatGrid
Definition GridBuilder.h:2030
Grid< Fp4 > Fp4Grid
Definition GridBuilder.h:2031
RootNode< BuildUpper< T > > BuildRoot
Definition GridBuilder.h:2026
Grid< Vec3d > Vec3dGrid
Definition GridBuilder.h:2040
Grid< int32_t > Int32Grid
Definition GridBuilder.h:2036
Grid< uint32_t > UInt32Grid
Definition GridBuilder.h:2037
Grid< Vec4f > Vec4fGrid
Definition GridBuilder.h:2041
Grid< ValueMask > MaskGrid
Definition GridBuilder.h:2043
LeafNode< T > BuildLeaf
Definition GridBuilder.h:2020
Grid< ValueOnIndex > OnIndexGrid
Definition GridBuilder.h:2045
InternalNode< BuildLower< T > > BuildUpper
Definition GridBuilder.h:2024
void levelSetToFog(NodeManagerT &mgr, bool rebuild=true)
Definition GridBuilder.h:2165
Grid< double > DoubleGrid
Definition GridBuilder.h:2035
Grid< Fp16 > Fp16Grid
Definition GridBuilder.h:2033
Grid< Fp8 > Fp8Grid
Definition GridBuilder.h:2032
Grid< FpN > FpNGrid
Definition GridBuilder.h:2034
Grid< int64_t > Int64Grid
Definition GridBuilder.h:2038
util::enable_if< util::is_floating_point< typenameNodeManagerT::ValueType >::value >::type sdfToLevelSet(NodeManagerT &mgr)
Definition GridBuilder.h:2147
Grid< ValueIndex > IndexGrid
Definition GridBuilder.h:2044
Grid< Vec4d > Vec4dGrid
Definition GridBuilder.h:2042
Grid< bool > BoolGrid
Definition GridBuilder.h:2046
typename BuildRoot< T >::Tile BuildTile
Definition GridBuilder.h:2028
InternalNode< BuildLeaf< T > > BuildLower
Definition GridBuilder.h:2022
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:42
Range< 1, size_t > Range1D
Definition Range.h:33
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:34
GridType toGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:848
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition NanoVDB.h:292
@ FogVolume
Definition NanoVDB.h:294
@ Unknown
Definition NanoVDB.h:292
@ LevelSet
Definition NanoVDB.h:293
GridType
List of types that are currently supported by NanoVDB.
Definition NanoVDB.h:223
math::Vec3< double > Vec3d
Definition Math.h:2826
math::BBox< Coord > CoordBBox
Definition Math.h:2838
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:337
#define NANOVDB_ASSERT(x)
Definition Util.h:53
T type
Definition NanoVDB.h:532
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:1399
Trait to map from LEVEL to node type.
Definition NanoVDB.h:4703
Implements Tree::isActive(Coord)
Definition GridBuilder.h:2260
static bool get(const BuildRoot< T > &)
Definition GridBuilder.h:2261
static bool get(const BuildTile< T > &tile)
Definition GridBuilder.h:2262
static bool get(const BuildUpper< T > &node, uint32_t n)
Definition GridBuilder.h:2263
static bool get(const BuildLower< T > &node, uint32_t n)
Definition GridBuilder.h:2264
static bool get(const BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2265
Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate ijk.
Definition GridBuilder.h:2249
static auto get(const BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2254
static auto get(const BuildLower< T > &node, uint32_t n)
Definition GridBuilder.h:2253
static auto get(const BuildRoot< T > &root)
Definition GridBuilder.h:2250
static auto get(const BuildTile< T > &tile)
Definition GridBuilder.h:2251
static auto get(const BuildUpper< T > &node, uint32_t n)
Definition GridBuilder.h:2252
Definition GridBuilder.h:1880
const GridType & gridType() const
Definition GridBuilder.h:1903
TreeType & tree()
Definition GridBuilder.h:1902
void setTransform(double scale=1.0, const Vec3d &translation=Vec3d(0.0))
Definition GridBuilder.h:1906
Grid(const ValueType &background, const std::string &name="", GridClass gClass=GridClass::Unknown)
Definition GridBuilder.h:1894
const std::string & getName() const
Definition GridBuilder.h:1908
std::string mName
Definition GridBuilder.h:1892
RootNode< Node2 > RootNodeType
Definition GridBuilder.h:1887
GridType mGridType
Definition GridBuilder.h:1890
const GridClass & gridClass() const
Definition GridBuilder.h:1904
GridClass mGridClass
Definition GridBuilder.h:1889
InternalNode< Node1 > Node2
Definition GridBuilder.h:1886
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:1927
Tree< BuildT > TreeType
Definition GridBuilder.h:1883
void setName(const std::string &name)
Definition GridBuilder.h:1909
LeafNode< BuildT > Node0
Definition GridBuilder.h:1884
Map mMap
Definition GridBuilder.h:1891
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1882
InternalNode< Node0 > Node1
Definition GridBuilder.h:1885
const std::string & gridName() const
Definition GridBuilder.h:1907
const Map & map() const
Definition GridBuilder.h:1905
BuildT BuildType
Definition GridBuilder.h:1881
Tile(const ValueType &v)
Definition GridBuilder.h:631
Tile(ChildT *c=nullptr)
Definition GridBuilder.h:630
ChildT * child
Definition GridBuilder.h:633
ValueType value
Definition GridBuilder.h:634
Definition GridBuilder.h:612
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
InternalNode & operator=(InternalNode &&)=delete
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition GridBuilder.h:882
const MaskT & valueMask() const
Definition GridBuilder.h:742
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:775
void getNodes(std::vector< NodeT * > &array)
Definition GridBuilder.h:957
ValueType getLastValue() const
Definition GridBuilder.h:783
MaskT mChildMask
Definition GridBuilder.h:639
const MaskT & getValueMask() const
Definition GridBuilder.h:741
ValueOnIterator beginValueOn()
Definition GridBuilder.h:694
~InternalNode()
Definition GridBuilder.h:735
static constexpr uint32_t MASK
Definition GridBuilder.h:621
typename MaskT::template Iterator< On > MaskIterT
Definition GridBuilder.h:626
typename ChildT::BuildType BuildType
Definition GridBuilder.h:614
typename NanoNode< BuildType, LEVEL >::Type NanoNodeT
Definition GridBuilder.h:627
static constexpr uint32_t LEVEL
Definition GridBuilder.h:622
void addChild(ChildT *&child)
Definition GridBuilder.h:970
void nodeCount(std::array< size_t, 3 > &count) const
Definition GridBuilder.h:747
Tile mTable[SIZE]
Definition GridBuilder.h:640
const Coord & origin() const
Definition GridBuilder.h:745
static uint32_t CoordToOffset(const Coord &ijk)
Definition GridBuilder.h:755
Mask< LOG2DIM > MaskT
Definition GridBuilder.h:624
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:898
static constexpr uint32_t DIM
Definition GridBuilder.h:619
void addNode(NodeT *&node)
Definition GridBuilder.h:1017
uint32_t nodeCount() const
Definition GridBuilder.h:941
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:769
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:856
uint64_t mDstOffset
Definition GridBuilder.h:644
DenseIterator beginDense()
Definition GridBuilder.h:720
ChildT ChildNodeType
Definition GridBuilder.h:615
auto setAndCache(const Coord &ijk, const AccT &acc, ArgsT &&... args)
Definition GridBuilder.h:824
ValueIterator beginValue()
Definition GridBuilder.h:678
util::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:1060
ChildIterator beginChild()
Definition GridBuilder.h:661
DenseIterator cbeginChildAll() const
Definition GridBuilder.h:721
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:762
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:786
typename ChildT::LeafNodeType LeafNodeType
Definition GridBuilder.h:616
static constexpr uint32_t TOTAL
Definition GridBuilder.h:618
ValueType getFirstValue() const
Definition GridBuilder.h:782
InternalNode(InternalNode &&)=delete
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:617
typename ChildT::ValueType ValueType
Definition GridBuilder.h:613
InternalNode(const Coord &origin, const ValueType &value, bool state)
Definition GridBuilder.h:723
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:679
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:695
MaskT mValueMask
Definition GridBuilder.h:638
void merge(InternalNode &other)
Definition GridBuilder.h:1035
auto getAndCache(const Coord &ijk, const AccT &acc, ArgsT &&... args) const
Definition GridBuilder.h:810
NanoNodeT * mDstNode
Definition GridBuilder.h:643
static constexpr uint32_t SIZE
Definition GridBuilder.h:620
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:794
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:871
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:848
const MaskT & getChildMask() const
Definition GridBuilder.h:743
const MaskT & childMask() const
Definition GridBuilder.h:744
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:623
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:914
Coord mOrigin
Definition GridBuilder.h:637
InternalNode & operator=(const InternalNode &)=delete
ChildIterator cbeginChildOn() const
Definition GridBuilder.h:662
InternalNode(const InternalNode &)=delete
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:929
Mask< LOG2DIM > NodeMaskType
Definition GridBuilder.h:1300
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1400
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1302
bool getLastValue() const
Definition GridBuilder.h:1408
LeafNode & operator=(LeafNode &&)=delete
void merge(LeafNode &other)
Definition GridBuilder.h:1449
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1433
bool getFirstValue() const
Definition GridBuilder.h:1407
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1325
static constexpr uint32_t MASK
Definition GridBuilder.h:1297
LeafNode< BuildType > LeafNodeType
Definition GridBuilder.h:1292
void setValueAndCache(const Coord &ijk, bool, const AccT &)
Definition GridBuilder.h:1426
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition GridBuilder.h:1303
static constexpr uint32_t LEVEL
Definition GridBuilder.h:1298
ValueMask BuildType
Definition GridBuilder.h:1291
bool getValue(uint32_t i) const
Definition GridBuilder.h:1409
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1342
LeafNode & operator=(const LeafNode &)=delete
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1379
const Coord & origin() const
Definition GridBuilder.h:1381
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1384
LeafNode(const Coord &ijk, const ValueType &, bool state)
Definition GridBuilder.h:1367
static constexpr uint32_t DIM
Definition GridBuilder.h:1295
NanoLeafT * mDstNode
Definition GridBuilder.h:1308
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1398
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1420
uint64_t mDstOffset
Definition GridBuilder.h:1309
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1440
bool ValueType
Definition GridBuilder.h:1290
ValueIterator beginValue()
Definition GridBuilder.h:1364
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1391
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1306
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1413
static constexpr uint32_t TOTAL
Definition GridBuilder.h:1294
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:1293
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1380
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1365
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1326
void setValue(const Coord &ijk)
Definition GridBuilder.h:1447
void setValue(uint32_t n, bool)
Definition GridBuilder.h:1446
static constexpr uint32_t SIZE
Definition GridBuilder.h:1296
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:1416
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1341
bool getValue(const Coord &ijk) const
Definition GridBuilder.h:1410
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:1299
Coord mOrigin
Definition GridBuilder.h:1305
Mask< LOG2DIM > NodeMaskType
Definition GridBuilder.h:1471
Mask< LOG2DIM > mValues
Definition GridBuilder.h:1477
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1575
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1473
bool getLastValue() const
Definition GridBuilder.h:1582
LeafNode & operator=(LeafNode &&)=delete
void merge(LeafNode &other)
Definition GridBuilder.h:1625
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1611
bool getFirstValue() const
Definition GridBuilder.h:1581
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1496
static constexpr uint32_t MASK
Definition GridBuilder.h:1468
void setValue(uint32_t n, bool value)
Definition GridBuilder.h:1618
LeafNode< BuildType > LeafNodeType
Definition GridBuilder.h:1463
typename NanoNode< BuildType, 0 >::Type NanoLeafT
Definition GridBuilder.h:1474
static constexpr uint32_t LEVEL
Definition GridBuilder.h:1469
ValueMask BuildType
Definition GridBuilder.h:1462
bool getValue(uint32_t i) const
Definition GridBuilder.h:1584
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1513
LeafNode & operator=(const LeafNode &)=delete
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1551
const Coord & origin() const
Definition GridBuilder.h:1553
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1556
void setValue(const Coord &ijk, bool value)
Definition GridBuilder.h:1623
static constexpr uint32_t DIM
Definition GridBuilder.h:1466
NanoLeafT * mDstNode
Definition GridBuilder.h:1479
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1570
bool getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1597
uint64_t mDstOffset
Definition GridBuilder.h:1480
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1591
bool ValueType
Definition GridBuilder.h:1461
ValueIterator beginValue()
Definition GridBuilder.h:1535
LeafNode(const Coord &ijk, bool value, bool state)
Definition GridBuilder.h:1538
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1563
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1477
static constexpr uint32_t TOTAL
Definition GridBuilder.h:1465
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:1464
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1552
LeafNode(const LeafNode &)=delete
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1536
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1497
static constexpr uint32_t SIZE
Definition GridBuilder.h:1467
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1512
bool getValue(const Coord &ijk) const
Definition GridBuilder.h:1585
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:1470
void setValueAndCache(const Coord &ijk, bool value, const AccT &)
Definition GridBuilder.h:1603
Coord mOrigin
Definition GridBuilder.h:1476
Definition GridBuilder.h:1094
Mask< LOG2DIM > NodeMaskType
Definition GridBuilder.h:1105
Coord offsetToGlobalCoord(uint32_t n) const
Definition GridBuilder.h:1215
ValueType mValues[SIZE]
Definition GridBuilder.h:1112
ValueType getLastValue() const
Definition GridBuilder.h:1223
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
Definition GridBuilder.h:1107
LeafNode & operator=(LeafNode &&)=delete
void merge(LeafNode &other)
Definition GridBuilder.h:1269
LeafNode< BuildT > LeafNodeType
Definition GridBuilder.h:1097
void setValueOnAndCache(const Coord &ijk, const AccT &)
Definition GridBuilder.h:1249
ValueOnIterator beginValueOn()
Definition GridBuilder.h:1131
static constexpr uint32_t MASK
Definition GridBuilder.h:1102
static constexpr uint32_t LEVEL
Definition GridBuilder.h:1103
const ValueType & getValue(const Coord &ijk) const
Definition GridBuilder.h:1225
ValueOffIterator cbeginValueOff() const
Definition GridBuilder.h:1148
LeafNode & operator=(const LeafNode &)=delete
const Mask< LOG2DIM > & valueMask() const
Definition GridBuilder.h:1192
const Coord & origin() const
Definition GridBuilder.h:1193
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
Definition GridBuilder.h:1196
static constexpr uint32_t DIM
Definition GridBuilder.h:1100
NanoLeafT * mDstNode
Definition GridBuilder.h:1114
void localToGlobalCoord(Coord &ijk) const
Definition GridBuilder.h:1210
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1267
const ValueType & getValue(uint32_t i) const
Definition GridBuilder.h:1224
uint64_t mDstOffset
Definition GridBuilder.h:1115
const ValueType & getValueAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1235
bool isActiveAndCache(const Coord &ijk, const AccT &) const
Definition GridBuilder.h:1256
LeafNode(LeafNode &&)=delete
ValueIterator beginValue()
Definition GridBuilder.h:1171
util::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:1638
static Coord OffsetToLocalCoord(uint32_t n)
Definition GridBuilder.h:1203
Mask< LOG2DIM > mValueMask
Definition GridBuilder.h:1111
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1228
static constexpr uint32_t TOTAL
Definition GridBuilder.h:1099
ValueType getFirstValue() const
Definition GridBuilder.h:1222
static constexpr uint32_t LOG2DIM
Definition GridBuilder.h:1098
const Mask< LOG2DIM > & getValueMask() const
Definition GridBuilder.h:1191
LeafNode(const LeafNode &)=delete
typename NanoNode< BuildT, 0 >::Type NanoLeafT
Definition GridBuilder.h:1108
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1096
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:1172
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:1132
void setValueAndCache(const Coord &ijk, const ValueType &value, const AccT &)
Definition GridBuilder.h:1241
static constexpr uint32_t SIZE
Definition GridBuilder.h:1101
auto set(const Coord &ijk, ArgsT &&... args)
Definition GridBuilder.h:1231
ValueOffIterator beginValueOff()
Definition GridBuilder.h:1147
LeafNode(const Coord &ijk, const ValueType &value, bool state)
Definition GridBuilder.h:1174
void setValue(uint32_t n, const ValueType &value)
Definition GridBuilder.h:1262
static constexpr uint64_t NUM_VALUES
Definition GridBuilder.h:1104
Coord mOrigin
Definition GridBuilder.h:1110
BuildT BuildType
Definition GridBuilder.h:1095
Implements Tree::probeLeaf(Coord)
Definition GridBuilder.h:2285
typename BuildLeaf< T >::ValueType ValueT
Definition GridBuilder.h:2286
static bool get(const BuildTile< T > &tile, ValueT &v)
Definition GridBuilder.h:2291
static bool get(const BuildLower< T > &node, uint32_t n, ValueT &v)
Definition GridBuilder.h:2299
static bool get(const BuildRoot< T > &root, ValueT &v)
Definition GridBuilder.h:2287
static bool get(const BuildUpper< T > &node, uint32_t n, ValueT &v)
Definition GridBuilder.h:2295
static bool get(const BuildLeaf< T > &leaf, uint32_t n, ValueT &v)
Definition GridBuilder.h:2303
Definition GridBuilder.h:55
bool isActive() const
Definition GridBuilder.h:60
Tile(const ValueType &v, bool s)
Definition GridBuilder.h:57
Tile(ChildT *c=nullptr)
Definition GridBuilder.h:56
ChildT * child
Definition GridBuilder.h:61
bool isValue() const
Definition GridBuilder.h:59
bool state
Definition GridBuilder.h:63
bool isChild() const
Definition GridBuilder.h:58
ValueType value
Definition GridBuilder.h:62
Definition GridBuilder.h:49
uint32_t tileCount() const
Definition GridBuilder.h:234
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
RootNode(RootNode &&)=default
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
Definition GridBuilder.h:387
void getNodes(std::vector< NodeT * > &array)
Definition GridBuilder.h:462
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:340
ValueOnIterator beginValueOn()
Definition GridBuilder.h:180
typename ChildT::BuildType BuildType
Definition GridBuilder.h:51
Tile * probeTile(const Coord &ijk)
Definition GridBuilder.h:69
static constexpr uint32_t LEVEL
Definition GridBuilder.h:54
void addChild(ChildT *&child)
Definition GridBuilder.h:477
void nodeCount(std::array< size_t, 3 > &count) const
Definition GridBuilder.h:238
uint32_t getTableSize() const
Definition GridBuilder.h:235
void merge(RootNode &other)
Definition GridBuilder.h:553
RootNode & operator=(const RootNode &)=delete
RootNode & operator=(RootNode &&)=default
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:406
bool empty() const
Definition GridBuilder.h:246
void addNode(NodeT *&node)
Definition GridBuilder.h:532
uint32_t nodeCount() const
Definition GridBuilder.h:445
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:342
RootNode(const RootNode &)=delete
ChildT ChildNodeType
Definition GridBuilder.h:52
ChildIterator cbeginChild() const
Definition GridBuilder.h:111
ValueIterator beginValue()
Definition GridBuilder.h:146
util::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Definition GridBuilder.h:579
RootNode(const ValueType &background)
Definition GridBuilder.h:226
TileIterator cbeginChildAll() const
Definition GridBuilder.h:222
typename ChildT::LeafNodeType LeafNodeType
Definition GridBuilder.h:53
ValueType mBackground
Definition GridBuilder.h:67
~RootNode()
Definition GridBuilder.h:232
std::map< Coord, Tile > MapT
Definition GridBuilder.h:65
typename ChildT::ValueType ValueType
Definition GridBuilder.h:50
void clear()
Definition GridBuilder.h:248
TileIterator beginTile()
Definition GridBuilder.h:221
ValueIterator cbeginValueAll() const
Definition GridBuilder.h:147
ValueOnIterator cbeginValueOn() const
Definition GridBuilder.h:181
const ValueType & background() const
Definition GridBuilder.h:236
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:374
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:324
const Tile * probeTile(const Coord &ijk) const
Definition GridBuilder.h:74
MapT mTable
Definition GridBuilder.h:66
static Coord CoordToKey(const Coord &ijk)
Definition GridBuilder.h:254
void touchLeafAndCache(const Coord &ijk, AccT &acc)
Definition GridBuilder.h:425
ChildIterator cbeginChildOn() const
Definition GridBuilder.h:112
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
Definition GridBuilder.h:361
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:2271
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n)
Definition GridBuilder.h:2272
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n, const typename BuildLeaf< T >::ValueType &v)
Definition GridBuilder.h:2276
Definition GridBuilder.h:2241
static BuildLeaf< T > & set(BuildLeaf< T > &leaf, uint32_t)
Definition GridBuilder.h:2242
Definition GridBuilder.h:1844
typename AccT::Node2 Node2
Definition GridBuilder.h:1849
~WriteAccessor()
Definition GridBuilder.h:1861
WriteAccessor(const WriteAccessor &)=delete
RootNodeType mRoot
Definition GridBuilder.h:1871
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1869
ValueAccessor< BuildT > AccT
Definition GridBuilder.h:1845
std::mutex & mMutex
Definition GridBuilder.h:1873
WriteAccessor(WriteAccessor &&)=default
RootNodeType & mParent
Definition GridBuilder.h:1871
typename AccT::Node1 Node1
Definition GridBuilder.h:1848
WriteAccessor(RootNodeType &parent, std::mutex &mx)
Definition GridBuilder.h:1852
void setValueOn(const Coord &ijk)
Definition GridBuilder.h:1868
AccT mAcc
Definition GridBuilder.h:1872
typename AccT::LeafT LeafT
Definition GridBuilder.h:1847
void merge()
Definition GridBuilder.h:1862
typename AccT::RootNodeType RootNodeType
Definition GridBuilder.h:1850
typename AccT::ValueType ValueType
Definition GridBuilder.h:1846
ValueAccessor< BuildT > getAccessor()
regular accessor for thread-safe reading and non-thread-safe writing
Definition GridBuilder.h:1835
RootNodeType & root()
Definition GridBuilder.h:1824
std::array< size_t, 3 > nodeCount() const
Definition GridBuilder.h:1828
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:1826
Tree & tree()
Definition GridBuilder.h:1823
RootNodeType mRoot
Definition GridBuilder.h:1817
RootNode< Node2 > RootNodeType
Definition GridBuilder.h:1813
void setValue(const Coord &ijk, const ValueType &value)
Definition GridBuilder.h:1827
InternalNode< Node1 > Node2
Definition GridBuilder.h:1812
std::mutex mMutex
Definition GridBuilder.h:1818
Tree(const Tree &)=delete
LeafNode< BuildT > Node0
Definition GridBuilder.h:1810
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1809
InternalNode< Node0 > Node1
Definition GridBuilder.h:1811
WriteAccessor getWriteAccessor()
special accessor for thread-safe writing only
Definition GridBuilder.h:1837
typename RootNodeType::LeafNodeType LeafNodeType
Definition GridBuilder.h:1814
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:1825
Tree(const ValueType &background)
Definition GridBuilder.h:1820
Definition GridBuilder.h:1670
RootNodeType & mRoot
Definition GridBuilder.h:1799
void * mNode[3]
Definition GridBuilder.h:1801
ValueType getValue(int i, int j, int k) const
Definition GridBuilder.h:1686
RootNode< Node2 > RootNodeType
Definition GridBuilder.h:1675
ValueAccessor(const ValueAccessor &)=delete
Coord mKeys[3]
Definition GridBuilder.h:1800
InternalNode< Node1 > Node2
Definition GridBuilder.h:1674
void touchLeaf(const Coord &ijk) const
Definition GridBuilder.h:1767
bool isActive(const Coord &ijk) const
Definition GridBuilder.h:1779
void insert(const Coord &ijk, NodeT *node) const
Definition GridBuilder.h:1794
bool isValueOn(const Coord &ijk) const
Definition GridBuilder.h:1792
LeafT * setValue(const Coord &ijk, const ValueType &value)
Sets value in a leaf node and returns it.
Definition GridBuilder.h:1741
auto get(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1696
ValueAccessor(ValueAccessor &&)=default
void setValueOn(const Coord &ijk)
Definition GridBuilder.h:1755
typename BuildToValueMap< BuildT >::type ValueType
Definition GridBuilder.h:1671
auto set(const Coord &ijk, ArgsT &&... args) const
Definition GridBuilder.h:1709
ValueAccessor(RootNodeType &root)
Definition GridBuilder.h:1678
typename RootNodeType::LeafNodeType LeafNodeType
Definition GridBuilder.h:1676
ValueType getValue(const Coord &ijk) const
Definition GridBuilder.h:1728
LeafNode< BuildT > LeafT
Definition GridBuilder.h:1672
InternalNode< LeafT > Node1
Definition GridBuilder.h:1673
bool isCached(const Coord &ijk) const
Definition GridBuilder.h:1688
C++11 implementation of std::enable_if.
Definition Util.h:384
C++11 implementation of std::is_same.
Definition Util.h:358
static constexpr bool value
Definition Util.h:359