10 #ifndef OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED
20 #include <unordered_map>
21 #include <unordered_set>
43 template <
typename TreeT>
49 using MaskTreeType =
typename TreeT::template ValueConverter<ValueMask>::Type;
55 : mTree(&tree), mSteal(true) { }
58 : mTreePtr(treePtr), mTree(mTreePtr.get()), mSteal(true) { }
66 : mTree(&tree), mSteal(false)
68 if (mTree &&
initialize) this->initializeMask();
82 void reset(
typename TreeType::Ptr treePtr,
Steal);
90 const RootNodeType* rootPtr()
const;
94 template<
typename NodeT>
95 const NodeT* probeConstNode(
const Coord& ijk)
const;
101 template <
typename NodeT>
102 std::unique_ptr<NodeT> stealOrDeepCopyNode(
const Coord& ijk);
106 template <
typename NodeT>
107 void addTile(
const Coord& ijk,
const ValueType& value,
bool active);
111 void initializeMask();
114 bool hasMask()
const;
124 typename TreeType::Ptr mTreePtr;
125 const TreeType* mTree;
132 template <
typename TreeT>
135 std::unique_ptr<MaskTreeType>
ptr;
142 : ptr(bool(other.ptr) ?
std::make_unique<
MaskTreeType>(*other.ptr) : nullptr) { }
145 ptr.reset(
bool(other.
ptr) ? std::make_unique<MaskTreeType>(*other.
ptr) :
nullptr);
152 template <
typename TreeT>
156 using RootT =
typename MaskT::RootNodeType;
157 using LeafT =
typename MaskT::LeafNodeType;
160 bool operator()(RootT& root,
size_t)
const;
161 template<
typename NodeT>
162 bool operator()(NodeT& node,
size_t)
const;
178 template<
typename TreeT,
bool Union>
181 using ValueT =
typename TreeT::ValueType;
182 using RootT =
typename TreeT::RootNodeType;
183 using LeafT =
typename TreeT::LeafNodeType;
188 template <
typename TagT>
200 template <
typename TreesT,
typename TagT>
203 for (
auto* tree : trees) {
205 mTreesToMerge.emplace_back(*tree, tag);
214 : mTreesToMerge(trees) { }
220 : mTreesToMerge(trees.cbegin(), trees.cend()) { }
223 bool empty()
const {
return mTreesToMerge.empty(); }
226 size_t size()
const {
return mTreesToMerge.size(); }
229 bool operator()(RootT& root,
size_t idx)
const;
232 template<
typename NodeT>
233 bool operator()(NodeT& node,
size_t idx)
const;
236 bool operator()(LeafT& leaf,
size_t idx)
const;
241 const ValueT& background()
const;
243 mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
244 mutable const ValueT* mBackground =
nullptr;
248 template <
typename TreeT>
251 template <
typename TreeT>
258 template<
typename TreeT>
261 using ValueT =
typename TreeT::ValueType;
262 using RootT =
typename TreeT::RootNodeType;
263 using LeafT =
typename TreeT::LeafNodeType;
268 template <
typename TagT>
280 size_t size()
const {
return 1; }
283 bool operator()(RootT& root,
size_t idx)
const;
286 template<
typename NodeT>
287 bool operator()(NodeT& node,
size_t idx)
const;
290 bool operator()(LeafT& leaf,
size_t idx)
const;
295 const ValueT& background()
const;
296 const ValueT& otherBackground()
const;
301 mutable const ValueT* mBackground =
nullptr;
302 mutable const ValueT* mOtherBackground =
nullptr;
309 template<
typename TreeT>
312 using ValueT =
typename TreeT::ValueType;
313 using RootT =
typename TreeT::RootNodeType;
314 using LeafT =
typename TreeT::LeafNodeType;
318 template <
typename TagT>
319 SumMergeOp(TreeT& tree, TagT tag) { mTreesToMerge.emplace_back(tree, tag); }
328 template <
typename TreesT,
typename TagT>
331 for (
auto* tree : trees) {
333 mTreesToMerge.emplace_back(*tree, tag);
342 : mTreesToMerge(trees) { }
348 : mTreesToMerge(trees.cbegin(), trees.cend()) { }
351 bool empty()
const {
return mTreesToMerge.empty(); }
354 size_t size()
const {
return mTreesToMerge.size(); }
357 bool operator()(RootT& root,
size_t idx)
const;
360 template<
typename NodeT>
361 bool operator()(NodeT& node,
size_t idx)
const;
364 bool operator()(LeafT& leaf,
size_t idx)
const;
369 const ValueT& background()
const;
371 mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
372 mutable const ValueT* mBackground =
nullptr;
379 template<
typename TreeT>
386 manager.foreachTopDown(op);
389 template<
typename TreeT>
392 return bool(mMaskTree.ptr);
395 template<
typename TreeT>
403 mTree = mTreePtr.get();
406 template<
typename TreeT>
410 return &mTree->root();
413 template<
typename TreeT>
414 template<
typename NodeT>
419 if (!mSteal && !this->mask()->isValueOn(ijk))
return nullptr;
420 return mTree->template probeConstNode<NodeT>(ijk);
423 template<
typename TreeT>
424 template<
typename NodeT>
425 std::unique_ptr<NodeT>
430 return std::unique_ptr<NodeT>(
431 tree->root().template stealNode<NodeT>(ijk, mTree->root().background(),
false)
434 auto* child = this->probeConstNode<NodeT>(ijk);
436 assert(this->hasMask());
437 auto result = std::make_unique<NodeT>(*child);
439 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
443 return std::unique_ptr<NodeT>();
446 template<
typename TreeT>
447 template<
typename NodeT>
452 if (NodeT::LEVEL == 0)
return;
456 auto* node = tree->template probeNode<NodeT>(ijk);
458 const Index pos = NodeT::coordToOffset(ijk);
459 node->addTile(pos, value, active);
462 auto* node = mTree->template probeConstNode<NodeT>(ijk);
465 assert(this->hasMask());
466 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
475 template <
typename TreeT>
478 using ChildT =
typename RootT::ChildNodeType;
480 const Index count = mTree.root().childCount();
482 std::vector<std::unique_ptr<ChildT>> children(count);
487 tbb::blocked_range<Index>(0, count),
488 [&](tbb::blocked_range<Index>& range)
490 for (
Index i = range.begin(); i < range.end(); i++) {
491 children[i] = std::make_unique<ChildT>(Coord::max(), true, true);
499 for (
auto iter = mTree.root().cbeginChildOn(); iter; ++iter) {
500 children[i]->setOrigin(iter->origin());
501 root.addChild(children[i].release());
508 template <
typename TreeT>
509 template <
typename NodeT>
512 using ChildT =
typename NodeT::ChildNodeType;
514 const auto* otherNode = mTree.template probeConstNode<NodeT>(node.origin());
515 if (!otherNode)
return false;
519 if (NodeT::LEVEL == 1) {
520 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
521 node.addTile(iter.pos(),
true,
true);
524 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
525 auto* child =
new ChildT(iter->origin(),
true,
true);
526 node.addChild(child);
537 namespace merge_internal {
540 template <
typename BufferT,
typename ValueT>
545 if (buffer.empty()) {
546 if (!buffer.isOutOfCore()) {
548 buffer.fill(background);
555 return !buffer.isOutOfCore() && buffer.empty();
559 template <
typename BufferT>
570 template <Index LEVEL>
573 template <
typename NodeT,
typename OpT>
574 static void run(NodeT& node, OpT& op)
576 using ChildT =
typename NodeT::ChildNodeType;
580 Index32 childCount = node.childCount();
581 if (childCount > 0) {
585 std::vector<ChildT*> children;
586 children.reserve(childCount);
587 for (
auto iter = node.beginChildOn(); iter; ++iter) {
588 children.push_back(&(*iter));
593 tbb::blocked_range<Index32>(0, childCount),
594 [&](tbb::blocked_range<Index32>& range) {
595 for (
Index32 n = range.begin(); n < range.end(); n++) {
596 DepthFirstNodeVisitor<ChildT>::visit(*children[n], op);
610 template <
typename NodeT,
typename OpT>
611 static void run(NodeT& node, OpT& op)
620 template <
typename TreeT>
623 using LeafT =
typename TreeT::LeafNodeType;
624 using ValueT =
typename TreeT::ValueType;
627 mValue(value), mActive(active) { }
629 template <
typename NodeT>
636 for (
auto iter = node.beginValueAll(); iter; ++iter) {
637 iter.setValue(mValue + *iter);
639 if (mActive) node.setValuesOn();
644 auto* data = leaf.buffer().data();
646 if (mValue != zeroVal<ValueT>()) {
647 for (
Index i = 0; i < LeafT::SIZE; ++i) {
651 if (mActive) leaf.setValuesOn();
654 template <
typename NodeT>
672 template <
typename TreeT,
bool Union>
675 const bool Intersect = !Union;
677 if (this->empty())
return false;
680 if (!mBackground) mBackground = &root.background();
683 auto keyExistsInRoot = [&](
const Coord& key) ->
bool
685 return root.getValueDepth(key) > -1;
689 auto keyExistsInAllTrees = [&](
const Coord& key) ->
bool
692 const auto* mergeRoot = mergeTree.rootPtr();
693 if (!mergeRoot)
return false;
694 if (mergeRoot->getValueDepth(key) == -1)
return false;
700 root.eraseBackgroundTiles();
705 std::vector<Coord> toDelete;
706 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
707 const Coord& key = valueIter.getCoord();
708 if (!keyExistsInAllTrees(key)) toDelete.push_back(key);
711 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
712 const Coord& key = childIter.getCoord();
713 if (!keyExistsInAllTrees(key)) toDelete.push_back(key);
717 for (
Coord& key : toDelete) root.addTile(key, *mBackground,
false);
718 root.eraseBackgroundTiles();
724 constexpr uint8_t ACTIVE_TILE = 0x1;
725 constexpr uint8_t INSIDE_TILE = 0x2;
726 constexpr uint8_t OUTSIDE_TILE = 0x4;
728 constexpr uint8_t INSIDE_STATE = Union ? INSIDE_TILE : OUTSIDE_TILE;
729 constexpr uint8_t OUTSIDE_STATE = Union ? OUTSIDE_TILE : INSIDE_TILE;
731 const ValueT insideBackground = Union ? -this->background() : this->background();
732 const ValueT outsideBackground = -insideBackground;
734 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
737 const ValueT& value = valueIter.getValue();
738 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
739 else if (value > zeroVal<ValueT>()) flag |= OUTSIDE_TILE;
740 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
744 std::unordered_map<
Coord, uint8_t> tiles;
746 if (root.getTableSize() > 0) {
747 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
748 const Coord& key = valueIter.getCoord();
749 tiles.insert({key, getTileFlag(valueIter)});
756 const auto* mergeRoot = mergeTree.rootPtr();
757 if (!mergeRoot)
continue;
758 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
759 const Coord& key = valueIter.getCoord();
760 auto it = tiles.find(key);
761 if (it == tiles.end()) {
763 tiles.insert({key, getTileFlag(valueIter)});
766 const uint8_t flag = it->second;
767 if (flag & OUTSIDE_STATE) {
768 const uint8_t newFlag = getTileFlag(valueIter);
769 if (newFlag & INSIDE_STATE) {
770 it->second = newFlag;
779 for (
auto it : tiles) {
780 const uint8_t flag = it.second;
781 if (flag & INSIDE_STATE) {
782 const Coord& key = it.first;
783 const bool state = flag & ACTIVE_TILE;
785 if (Union || keyExistsInRoot(key)) {
786 root.addTile(key, insideBackground, state);
791 std::unordered_set<Coord> children;
793 if (root.getTableSize() > 0) {
794 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
795 const Coord& key = childIter.getCoord();
796 children.insert(key);
800 bool continueRecurse =
false;
806 const auto* mergeRoot = mergeTree.rootPtr();
807 if (!mergeRoot)
continue;
808 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
809 const Coord& key = childIter.getCoord();
812 if (Intersect && !keyExistsInRoot(key))
continue;
815 if (children.count(key)) {
816 continueRecurse =
true;
821 auto it = tiles.find(key);
822 if (it != tiles.end() && it->second == INSIDE_STATE)
continue;
824 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
825 childPtr->resetBackground(mergeRoot->background(), root.background());
826 if (childPtr) root.addChild(childPtr.release());
828 children.insert(key);
834 for (
auto it : tiles) {
835 const uint8_t flag = it.second;
836 if (flag & OUTSIDE_STATE) {
837 const Coord& key = it.first;
838 if (!children.count(key)) {
839 const bool state = flag & ACTIVE_TILE;
841 if (Union || keyExistsInRoot(key)) {
842 root.addTile(key, outsideBackground, state);
849 root.eraseBackgroundTiles();
851 return continueRecurse;
854 template<
typename TreeT,
bool Union>
855 template<
typename NodeT>
858 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
860 if (this->empty())
return false;
862 const ValueT insideBackground = Union ? -this->background() : this->background();
863 const ValueT outsideBackground = -insideBackground;
865 using NodeMaskT =
typename NodeT::NodeMaskType;
869 NodeMaskT invalidTile;
871 auto isValid = [](
const ValueT& value)
873 return Union ? value < zeroVal<ValueT>() : value > zeroVal<ValueT>();
876 auto isInvalid = [](
const ValueT& value)
878 return Union ? value > zeroVal<ValueT>() : value < zeroVal<ValueT>();
881 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
882 if (isValid(iter.getValue())) {
883 validTile.setOn(iter.pos());
884 }
else if (isInvalid(iter.getValue())) {
885 invalidTile.setOn(iter.pos());
889 bool continueRecurse =
false;
893 auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
895 if (!mergeNode)
continue;
899 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
900 Index pos = iter.pos();
902 if (validTile.isOn(pos))
continue;
904 if (isValid(iter.getValue())) {
905 node.addTile(pos, insideBackground, iter.isValueOn());
906 validTile.setOn(pos);
912 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
913 Index pos = iter.pos();
914 const Coord& ijk = iter.getCoord();
916 if (validTile.isOn(pos)) {
917 mergeTree.template addTile<NonConstNodeT>(ijk, outsideBackground,
false);
918 }
else if (invalidTile.isOn(pos)) {
919 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
921 childPtr->resetBackground(mergeTree.rootPtr()->background(), this->background());
922 node.addChild(childPtr.release());
924 invalidTile.setOff(pos);
928 continueRecurse =
true;
933 return continueRecurse;
936 template <
typename TreeT,
bool Union>
939 using LeafT =
typename TreeT::LeafNodeType;
940 using ValueT =
typename LeafT::ValueType;
941 using BufferT =
typename LeafT::Buffer;
943 if (this->empty())
return false;
945 const ValueT background = Union ? this->background() : -this->background();
951 leaf.buffer(), background);
954 const LeafT* mergeLeaf = mergeTree.template probeConstNode<LeafT>(leaf.origin());
955 if (!mergeLeaf)
continue;
959 mergeLeaf->buffer())) {
963 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
964 const ValueT& newValue = mergeLeaf->getValue(i);
965 const bool doMerge = Union ? newValue < leaf.getValue(i) : newValue > leaf.getValue(i);
967 leaf.setValueOnly(i, newValue);
968 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
976 template <
typename TreeT,
bool Union>
989 template <
typename TreeT>
993 if (!mBackground) mBackground = &root.background();
994 if (!mOtherBackground) mOtherBackground = &mTree.rootPtr()->background();
999 constexpr uint8_t ACTIVE_TILE = 0x1;
1000 constexpr uint8_t INSIDE_TILE = 0x2;
1001 constexpr uint8_t CHILD = 0x4;
1003 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
1006 const ValueT& value = valueIter.getValue();
1007 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
1008 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
1013 root.eraseBackgroundTiles();
1015 std::unordered_map<
Coord, uint8_t> flags;
1017 if (root.getTableSize() > 0) {
1018 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
1019 const Coord& key = valueIter.getCoord();
1020 const uint8_t flag = getTileFlag(valueIter);
1021 if (flag & INSIDE_TILE) {
1022 flags.insert({key, getTileFlag(valueIter)});
1026 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
1027 const Coord& key = childIter.getCoord();
1028 flags.insert({key, CHILD});
1032 bool continueRecurse =
false;
1034 const auto* mergeRoot = mTree.rootPtr();
1037 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
1038 const Coord& key = valueIter.getCoord();
1039 const uint8_t flag = getTileFlag(valueIter);
1040 if (flag & INSIDE_TILE) {
1041 auto it = flags.find(key);
1042 if (it != flags.end()) {
1043 const bool state = flag & ACTIVE_TILE;
1044 root.addTile(key, this->background(), state);
1049 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
1050 const Coord& key = childIter.getCoord();
1051 auto it = flags.find(key);
1052 if (it != flags.end()) {
1053 const uint8_t otherFlag = it->second;
1054 if (otherFlag & CHILD) {
1056 continueRecurse =
true;
1057 }
else if (otherFlag & INSIDE_TILE) {
1058 auto childPtr = mTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
1060 childPtr->resetBackground(this->otherBackground(), this->background());
1062 root.addChild(childPtr.release());
1070 root.eraseBackgroundTiles();
1072 return continueRecurse;
1075 template<
typename TreeT>
1076 template<
typename NodeT>
1079 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
1081 using NodeMaskT =
typename NodeT::NodeMaskType;
1085 NodeMaskT insideTile;
1086 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
1087 if (iter.getValue() < zeroVal<ValueT>()) {
1088 insideTile.setOn(iter.pos());
1092 bool continueRecurse =
false;
1094 auto* mergeNode = mTree.template probeConstNode<NonConstNodeT>(node.origin());
1096 if (!mergeNode)
return continueRecurse;
1100 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
1101 Index pos = iter.pos();
1102 if (iter.getValue() < zeroVal<ValueT>()) {
1103 if (insideTile.isOn(pos) || node.isChildMaskOn(pos)) {
1104 node.addTile(pos, this->background(), iter.isValueOn());
1111 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
1112 Index pos = iter.pos();
1113 const Coord& ijk = iter.getCoord();
1114 if (insideTile.isOn(pos)) {
1115 auto childPtr = mTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
1117 childPtr->resetBackground(this->otherBackground(), this->background());
1119 node.addChild(childPtr.release());
1121 }
else if (node.isChildMaskOn(pos)) {
1124 continueRecurse =
true;
1128 return continueRecurse;
1131 template <
typename TreeT>
1134 using LeafT =
typename TreeT::LeafNodeType;
1135 using ValueT =
typename LeafT::ValueType;
1136 using BufferT =
typename LeafT::Buffer;
1142 leaf.buffer(), this->background());
1144 const LeafT* mergeLeaf = mTree.template probeConstNode<LeafT>(leaf.origin());
1145 if (!mergeLeaf)
return false;
1151 mergeLeaf->buffer())) {
1155 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
1156 const ValueT& aValue = leaf.getValue(i);
1158 if (aValue < bValue) {
1159 leaf.setValueOnly(i, bValue);
1160 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
1167 template <
typename TreeT>
1172 assert(mBackground);
1173 return *mBackground;
1176 template <
typename TreeT>
1177 const typename CsgDifferenceOp<TreeT>::ValueT&
1178 CsgDifferenceOp<TreeT>::otherBackground()
const
1181 assert(mOtherBackground);
1182 return *mOtherBackground;
1189 template <
typename TreeT>
1192 using ValueT =
typename RootT::ValueType;
1193 using ChildT =
typename RootT::ChildNodeType;
1194 using NonConstChildT =
typename std::remove_const<ChildT>::type;
1196 if (this->empty())
return false;
1199 if (!mBackground) mBackground = &root.background();
1202 auto keyExistsInRoot = [](
const auto& rootToTest,
const Coord& key) ->
bool
1204 return rootToTest.getValueDepth(key) > -1;
1207 constexpr uint8_t TILE = 0x1;
1208 constexpr uint8_t CHILD = 0x2;
1209 constexpr uint8_t TARGET_CHILD = 0x4;
1211 std::unordered_map<
Coord, uint8_t> children;
1215 if (root.getTableSize() > 0) {
1216 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
1217 const Coord& key = valueIter.getCoord();
1218 children.insert({key, TILE});
1221 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
1222 const Coord& key = childIter.getCoord();
1223 children.insert({key, CHILD | TARGET_CHILD});
1230 const auto* mergeRoot = mergeTree.rootPtr();
1231 if (!mergeRoot)
continue;
1233 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
1234 const Coord& key = valueIter.getCoord();
1235 auto it = children.find(key);
1236 if (it == children.end()) {
1238 children.insert({key, TILE});
1245 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
1246 const Coord& key = childIter.getCoord();
1247 auto it = children.find(key);
1248 if (it == children.end()) {
1250 children.insert({key, CHILD});
1253 it->second |= CHILD;
1260 for (
const auto& it : children) {
1261 if (!keyExistsInRoot(root, it.first)) {
1262 root.addTile(it.first, root.background(),
false);
1268 for (
const auto& it : children) {
1270 const Coord& key = it.first;
1274 if (it.second & TARGET_CHILD)
continue;
1277 const bool active = root.probeValue(key, value);
1280 const auto* mergeRoot = mergeTree.rootPtr();
1281 if (!mergeRoot)
continue;
1282 if (!keyExistsInRoot(*mergeRoot, key))
continue;
1288 const auto* mergeNode = mergeRoot->template probeConstNode<ChildT>(key);
1290 auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(key);
1291 childPtr->resetBackground(mergeRoot->background(), root.background());
1295 applyOp.
run(*childPtr);
1296 root.addChild(childPtr.release());
1302 const bool mergeActive = mergeRoot->probeValue(key, mergeValue);
1304 if (active || mergeActive) {
1305 value += mergeValue;
1306 root.addTile(key, value,
true);
1308 value += mergeValue;
1309 root.addTile(key, value,
false);
1313 mergeTree.template addTile<NonConstChildT>(key, zeroVal<ValueT>(),
false);
1320 template<
typename TreeT>
1321 template<
typename NodeT>
1324 using ChildT =
typename NodeT::ChildNodeType;
1325 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
1327 if (this->empty())
return false;
1330 const auto* mergeRoot = mergeTree.rootPtr();
1331 if (!mergeRoot)
continue;
1333 const auto* mergeNode = mergeRoot->template probeConstNode<NonConstNodeT>(node.origin());
1337 for (
auto iter = node.beginValueAll(); iter; ++iter) {
1338 if (mergeNode->isChildMaskOn(iter.pos())) {
1340 auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(iter.getCoord());
1341 childPtr->resetBackground(mergeRoot->background(), this->background());
1345 applyOp.
run(*childPtr);
1346 node.addChild(childPtr.release());
1350 const bool mergeActive = mergeNode->probeValue(iter.getCoord(), mergeValue);
1351 iter.setValue(*iter + mergeValue);
1352 if (mergeActive && !iter.isValueOn()) iter.setValueOn();
1360 const bool mergeActive = mergeRoot->probeValue(node.origin(), mergeValue);
1361 for (
auto iter = node.beginValueAll(); iter; ++iter) {
1362 iter.setValue(*iter + mergeValue);
1363 if (mergeActive && !iter.isValueOn()) iter.setValueOn();
1371 template <
typename TreeT>
1374 using RootT =
typename TreeT::RootNodeType;
1375 using RootChildT =
typename RootT::ChildNodeType;
1376 using NonConstRootChildT =
typename std::remove_const<RootChildT>::type;
1377 using LeafT =
typename TreeT::LeafNodeType;
1378 using ValueT =
typename LeafT::ValueType;
1379 using BufferT =
typename LeafT::Buffer;
1380 using NonConstLeafT =
typename std::remove_const<LeafT>::type;
1382 if (this->empty())
return false;
1384 const Coord& ijk = leaf.origin();
1390 leaf.buffer(), this->background());
1392 auto* data = leaf.buffer().data();
1395 const RootT* mergeRoot = mergeTree.rootPtr();
1396 if (!mergeRoot)
continue;
1398 const RootChildT* mergeRootChild = mergeRoot->template probeConstNode<NonConstRootChildT>(ijk);
1399 const LeafT* mergeLeaf = mergeRootChild ?
1400 mergeRootChild->template probeConstNode<NonConstLeafT>(ijk) :
nullptr;
1408 mergeLeaf->buffer())) {
1412 for (
Index i = 0; i < LeafT::SIZE; ++i) {
1413 data[i] += mergeLeaf->getValue(i);
1416 leaf.getValueMask() |= mergeLeaf->getValueMask();
1421 bool mergeActive = mergeRootChild ?
1422 mergeRootChild->probeValue(ijk, mergeValue) : mergeRoot->probeValue(ijk, mergeValue);
1424 if (mergeValue != zeroVal<ValueT>()) {
1425 for (
Index i = 0; i < LeafT::SIZE; ++i) {
1426 data[i] += mergeValue;
1430 if (mergeActive) leaf.setValuesOn();
1437 template <
typename TreeT>
1442 assert(mBackground);
1443 return *mBackground;
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
Implementation of a depth-first node visitor.
Tag dispatch class that distinguishes constructors that deep copy.
Definition: openvdb/Types.h:562
Definition: openvdb/Exceptions.h:63
Tag dispatch class that distinguishes constructors that steal.
Definition: openvdb/Types.h:564
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
Definition: NodeManager.h:884
void run(const char *ax, openvdb::GridBase &grid)
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 Index
Definition: openvdb/Types.h:50
OPENVDB_IMPORT void initialize()
Global registration of basic types.
uint32_t Index32
Definition: openvdb/Types.h:48
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178