15 #ifndef NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
16 #define NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
47 template<
typename ChildT>
54 static constexpr uint32_t
LEVEL = 1 + ChildT::LEVEL;
65 using MapT = std::map<Coord, Tile>;
71 return iter ==
mTable.end() ?
nullptr : &(iter->second);
76 return iter ==
mTable.end() ?
nullptr : &(iter->second);
82 typename MapT::const_iterator mIter;
86 while (mIter!=parent->
mTable.end() && mIter->second.child==
nullptr) ++mIter;
93 operator bool()
const {
return mParent && mIter!=mParent->
mTable.end();}
97 while (mIter!=mParent->
mTable.end() && mIter->second.child==
nullptr) ++mIter;
117 typename MapT::const_iterator mIter;
121 while (mIter!=parent->
mTable.end() && mIter->second.child!=
nullptr) ++mIter;
128 operator bool()
const {
return mParent && mIter!=mParent->
mTable.end();}
132 while (mIter!=mParent->
mTable.end() && mIter->second.child!=
nullptr) ++mIter;
152 typename MapT::const_iterator mIter;
156 while (mIter!=parent->
mTable.end() && (mIter->second.child!=
nullptr || !mIter->second.state)) ++mIter;
162 operator bool()
const {
return mParent && mIter!=mParent->
mTable.end();}
166 while (mIter!=mParent->
mTable.end() && (mIter->second.child!=
nullptr || !mIter->second.state)) ++mIter;
186 typename MapT::const_iterator mIter;
197 operator bool()
const {
return mParent && mIter!=mParent->
mTable.end();}
200 const ChildT *child = mIter->second.child;
201 if (child==
nullptr) value = mIter->second.value;
204 bool isValueOn()
const {
return mIter->second.child==
nullptr && mIter->second.state;}
241 count[ChildT::LEVEL] += 1;
242 it->nodeCount(count);
250 for (
auto iter =
mTable.begin(); iter !=
mTable.end(); ++iter)
delete iter->second.child;
256 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
257 template<
typename OpT,
typename... ArgsT>
258 auto get(
const Coord& ijk, ArgsT&&...
args)
const
260 if (
const Tile *tile = this->
probeTile(ijk)) {
261 if (
auto *child = tile->child)
return child->template get<OpT>(ijk,
args...);
266 template<
typename OpT,
typename... ArgsT>
267 auto set(
const Coord& ijk, ArgsT&&...
args)
269 ChildT* child =
nullptr;
271 auto iter =
mTable.find(key);
272 if (iter ==
mTable.end()) {
274 mTable[key] = Tile(child);
275 }
else if (iter->second.child !=
nullptr) {
276 child = iter->second.child;
278 child =
new ChildT(ijk, iter->second.value, iter->second.state);
279 iter->second.child = child;
282 return child->template set<OpT>(ijk,
args...);
284 template<
typename OpT,
typename AccT,
typename... ArgsT>
285 auto getAndCache(
const Coord& ijk,
const AccT& acc, ArgsT&&...
args)
const
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...);
297 template<
typename OpT,
typename AccT,
typename... ArgsT>
298 auto setAndCache(
const Coord& ijk,
const AccT& acc, ArgsT&&...
args)
300 ChildT* child =
nullptr;
302 auto iter =
mTable.find(key);
303 if (iter ==
mTable.end()) {
305 mTable[key] = Tile(child);
306 }
else if (iter->second.child !=
nullptr) {
307 child = iter->second.child;
309 child =
new ChildT(ijk, iter->second.value, iter->second.state);
310 iter->second.child = child;
313 acc.insert(ijk, child);
314 return child->template setAndCache<OpT>(ijk, acc,
args...);
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));}
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);}
327 if (
auto *tile = this->
probeTile(ijk))
return tile->child ? tile->child->getValue(ijk) : tile->value;
331 if (iter ==
mTable.end()) {
333 }
else if (iter->second.child) {
334 return iter->second.child->getValue(ijk);
336 return iter->second.value;
344 ChildT* child =
nullptr;
346 auto iter =
mTable.find(key);
347 if (iter ==
mTable.end()) {
349 mTable[key] = Tile(child);
350 }
else if (iter->second.child !=
nullptr) {
351 child = iter->second.child;
353 child =
new ChildT(ijk, iter->second.value, iter->second.state);
354 iter->second.child = child;
357 child->setValue(ijk, value);
360 template<
typename AccT>
366 if (iter->second.child) {
367 acc.insert(ijk, iter->second.child);
368 return iter->second.child->isActiveAndCache(ijk, acc);
370 return iter->second.state;
373 template<
typename AccT>
379 if (iter->second.child) {
380 acc.insert(ijk, iter->second.child);
381 return iter->second.child->getValueAndCache(ijk, acc);
383 return iter->second.value;
386 template<
typename AccT>
389 ChildT* child =
nullptr;
391 auto iter =
mTable.find(key);
392 if (iter ==
mTable.end()) {
394 mTable[key] = Tile(child);
395 }
else if (iter->second.child !=
nullptr) {
396 child = iter->second.child;
398 child =
new ChildT(ijk, iter->second.value, iter->second.state);
399 iter->second.child = child;
402 acc.insert(ijk, child);
403 child->setValueAndCache(ijk, value, acc);
405 template<
typename AccT>
408 ChildT* child =
nullptr;
410 auto iter =
mTable.find(key);
411 if (iter ==
mTable.end()) {
413 mTable[key] = Tile(child);
414 }
else if (iter->second.child !=
nullptr) {
415 child = iter->second.child;
417 child =
new ChildT(ijk, iter->second.value, iter->second.state);
418 iter->second.child = child;
421 acc.insert(ijk, child);
422 child->setValueOnAndCache(ijk, acc);
424 template<
typename AccT>
427 ChildT* child =
nullptr;
429 auto iter =
mTable.find(key);
430 if (iter ==
mTable.end()) {
432 mTable[key] = Tile(child);
433 }
else if (iter->second.child !=
nullptr) {
434 child = iter->second.child;
436 child =
new ChildT(ijk, iter->second.value, iter->second.state);
437 iter->second.child = child;
439 acc.insert(ijk, child);
440 child->touchLeafAndCache(ijk, acc);
442 #endif// NANOVDB_NEW_ACCESSOR_METHODS
444 template<
typename NodeT>
448 static_assert(NodeT::LEVEL <
LEVEL,
"Root::getNodes: LEVEL error");
450 for (
auto iter =
mTable.begin(); iter !=
mTable.end(); ++iter) {
451 if (iter->second.child ==
nullptr)
continue;
455 sum += iter->second.child->template nodeCount<NodeT>();
461 template<
typename NodeT>
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)
470 array.push_back(reinterpret_cast<NodeT*>(iter->second.child));
472 iter->second.child->getNodes(array);
481 auto iter =
mTable.find(key);
482 if (iter !=
mTable.end() && iter->second.child !=
nullptr) {
483 delete iter->second.child;
484 iter->second.child = child;
486 mTable[key] = Tile(child);
498 template <u
int32_t level>
501 static_assert(
level > 0 &&
level <=
LEVEL,
"invalid template value of level");
503 auto iter =
mTable.find(key);
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;
511 delete iter->second.child;
512 iter->second.child =
nullptr;
513 iter->second.value =
value;
514 iter->second.state = state;
517 ChildT* child =
nullptr;
518 if (iter ==
mTable.end()) {
520 mTable[key] = Tile(child);
521 }
else if (iter->second.child !=
nullptr) {
522 child = iter->second.child;
524 child =
new ChildT(ijk, iter->second.value, iter->second.state);
525 iter->second.child = child;
527 child->template addTile<level>(ijk,
value, state);
531 template<
typename NodeT>
535 this->
addChild(reinterpret_cast<ChildT*&>(node));
537 ChildT* child =
nullptr;
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;
546 child =
new ChildT(node->mOrigin, iter->second.value, iter->second.state);
547 iter->second.child = child;
549 child->addNode(node);
555 for (
auto iter1 = other.
mTable.begin(); iter1 != other.
mTable.end(); ++iter1) {
556 if (iter1->second.child ==
nullptr)
continue;
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;
562 iter2->second.child->merge(*iter1->second.child);
576 template<
typename ChildT>
581 std::map<Coord, ChildT*> nodeKeys;
582 for (
auto iter = mTable.begin(); iter != mTable.end(); ++iter) {
583 if (iter->second.child ==
nullptr)
585 nodeKeys.insert(std::pair<Coord, ChildT*>(iter->first, iter->second.child));
590 auto b = nodeKeys.begin(), e = nodeKeys.end();
593 for (
auto a =
b++;
b != e; ++
a, ++
b) {
595 if (d[0] != 0 || d[1] != 0 || d[2] ==
int(ChildT::DIM))
597 const ValueType fill[] = {
a->second->getLastValue(),
b->second->getFirstValue()};
598 if (!(fill[0] < 0) || !(fill[1] < 0))
601 for (; c[2] !=
b->first[2]; c[2] += ChildT::DIM) {
610 template<
typename ChildT>
617 static constexpr uint32_t
LOG2DIM = ChildT::LOG2DIM + 1;
622 static constexpr uint32_t
LEVEL = 1 + ChildT::LEVEL;
626 using MaskIterT =
typename MaskT::template Iterator<On>;
709 ChildT *child =
nullptr;
729 for (uint32_t i = 0; i <
SIZE; ++i)
mTable[i].value = value;
750 if constexpr(ChildT::LEVEL>0) {
751 for (
auto it = const_cast<InternalNode*>(
this)->
beginChild(); it; ++it) it->nodeCount(count);
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);
765 const uint32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
771 ijk <<= ChildT::TOTAL;
785 template<
typename OpT,
typename... ArgsT>
793 template<
typename OpT,
typename... ArgsT>
797 ChildT* child =
nullptr;
806 return child->template set<OpT>(ijk,
args...);
809 template<
typename OpT,
typename AccT,
typename... ArgsT>
815 acc.insert(ijk, child);
816 if constexpr(ChildT::LEVEL == 0) {
817 return child->template get<OpT>(ijk,
args...);
819 return child->template getAndCache<OpT>(ijk, acc,
args...);
823 template<
typename OpT,
typename AccT,
typename... ArgsT>
827 ChildT* child =
nullptr;
836 acc.insert(ijk, child);
837 if constexpr(ChildT::LEVEL == 0) {
838 return child->template set<OpT>(ijk,
args...);
840 return child->template setAndCache<OpT>(ijk, acc,
args...);
844 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
859 ChildT* child =
nullptr;
867 child->setValue(ijk, value);
870 template<
typename AccT>
875 acc.insert(ijk, const_cast<ChildT*>(
mTable[n].child));
881 template<
typename AccT>
885 ChildT* child =
nullptr;
893 acc.insert(ijk, child);
894 child->setValueAndCache(ijk, value, acc);
897 template<
typename AccT>
901 ChildT* child =
nullptr;
909 acc.insert(ijk, child);
910 child->setValueOnAndCache(ijk, acc);
913 template<
typename AccT>
917 ChildT* child =
nullptr;
925 acc.insert(ijk, child);
926 if constexpr(
LEVEL>1) child->touchLeafAndCache(ijk, acc);
928 template<
typename AccT>
933 acc.insert(ijk, const_cast<ChildT*>(
mTable[n].child));
940 template<
typename NodeT>
948 }
else if constexpr(
LEVEL>1) {
950 sum +=
mTable[*iter].
child->template nodeCount<NodeT>();
956 template<
typename NodeT>
963 array.push_back(reinterpret_cast<NodeT*>(
mTable[*iter].child));
964 }
else if constexpr(
LEVEL>1) {
990 template <u
int32_t level>
993 static_assert(
level > 0 &&
level <=
LEVEL,
"invalid template value of level");
1004 ChildT* child =
nullptr;
1008 child =
new ChildT(ijk, value, state);
1012 child->template addTile<level>(ijk,
value, state);
1016 template<
typename NodeT>
1020 this->
addChild(reinterpret_cast<ChildT*&>(node));
1021 }
else if constexpr(
LEVEL>1) {
1023 ChildT* child =
nullptr;
1031 child->addNode(node);
1038 const uint32_t
n = *iter;
1049 template<
typename T>
1057 template<
typename ChildT>
1058 template<
typename T>
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);
1068 if (mChildMask.isOn(x00)) {
1069 xInside = mTable[x00].child->getLastValue() < 0;
1072 for (uint32_t
y = 0;
y != (1u << LOG2DIM); ++
y) {
1073 const uint32_t xy0 = x00 + (
y << LOG2DIM);
1074 if (mChildMask.isOn(xy0))
1075 yInside = mTable[xy0].child->getLastValue() < 0;
1077 for (uint32_t
z = 0;
z != (1 << LOG2DIM); ++
z) {
1078 const uint32_t xyz = xy0 +
z;
1079 if (mChildMask.isOn(xyz)) {
1080 zInside = mTable[xyz].child->getLastValue() < 0;
1082 mTable[xyz].value = zInside ? -outside : outside;
1092 template<
typename BuildT>
1162 operator bool()
const {
return mPos <
SIZE;}
1198 return ((ijk[0] & int32_t(
MASK)) << (2 *
LOG2DIM)) +
1200 (ijk[2] & int32_t(
MASK));
1206 const int32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
1227 template<
typename OpT,
typename... ArgsT>
1230 template<
typename OpT,
typename... ArgsT>
1233 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1234 template<
typename AccT>
1240 template<
typename AccT>
1248 template<
typename AccT>
1255 template<
typename AccT>
1272 for (
auto iter = other.
mValueMask.beginOn(); iter; ++iter) {
1273 const uint32_t
n = *iter;
1279 template<
typename T>
1357 operator bool()
const {
return mPos <
SIZE;}
1388 return ((ijk[0] & int32_t(
MASK)) << (2 *
LOG2DIM)) +
1390 (ijk[2] & int32_t(
MASK));
1396 const int32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
1414 template<
typename OpT,
typename... ArgsT>
1417 template<
typename OpT,
typename... ArgsT>
1420 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1421 template<
typename AccT>
1427 template<
typename AccT>
1434 template<
typename AccT>
1441 template<
typename AccT>
1530 operator bool()
const {
return mPos <
SIZE;}
1562 return ((ijk[0] & int32_t(
MASK)) << (2 *
LOG2DIM)) +
1564 (ijk[2] & int32_t(
MASK));
1570 const int32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
1593 #ifndef NANOVDB_NEW_ACCESSOR_METHODS
1594 template<
typename AccT>
1600 template<
typename AccT>
1606 template<
typename AccT>
1614 template<
typename AccT>
1639 template<
typename BuildT>
1640 template<
typename T>
1646 bool xInside =
mValues[
first] < 0, yInside = xInside, zInside = xInside;
1647 for (uint32_t
x = 0;
x != DIM; ++
x) {
1648 const uint32_t x00 =
x << (2 * LOG2DIM);
1652 for (uint32_t
y = 0;
y != DIM; ++
y) {
1653 const uint32_t xy0 = x00 + (
y << LOG2DIM);
1657 for (uint32_t
z = 0;
z != (1 << LOG2DIM); ++
z) {
1658 const uint32_t xyz = xy0 +
z;
1662 mValues[xyz] = zInside ? -outside : outside;
1672 template<
typename BuildT>
1685 ,
mNode{
nullptr,
nullptr,
nullptr}
1691 template<
typename NodeT>
1694 return (ijk[0] & int32_t(~NodeT::MASK)) ==
mKeys[NodeT::LEVEL][0] &&
1695 (ijk[1] & int32_t(~NodeT::MASK)) ==
mKeys[NodeT::LEVEL][1] &&
1696 (ijk[2] & int32_t(~NodeT::MASK)) ==
mKeys[NodeT::LEVEL][2];
1699 template <
typename OpT,
typename... ArgsT>
1702 if (this->
template isCached<LeafT>(ijk)) {
1703 return ((
const LeafT*)
mNode[0])->
template get<OpT>(ijk,
args...);
1704 }
else if (this->
template isCached<Node1>(ijk)) {
1705 return ((
const Node1*)
mNode[1])->
template getAndCache<OpT>(ijk, *
this,
args...);
1706 }
else if (this->
template isCached<Node2>(ijk)) {
1707 return ((
const Node2*)
mNode[2])->
template getAndCache<OpT>(ijk, *
this,
args...);
1709 return mRoot.template getAndCache<OpT>(ijk, *
this,
args...);
1712 template <
typename OpT,
typename... ArgsT>
1715 if (this->
template isCached<LeafT>(ijk)) {
1717 }
else if (this->
template isCached<Node1>(ijk)) {
1718 return ((
Node1*)
mNode[1])->template setAndCache<OpT>(ijk, *
this,
args...);
1719 }
else if (this->
template isCached<Node2>(ijk)) {
1720 return ((
Node2*)
mNode[2])->template setAndCache<OpT>(ijk, *
this,
args...);
1722 return mRoot.template setAndCache<OpT>(ijk, *
this,
args...);
1725 #ifdef NANOVDB_NEW_ACCESSOR_METHODS
1728 LeafT*
setValueOn(
const Coord& ijk) {
return this->
template set<SetValue<BuildT>>(ijk);}
1729 LeafT&
touchLeaf(
const Coord& ijk) {
return this->
template set<TouchLeaf<BuildT>>(ijk);}
1730 bool isActive(
const Coord& ijk)
const {
return this->
template get<GetState<BuildT>>(ijk);}
1734 if (this->
template isCached<LeafT>(ijk)) {
1735 return ((
LeafT*)
mNode[0])->getValueAndCache(ijk, *
this);
1736 }
else if (this->
template isCached<Node1>(ijk)) {
1737 return ((
Node1*)
mNode[1])->getValueAndCache(ijk, *
this);
1738 }
else if (this->
template isCached<Node2>(ijk)) {
1739 return ((
Node2*)
mNode[2])->getValueAndCache(ijk, *
this);
1747 if (this->
template isCached<LeafT>(ijk)) {
1749 }
else if (this->
template isCached<Node1>(ijk)) {
1750 ((
Node1*)
mNode[1])->setValueAndCache(ijk, value, *
this);
1751 }
else if (this->
template isCached<Node2>(ijk)) {
1752 ((
Node2*)
mNode[2])->setValueAndCache(ijk, value, *
this);
1761 if (this->
template isCached<LeafT>(ijk)) {
1762 ((
LeafT*)
mNode[0])->setValueOnAndCache(ijk, *
this);
1763 }
else if (this->
template isCached<Node1>(ijk)) {
1764 ((
Node1*)
mNode[1])->setValueOnAndCache(ijk, *
this);
1765 }
else if (this->
template isCached<Node2>(ijk)) {
1766 ((
Node2*)
mNode[2])->setValueOnAndCache(ijk, *
this);
1773 if (this->
template isCached<LeafT>(ijk)) {
1775 }
else if (this->
template isCached<Node1>(ijk)) {
1776 ((
Node1*)
mNode[1])->touchLeafAndCache(ijk, *
this);
1777 }
else if (this->
template isCached<Node2>(ijk)) {
1778 ((
Node2*)
mNode[2])->touchLeafAndCache(ijk, *
this);
1785 if (this->
template isCached<LeafT>(ijk)) {
1786 return ((
LeafT*)
mNode[0])->isActiveAndCache(ijk, *
this);
1787 }
else if (this->
template isCached<Node1>(ijk)) {
1788 return ((
Node1*)
mNode[1])->isActiveAndCache(ijk, *
this);
1789 }
else if (this->
template isCached<Node2>(ijk)) {
1790 return ((
Node2*)
mNode[2])->isActiveAndCache(ijk, *
this);
1797 template<
typename NodeT>
1800 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
1801 mNode[NodeT::LEVEL] = node;
1810 template<
typename BuildT>
1834 std::array<size_t, 3>
count{0,0,0};
1846 template<
typename BuildT>
1858 ,
mRoot(parent.mBackground)
1869 mParent.merge(
mRoot);
1882 template<
typename BuildT>
1925 template <
typename Func>
1929 template <
typename BuildT>
1930 template <
typename Func>
1933 auto &root = this->tree().root();
1934 #if __cplusplus >= 201703L
1936 #else// invoke_result was introduced in C++17 and result_of was removed in C++20
1939 const CoordBBox leafBBox(bbox[0] >> Node0::TOTAL, bbox[1] >> Node0::TOTAL);
1942 Node0* leaf =
nullptr;
1943 for (
auto it = b.begin(); it; ++it) {
1947 if (leaf ==
nullptr) {
1948 leaf =
new Node0(b[0], root.mBackground,
false);
1954 for (
auto ijk = b.begin(); ijk; ++ijk) {
1955 const auto v =
func(*ijk);
1956 if (
v != root.mBackground) leaf->
setValue(*ijk,
v);
1967 std::lock_guard<std::mutex> guard(mutex);
1973 if (leaf)
delete leaf;
1977 for (
auto it2 = root.mTable.begin(); it2 != root.mTable.end(); ++it2) {
1978 if (
auto *
upper = it2->second.child) {
1979 for (
auto it1 =
upper->mChildMask.beginOn(); it1; ++it1) {
1981 for (
auto it0 =
lower->mChildMask.beginOn(); it0; ++it0) {
1982 auto *leaf =
lower->mTable[*it0].child;
1983 if (leaf->mDstOffset) {
1984 lower->mTable[*it0].value = leaf->getFirstValue();
1985 lower->mChildMask.setOff(*it0);
1986 lower->mValueMask.setOn(*it0);
1990 if (
lower->mChildMask.isOff()) {
1994 if (
lower->mTable[n++].value !=
first)
break;
1998 upper->mChildMask.setOff(*it1);
1999 upper->mValueMask.setOn(*it1);
2004 if (
upper->mChildMask.isOff()) {
2008 if (
upper->mTable[n++].value !=
first)
break;
2011 it2->second.value =
first;
2012 it2->second.state =
upper->mValueMask.isOn();
2013 it2->second.child =
nullptr;
2023 template <
typename T>
2025 template <
typename T>
2027 template <
typename T>
2029 template <
typename T>
2031 template <
typename T>
2055 template <
typename Gr
idT>
2065 static_assert(RootNodeType::LEVEL == 3,
"NodeManager expected LEVEL=3");
2066 using Node2 =
typename RootNodeType::ChildNodeType;
2067 using Node1 =
typename Node2::ChildNodeType;
2068 using Node0 =
typename Node1::ChildNodeType;
2076 auto counts =
mGrid.tree().nodeCount();
2081 for (
auto it2 =
mGrid.tree().root().cbeginChildOn(); it2; ++it2) {
2084 for (
auto it1 = upper.cbeginChildOn(); it1; ++it1) {
2087 for (
auto it0 = lower.cbeginChildOn(); it0; ++it0) {
2103 template <
int LEVEL>
2105 template <
int LEVEL>
2107 template <
int LEVEL>
2109 template <
int LEVEL>
2111 template <
int LEVEL>
2113 template <
int LEVEL>
2149 template <
typename NodeManagerT>
2155 const auto outside = mgr.root().mBackground;
2157 for (
auto i =
r.begin(); i !=
r.end(); ++i) mgr.leaf(i).signedFloodFill(outside);
2160 for (
auto i =
r.begin(); i !=
r.end(); ++i) mgr.lower(i).signedFloodFill(outside);
2163 for (
auto i =
r.begin(); i !=
r.end(); ++i) mgr.upper(i).signedFloodFill(outside);
2165 mgr.root().signedFloodFill(outside);
2168 template <
typename NodeManagerT>
2173 const ValueType d = -mgr.root().mBackground,
w = 1.0f / d;
2174 std::atomic_bool
prune{
false};
2184 for (
auto i =
r.begin(); i !=
r.end(); ++i) {
2185 auto& leaf = mgr.leaf(i);
2186 for (uint32_t i = 0; i < 512u; ++i) leaf.mValueMask.set(i, op(leaf.mValues[i]));
2190 for (
auto i =
r.begin(); i !=
r.end(); ++i) {
2191 auto& node = mgr.lower(i);
2192 for (uint32_t i = 0; i < 4096u; ++i) {
2193 if (node.mChildMask.isOn(i)) {
2194 auto* leaf = node.mTable[i].child;
2195 if (leaf->mValueMask.isOff()) {
2196 node.mTable[i].value = leaf->getFirstValue();
2197 node.mChildMask.setOff(i);
2202 node.mValueMask.set(i, op(node.mTable[i].value));
2208 for (
auto i =
r.begin(); i !=
r.end(); ++i) {
2209 auto& node = mgr.upper(i);
2210 for (uint32_t i = 0; i < 32768u; ++i) {
2211 if (node.mChildMask.isOn(i)) {
2212 auto* child = node.mTable[i].child;
2213 if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2214 node.mTable[i].value = child->getFirstValue();
2215 node.mChildMask.setOff(i);
2220 node.mValueMask.set(i, op(node.mTable[i].value));
2226 for (
auto it = mgr.root().mTable.begin(); it != mgr.root().mTable.end(); ++it) {
2227 auto* child = it->second.child;
2228 if (child ==
nullptr) {
2229 it->second.state = op(it->second.value);
2230 }
else if (child->mChildMask.isOff() && child->mValueMask.isOff()) {
2231 it->second.value = child->getFirstValue();
2232 it->second.state =
false;
2233 it->second.child =
nullptr;
2238 if (rebuild &&
prune) mgr.init();
2243 template <
typename T>
2251 template <
typename T>
2262 template <
typename T>
2268 static bool get(
const BuildLeaf<T> &leaf, uint32_t
n) {
return leaf.mValueMask.isOn(
n);}
2273 template <
typename T>
2287 template <
typename T>
2291 v = root.mBackground;
2299 v = node.mTable[
n].value;
2300 return node.mValueMask.isOn(
n);
2303 v = node.mTable[
n].value;
2304 return node.mValueMask.isOn(
n);
2307 v = leaf.getValue(
n);
2308 return leaf.isActive(
n);
2316 #endif // NANOVDB_GRID_BUILDER_H_HAS_BEEN_INCLUDED
void getNodes(std::vector< NodeT * > &array)
ValueOnIterator beginValueOn()
static constexpr uint32_t SIZE
void setValueAndCache(const Coord &ijk, bool value, const AccT &)
ChildIterator cbeginChildOn() const
uint64_t upperCount() const
const Mask< LOG2DIM > & valueMask() const
static constexpr uint32_t LEVEL
uint32_t tileCount() const
ValueIterator operator++(int)
const MaskT & valueMask() const
bool isActiveAndCache(const Coord &ijk, const AccT &) const
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
static constexpr uint32_t MASK
ValueType getValue(const Coord &ijk) const
std::string upper(string_view a)
Return an all-upper case version of a (locale-independent).
InternalNode(const Coord &origin, const ValueType &value, bool state)
void addChild(ChildT *&child)
typename DataType::Tile Tile
LeafNode(const Coord &ijk, const ValueType &value, bool state)
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
TileIterator & operator=(const TileIterator &)=default
ValueIterator operator++(int)
ValueOffIterator beginValueOff()
typename GridT::TreeType TreeType
ChildIterator beginChild()
Bit-mask to encode active states and facilitate sequential iterators and a fast codec for I/O compres...
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
ValueType operator*() const
void setValueAndCache(const Coord &ijk, const ValueType &value, const AccT &)
DenseIterator & operator=(const DenseIterator &)=default
const Mask< LOG2DIM > & valueMask() const
const MaskT & getChildMask() const
static BuildLeaf< T > & set(BuildLeaf< T > &leaf, uint32_t)
ChildIterator & operator=(const ChildIterator &)=default
DenseIterator beginDense()
ValueOnIterator cbeginValueOn() const
void localToGlobalCoord(Coord &ijk) const
void setValueOnAndCache(const Coord &ijk, const AccT &)
enable_if< LEVEL==1, const Node1 & >::type node(int i) const
std::vector< Node2 * > mArray2
bool isActiveAndCache(const Coord &ijk, const AccT &) const
DenseIterator cbeginChildAll() const
static uint32_t CoordToOffset(const Coord &ijk)
GridType
List of types that are currently supported by NanoVDB.
ValueType getFirstValue() const
ValueIterator(const LeafNode *parent)
void setValueOnAndCache(const Coord &ijk, const AccT &)
ValueIterator beginValue()
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
ValueOnIterator cbeginValueOn() const
void touchLeafAndCache(const Coord &ijk, AccT &acc)
ValueOnIterator & operator=(const ValueOnIterator &)=default
typename GridT::BuildType BuildType
GLsizei const GLchar *const * string
typename AccT::Node1 Node1
GLsizei const GLfloat * value
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
typename ChildT::ValueType ValueType
void setValue(uint32_t n, bool)
ValueType getValue(int i, int j, int k) const
static Coord CoordToKey(const Coord &ijk)
const GridType & grid() const
Visits all values in a leaf node, i.e. both active and inactive values.
typename GridT::ValueType ValueType
bool getValue(const Coord &ijk) const
void setValue(const Coord &ijk, const ValueType &value)
typename Node2::LeafNodeType LeafNodeType
static constexpr uint32_t LEVEL
GLdouble GLdouble GLdouble z
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
ValueOffIterator cbeginValueOff() const
bool isActive(const Coord &ijk) const
Visits all tile values in this node, i.e. both inactive and active tiles.
typename RootNodeType::LeafNodeType LeafNodeType
ValueOffIterator beginValueOff()
__hostdev__ uint64_t first(uint32_t i) const
bool isActiveAndCache(const Coord &ijk, AccT &acc) const
static constexpr uint32_t MASK
GLboolean GLboolean GLboolean GLboolean a
const Node1 & lower(uint32_t i) const
Return the i'th lower internal node with respect to breadth-first ordering.
Tree(const ValueType &background)
uint32_t nodeCount() const
typename NanoNode< nanovdb::ValueMask, 0 >::Type NanoLeafT
__hostdev__ Coord & minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
LeafNode(const Coord &ijk, const ValueType &, bool state)
void insert(const Coord &ijk, NodeT *node) const
Implements Tree::probeLeaf(Coord)
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ValueOnIterator beginValueOn()
void setValue(const Coord &ijk, const ValueType &value)
Maps one type (e.g. the build types above) to other (actual) types.
__hostdev__ void setOff(uint32_t n)
Set the specified bit off.
void setValueOn(const Coord &ijk)
**But if you need a or simply need to know when the task has note that the like this
ValueOffIterator beginValueOff()
ValueType getValue(const Coord &ijk) const
const Node2 & upper(uint32_t i) const
Return the i'th upper internal node with respect to breadth-first ordering.
ValueType getValue(const Coord &ijk) const
typename BuildLeaf< T >::ValueType ValueT
void localToGlobalCoord(Coord &ijk) const
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
ValueIterator(const InternalNode *parent)
void setValueOnAndCache(const Coord &ijk, AccT &acc)
__hostdev__ void setOn(uint32_t n)
Set the specified bit on.
const ValueType & getValue(const Coord &ijk) const
Visits active tile values of this node only.
InternalNode & operator=(const InternalNode &)=delete
typename RootNodeType::ChildNodeType Node2
void getNodes(std::vector< NodeT * > &array)
uint64_t leafCount() const
const ValueType & background() const
typename ChildT::LeafNodeType LeafNodeType
ValueIterator & operator=(const ValueIterator &)=default
ValueIterator operator++(int)
const std::string & gridName() const
bool isActiveAndCache(const Coord &ijk, const AccT &) const
ChildIterator cbeginChildOn() const
#define NANOVDB_ASSERT(x)
ValueIterator cbeginValueAll() const
__hostdev__ OnIterator beginOn() const
static Coord OffsetToLocalCoord(uint32_t n)
typename NanoNode< BuildType, 0 >::Type NanoLeafT
void nodeCount(std::array< size_t, 3 > &count) const
ValueOffIterator cbeginValueOff() const
void setValueOnAndCache(const Coord &ijk, const AccT &)
typename BuildToValueMap< BuildT >::type ValueType
void setTransform(double scale=1.0, const Vec3d &translation=Vec3d(0.0))
Visits all active values in a leaf node.
ValueOnIterator cbeginValueOn() const
static constexpr uint32_t SIZE
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
const GridClass & gridClass() const
void setValue(const Coord &ijk, const ValueType &value)
ValueType operator*() const
typename NanoNode< BuildType, 0 >::Type NanoLeafT
typename AccT::LeafT LeafT
LeafNode(const Coord &ijk, bool value, bool state)
ValueType operator*() const
ValueIterator & operator=(const ValueIterator &)=default
static Coord OffsetToLocalCoord(uint32_t n)
ValueOffIterator cbeginValueOff() const
void addChild(ChildT *&child)
typename Node2::BuildType BuildType
void set(const MatT &mat, const MatT &invMat, const Vec3T &translate, double taper=1.0)
Initialize the member data from 3x3 or 4x4 matrices.
bool getValue(const Coord &ijk) const
GA_API const UT_StringHolder scale
ValueOnIterator beginValueOn()
ValueOnIterator(const LeafNode *parent)
static Coord OffsetToLocalCoord(uint32_t n)
const Mask< LOG2DIM > & valueMask() const
typename BuildToValueMap< BuildT >::type ValueType
ValueIterator operator++(int)
__hostdev__ void set(uint32_t n, bool on)
Set the specified bit on or off.
void setValue(const Coord &ijk, bool value)
typename TreeType::RootNodeType RootNodeType
ValueOnIterator(const LeafNode *parent)
bool getValue(uint32_t i) const
std::map< Coord, Tile > MapT
TileIterator(const RootNode *parent)
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
build::LeafNode< BuildT > LeafT
enable_if< LEVEL==1, Node1 & >::type node(int i)
typename Node2::ValueType ValueType
__hostdev__ bool isOff(uint32_t n) const
Return true if the given bit is NOT set.
void merge(RootNode &other)
Node2 & upper(uint32_t i)
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
ValueType getLastValue() const
static constexpr uint64_t NUM_VALUES
ValueOnIterator & operator=(const ValueOnIterator &)=default
void setValueAndCache(const Coord &ijk, bool, const AccT &)
RootNode(const ValueType &background)
typename ChildT::BuildType BuildType
const ValueType & getValue(uint32_t i) const
const std::string & getName() const
static constexpr uint32_t TOTAL
auto setAndCache(const Coord &ijk, const AccT &acc, ArgsT &&...args)
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
ValueIterator & operator++()
ValueIterator & operator=(const ValueIterator &)=default
ChildT * probeChild(ValueType &value) const
void merge(LeafNode &other)
__hostdev__ uint32_t countOn() const
Return the total number of set bits in this Mask.
auto set(const Coord &ijk, ArgsT &&...args) const
WriteAccessor getWriteAccessor()
special accessor for thread-safe writing only
LeafNode & operator=(const LeafNode &)=delete
ChildIterator & operator++()
uint32_t getTableSize() const
const ChildT * probeChild(ValueType &value)
ValueIterator(const RootNode *parent)
ValueType operator*() const
std::array< size_t, 3 > nodeCount() const
void addNode(NodeT *&node)
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation...
const RootNodeType & root() const
ChildT & operator*() const
void levelSetToFog(NodeManagerT &mgr, bool rebuild=true)
ChildT * operator->() const
ValueIterator beginValue()
ValueOffIterator(const LeafNode *parent)
ValueIterator cbeginValueAll() const
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n)
ValueType getValue(int i, int j, int k) const
ChildIterator operator++(int)
const Coord & origin() const
const Mask< LOG2DIM > & getValueMask() const
uint64_t nodeCount(int level) const
Return the number of tree nodes at the specified level.
void merge(LeafNode &other)
auto get(const UT_ARTIterator< T > &it) -> decltype(it.key())
void setValue(const Coord &ijk, const ValueType &value)
ValueOnIterator & operator++()
ValueIterator & operator++()
Visits all inactive values in a leaf node.
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
ValueType operator*() const
static constexpr uint32_t LEVEL
auto set(const Coord &ijk, ArgsT &&...args)
ValueType operator*() const
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
ValueType operator*() const
static constexpr uint32_t TOTAL
static constexpr uint32_t DIM
ValueType getValueAndCache(const Coord &ijk, AccT &acc) const
Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate ijk...
GLuint const GLchar * name
Custom Range class that is compatible with the tbb::blocked_range classes.
__hostdev__ bool isOn(uint32_t n) const
Return true if the given bit is set.
Maximum floating-point values.
Visits child nodes of this node only.
static constexpr uint32_t LOG2DIM
bool getValueAndCache(const Coord &ijk, const AccT &) const
typename BuildToValueMap< BuildT >::type ValueType
static constexpr uint32_t DIM
void setValue(uint32_t n, bool value)
GLboolean GLboolean GLboolean b
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
ValueOnIterator & operator=(const ValueOnIterator &)=default
void addNode(NodeT *&node)
ValueIterator cbeginValueAll() const
Grid(const ValueType &background, const std::string &name="", GridClass gClass=GridClass::Unknown)
bool getFirstValue() const
ValueType getFirstValue() const
void merge(InternalNode &other)
MaskT< LOG2DIM > mValueMask
DenseIterator(const InternalNode *parent)
void localToGlobalCoord(Coord &ijk) const
void touchLeaf(const Coord &ijk) const
void setValueOn(const Coord &ijk)
const Tile * probeTile(const Coord &ijk) const
Node1 & lower(uint32_t i)
ChildIterator(const RootNode *parent)
WriteAccessor(RootNodeType &parent, std::mutex &mx)
Implements Tree::isActive(Coord)
uint32_t nodeCount() const
Implements Tree::isActive(Coord)
const Mask< LOG2DIM > & getValueMask() const
bool isValueOn(const Coord &ijk) const
ValueIterator & operator++()
uint64_t lowerCount() const
void setValue(const Coord &ijk, const ValueType &value)
ValueOnIterator cbeginValueOn() const
ValueOnIterator beginValueOn()
const Mask< LOG2DIM > & getValueMask() const
ValueIterator beginValue()
enable_if< LEVEL==0, Node0 & >::type node(int i)
const Coord & origin() const
std::vector< Node1 * > mArray1
ChildIterator & operator=(const ChildIterator &)=default
enable_if< is_floating_point< typename NodeManagerT::ValueType >::value >::type sdfToLevelSet(NodeManagerT &mgr)
typename AccT::RootNodeType RootNodeType
ValueIterator(const LeafNode *parent)
ChildIterator(const InternalNode *parent)
typename MaskT::template Iterator< On > MaskIterT
std::vector< Node0 * > mArray0
ValueOnIterator cbeginValueOn() const
TileIterator cbeginChildAll() const
Coord offsetToGlobalCoord(uint32_t n) const
static BuildLeaf< T > * set(BuildLeaf< T > &leaf, uint32_t n, const typename BuildLeaf< T >::ValueType &v)
std::string lower(string_view a)
Return an all-upper case version of a (locale-independent).
TileIterator & operator++()
void operator()(const Func &func, const CoordBBox &bbox, ValueType delta=ValueType(0))
Sets grids values in domain of the bbox to those returned by the specified func with the expected sig...
TileIterator operator++(int)
const ChildT & operator*() const
std::enable_if< std::is_floating_point< T >::value >::type signedFloodFill(T outside)
Tile * probeTile(const Coord &ijk)
RootNode & operator=(const RootNode &)=delete
typename BuildToValueMap< nanovdb::ValueMask >::type ValueType
bool getFirstValue() const
ValueAccessor(RootNodeType &root)
void setValueOnAndCache(const Coord &ijk, AccT &acc)
Coord offsetToGlobalCoord(uint32_t n) const
Dummy type for a voxel whose value equals its binary active state.
bool getValue(uint32_t i) const
typename NanoNode< BuildType, LEVEL >::Type NanoNodeT
ValueIterator beginValue()
const TreeType & tree() const
ValueOnIterator beginValueOn()
ValueOnIterator(const LeafNode *parent)
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void setValueAndCache(const Coord &ijk, const ValueType &value, AccT &acc)
void nodeCount(std::array< size_t, 3 > &count) const
Tile(const ValueType &v, bool s)
static Coord OffsetToLocalCoord(uint32_t n)
Coord offsetToGlobalCoord(uint32_t n) const
const Tile * operator->() const
**If you just want to fire and args
typename BuildRoot< T >::Tile BuildTile
ChildIterator cbeginChild() const
bool getLastValue() const
static constexpr uint64_t NUM_VALUES
auto getAndCache(const Coord &ijk, const AccT &acc, ArgsT &&...args) const
ValueOffIterator(const LeafNode *parent)
typename Mask< LOG2DIM >::template Iterator< ON > MaskIterT
const MaskT & getValueMask() const
static constexpr uint32_t LOG2DIM
ValueIterator cbeginValueAll() const
const Coord & origin() const
GLubyte GLubyte GLubyte GLubyte w
ValueOnIterator(const RootNode *parent)
ValueType getValue(const Coord &ijk) const
ValueOffIterator(const LeafNode *parent)
typename Node1::ChildNodeType Node0
Visits all tile values and child nodes of this node.
Coord offsetToGlobalCoord(uint32_t n) const
enable_if< LEVEL==2, Node2 & >::type node(int i)
bool getLastValue() const
ValueOnIterator(const InternalNode *parent)
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...
ValueAccessor< BuildT > getAccessor()
regular accessor for thread-safe reading and non-thread-safe writing
ValueIterator(const LeafNode *parent)
bool getValueAndCache(const Coord &ijk, const AccT &) const
ValueOnIterator operator++(int)
SIM_API const UT_StringHolder distance
enable_if< LEVEL==0, const Node0 & >::type node(int i) const
ValueType getLastValue() const
ValueOffIterator & operator=(const ValueOffIterator &)=default
void setName(const std::string &name)
LeafT * setValue(const Coord &ijk, const ValueType &value)
Sets value in a leaf node and returns it.
const ValueType & getValueAndCache(const Coord &ijk, const AccT &) const
auto set(const Coord &ijk, ArgsT &&...args)
Mask< LOG2DIM > mValueMask
enable_if< LEVEL==2, const Node2 & >::type node(int i) const
__hostdev__ GridType mapToGridType()
Maps from a templated build type to a GridType enum.
const Coord & origin() const
ValueIterator & operator++()
typename RootNodeType::LeafNodeType LeafNodeType
const Tile & operator*() const
const GridType & gridType() const
static uint32_t CoordToOffset(const Coord &ijk)
Return the linear offset corresponding to the given coordinate.
bool isCached(const Coord &ijk) const
ValueIterator cbeginValueAll() const
Implements Tree::getValue(Coord), i.e. return the value associated with a specific coordinate ijk...
ValueType getValue(int i, int j, int k) const
void localToGlobalCoord(Coord &ijk) const
typename AccT::ValueType ValueType
void touchLeafAndCache(const Coord &ijk, AccT &acc)
ValueIterator beginValue()
C++11 implementation of std::enable_if.
Implements Tree::probeLeaf(Coord)
const ChildT * operator->() const
typename AccT::Node2 Node2
const MaskT & childMask() const
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...
void setValue(uint32_t n, const ValueType &value)
C++11 implementation of std::is_same.
const Node0 & leaf(uint32_t i) const
Return the i'th leaf node with respect to breadth-first ordering.
Set the value and its state at the leaf level mapped to by ijk, and create the leaf node and branch i...
auto set(const Coord &ijk, ArgsT &&...args)
Trait to map from LEVEL to node type.
typename Node2::ChildNodeType Node1
Mask< LOG2DIM > mValueMask
void setValue(const Coord &ijk)
void merge(LeafNode &other)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.