15#ifndef NANOVDB_TOOLS_BUILD_GRIDBUILDER_H_HAS_BEEN_INCLUDED
16#define NANOVDB_TOOLS_BUILD_GRIDBUILDER_H_HAS_BEEN_INCLUDED
39template <
typename T>
struct GetValue;
40template <
typename T>
struct SetValue;
42template <
typename T>
struct GetState;
47template<
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;
107 return uint32_t(std::distance(mParent->mTable.begin(), 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;
142 return uint32_t(std::distance(mParent->mTable.begin(), 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;
176 return uint32_t(std::distance(mParent->mTable.begin(), 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;}
217 return uint32_t(std::distance(mParent->mTable.begin(), mIter));
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...);
262 return OpT::get(*tile, args...);
264 return OpT::get(*
this, 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
288 if (
auto *child = tile->child) {
289 acc.insert(ijk, child);
290 return child->template get<OpT>(ijk, args...);
292 return OpT::get(*tile, args...);
294 return OpT::get(*
this, 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()) {
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));}
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);}
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);
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;
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);
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;
511 delete iter->second.child;
512 iter->second.child =
nullptr;
513 iter->second.value = value;
514 iter->second.state = state;
516 }
else if constexpr(level <
LEVEL) {
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;
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);
576template<
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) {
594 Coord d = b->first - a->first;
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))
600 Coord c = a->first +
Coord(0u, 0u, ChildT::DIM);
601 for (; c[2] != b->first[2]; c[2] += ChildT::DIM) {
610template<
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;
710 if (mParent->mChildMask.isOn(BaseT::pos())) {
711 child = mParent->mTable[BaseT::pos()].child;
713 value = mParent->mTable[BaseT::pos()].value;
729 for (uint32_t i = 0; i <
SIZE; ++i)
mTable[i].value = value;
737 for (
auto iter =
mChildMask.beginOn(); iter; ++iter) {
738 delete mTable[*iter].child;
750 if constexpr(ChildT::LEVEL>0) {
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>
790 return OpT::get(*
this, n, args...);
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>
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...);
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...);
844#ifdef NANOVDB_NEW_ACCESSOR_METHODS
852 return mTable[n].child->getValue(ijk);
859 ChildT* child =
nullptr;
867 child->setValue(ijk, value);
870 template<
typename AccT>
875 acc.insert(ijk,
const_cast<ChildT*
>(
mTable[n].child));
876 return mTable[n].child->getValueAndCache(ijk, acc);
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));
934 return mTable[n].child->isActiveAndCache(ijk, acc);
940 template<
typename NodeT>
948 }
else if constexpr(
LEVEL>1) {
949 for (
auto iter =
mChildMask.beginOn(); iter; ++iter) {
956 template<
typename NodeT>
961 for (
auto iter =
mChildMask.beginOn(); iter; ++iter) {
963 array.push_back(
reinterpret_cast<NodeT*
>(
mTable[*iter].child));
964 }
else if constexpr(
LEVEL>1) {
965 mTable[*iter].child->getNodes(array);
990 template <u
int32_t level>
993 static_assert(level > 0 && level <=
LEVEL,
"invalid template value of level");
995 if constexpr(level ==
LEVEL) {
1003 }
else if constexpr(level <
LEVEL) {
1004 ChildT* child =
nullptr;
1008 child =
new ChildT(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>
1057template<
typename ChildT>
1062 const uint32_t first = *
mChildMask.beginOn();
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);
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);
1075 yInside =
mTable[xy0].child->getLastValue() < 0;
1077 for (uint32_t z = 0; z != (1 <<
LOG2DIM); ++z) {
1078 const uint32_t xyz = xy0 + z;
1080 zInside =
mTable[xyz].child->getLastValue() < 0;
1082 mTable[xyz].value = zInside ? -outside : outside;
1092template<
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>
1355 operator bool()
const {
return mPos <
SIZE;}
1386 return ((ijk[0] & int32_t(
MASK)) << (2 *
LOG2DIM)) +
1388 (ijk[2] & int32_t(
MASK));
1394 const int32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
1412 template<
typename OpT,
typename... ArgsT>
1415 template<
typename OpT,
typename... ArgsT>
1418#ifndef NANOVDB_NEW_ACCESSOR_METHODS
1419 template<
typename AccT>
1425 template<
typename AccT>
1432 template<
typename AccT>
1439 template<
typename AccT>
1526 operator bool()
const {
return mPos <
SIZE;}
1558 return ((ijk[0] & int32_t(
MASK)) << (2 *
LOG2DIM)) +
1560 (ijk[2] & int32_t(
MASK));
1566 const int32_t m = n & ((1 << 2 *
LOG2DIM) - 1);
1589#ifndef NANOVDB_NEW_ACCESSOR_METHODS
1590 template<
typename AccT>
1596 template<
typename AccT>
1602 template<
typename AccT>
1610 template<
typename AccT>
1635template<
typename BuildT>
1640 const uint32_t first = *
mValueMask.beginOn();
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);
1648 for (uint32_t y = 0; y !=
DIM; ++y) {
1649 const uint32_t xy0 = x00 + (y <<
LOG2DIM);
1653 for (uint32_t z = 0; z != (1 <<
LOG2DIM); ++z) {
1654 const uint32_t xyz = xy0 + z;
1658 mValues[xyz] = zInside ? -outside : outside;
1668template<
typename BuildT>
1681 ,
mNode{nullptr, nullptr, nullptr}
1687 template<
typename NodeT>
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];
1695 template <
typename OpT,
typename... ArgsT>
1701 return ((
const Node1*)
mNode[1])->template getAndCache<OpT>(ijk, *
this, args...);
1703 return ((
const Node2*)
mNode[2])->template getAndCache<OpT>(ijk, *
this, args...);
1705 return mRoot.template getAndCache<OpT>(ijk, *
this, args...);
1708 template <
typename OpT,
typename... ArgsT>
1714 return ((
Node1*)
mNode[1])->template setAndCache<OpT>(ijk, *
this, args...);
1716 return ((
Node2*)
mNode[2])->template setAndCache<OpT>(ijk, *
this, args...);
1718 return mRoot.template setAndCache<OpT>(ijk, *
this, args...);
1721#ifdef NANOVDB_NEW_ACCESSOR_METHODS
1731 return ((
LeafT*)
mNode[0])->getValueAndCache(ijk, *
this);
1733 return ((
Node1*)
mNode[1])->getValueAndCache(ijk, *
this);
1735 return ((
Node2*)
mNode[2])->getValueAndCache(ijk, *
this);
1737 return mRoot.getValueAndCache(ijk, *
this);
1744 ((
LeafT*)
mNode[0])->setValueAndCache(ijk, value, *
this);
1746 ((
Node1*)
mNode[1])->setValueAndCache(ijk, value, *
this);
1748 ((
Node2*)
mNode[2])->setValueAndCache(ijk, value, *
this);
1750 mRoot.setValueAndCache(ijk, value, *
this);
1758 ((
LeafT*)
mNode[0])->setValueOnAndCache(ijk, *
this);
1760 ((
Node1*)
mNode[1])->setValueOnAndCache(ijk, *
this);
1762 ((
Node2*)
mNode[2])->setValueOnAndCache(ijk, *
this);
1764 mRoot.setValueOnAndCache(ijk, *
this);
1772 ((
Node1*)
mNode[1])->touchLeafAndCache(ijk, *
this);
1774 ((
Node2*)
mNode[2])->touchLeafAndCache(ijk, *
this);
1776 mRoot.touchLeafAndCache(ijk, *
this);
1782 return ((
LeafT*)
mNode[0])->isActiveAndCache(ijk, *
this);
1784 return ((
Node1*)
mNode[1])->isActiveAndCache(ijk, *
this);
1786 return ((
Node2*)
mNode[2])->isActiveAndCache(ijk, *
this);
1788 return mRoot.isActiveAndCache(ijk, *
this);
1793 template<
typename NodeT>
1796 mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
1797 mNode[NodeT::LEVEL] = node;
1806template<
typename BuildT>
1830 std::array<size_t, 3> count{0,0,0};
1831 mRoot.nodeCount(count);
1842template<
typename BuildT>
1854 ,
mRoot(parent.mBackground)
1878template<
typename BuildT>
1921 template <
typename Func>
1925template <
typename BuildT>
1926template <
typename Func>
1930#if __cplusplus >= 201703L
1933 static_assert(
util::is_same<
ValueType,
typename std::result_of<Func(
const Coord&)>::type>::value,
"GridBuilder: mismatched ValueType");
1938 Node0* leaf =
nullptr;
1939 for (
auto it = b.begin(); it; ++it) {
1941 const CoordBBox b(min.maxComponent(bbox.min()),
1942 max.minComponent(bbox.max()));
1943 if (leaf ==
nullptr) {
1944 leaf =
new Node0(b[0],
root.mBackground,
false);
1950 for (
auto ijk = b.begin(); ijk; ++ijk) {
1951 const auto v = func(*ijk);
1959 if (leaf->
mValues[n++] != first)
break;
1963 std::lock_guard<std::mutex> guard(mutex);
1973 for (
auto it2 =
root.mTable.begin(); it2 !=
root.mTable.end(); ++it2) {
1974 if (
auto *upper = it2->second.child) {
1975 for (
auto it1 = upper->mChildMask.beginOn(); it1; ++it1) {
1976 auto *lower = upper->mTable[*it1].child;
1977 for (
auto it0 = lower->mChildMask.beginOn(); it0; ++it0) {
1978 auto *leaf = lower->mTable[*it0].child;
1979 if (leaf->mDstOffset) {
1980 lower->mTable[*it0].value = leaf->getFirstValue();
1981 lower->mChildMask.setOff(*it0);
1982 lower->mValueMask.setOn(*it0);
1986 if (lower->mChildMask.isOff()) {
1987 const auto first = lower->getFirstValue();
1990 if (lower->mTable[n++].value != first)
break;
1993 upper->mTable[*it1].value = first;
1994 upper->mChildMask.setOff(*it1);
1995 upper->mValueMask.setOn(*it1);
2000 if (upper->mChildMask.isOff()) {
2001 const auto first = upper->getFirstValue();
2004 if (upper->mTable[n++].value != first)
break;
2007 it2->second.value = first;
2008 it2->second.state = upper->mValueMask.isOn();
2009 it2->second.child =
nullptr;
2019template <
typename T>
2021template <
typename T>
2023template <
typename T>
2025template <
typename T>
2027template <
typename T>
2051template <
typename Gr
idT>
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;
2072 auto counts =
mGrid.tree().nodeCount();
2077 for (
auto it2 =
mGrid.tree().root().cbeginChildOn(); it2; ++it2) {
2080 for (
auto it1 =
upper.cbeginChildOn(); it1; ++it1) {
2083 for (
auto it0 =
lower.cbeginChildOn(); it0; ++it0) {
2099 template <
int LEVEL>
2101 template <
int LEVEL>
2103 template <
int LEVEL>
2105 template <
int LEVEL>
2107 template <
int LEVEL>
2109 template <
int LEVEL>
2145template <
typename NodeManagerT>
2151 const auto outside = mgr.root().mBackground;
2153 for (auto i = r.begin(); i != r.end(); ++i) mgr.leaf(static_cast<uint32_t>(i)).signedFloodFill(outside);
2156 for (auto i = r.begin(); i != r.end(); ++i) mgr.lower(static_cast<uint32_t>(i)).signedFloodFill(outside);
2159 for (auto i = r.begin(); i != r.end(); ++i) mgr.upper(static_cast<uint32_t>(i)).signedFloodFill(outside);
2161 mgr.root().signedFloodFill(outside);
2164template <
typename NodeManagerT>
2167 using ValueType =
typename NodeManagerT::ValueType;
2169 const ValueType d = -mgr.root().mBackground, w = 1.0f / d;
2171 std::atomic<bool> prune{
false};
2172 auto op = [&](ValueType& v) ->
bool {
2173 if (v > ValueType(0)) {
2177 v = v > d ? v * w : ValueType(1);
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]));
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()) {
2193 node.mTable[i].value = leaf->getFirstValue();
2194 node.mChildMask.setOff(i);
2199 node.mValueMask.set(i, op(node.mTable[i].value));
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)) {
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);
2217 node.mValueMask.set(i, op(node.mTable[i].value));
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;
2235 if (rebuild && prune) mgr.init();
2240template <
typename T>
2248template <
typename T>
2259template <
typename T>
2270template <
typename T>
2284template <
typename T>
2296 v = node.
mTable[n].value;
2300 v = node.
mTable[n].value;
2305 return leaf.isActive(n);
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
Definition DitherLUT.h:19
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
#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
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