31 #ifndef OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
32 #define OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
34 #include <tbb/null_mutex.h>
35 #include <tbb/spin_mutex.h>
40 #include <type_traits>
49 template<
typename TreeType,
bool IsSafe = true>
51 template<
typename TreeType,
bool IsSafe = true, Index L0 = 0>
53 template<
typename TreeType,
bool IsSafe = true, Index L0 = 0, Index L1 = 1>
55 template<
typename TreeType,
bool IsSafe = true, Index L0 = 0, Index L1 = 1, Index L2 = 2>
57 template<
typename TreeCacheT,
typename NodeVecT,
bool AtRoot>
class CacheItem;
83 template<
typename TreeType,
bool IsSafe>
95 static bool isSafe() {
return IsSafe; }
99 if (IsSafe) tree.attachAccessor(*
this);
114 if (IsSafe &&
mTree)
mTree->attachAccessor(*
this);
119 if (&other !=
this) {
120 if (IsSafe &&
mTree)
mTree->releaseAccessor(*
this);
122 if (IsSafe &&
mTree)
mTree->attachAccessor(*
this);
127 virtual void clear() = 0;
131 template<
typename>
friend class Tree;
178 template<
typename _TreeType,
180 Index CacheLevels = _TreeType::DEPTH-1,
181 typename MutexType = tbb::null_mutex>
185 static_assert(CacheLevels < _TreeType::DEPTH,
"cache size exceeds tree depth");
192 using LockT =
typename MutexType::scoped_lock;
197 mCache.
insert(Coord(), &tree.root());
204 if (&other !=
this) {
206 mCache.
copy(*
this, other.mCache);
275 template<
typename ModifyOp>
284 template<
typename ModifyOp>
303 template<
typename NodeType>
307 NodeType* node =
nullptr;
314 template<
typename NodeType>
318 mCache.
insert(xyz, &node);
324 template<
typename NodeType>
340 mCache.
addTile(level, xyz, value, state);
357 template<
typename NodeT>
361 return mCache.template probeNode<NodeT>(xyz);
363 template<
typename NodeT>
367 return mCache.template probeConstNode<NodeT>(xyz);
369 template<
typename NodeT>
372 return this->
template probeConstNode<NodeT>(xyz);
406 template<
typename>
friend class Tree;
410 void release()
override
421 template<
typename NodeType>
422 void insert(
const Coord& xyz, NodeType* node) { mCache.
insert(xyz, node); }
425 using InvTreeT =
typename RootNodeT::NodeChainType;
427 static constexpr int64_t First = CacheLevels;
429 using SubtreeT =
typename InvTreeT::template RemoveByIndex<First, Last-1>;
430 using CacheItemT = CacheItem<ValueAccessor, SubtreeT, SubtreeT::Size==1>;
433 mutable CacheItemT mCache;
434 mutable MutexType mMutex;
442 template<
typename TreeType,
bool IsSafe>
454 template<
typename TreeType,
bool IsSafe>
466 template<
typename TreeType,
bool IsSafe>
478 template<
typename TreeType,
bool IsSafe>
500 template<
typename TreeType,
bool IsSafe = true>
519 template<
typename TreeCacheT,
typename NodeVecT,
bool AtRoot>
542 mNext(parent, other.mNext)
551 mNext.copy(parent, other.mNext);
558 return (this->isHashed(xyz) || mNext.isCached(xyz));
564 mHash = (node !=
nullptr) ? xyz & ~(NodeType::DIM-1) :
Coord::max();
568 template<
typename OtherNodeType>
569 void insert(
const Coord& xyz,
const OtherNodeType* node) { mNext.insert(xyz, node); }
574 template<
typename OtherNodeType>
575 void erase(
const OtherNodeType* node) { mNext.erase(node); }
587 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
588 node =
const_cast<NodeType*
>(mNode);
591 template<
typename OtherNodeType>
592 void getNode(OtherNodeType*& node) { mNext.getNode(node); }
597 if (this->isHashed(xyz)) {
599 return mNode->getValueAndCache(xyz, *mParent);
601 return mNext.getValue(xyz);
606 static_assert(!TreeCacheT::IsConstTree,
"can't add a node to a const tree");
607 if (NodeType::LEVEL == 0)
return;
608 if (this->isHashed(leaf->origin())) {
610 return const_cast<NodeType*
>(mNode)->addLeafAndCache(leaf, *mParent);
617 static_assert(!TreeCacheT::IsConstTree,
"can't add a tile to a const tree");
618 if (NodeType::LEVEL < level)
return;
619 if (this->isHashed(xyz)) {
621 return const_cast<NodeType*
>(mNode)->addTileAndCache(
622 level, xyz, value, state, *mParent);
624 mNext.addTile(level, xyz, value, state);
629 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
630 if (this->isHashed(xyz)) {
632 return const_cast<NodeType*
>(mNode)->touchLeafAndCache(xyz, *mParent);
634 return mNext.touchLeaf(xyz);
639 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
640 if (this->isHashed(xyz)) {
642 return const_cast<NodeType*
>(mNode)->probeLeafAndCache(xyz, *mParent);
644 return mNext.probeLeaf(xyz);
649 if (this->isHashed(xyz)) {
651 return mNode->probeConstLeafAndCache(xyz, *mParent);
653 return mNext.probeConstLeaf(xyz);
656 template<
typename NodeT>
659 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
661 if (this->isHashed(xyz)) {
664 return reinterpret_cast<NodeT*
>(
const_cast<NodeType*
>(mNode));
666 return const_cast<NodeType*
>(mNode)->
template probeNodeAndCache<NodeT>(xyz, *mParent);
668 return mNext.template probeNode<NodeT>(xyz);
672 template<
typename NodeT>
676 if (this->isHashed(xyz)) {
679 return reinterpret_cast<const NodeT*
>(mNode);
681 return mNode->template probeConstNodeAndCache<NodeT>(xyz, *mParent);
683 return mNext.template probeConstNode<NodeT>(xyz);
690 if (this->isHashed(xyz)) {
692 return mNode->isValueOnAndCache(xyz, *mParent);
694 return mNext.isValueOn(xyz);
700 if (this->isHashed(xyz)) {
702 return mNode->probeValueAndCache(xyz, value, *mParent);
704 return mNext.probeValue(xyz, value);
709 if (this->isHashed(xyz)) {
711 return static_cast<int>(TreeCacheT::RootNodeT::LEVEL) -
712 static_cast<int>(mNode->getValueLevelAndCache(xyz, *mParent));
714 return mNext.getValueDepth(xyz);
720 if (this->isHashed(xyz)) {
722 return mNode->getValueLevelAndCache(xyz, *mParent)==0;
724 return mNext.isVoxel(xyz);
731 if (this->isHashed(xyz)) {
733 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
734 const_cast<NodeType*
>(mNode)->setValueAndCache(xyz, value, *mParent);
736 mNext.setValue(xyz, value);
741 if (this->isHashed(xyz)) {
743 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
744 const_cast<NodeType*
>(mNode)->setValueOnlyAndCache(xyz, value, *mParent);
746 mNext.setValueOnly(xyz, value);
754 template<
typename ModifyOp>
757 if (this->isHashed(xyz)) {
759 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
760 const_cast<NodeType*
>(mNode)->modifyValueAndCache(xyz, op, *mParent);
762 mNext.modifyValue(xyz, op);
768 template<
typename ModifyOp>
771 if (this->isHashed(xyz)) {
773 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
774 const_cast<NodeType*
>(mNode)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
776 mNext.modifyValueAndActiveState(xyz, op);
783 if (this->isHashed(xyz)) {
785 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
786 const_cast<NodeType*
>(mNode)->setValueOffAndCache(xyz, value, *mParent);
788 mNext.setValueOff(xyz, value);
795 if (this->isHashed(xyz)) {
797 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
798 const_cast<NodeType*
>(mNode)->setActiveStateAndCache(xyz, on, *mParent);
800 mNext.setActiveState(xyz, on);
808 bool isHashed(
const Coord& xyz)
const
810 return (xyz[0] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[0]
811 && (xyz[1] & ~Coord
::ValueType(NodeType::DIM-1)) == mHash[1]
812 && (xyz[2] & ~Coord::ValueType(NodeType::DIM-1)) == mHash[2];
818 using RestT =
typename NodeVecT::PopFront;
819 CacheItem<TreeCacheT, RestT, RestT::Size == 1> mNext;
824 template<
typename TreeCacheT,
typename NodeVecT>
832 CacheItem(TreeCacheT& parent): mParent(&parent), mRoot(nullptr) {}
842 bool isCached(
const Coord& xyz)
const {
return this->isHashed(xyz); }
847 template<
typename OtherNodeType>
848 void insert(
const Coord&,
const OtherNodeType*) {}
856 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
864 static_assert(!TreeCacheT::IsConstTree,
"can't add a node to a const tree");
865 const_cast<RootNodeType*
>(mRoot)->addLeafAndCache(leaf, *mParent);
871 static_assert(!TreeCacheT::IsConstTree,
"can't add a tile to a const tree");
872 const_cast<RootNodeType*
>(mRoot)->addTileAndCache(level, xyz, value, state, *mParent);
878 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
879 return const_cast<RootNodeType*
>(mRoot)->touchLeafAndCache(xyz, *mParent);
885 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
886 return const_cast<RootNodeType*
>(mRoot)->probeLeafAndCache(xyz, *mParent);
892 return mRoot->probeConstLeafAndCache(xyz, *mParent);
895 template<
typename NodeType>
899 static_assert(!TreeCacheT::IsConstTree,
"can't get a non-const node from a const tree");
901 template probeNodeAndCache<NodeType>(xyz, *mParent);
904 template<
typename NodeType>
908 return mRoot->template probeConstNodeAndCache<NodeType>(xyz, *mParent);
914 return mRoot->getValueDepthAndCache(xyz, *mParent);
919 return mRoot->isValueOnAndCache(xyz, *mParent);
925 return mRoot->probeValueAndCache(xyz, value, *mParent);
930 return mRoot->getValueDepthAndCache(xyz, *mParent) ==
931 static_cast<int>(RootNodeType::LEVEL);
936 return mRoot->getValueAndCache(xyz, *mParent);
942 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
943 const_cast<RootNodeType*
>(mRoot)->setValueAndCache(xyz, value, *mParent);
948 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
949 const_cast<RootNodeType*
>(mRoot)->setValueOnlyAndCache(xyz, value, *mParent);
953 template<
typename ModifyOp>
957 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
958 const_cast<RootNodeType*
>(mRoot)->modifyValueAndCache(xyz, op, *mParent);
961 template<
typename ModifyOp>
965 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
966 const_cast<RootNodeType*
>(mRoot)->modifyValueAndActiveStateAndCache(xyz, op, *mParent);
972 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
973 const_cast<RootNodeType*
>(mRoot)->setValueOffAndCache(xyz, value, *mParent);
979 static_assert(!TreeCacheT::IsConstTree,
"can't modify a const tree's values");
980 const_cast<RootNodeType*
>(mRoot)->setActiveStateAndCache(xyz, on, *mParent);
987 bool isHashed(
const Coord&)
const {
return false; }
990 const RootNodeType* mRoot;
1000 template<
typename _TreeType,
bool IsSafe>
1001 class ValueAccessor0:
public ValueAccessorBase<_TreeType, IsSafe>
1063 return BaseT::mTree->getValueDepth(xyz) ==
static_cast<int>(RootNodeT::LEVEL);
1096 template<
typename ModifyOp>
1106 template<
typename ModifyOp>
1127 template<
typename NodeT> NodeT*
getNode() {
return nullptr; }
1131 template<
typename NodeT>
void insertNode(
const Coord&, NodeT&) {}
1148 BaseT::mTree->root().addTile(level, xyz, value, state);
1163 template<
typename NodeT>
1171 template<
typename NodeT>
1175 return BaseT::mTree->template probeConstNode<NodeT>(xyz);
1180 return this->
template probeNode<LeafNodeT>(xyz);
1185 return this->
template probeConstNode<LeafNodeT>(xyz);
1198 template<
typename>
friend class Tree;
1213 template<
typename _TreeType,
bool IsSafe, Index L0>
1214 class ValueAccessor1 :
public ValueAccessorBase<_TreeType, IsSafe>
1217 static_assert(_TreeType::DEPTH >= 2,
"cache size exceeds tree depth");
1218 static_assert(L0 < _TreeType::RootNodeType::LEVEL,
"invalid cache level");
1225 using NodeT0 =
typename InvTreeT::template Get<L0>;
1241 if (&other !=
this) {
1242 this->BaseT::operator=(other);
1255 assert(BaseT::mTree);
1256 return this->isHashed(xyz);
1262 assert(BaseT::mTree);
1263 if (this->isHashed(xyz)) {
1265 return mNode0->getValueAndCache(xyz, this->
self());
1267 return BaseT::mTree->root().getValueAndCache(xyz, this->
self());
1273 assert(BaseT::mTree);
1274 if (this->isHashed(xyz)) {
1276 return mNode0->isValueOnAndCache(xyz, this->
self());
1278 return BaseT::mTree->root().isValueOnAndCache(xyz, this->
self());
1284 assert(BaseT::mTree);
1285 if (this->isHashed(xyz)) {
1287 return mNode0->probeValueAndCache(xyz, value, this->
self());
1289 return BaseT::mTree->root().probeValueAndCache(xyz, value, this->
self());
1297 assert(BaseT::mTree);
1298 if (this->isHashed(xyz)) {
1300 return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->
self());
1302 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self());
1309 assert(BaseT::mTree);
1310 if (this->isHashed(xyz)) {
1312 return mNode0->getValueLevelAndCache(xyz, this->
self()) == 0;
1314 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self()) ==
1315 static_cast<int>(RootNodeT::LEVEL);
1322 assert(BaseT::mTree);
1323 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1324 if (this->isHashed(xyz)) {
1326 const_cast<NodeT0*
>(mNode0)->setValueAndCache(xyz, value, *
this);
1328 BaseT::mTree->root().setValueAndCache(xyz, value, *
this);
1337 assert(BaseT::mTree);
1338 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1339 if (this->isHashed(xyz)) {
1341 const_cast<NodeT0*
>(mNode0)->setValueOnlyAndCache(xyz, value, *
this);
1343 BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *
this);
1350 assert(BaseT::mTree);
1351 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1352 if (this->isHashed(xyz)) {
1354 const_cast<NodeT0*
>(mNode0)->setValueOffAndCache(xyz, value, *
this);
1356 BaseT::mTree->root().setValueOffAndCache(xyz, value, *
this);
1363 template<
typename ModifyOp>
1366 assert(BaseT::mTree);
1367 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1368 if (this->isHashed(xyz)) {
1370 const_cast<NodeT0*
>(mNode0)->modifyValueAndCache(xyz, op, *
this);
1372 BaseT::mTree->root().modifyValueAndCache(xyz, op, *
this);
1378 template<
typename ModifyOp>
1381 assert(BaseT::mTree);
1382 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1383 if (this->isHashed(xyz)) {
1385 const_cast<NodeT0*
>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
1387 BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *
this);
1394 assert(BaseT::mTree);
1395 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1396 if (this->isHashed(xyz)) {
1398 const_cast<NodeT0*
>(mNode0)->setActiveStateAndCache(xyz, on, *
this);
1400 BaseT::mTree->root().setActiveStateAndCache(xyz, on, *
this);
1404 void setValueOn(
const Coord& xyz) { this->setActiveState(xyz,
true); }
1406 void setValueOff(
const Coord& xyz) { this->setActiveState(xyz,
false); }
1409 template<
typename NodeT>
1412 const NodeT* node =
nullptr;
1413 this->getNode(node);
1414 return const_cast<NodeT*
>(node);
1419 template<
typename NodeT>
1425 template<
typename NodeT>
1428 const NodeT* node =
nullptr;
1429 this->eraseNode(node);
1436 assert(BaseT::mTree);
1437 static_assert(!BaseT::IsConstTree,
"can't add a node to a const tree");
1438 BaseT::mTree->root().addLeaf(leaf);
1445 assert(BaseT::mTree);
1446 static_assert(!BaseT::IsConstTree,
"can't add a tile to a const tree");
1447 BaseT::mTree->root().addTile(level, xyz, value, state);
1458 assert(BaseT::mTree);
1459 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
1460 if (this->isHashed(xyz)) {
1462 return const_cast<NodeT0*
>(mNode0)->touchLeafAndCache(xyz, *
this);
1464 return BaseT::mTree->root().touchLeafAndCache(xyz, *
this);
1469 template<
typename NodeT>
1472 assert(BaseT::mTree);
1473 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
1476 if (this->isHashed(xyz)) {
1478 return reinterpret_cast<NodeT*
>(
const_cast<NodeT0*
>(mNode0));
1480 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
1487 return this->
template probeNode<LeafNodeT>(xyz);
1492 template<
typename NodeT>
1495 assert(BaseT::mTree);
1498 if (this->isHashed(xyz)) {
1500 return reinterpret_cast<const NodeT*
>(mNode0);
1502 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1509 return this->
template probeConstNode<LeafNodeT>(xyz);
1526 template<
typename>
friend class Tree;
1531 void getNode(
const NodeT0*& node) { node = mNode0; }
1532 void getNode(
const RootNodeT*& node)
1534 node = (BaseT::mTree ? &BaseT::mTree->root() :
nullptr);
1536 template<
typename OtherNodeType>
void getNode(
const OtherNodeType*& node) { node =
nullptr; }
1537 void eraseNode(
const NodeT0*) { mKey0 =
Coord::max(); mNode0 =
nullptr; }
1538 template<
typename OtherNodeType>
void eraseNode(
const OtherNodeType*) {}
1541 inline void copy(
const ValueAccessor1& other)
1543 mKey0 = other.mKey0;
1544 mNode0 = other.mNode0;
1549 void release()
override
1551 this->BaseT::release();
1558 inline void insert(
const Coord& xyz,
const NodeT0* node)
1561 mKey0 = xyz & ~(NodeT0::DIM-1);
1567 template<
typename OtherNodeType>
inline void insert(
const Coord&,
const OtherNodeType*) {}
1569 inline bool isHashed(
const Coord& xyz)
const
1571 return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
1572 && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
1573 && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
1575 mutable Coord mKey0;
1576 mutable const NodeT0* mNode0;
1587 template<
typename _TreeType,
bool IsSafe, Index L0, Index L1>
1588 class ValueAccessor2 :
public ValueAccessorBase<_TreeType, IsSafe>
1591 static_assert(_TreeType::DEPTH >= 3,
"cache size exceeds tree depth");
1592 static_assert(L0 < L1,
"invalid cache level");
1593 static_assert(L1 < _TreeType::RootNodeType::LEVEL,
"invalid cache level");
1601 using NodeT0 =
typename InvTreeT::template Get<L0>;
1602 using NodeT1 =
typename InvTreeT::template Get<L1>;
1606 mKey0(Coord::
max()), mNode0(nullptr),
1607 mKey1(Coord::
max()), mNode1(nullptr) {}
1618 if (&other !=
this) {
1619 this->BaseT::operator=(other);
1632 assert(BaseT::mTree);
1633 return this->isHashed1(xyz) || this->isHashed0(xyz);
1639 assert(BaseT::mTree);
1640 if (this->isHashed0(xyz)) {
1642 return mNode0->getValueAndCache(xyz, this->
self());
1643 }
else if (this->isHashed1(xyz)) {
1645 return mNode1->getValueAndCache(xyz, this->
self());
1647 return BaseT::mTree->root().getValueAndCache(xyz, this->
self());
1653 assert(BaseT::mTree);
1654 if (this->isHashed0(xyz)) {
1656 return mNode0->isValueOnAndCache(xyz, this->
self());
1657 }
else if (this->isHashed1(xyz)) {
1659 return mNode1->isValueOnAndCache(xyz, this->
self());
1661 return BaseT::mTree->root().isValueOnAndCache(xyz, this->
self());
1667 assert(BaseT::mTree);
1668 if (this->isHashed0(xyz)) {
1670 return mNode0->probeValueAndCache(xyz, value, this->
self());
1671 }
else if (this->isHashed1(xyz)) {
1673 return mNode1->probeValueAndCache(xyz, value, this->
self());
1675 return BaseT::mTree->root().probeValueAndCache(xyz, value, this->
self());
1683 assert(BaseT::mTree);
1684 if (this->isHashed0(xyz)) {
1686 return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->
self());
1687 }
else if (this->isHashed1(xyz)) {
1689 return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->
self());
1691 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self());
1698 assert(BaseT::mTree);
1699 if (this->isHashed0(xyz)) {
1701 return mNode0->getValueLevelAndCache(xyz, this->
self())==0;
1702 }
else if (this->isHashed1(xyz)) {
1704 return mNode1->getValueLevelAndCache(xyz, this->
self())==0;
1706 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self()) ==
1707 static_cast<int>(RootNodeT::LEVEL);
1714 assert(BaseT::mTree);
1715 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1716 if (this->isHashed0(xyz)) {
1718 const_cast<NodeT0*
>(mNode0)->setValueAndCache(xyz, value, *
this);
1719 }
else if (this->isHashed1(xyz)) {
1721 const_cast<NodeT1*
>(mNode1)->setValueAndCache(xyz, value, *
this);
1723 BaseT::mTree->root().setValueAndCache(xyz, value, *
this);
1732 assert(BaseT::mTree);
1733 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1734 if (this->isHashed0(xyz)) {
1736 const_cast<NodeT0*
>(mNode0)->setValueOnlyAndCache(xyz, value, *
this);
1737 }
else if (this->isHashed1(xyz)) {
1739 const_cast<NodeT1*
>(mNode1)->setValueOnlyAndCache(xyz, value, *
this);
1741 BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *
this);
1748 assert(BaseT::mTree);
1749 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1750 if (this->isHashed0(xyz)) {
1752 const_cast<NodeT0*
>(mNode0)->setValueOffAndCache(xyz, value, *
this);
1753 }
else if (this->isHashed1(xyz)) {
1755 const_cast<NodeT1*
>(mNode1)->setValueOffAndCache(xyz, value, *
this);
1757 BaseT::mTree->root().setValueOffAndCache(xyz, value, *
this);
1764 template<
typename ModifyOp>
1767 assert(BaseT::mTree);
1768 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1769 if (this->isHashed0(xyz)) {
1771 const_cast<NodeT0*
>(mNode0)->modifyValueAndCache(xyz, op, *
this);
1772 }
else if (this->isHashed1(xyz)) {
1774 const_cast<NodeT1*
>(mNode1)->modifyValueAndCache(xyz, op, *
this);
1776 BaseT::mTree->root().modifyValueAndCache(xyz, op, *
this);
1782 template<
typename ModifyOp>
1785 assert(BaseT::mTree);
1786 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1787 if (this->isHashed0(xyz)) {
1789 const_cast<NodeT0*
>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
1790 }
else if (this->isHashed1(xyz)) {
1792 const_cast<NodeT1*
>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
1794 BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *
this);
1801 assert(BaseT::mTree);
1802 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
1803 if (this->isHashed0(xyz)) {
1805 const_cast<NodeT0*
>(mNode0)->setActiveStateAndCache(xyz, on, *
this);
1806 }
else if (this->isHashed1(xyz)) {
1808 const_cast<NodeT1*
>(mNode1)->setActiveStateAndCache(xyz, on, *
this);
1810 BaseT::mTree->root().setActiveStateAndCache(xyz, on, *
this);
1814 void setValueOn(
const Coord& xyz) { this->setActiveState(xyz,
true); }
1816 void setValueOff(
const Coord& xyz) { this->setActiveState(xyz,
false); }
1819 template<
typename NodeT>
1822 const NodeT* node =
nullptr;
1823 this->getNode(node);
1824 return const_cast<NodeT*
>(node);
1829 template<
typename NodeT>
1835 template<
typename NodeT>
1838 const NodeT* node =
nullptr;
1839 this->eraseNode(node);
1846 assert(BaseT::mTree);
1847 static_assert(!BaseT::IsConstTree,
"can't add a node to a const tree");
1848 if (this->isHashed1(leaf->origin())) {
1850 return const_cast<NodeT1*
>(mNode1)->addLeafAndCache(leaf, *
this);
1852 BaseT::mTree->root().addLeafAndCache(leaf, *
this);
1859 assert(BaseT::mTree);
1860 static_assert(!BaseT::IsConstTree,
"can't add a tile to a const tree");
1861 if (this->isHashed1(xyz)) {
1863 return const_cast<NodeT1*
>(mNode1)->addTileAndCache(level, xyz, value, state, *
this);
1865 BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *
this);
1876 assert(BaseT::mTree);
1877 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
1878 if (this->isHashed0(xyz)) {
1880 return const_cast<NodeT0*
>(mNode0)->touchLeafAndCache(xyz, *
this);
1881 }
else if (this->isHashed1(xyz)) {
1883 return const_cast<NodeT1*
>(mNode1)->touchLeafAndCache(xyz, *
this);
1885 return BaseT::mTree->root().touchLeafAndCache(xyz, *
this);
1889 template<
typename NodeT>
1892 assert(BaseT::mTree);
1893 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
1896 if (this->isHashed0(xyz)) {
1898 return reinterpret_cast<NodeT*
>(
const_cast<NodeT0*
>(mNode0));
1899 }
else if (this->isHashed1(xyz)) {
1901 return const_cast<NodeT1*
>(mNode1)->
template probeNodeAndCache<NodeT>(xyz, *
this);
1903 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
1905 if (this->isHashed1(xyz)) {
1907 return reinterpret_cast<NodeT*
>(
const_cast<NodeT1*
>(mNode1));
1909 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
1920 template<
typename NodeT>
1925 if (this->isHashed0(xyz)) {
1927 return reinterpret_cast<const NodeT*
>(mNode0);
1928 }
else if (this->isHashed1(xyz)) {
1930 return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1932 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1934 if (this->isHashed1(xyz)) {
1936 return reinterpret_cast<const NodeT*
>(mNode1);
1938 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1947 return this->
template probeConstNode<LeafNodeT>(xyz);
1953 template<
typename NodeT>
1956 assert(BaseT::mTree);
1959 if (this->isHashed0(xyz)) {
1961 return reinterpret_cast<const NodeT*
>(mNode0);
1962 }
else if (this->isHashed1(xyz)) {
1964 return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1966 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1968 if (this->isHashed1(xyz)) {
1970 return reinterpret_cast<const NodeT*
>(mNode1);
1972 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
1993 template<
typename>
friend class Tree;
1998 void getNode(
const NodeT0*& node) { node = mNode0; }
1999 void getNode(
const NodeT1*& node) { node = mNode1; }
2000 void getNode(
const RootNodeT*& node)
2002 node = (BaseT::mTree ? &BaseT::mTree->root() :
nullptr);
2004 template<
typename OtherNodeType>
void getNode(
const OtherNodeType*& node) { node =
nullptr; }
2006 void eraseNode(
const NodeT0*) { mKey0 =
Coord::max(); mNode0 =
nullptr; }
2007 void eraseNode(
const NodeT1*) { mKey1 =
Coord::max(); mNode1 =
nullptr; }
2008 template<
typename OtherNodeType>
void eraseNode(
const OtherNodeType*) {}
2011 inline void copy(
const ValueAccessor2& other)
2013 mKey0 = other.mKey0;
2014 mNode0 = other.mNode0;
2015 mKey1 = other.mKey1;
2016 mNode1 = other.mNode1;
2021 void release()
override
2023 this->BaseT::release();
2031 inline void insert(
const Coord& xyz,
const NodeT0* node)
2034 mKey0 = xyz & ~(NodeT0::DIM-1);
2037 inline void insert(
const Coord& xyz,
const NodeT1* node)
2040 mKey1 = xyz & ~(NodeT1::DIM-1);
2045 template<
typename NodeT>
inline void insert(
const Coord&,
const NodeT*) {}
2047 inline bool isHashed0(
const Coord& xyz)
const
2049 return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2050 && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2051 && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2053 inline bool isHashed1(
const Coord& xyz)
const
2055 return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2056 && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2057 && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2059 mutable Coord mKey0;
2060 mutable const NodeT0* mNode0;
2061 mutable Coord mKey1;
2062 mutable const NodeT1* mNode1;
2076 template<
typename _TreeType,
bool IsSafe, Index L0, Index L1, Index L2>
2077 class ValueAccessor3 :
public ValueAccessorBase<_TreeType, IsSafe>
2080 static_assert(_TreeType::DEPTH >= 4,
"cache size exceeds tree depth");
2081 static_assert(L0 < L1,
"invalid cache level");
2082 static_assert(L1 < L2,
"invalid cache level");
2083 static_assert(L2 < _TreeType::RootNodeType::LEVEL,
"invalid cache level");
2091 using NodeT0 =
typename InvTreeT::template Get<L0>;
2092 using NodeT1 =
typename InvTreeT::template Get<L1>;
2093 using NodeT2 =
typename InvTreeT::template Get<L2>;
2097 mKey0(Coord::
max()), mNode0(nullptr),
2098 mKey1(Coord::
max()), mNode1(nullptr),
2099 mKey2(Coord::
max()), mNode2(nullptr) {}
2107 if (&other !=
this) {
2108 this->BaseT::operator=(other);
2124 assert(BaseT::mTree);
2125 return this->isHashed2(xyz) || this->isHashed1(xyz) || this->isHashed0(xyz);
2131 assert(BaseT::mTree);
2132 if (this->isHashed0(xyz)) {
2134 return mNode0->getValueAndCache(xyz, this->
self());
2135 }
else if (this->isHashed1(xyz)) {
2137 return mNode1->getValueAndCache(xyz, this->
self());
2138 }
else if (this->isHashed2(xyz)) {
2140 return mNode2->getValueAndCache(xyz, this->
self());
2142 return BaseT::mTree->root().getValueAndCache(xyz, this->
self());
2148 assert(BaseT::mTree);
2149 if (this->isHashed0(xyz)) {
2151 return mNode0->isValueOnAndCache(xyz, this->
self());
2152 }
else if (this->isHashed1(xyz)) {
2154 return mNode1->isValueOnAndCache(xyz, this->
self());
2155 }
else if (this->isHashed2(xyz)) {
2157 return mNode2->isValueOnAndCache(xyz, this->
self());
2159 return BaseT::mTree->root().isValueOnAndCache(xyz, this->
self());
2165 assert(BaseT::mTree);
2166 if (this->isHashed0(xyz)) {
2168 return mNode0->probeValueAndCache(xyz, value, this->
self());
2169 }
else if (this->isHashed1(xyz)) {
2171 return mNode1->probeValueAndCache(xyz, value, this->
self());
2172 }
else if (this->isHashed2(xyz)) {
2174 return mNode2->probeValueAndCache(xyz, value, this->
self());
2176 return BaseT::mTree->root().probeValueAndCache(xyz, value, this->
self());
2184 assert(BaseT::mTree);
2185 if (this->isHashed0(xyz)) {
2187 return RootNodeT::LEVEL - mNode0->getValueLevelAndCache(xyz, this->
self());
2188 }
else if (this->isHashed1(xyz)) {
2190 return RootNodeT::LEVEL - mNode1->getValueLevelAndCache(xyz, this->
self());
2191 }
else if (this->isHashed2(xyz)) {
2193 return RootNodeT::LEVEL - mNode2->getValueLevelAndCache(xyz, this->
self());
2195 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self());
2202 assert(BaseT::mTree);
2203 if (this->isHashed0(xyz)) {
2205 return mNode0->getValueLevelAndCache(xyz, this->
self())==0;
2206 }
else if (this->isHashed1(xyz)) {
2208 return mNode1->getValueLevelAndCache(xyz, this->
self())==0;
2209 }
else if (this->isHashed2(xyz)) {
2211 return mNode2->getValueLevelAndCache(xyz, this->
self())==0;
2213 return BaseT::mTree->root().getValueDepthAndCache(xyz, this->
self()) ==
2214 static_cast<int>(RootNodeT::LEVEL);
2221 assert(BaseT::mTree);
2222 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2223 if (this->isHashed0(xyz)) {
2225 const_cast<NodeT0*
>(mNode0)->setValueAndCache(xyz, value, *
this);
2226 }
else if (this->isHashed1(xyz)) {
2228 const_cast<NodeT1*
>(mNode1)->setValueAndCache(xyz, value, *
this);
2229 }
else if (this->isHashed2(xyz)) {
2231 const_cast<NodeT2*
>(mNode2)->setValueAndCache(xyz, value, *
this);
2233 BaseT::mTree->root().setValueAndCache(xyz, value, *
this);
2242 assert(BaseT::mTree);
2243 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2244 if (this->isHashed0(xyz)) {
2246 const_cast<NodeT0*
>(mNode0)->setValueOnlyAndCache(xyz, value, *
this);
2247 }
else if (this->isHashed1(xyz)) {
2249 const_cast<NodeT1*
>(mNode1)->setValueOnlyAndCache(xyz, value, *
this);
2250 }
else if (this->isHashed2(xyz)) {
2252 const_cast<NodeT2*
>(mNode2)->setValueOnlyAndCache(xyz, value, *
this);
2254 BaseT::mTree->root().setValueOnlyAndCache(xyz, value, *
this);
2261 assert(BaseT::mTree);
2262 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2263 if (this->isHashed0(xyz)) {
2265 const_cast<NodeT0*
>(mNode0)->setValueOffAndCache(xyz, value, *
this);
2266 }
else if (this->isHashed1(xyz)) {
2268 const_cast<NodeT1*
>(mNode1)->setValueOffAndCache(xyz, value, *
this);
2269 }
else if (this->isHashed2(xyz)) {
2271 const_cast<NodeT2*
>(mNode2)->setValueOffAndCache(xyz, value, *
this);
2273 BaseT::mTree->root().setValueOffAndCache(xyz, value, *
this);
2280 template<
typename ModifyOp>
2283 assert(BaseT::mTree);
2284 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2285 if (this->isHashed0(xyz)) {
2287 const_cast<NodeT0*
>(mNode0)->modifyValueAndCache(xyz, op, *
this);
2288 }
else if (this->isHashed1(xyz)) {
2290 const_cast<NodeT1*
>(mNode1)->modifyValueAndCache(xyz, op, *
this);
2291 }
else if (this->isHashed2(xyz)) {
2293 const_cast<NodeT2*
>(mNode2)->modifyValueAndCache(xyz, op, *
this);
2295 BaseT::mTree->root().modifyValueAndCache(xyz, op, *
this);
2301 template<
typename ModifyOp>
2304 assert(BaseT::mTree);
2305 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2306 if (this->isHashed0(xyz)) {
2308 const_cast<NodeT0*
>(mNode0)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
2309 }
else if (this->isHashed1(xyz)) {
2311 const_cast<NodeT1*
>(mNode1)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
2312 }
else if (this->isHashed2(xyz)) {
2314 const_cast<NodeT2*
>(mNode2)->modifyValueAndActiveStateAndCache(xyz, op, *
this);
2316 BaseT::mTree->root().modifyValueAndActiveStateAndCache(xyz, op, *
this);
2323 assert(BaseT::mTree);
2324 static_assert(!BaseT::IsConstTree,
"can't modify a const tree's values");
2325 if (this->isHashed0(xyz)) {
2327 const_cast<NodeT0*
>(mNode0)->setActiveStateAndCache(xyz, on, *
this);
2328 }
else if (this->isHashed1(xyz)) {
2330 const_cast<NodeT1*
>(mNode1)->setActiveStateAndCache(xyz, on, *
this);
2331 }
else if (this->isHashed2(xyz)) {
2333 const_cast<NodeT2*
>(mNode2)->setActiveStateAndCache(xyz, on, *
this);
2335 BaseT::mTree->root().setActiveStateAndCache(xyz, on, *
this);
2339 void setValueOn(
const Coord& xyz) { this->setActiveState(xyz,
true); }
2341 void setValueOff(
const Coord& xyz) { this->setActiveState(xyz,
false); }
2344 template<
typename NodeT>
2347 const NodeT* node =
nullptr;
2348 this->getNode(node);
2349 return const_cast<NodeT*
>(node);
2354 template<
typename NodeT>
2360 template<
typename NodeT>
2363 const NodeT* node =
nullptr;
2364 this->eraseNode(node);
2371 assert(BaseT::mTree);
2372 static_assert(!BaseT::IsConstTree,
"can't add a node to a const tree");
2373 if (this->isHashed1(leaf->origin())) {
2375 return const_cast<NodeT1*
>(mNode1)->addLeafAndCache(leaf, *
this);
2376 }
else if (this->isHashed2(leaf->origin())) {
2378 return const_cast<NodeT2*
>(mNode2)->addLeafAndCache(leaf, *
this);
2380 BaseT::mTree->root().addLeafAndCache(leaf, *
this);
2387 assert(BaseT::mTree);
2388 static_assert(!BaseT::IsConstTree,
"can't add a tile to a const tree");
2389 if (this->isHashed1(xyz)) {
2391 return const_cast<NodeT1*
>(mNode1)->addTileAndCache(level, xyz, value, state, *
this);
2392 }
if (this->isHashed2(xyz)) {
2394 return const_cast<NodeT2*
>(mNode2)->addTileAndCache(level, xyz, value, state, *
this);
2396 BaseT::mTree->root().addTileAndCache(level, xyz, value, state, *
this);
2407 assert(BaseT::mTree);
2408 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
2409 if (this->isHashed0(xyz)) {
2411 return const_cast<NodeT0*
>(mNode0);
2412 }
else if (this->isHashed1(xyz)) {
2414 return const_cast<NodeT1*
>(mNode1)->touchLeafAndCache(xyz, *
this);
2415 }
else if (this->isHashed2(xyz)) {
2417 return const_cast<NodeT2*
>(mNode2)->touchLeafAndCache(xyz, *
this);
2419 return BaseT::mTree->root().touchLeafAndCache(xyz, *
this);
2423 template<
typename NodeT>
2426 assert(BaseT::mTree);
2427 static_assert(!BaseT::IsConstTree,
"can't get a non-const node from a const tree");
2430 if (this->isHashed0(xyz)) {
2432 return reinterpret_cast<NodeT*
>(
const_cast<NodeT0*
>(mNode0));
2433 }
else if (this->isHashed1(xyz)) {
2435 return const_cast<NodeT1*
>(mNode1)->
template probeNodeAndCache<NodeT>(xyz, *
this);
2436 }
else if (this->isHashed2(xyz)) {
2438 return const_cast<NodeT2*
>(mNode2)->
template probeNodeAndCache<NodeT>(xyz, *
this);
2440 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
2442 if (this->isHashed1(xyz)) {
2444 return reinterpret_cast<NodeT*
>(
const_cast<NodeT1*
>(mNode1));
2445 }
else if (this->isHashed2(xyz)) {
2447 return const_cast<NodeT2*
>(mNode2)->
template probeNodeAndCache<NodeT>(xyz, *
this);
2449 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
2451 if (this->isHashed2(xyz)) {
2453 return reinterpret_cast<NodeT*
>(
const_cast<NodeT2*
>(mNode2));
2455 return BaseT::mTree->root().template probeNodeAndCache<NodeT>(xyz, *
this);
2466 template<
typename NodeT>
2469 assert(BaseT::mTree);
2472 if (this->isHashed0(xyz)) {
2474 return reinterpret_cast<const NodeT*
>(mNode0);
2475 }
else if (this->isHashed1(xyz)) {
2477 return mNode1->template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2478 }
else if (this->isHashed2(xyz)) {
2480 return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2482 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2484 if (this->isHashed1(xyz)) {
2486 return reinterpret_cast<const NodeT*
>(mNode1);
2487 }
else if (this->isHashed2(xyz)) {
2489 return mNode2->template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2491 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2493 if (this->isHashed2(xyz)) {
2495 return reinterpret_cast<const NodeT*
>(mNode2);
2497 return BaseT::mTree->root().template probeConstNodeAndCache<NodeT>(xyz, this->
self());
2506 return this->
template probeConstNode<LeafNodeT>(xyz);
2527 template<
typename>
friend class Tree;
2535 mKey0 = other.mKey0;
2536 mNode0 = other.mNode0;
2537 mKey1 = other.mKey1;
2538 mNode1 = other.mNode1;
2539 mKey2 = other.mKey2;
2540 mNode2 = other.mNode2;
2545 void release()
override
2547 this->BaseT::release();
2550 void getNode(
const NodeT0*& node) { node = mNode0; }
2551 void getNode(
const NodeT1*& node) { node = mNode1; }
2552 void getNode(
const NodeT2*& node) { node = mNode2; }
2553 void getNode(
const RootNodeT*& node)
2555 node = (BaseT::mTree ? &BaseT::mTree->root() :
nullptr);
2557 template<
typename OtherNodeType>
void getNode(
const OtherNodeType*& node) { node =
nullptr; }
2559 void eraseNode(
const NodeT0*) { mKey0 =
Coord::max(); mNode0 =
nullptr; }
2560 void eraseNode(
const NodeT1*) { mKey1 =
Coord::max(); mNode1 =
nullptr; }
2561 void eraseNode(
const NodeT2*) { mKey2 =
Coord::max(); mNode2 =
nullptr; }
2562 template<
typename OtherNodeType>
void eraseNode(
const OtherNodeType*) {}
2568 inline void insert(
const Coord& xyz,
const NodeT0* node)
2571 mKey0 = xyz & ~(NodeT0::DIM-1);
2574 inline void insert(
const Coord& xyz,
const NodeT1* node)
2577 mKey1 = xyz & ~(NodeT1::DIM-1);
2580 inline void insert(
const Coord& xyz,
const NodeT2* node)
2583 mKey2 = xyz & ~(NodeT2::DIM-1);
2588 template<
typename OtherNodeType>
2589 inline void insert(
const Coord&,
const OtherNodeType*)
2592 inline bool isHashed0(
const Coord& xyz)
const
2594 return (xyz[0] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[0]
2595 && (xyz[1] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[1]
2596 && (xyz[2] & ~Coord::ValueType(NodeT0::DIM-1)) == mKey0[2];
2598 inline bool isHashed1(
const Coord& xyz)
const
2600 return (xyz[0] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[0]
2601 && (xyz[1] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[1]
2602 && (xyz[2] & ~Coord::ValueType(NodeT1::DIM-1)) == mKey1[2];
2604 inline bool isHashed2(
const Coord& xyz)
const
2606 return (xyz[0] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[0]
2607 && (xyz[1] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[1]
2608 && (xyz[2] & ~Coord::ValueType(NodeT2::DIM-1)) == mKey2[2];
2610 mutable Coord mKey0;
2611 mutable const NodeT0* mNode0;
2612 mutable Coord mKey1;
2613 mutable const NodeT1* mNode1;
2614 mutable Coord mKey2;
2615 mutable const NodeT2* mNode2;
2622 #endif // OPENVDB_TREE_VALUEACCESSOR_HAS_BEEN_INCLUDED
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
ValueAccessor0(const ValueAccessor0 &other)
ValueAccessor(const ValueAccessor &other)
typename RootNodeType::LeafNodeType LeafNodeType
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
void setValueOn(const Coord &xyz, const ValueType &value)
const NodeType * probeConstNode(const Coord &xyz)
void insertNode(const Coord &xyz, NodeT &node)
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
void insert(const Coord &xyz, const OtherNodeType *node)
Forward the given node to another level of the cache.
int getValueDepth(const Coord &xyz) const
void modifyValue(const Coord &xyz, const ModifyOp &op)
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
typename NodeType::LeafNodeType LeafNodeType
typename TreeType::RootNodeType RootNodeT
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
const LeafNodeT * probeLeaf(const Coord &xyz) const
bool isVoxel(const Coord &xyz)
typename InvTreeT::template Get< 0 > NodeT0
const LeafNodeT * probeLeaf(const Coord &xyz) const
typename TreeType::LeafNodeType LeafNodeT
void insertNode(const Coord &xyz, NodeT &node)
void clear() override
Remove all nodes from this cache, then reinsert the root node.
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
typename TreeType::ValueType ValueType
void addLeaf(LeafNodeType *leaf)
typename RootNodeT::ValueType ValueType
Value accessor with two levels of node caching.
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
void clear() override
Remove all nodes from this cache, then reinsert the root node.
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
const NodeT * probeConstNode(const Coord &xyz) const
ValueAccessor1(const ValueAccessor1 &other)
Copy constructor.
void erase(const OtherNodeType *node)
Erase the node at another level of the cache.
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
void insert(const Coord &, const RootNodeType *root)
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
LeafNodeType * touchLeaf(const Coord &xyz)
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
const NodeT * probeNode(const Coord &xyz) const
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
Value accessor with three levels of node caching.
NodeT * probeNode(const Coord &xyz)
const NodeT * probeConstNode(const Coord &xyz) const
CacheItem(TreeCacheT &parent)
ValueAccessor0 & operator=(const ValueAccessor0 &other)
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
ValueAccessor3(const ValueAccessor3 &other)
Copy constructor.
typename TreeType::LeafNodeType LeafNodeT
void setValue(const Coord &xyz, const ValueType &value)
void insert(const Coord &xyz, const NodeType *node)
Cache the given node at this level.
bool isVoxel(const Coord &xyz) const
void getNode(RootNodeType *&node)
LeafNodeType * probeLeaf(const Coord &xyz)
bool isCached(const Coord &xyz) const
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
ValueAccessorBase & operator=(const ValueAccessorBase &other)
LeafNodeT * touchLeaf(const Coord &xyz)
typename TreeType::RootNodeType RootNodeT
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
bool isVoxel(const Coord &xyz) const
ValueAccessorRW(TreeType &tree)
NodeT * probeNode(const Coord &xyz)
const ValueType & getValue(const Coord &xyz)
Return the value of the voxel at the given coordinates.
ValueAccessor(const ValueAccessor &other)
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
const LeafNodeT * probeLeaf(const Coord &xyz) const
#define OPENVDB_USE_VERSION_NAMESPACE
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates without changing its value.
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
NodeType * probeNode(const Coord &xyz)
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
**But if you need a or simply need to know when the task has note that the like this
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
friend class InternalNode
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
ValueAccessorBase(const ValueAccessorBase &other)
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
int getValueDepth(const Coord &xyz) const
void setValueOn(const Coord &xyz, const ValueType &value)
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
OIIO_FORCEINLINE vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
bool isValueOn(const Coord &xyz)
Return the active state of the voxel at the given coordinates.
const LeafNodeT * probeLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
int getValueDepth(const Coord &xyz) const
Value accessor with one level of node caching.
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
typename InvTreeT::template Get< 0 > NodeT0
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
typename NodeType::ValueType ValueType
typename TreeType::ValueType ValueType
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
friend class InternalNode
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
ValueAccessorBase(TreeType &tree)
ValueAccessor(const ValueAccessor &other)
typename TreeType::RootNodeType RootNodeT
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
typename InvTreeT::template Get< 1 > NodeT1
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don't change its active state.
ValueAccessor(const ValueAccessor &other)
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
bool isVoxel(const Coord &xyz) const
const LeafNodeType * probeConstLeaf(const Coord &xyz)
LeafNodeT * touchLeaf(const Coord &xyz)
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
bool isCached(const Coord &xyz) const
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
void erase(const NodeType *)
Erase the node at this level.
typename TreeType::ValueType ValueType
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
void insert(const Coord &, const OtherNodeType *)
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
void insertNode(const Coord &xyz, NodeT &node)
std::numeric_limits< Int32 > CoordLimits
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
ValueAccessor(TreeType &tree)
LeafNodeType * probeLeaf(const Coord &xyz)
friend class InternalNode
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
typename RootNodeT::NodeChainType InvTreeT
typename TreeType::LeafNodeType LeafNodeT
NodeT * probeNode(const Coord &xyz)
bool probeValue(const Coord &xyz, ValueType &value)
Return the active state and value of the voxel at the given coordinates.
ValueAccessor(TreeType &tree)
typename TreeType::ValueType ValueType
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but don't change its active state.
const ValueType & getValue(const Coord &xyz)
int getValueDepth(const Coord &xyz)
void getNode(const RootNodeType *&node) const
CacheItem(TreeCacheT &parent)
bool isCached(const Coord &xyz) const
ValueAccessor with no mutex and no node caching.
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
~ValueAccessor() override=default
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
void clear() override
Remove all the cached nodes and invalidate the corresponding hash-keys.
ValueAccessor2(TreeType &tree)
Constructor from a tree.
ValueAccessor & operator=(const ValueAccessor &other)
void setValueOff(const Coord &xyz, const ValueType &value)
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
LeafNodeT * probeLeaf(const Coord &xyz)
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active without changing its value.
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
ValueAccessor3 & operator=(const ValueAccessor3 &other)
Assignment operator.
void insertNode(const Coord &xyz, NodeType &node)
typename NodeVecT::Front RootNodeType
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
typename SubtreeT::Front NodeType
void erase(const RootNodeType *)
void setActiveState(const Coord &xyz, bool on=true)
Set the active state of the voxel at the given coordinates but don't change its value.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
bool isCached(const Coord &xyz) const
Return true if nodes along the path to the given voxel have been cached.
typename TreeType::LeafNodeType LeafNodeT
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
TreeType * getTree() const
Return a pointer to the tree associated with this accessor.
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
ValueAccessor1 & operator=(const ValueAccessor1 &other)
Assignment operator.
~ValueAccessor0() override=default
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
const LeafNodeType * probeConstLeaf(const Coord &xyz)
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
ValueAccessor(TreeType &tree)
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinate but preserves its active state.
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
ValueAccessor3(TreeType &tree)
Constructor from a tree.
void addLeaf(LeafNodeType *leaf)
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
const LeafNodeT * probeLeaf(const Coord &xyz) const
Library and file format version numbers.
void getNode(NodeType *&node)
static const bool IsConstTree
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
NodeT * probeNode(const Coord &xyz)
const NodeT * probeConstNode(const Coord &xyz)
static Index numCacheLevels()
Return the number of cache levels employed by this ValueAccessor.
bool isVoxel(const Coord &xyz) const
LeafNodeT * touchLeaf(const Coord &xyz)
CacheItem(TreeCacheT &parent, const CacheItem &other)
const NodeT * probeConstNode(const Coord &xyz) const
Return a pointer to the node of the specified type that contains voxel (x, y, z), or nullptr if no su...
static Index numCacheLevels()
Return the number of cache levels employed by this accessor.
LeafNodeT * probeLeaf(const Coord &xyz)
ValueAccessor(TreeType &tree)
typename TreeType::LeafNodeType LeafNodeT
NodeT * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
LeafNodeT * probeLeaf(const Coord &xyz)
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
ValueAccessor2(const ValueAccessor2 &other)
Copy constructor.
typename TreeType::RootNodeType RootNodeT
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
void insertNode(const Coord &, NodeT &)
typename RootNodeT::NodeChainType InvTreeT
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void setValueOnly(const Coord &xyz, const ValueType &value)
const NodeT * probeConstNode(const Coord &xyz) const
CacheItem & copy(TreeCacheT &parent, const CacheItem &other)
Copy another CacheItem's node pointers and hash keys, but not its parent pointer. ...
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
int getValueDepth(const Coord &xyz) const
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
ValueAccessor2 & operator=(const ValueAccessor2 &other)
Assignment operator.
const NodeT * probeConstLeaf(const Coord &xyz) const
GLsizei const GLfloat * value
void setActiveState(const Coord &xyz, bool on)
typename tbb::null_mutex::scoped_lock LockT
int getValueDepth(const Coord &xyz)
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
bool isCached(const Coord &) const
Return true if nodes along the path to the given voxel have been cached.
ValueAccessor1(TreeType &tree)
Constructor from a tree.
bool isVoxel(const Coord &xyz) const
typename TreeType::RootNodeType RootNodeT
CacheItem(TreeCacheT &parent, const CacheItem &other)
Copy another CacheItem's node pointers and hash keys, but not its parent pointer. ...
bool isValueOn(const Coord &xyz)
void setValueOnly(const Coord &xyz, const ValueType &value)
ValueAccessor0(TreeType &tree)
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state and, in value, the value of the voxel at the given coordinates.
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
LeafNodeType * touchLeaf(const Coord &xyz)
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
typename InvTreeT::template Get< 0 > NodeT0
bool isCached(const Coord &xyz) const
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive without changing its value.
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
LeafNodeT * touchLeaf(const Coord &xyz)
bool isVoxel(const Coord &xyz)
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
typename InvTreeT::template Get< 1 > NodeT1
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
This accessor is thread-safe (at the cost of speed) for both reading and writing to a tree...
NodeT * probeNode(const Coord &xyz)
static bool isSafe()
Return true if this accessor is safe, i.e. registered by the tree from which it is constructed...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
friend class InternalNode
void getNode(const NodeType *&node) const
Return the cached node (if any) at this level.
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
int getValueDepth(const Coord &xyz) const
void getNode(OtherNodeType *&node)
Forward the request to another level of the cache.
const NodeT * probeConstNode(const Coord &xyz) const
LeafNodeT * probeLeaf(const Coord &xyz)
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
typename RootNodeT::NodeChainType InvTreeT
void clear()
Erase the nodes at this and lower levels of the cache.
void getNode(const NodeType *&node)
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
bool isCached(const Coord &xyz) const
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates.
ValueAccessor(TreeType &tree)
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly deleting existing node...
TreeType & tree() const
Return a reference to the tree associated with this accessor.
virtual ~ValueAccessorBase()
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
typename InvTreeT::template Get< 2 > NodeT2
typename RootNodeType::ValueType ValueType
bool probeValue(const Coord &xyz, ValueType &value)