10 #ifndef OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED 11 #define OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED 22 #include <unordered_map> 23 #include <unordered_set> 45 template <
typename TreeT>
51 using MaskTreeType =
typename TreeT::template ValueConverter<ValueMask>::Type;
57 : mTree(&tree), mSteal(true) { }
60 : mTreePtr(treePtr), mTree(mTreePtr.get()), mSteal(true) { }
68 : mTree(&tree), mSteal(false)
70 if (mTree &&
initialize) this->initializeMask();
84 void reset(
typename TreeType::Ptr treePtr,
Steal);
96 template<
typename NodeT>
97 const NodeT* probeConstNode(
const Coord& ijk)
const;
103 template <
typename NodeT>
104 std::unique_ptr<NodeT> stealOrDeepCopyNode(
const Coord& ijk);
108 template <
typename NodeT>
109 void addTile(
const Coord& ijk,
const ValueType&
value,
bool active);
113 void initializeMask();
116 bool hasMask()
const;
126 typename TreeType::Ptr mTreePtr;
134 template <
typename TreeT>
137 std::unique_ptr<MaskTreeType>
ptr;
144 : ptr(bool(other.ptr) ?
std::make_unique<
MaskTreeType>(*other.ptr) : nullptr) { }
147 if (
bool(other.
ptr)) ptr = std::make_unique<MaskTreeType>(*other.
ptr);
155 template <
typename TreeT>
159 using RootT =
typename MaskT::RootNodeType;
160 using LeafT =
typename MaskT::LeafNodeType;
163 bool operator()(
RootT& root,
size_t)
const;
164 template<
typename NodeT>
165 bool operator()(NodeT& node,
size_t)
const;
181 template<
typename TreeT,
bool Union>
184 using ValueT =
typename TreeT::ValueType;
185 using RootT =
typename TreeT::RootNodeType;
186 using LeafT =
typename TreeT::LeafNodeType;
191 template <
typename TagT>
203 template <
typename TreesT,
typename TagT>
206 for (
auto* tree : trees) {
208 mTreesToMerge.emplace_back(*tree, tag);
217 : mTreesToMerge(trees) { }
223 : mTreesToMerge(trees.cbegin(), trees.cend()) { }
226 bool empty()
const {
return mTreesToMerge.empty(); }
229 size_t size()
const {
return mTreesToMerge.size(); }
232 bool operator()(
RootT& root,
size_t idx)
const;
235 template<
typename NodeT>
236 bool operator()(NodeT& node,
size_t idx)
const;
239 bool operator()(
LeafT& leaf,
size_t idx)
const;
244 const ValueT& background()
const;
246 mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
247 mutable const ValueT* mBackground =
nullptr;
251 template <
typename TreeT>
254 template <
typename TreeT>
261 template<
typename TreeT>
264 using ValueT =
typename TreeT::ValueType;
265 using RootT =
typename TreeT::RootNodeType;
266 using LeafT =
typename TreeT::LeafNodeType;
271 template <
typename TagT>
283 size_t size()
const {
return 1; }
286 bool operator()(
RootT& root,
size_t idx)
const;
289 template<
typename NodeT>
290 bool operator()(NodeT& node,
size_t idx)
const;
293 bool operator()(
LeafT& leaf,
size_t idx)
const;
298 const ValueT& background()
const;
299 const ValueT& otherBackground()
const;
304 mutable const ValueT* mBackground =
nullptr;
305 mutable const ValueT* mOtherBackground =
nullptr;
312 template<
typename TreeT>
315 using ValueT =
typename TreeT::ValueType;
316 using RootT =
typename TreeT::RootNodeType;
317 using LeafT =
typename TreeT::LeafNodeType;
321 template <
typename TagT>
322 SumMergeOp(TreeT& tree, TagT tag) { mTreesToMerge.emplace_back(tree, tag); }
331 template <
typename TreesT,
typename TagT>
334 for (
auto* tree : trees) {
336 mTreesToMerge.emplace_back(*tree, tag);
345 : mTreesToMerge(trees) { }
351 : mTreesToMerge(trees.cbegin(), trees.cend()) { }
354 bool empty()
const {
return mTreesToMerge.empty(); }
357 size_t size()
const {
return mTreesToMerge.size(); }
360 bool operator()(
RootT& root,
size_t idx)
const;
363 template<
typename NodeT>
364 bool operator()(NodeT& node,
size_t idx)
const;
367 bool operator()(
LeafT& leaf,
size_t idx)
const;
372 const ValueT& background()
const;
374 mutable std::vector<TreeToMerge<TreeT>> mTreesToMerge;
375 mutable const ValueT* mBackground =
nullptr;
382 template<
typename TreeT>
389 manager.foreachTopDown(op);
392 template<
typename TreeT>
395 return bool(mMaskTree.ptr);
398 template<
typename TreeT>
406 mTree = mTreePtr.get();
409 template<
typename TreeT>
413 return &mTree->root();
416 template<
typename TreeT>
417 template<
typename NodeT>
422 if (!mSteal && !this->mask()->isValueOn(ijk))
return nullptr;
423 return mTree->template probeConstNode<NodeT>(ijk);
426 template<
typename TreeT>
427 template<
typename NodeT>
428 std::unique_ptr<NodeT>
433 return std::unique_ptr<NodeT>(
434 tree->root().template stealNode<NodeT>(ijk, mTree->root().background(),
false)
437 auto*
child = this->probeConstNode<NodeT>(ijk);
439 assert(this->hasMask());
440 auto result = std::make_unique<NodeT>(*child);
442 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
446 return std::unique_ptr<NodeT>();
449 template<
typename TreeT>
450 template<
typename NodeT>
455 if (NodeT::LEVEL == 0)
return;
459 auto* node = tree->template probeNode<NodeT>(ijk);
461 const Index pos = NodeT::coordToOffset(ijk);
462 node->addTile(pos, value, active);
465 auto* node = mTree->template probeConstNode<NodeT>(ijk);
468 assert(this->hasMask());
469 this->mask()->addTile(NodeT::LEVEL, ijk,
false,
false);
478 template <
typename TreeT>
481 using ChildT =
typename RootT::ChildNodeType;
483 const Index count = mTree.root().childCount();
485 std::vector<std::unique_ptr<ChildT>> children(count);
490 tbb::blocked_range<Index>(0, count),
491 [&](tbb::blocked_range<Index>& range)
493 for (
Index i = range.begin(); i < range.end(); i++) {
494 children[i] = std::make_unique<ChildT>(
Coord::max(),
true,
true);
502 for (
auto iter = mTree.root().cbeginChildOn(); iter; ++iter) {
503 children[i]->setOrigin(iter->origin());
504 root.addChild(children[i].release());
511 template <
typename TreeT>
512 template <
typename NodeT>
515 using ChildT =
typename NodeT::ChildNodeType;
517 const auto* otherNode = mTree.template probeConstNode<NodeT>(node.origin());
518 if (!otherNode)
return false;
522 if (NodeT::LEVEL == 1) {
523 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
524 node.
addTile(iter.pos(),
true,
true);
527 for (
auto iter = otherNode->cbeginChildOn(); iter; ++iter) {
528 auto*
child =
new ChildT(iter->origin(),
true,
true);
529 node.addChild(
child);
541 namespace merge_internal {
544 template <
typename BufferT,
typename ValueT>
545 struct UnallocatedBuffer
547 static void allocateAndFill(BufferT& buffer,
const ValueT& background)
549 if (buffer.empty()) {
550 if (!buffer.isOutOfCore()) {
552 buffer.fill(background);
557 static bool isPartiallyConstructed(
const BufferT& buffer)
559 return !buffer.isOutOfCore() && buffer.empty();
563 template <
typename BufferT>
564 struct UnallocatedBuffer<BufferT, bool>
567 static void allocateAndFill(BufferT&,
const bool&) { }
568 static bool isPartiallyConstructed(
const BufferT&) {
return false; }
574 template <Index LEVEL>
577 template <
typename NodeT,
typename OpT>
578 static void run(NodeT& node, OpT& op)
580 using ChildT =
typename NodeT::ChildNodeType;
584 Index32 childCount = node.childCount();
585 if (childCount > 0) {
589 std::vector<ChildT*> children;
590 children.reserve(childCount);
591 for (
auto iter = node.beginChildOn(); iter; ++iter) {
592 children.push_back(&(*iter));
597 tbb::blocked_range<Index32>(0, childCount),
598 [&](tbb::blocked_range<Index32>& range) {
599 for (
Index32 n = range.begin(); n < range.end(); n++) {
614 template <
typename NodeT,
typename OpT>
615 static void run(NodeT& node, OpT& op)
624 template <
typename TreeT>
625 struct ApplyTileToNodeOp
627 using LeafT =
typename TreeT::LeafNodeType;
628 using ValueT =
typename TreeT::ValueType;
630 ApplyTileToNodeOp(
const ValueT&
value,
const bool active):
631 mValue(value), mActive(active) { }
633 template <
typename NodeT>
634 void operator()(NodeT& node,
size_t)
const 640 for (
auto iter = node.beginValueAll(); iter; ++iter) {
641 iter.setValue(mValue + *iter);
643 if (mActive) node.setValuesOn();
646 void operator()(
LeafT& leaf,
size_t)
const 648 auto* data = leaf.buffer().data();
650 if (mValue != zeroVal<ValueT>()) {
651 for (
Index i = 0; i < LeafT::SIZE; ++i) {
655 if (mActive) leaf.setValuesOn();
658 template <
typename NodeT>
659 void run(NodeT& node)
678 template <
typename TreeT,
bool Union>
681 const bool Intersect = !Union;
683 if (this->empty())
return false;
686 if (!mBackground) mBackground = &root.background();
689 auto keyExistsInRoot = [&](
const Coord& key) ->
bool 691 return root.getValueDepth(key) > -1;
695 auto keyExistsInAllTrees = [&](
const Coord& key) ->
bool 698 const auto* mergeRoot = mergeTree.rootPtr();
699 if (!mergeRoot)
return false;
700 if (mergeRoot->getValueDepth(key) == -1)
return false;
706 root.eraseBackgroundTiles();
711 std::vector<Coord> toDelete;
712 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
713 const Coord& key = valueIter.getCoord();
714 if (!keyExistsInAllTrees(key)) toDelete.push_back(key);
717 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
718 const Coord& key = childIter.getCoord();
719 if (!keyExistsInAllTrees(key)) toDelete.push_back(key);
723 for (Coord& key : toDelete) root.addTile(key, *mBackground,
false);
724 root.eraseBackgroundTiles();
730 constexpr uint8_t ACTIVE_TILE = 0x1;
731 constexpr uint8_t INSIDE_TILE = 0x2;
732 constexpr uint8_t OUTSIDE_TILE = 0x4;
734 constexpr uint8_t INSIDE_STATE = Union ? INSIDE_TILE : OUTSIDE_TILE;
735 constexpr uint8_t OUTSIDE_STATE = Union ? OUTSIDE_TILE : INSIDE_TILE;
737 const ValueT insideBackground = Union ? -this->background() : this->background();
738 const ValueT outsideBackground = -insideBackground;
740 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
744 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
745 else if (value > zeroVal<ValueT>()) flag |= OUTSIDE_TILE;
746 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
750 std::unordered_map<Coord, uint8_t> tiles;
752 if (root.getTableSize() > 0) {
753 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
754 const Coord& key = valueIter.getCoord();
755 tiles.insert({key, getTileFlag(valueIter)});
762 const auto* mergeRoot = mergeTree.rootPtr();
763 if (!mergeRoot)
continue;
764 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
765 const Coord& key = valueIter.getCoord();
766 auto it = tiles.find(key);
767 if (it == tiles.end()) {
769 tiles.insert({key, getTileFlag(valueIter)});
772 const uint8_t flag = it->second;
773 if (flag & OUTSIDE_STATE) {
774 const uint8_t newFlag = getTileFlag(valueIter);
775 if (newFlag & INSIDE_STATE) {
776 it->second = newFlag;
785 for (
auto it : tiles) {
786 const uint8_t flag = it.second;
787 if (flag & INSIDE_STATE) {
788 const Coord& key = it.first;
789 const bool state = flag & ACTIVE_TILE;
791 if (Union || keyExistsInRoot(key)) {
792 root.addTile(key, insideBackground, state);
797 std::unordered_set<Coord> children;
799 if (root.getTableSize() > 0) {
800 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
801 const Coord& key = childIter.getCoord();
802 children.insert(key);
806 bool continueRecurse =
false;
812 const auto* mergeRoot = mergeTree.rootPtr();
813 if (!mergeRoot)
continue;
814 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
815 const Coord& key = childIter.getCoord();
818 if (Intersect && !keyExistsInRoot(key))
continue;
821 if (children.count(key)) {
822 continueRecurse =
true;
827 auto it = tiles.find(key);
828 if (it != tiles.end() && it->second == INSIDE_STATE)
continue;
830 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
831 childPtr->resetBackground(mergeRoot->background(), root.background());
832 if (childPtr) root.addChild(childPtr.release());
834 children.insert(key);
840 for (
auto it : tiles) {
841 const uint8_t flag = it.second;
842 if (flag & OUTSIDE_STATE) {
843 const Coord& key = it.first;
844 if (!children.count(key)) {
845 const bool state = flag & ACTIVE_TILE;
847 if (Union || keyExistsInRoot(key)) {
848 root.addTile(key, outsideBackground, state);
855 root.eraseBackgroundTiles();
857 return continueRecurse;
860 template<
typename TreeT,
bool Union>
861 template<
typename NodeT>
864 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
866 if (this->empty())
return false;
868 const ValueT insideBackground = Union ? -this->background() : this->background();
869 const ValueT outsideBackground = -insideBackground;
871 using NodeMaskT =
typename NodeT::NodeMaskType;
875 NodeMaskT invalidTile;
879 return Union ? value < zeroVal<ValueT>() :
value > zeroVal<ValueT>();
884 return Union ?
value > zeroVal<ValueT>() :
value < zeroVal<ValueT>();
887 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
888 if (
isValid(iter.getValue())) {
889 validTile.setOn(iter.pos());
890 }
else if (isInvalid(iter.getValue())) {
891 invalidTile.setOn(iter.pos());
895 bool continueRecurse =
false;
899 auto* mergeNode = mergeTree.template probeConstNode<NonConstNodeT>(node.origin());
901 if (!mergeNode)
continue;
905 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
906 Index pos = iter.pos();
908 if (validTile.isOn(pos))
continue;
910 if (
isValid(iter.getValue())) {
911 node.addTile(pos, insideBackground, iter.isValueOn());
912 validTile.setOn(pos);
918 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
919 Index pos = iter.pos();
920 const Coord& ijk = iter.getCoord();
922 if (validTile.isOn(pos)) {
923 mergeTree.template addTile<NonConstNodeT>(ijk, outsideBackground,
false);
924 }
else if (invalidTile.isOn(pos)) {
925 auto childPtr = mergeTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
927 childPtr->resetBackground(mergeTree.rootPtr()->background(), this->background());
928 node.addChild(childPtr.release());
930 invalidTile.setOff(pos);
934 continueRecurse =
true;
939 return continueRecurse;
942 template <
typename TreeT,
bool Union>
945 using LeafT =
typename TreeT::LeafNodeType;
946 using ValueT =
typename LeafT::ValueType;
947 using BufferT =
typename LeafT::Buffer;
949 if (this->empty())
return false;
951 const ValueT background = Union ? this->background() : -this->background();
956 merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
957 leaf.buffer(), background);
960 const LeafT* mergeLeaf = mergeTree.template probeConstNode<LeafT>(leaf.origin());
961 if (!mergeLeaf)
continue;
964 if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
965 mergeLeaf->buffer())) {
969 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
970 const ValueT& newValue = mergeLeaf->getValue(i);
971 const bool doMerge = Union ? newValue < leaf.getValue(i) : newValue > leaf.getValue(i);
973 leaf.setValueOnly(i, newValue);
974 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
982 template <
typename TreeT,
bool Union>
995 template <
typename TreeT>
999 if (!mBackground) mBackground = &root.background();
1000 if (!mOtherBackground) mOtherBackground = &mTree.rootPtr()->background();
1005 constexpr uint8_t ACTIVE_TILE = 0x1;
1006 constexpr uint8_t INSIDE_TILE = 0x2;
1007 constexpr uint8_t CHILD = 0x4;
1009 auto getTileFlag = [&](
auto& valueIter) -> uint8_t
1013 if (value < zeroVal<ValueT>()) flag |= INSIDE_TILE;
1014 if (valueIter.isValueOn()) flag |= ACTIVE_TILE;
1019 root.eraseBackgroundTiles();
1021 std::unordered_map<Coord, uint8_t> flags;
1023 if (root.getTableSize() > 0) {
1024 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
1025 const Coord& key = valueIter.getCoord();
1026 const uint8_t flag = getTileFlag(valueIter);
1027 if (flag & INSIDE_TILE) {
1028 flags.insert({key, getTileFlag(valueIter)});
1032 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
1033 const Coord& key = childIter.getCoord();
1034 flags.insert({key, CHILD});
1038 bool continueRecurse =
false;
1040 const auto* mergeRoot = mTree.rootPtr();
1043 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
1044 const Coord& key = valueIter.getCoord();
1045 const uint8_t flag = getTileFlag(valueIter);
1046 if (flag & INSIDE_TILE) {
1047 auto it = flags.find(key);
1048 if (it != flags.end()) {
1049 const bool state = flag & ACTIVE_TILE;
1050 root.addTile(key, this->background(), state);
1055 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
1056 const Coord& key = childIter.getCoord();
1057 auto it = flags.find(key);
1058 if (it != flags.end()) {
1059 const uint8_t otherFlag = it->second;
1060 if (otherFlag & CHILD) {
1062 continueRecurse =
true;
1063 }
else if (otherFlag & INSIDE_TILE) {
1064 auto childPtr = mTree.template stealOrDeepCopyNode<typename RootT::ChildNodeType>(key);
1066 childPtr->resetBackground(this->otherBackground(), this->background());
1068 root.addChild(childPtr.release());
1076 root.eraseBackgroundTiles();
1078 return continueRecurse;
1081 template<
typename TreeT>
1082 template<
typename NodeT>
1085 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
1087 using NodeMaskT =
typename NodeT::NodeMaskType;
1091 NodeMaskT insideTile;
1092 for (
auto iter = node.cbeginValueAll(); iter; ++iter) {
1093 if (iter.getValue() < zeroVal<ValueT>()) {
1094 insideTile.setOn(iter.pos());
1098 bool continueRecurse =
false;
1100 auto* mergeNode = mTree.template probeConstNode<NonConstNodeT>(node.origin());
1102 if (!mergeNode)
return continueRecurse;
1106 for (
auto iter = mergeNode->cbeginValueAll(); iter; ++iter) {
1107 Index pos = iter.pos();
1108 if (iter.getValue() < zeroVal<ValueT>()) {
1109 if (insideTile.isOn(pos) || node.isChildMaskOn(pos)) {
1110 node.addTile(pos, this->background(), iter.isValueOn());
1117 for (
auto iter = mergeNode->cbeginChildOn(); iter; ++iter) {
1118 Index pos = iter.pos();
1119 const Coord& ijk = iter.getCoord();
1120 if (insideTile.isOn(pos)) {
1121 auto childPtr = mTree.template stealOrDeepCopyNode<typename NodeT::ChildNodeType>(ijk);
1123 childPtr->resetBackground(this->otherBackground(), this->background());
1125 node.addChild(childPtr.release());
1127 }
else if (node.isChildMaskOn(pos)) {
1130 continueRecurse =
true;
1134 return continueRecurse;
1137 template <
typename TreeT>
1140 using LeafT =
typename TreeT::LeafNodeType;
1141 using ValueT =
typename LeafT::ValueType;
1142 using BufferT =
typename LeafT::Buffer;
1147 merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
1148 leaf.buffer(), this->background());
1150 const LeafT* mergeLeaf = mTree.template probeConstNode<LeafT>(leaf.origin());
1151 if (!mergeLeaf)
return false;
1156 if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
1157 mergeLeaf->buffer())) {
1161 for (
Index i = 0 ; i < LeafT::SIZE; i++) {
1162 const ValueT& aValue = leaf.getValue(i);
1164 if (aValue < bValue) {
1165 leaf.setValueOnly(i, bValue);
1166 leaf.setActiveState(i, mergeLeaf->isValueOn(i));
1173 template <
typename TreeT>
1178 assert(mBackground);
1179 return *mBackground;
1182 template <
typename TreeT>
1187 assert(mOtherBackground);
1188 return *mOtherBackground;
1195 template <
typename TreeT>
1198 using ValueT =
typename RootT::ValueType;
1199 using ChildT =
typename RootT::ChildNodeType;
1200 using NonConstChildT =
typename std::remove_const<ChildT>::type;
1202 if (this->empty())
return false;
1205 if (!mBackground) mBackground = &root.background();
1208 auto keyExistsInRoot = [](
const auto& rootToTest,
const Coord& key) ->
bool 1210 return rootToTest.getValueDepth(key) > -1;
1213 constexpr uint8_t TILE = 0x1;
1214 constexpr uint8_t CHILD = 0x2;
1215 constexpr uint8_t TARGET_CHILD = 0x4;
1217 std::unordered_map<Coord, uint8_t> children;
1221 if (root.getTableSize() > 0) {
1222 for (
auto valueIter = root.cbeginValueAll(); valueIter; ++valueIter) {
1223 const Coord& key = valueIter.getCoord();
1224 children.insert({key, TILE});
1227 for (
auto childIter = root.cbeginChildOn(); childIter; ++childIter) {
1228 const Coord& key = childIter.getCoord();
1229 children.insert({key, CHILD | TARGET_CHILD});
1236 const auto* mergeRoot = mergeTree.rootPtr();
1237 if (!mergeRoot)
continue;
1239 for (
auto valueIter = mergeRoot->cbeginValueAll(); valueIter; ++valueIter) {
1240 const Coord& key = valueIter.getCoord();
1241 auto it = children.find(key);
1242 if (it == children.end()) {
1244 children.insert({key, TILE});
1251 for (
auto childIter = mergeRoot->cbeginChildOn(); childIter; ++childIter) {
1252 const Coord& key = childIter.getCoord();
1253 auto it = children.find(key);
1254 if (it == children.end()) {
1256 children.insert({key, CHILD});
1259 it->second |= CHILD;
1266 for (
const auto& it : children) {
1267 if (!keyExistsInRoot(root, it.first)) {
1268 root.addTile(it.first, root.background(),
false);
1274 for (
const auto& it : children) {
1276 const Coord& key = it.first;
1280 if (it.second & TARGET_CHILD)
continue;
1283 const bool active = root.probeValue(key, value);
1286 const auto* mergeRoot = mergeTree.rootPtr();
1287 if (!mergeRoot)
continue;
1288 if (!keyExistsInRoot(*mergeRoot, key))
continue;
1294 const auto* mergeNode = mergeRoot->template probeConstNode<ChildT>(key);
1296 auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(key);
1297 childPtr->resetBackground(mergeRoot->background(), root.background());
1300 merge_internal::ApplyTileToNodeOp<TreeT> applyOp(value, active);
1301 applyOp.run(*childPtr);
1302 root.addChild(childPtr.release());
1308 const bool mergeActive = mergeRoot->probeValue(key, mergeValue);
1310 if (active || mergeActive) {
1311 value += mergeValue;
1312 root.addTile(key, value,
true);
1314 value += mergeValue;
1315 root.addTile(key, value,
false);
1319 mergeTree.template addTile<NonConstChildT>(key, zeroVal<ValueT>(),
false);
1326 template<
typename TreeT>
1327 template<
typename NodeT>
1330 using ChildT =
typename NodeT::ChildNodeType;
1331 using NonConstNodeT =
typename std::remove_const<NodeT>::type;
1333 if (this->empty())
return false;
1336 const auto* mergeRoot = mergeTree.rootPtr();
1337 if (!mergeRoot)
continue;
1339 const auto* mergeNode = mergeRoot->template probeConstNode<NonConstNodeT>(node.origin());
1343 for (
auto iter = node.beginValueAll(); iter; ++iter) {
1344 if (mergeNode->isChildMaskOn(iter.pos())) {
1346 auto childPtr = mergeTree.template stealOrDeepCopyNode<ChildT>(iter.getCoord());
1347 childPtr->resetBackground(mergeRoot->background(), this->background());
1350 merge_internal::ApplyTileToNodeOp<TreeT> applyOp(*iter, iter.isValueOn());
1351 applyOp.run(*childPtr);
1352 node.addChild(childPtr.release());
1356 const bool mergeActive = mergeNode->probeValue(iter.getCoord(), mergeValue);
1357 iter.setValue(*iter + mergeValue);
1358 if (mergeActive && !iter.isValueOn()) iter.setValueOn();
1366 const bool mergeActive = mergeRoot->probeValue(node.origin(), mergeValue);
1367 for (
auto iter = node.beginValueAll(); iter; ++iter) {
1368 iter.setValue(*iter + mergeValue);
1369 if (mergeActive && !iter.isValueOn()) iter.setValueOn();
1377 template <
typename TreeT>
1380 using RootT =
typename TreeT::RootNodeType;
1381 using RootChildT =
typename RootT::ChildNodeType;
1382 using NonConstRootChildT =
typename std::remove_const<RootChildT>::type;
1383 using LeafT =
typename TreeT::LeafNodeType;
1384 using ValueT =
typename LeafT::ValueType;
1385 using BufferT =
typename LeafT::Buffer;
1386 using NonConstLeafT =
typename std::remove_const<LeafT>::type;
1388 if (this->empty())
return false;
1390 const Coord& ijk = leaf.origin();
1395 merge_internal::UnallocatedBuffer<BufferT, ValueT>::allocateAndFill(
1396 leaf.buffer(), this->background());
1398 auto* data = leaf.buffer().data();
1401 const RootT* mergeRoot = mergeTree.rootPtr();
1402 if (!mergeRoot)
continue;
1404 const RootChildT* mergeRootChild = mergeRoot->template probeConstNode<NonConstRootChildT>(ijk);
1405 const LeafT* mergeLeaf = mergeRootChild ?
1406 mergeRootChild->template probeConstNode<NonConstLeafT>(ijk) :
nullptr;
1413 if (merge_internal::UnallocatedBuffer<BufferT, ValueT>::isPartiallyConstructed(
1414 mergeLeaf->buffer())) {
1418 for (
Index i = 0; i < LeafT::SIZE; ++i) {
1419 data[i] += mergeLeaf->getValue(i);
1422 leaf.getValueMask() |= mergeLeaf->getValueMask();
1427 bool mergeActive = mergeRootChild ?
1428 mergeRootChild->probeValue(ijk, mergeValue) : mergeRoot->probeValue(ijk, mergeValue);
1430 if (mergeValue != zeroVal<ValueT>()) {
1431 for (
Index i = 0; i < LeafT::SIZE; ++i) {
1432 data[i] += mergeValue;
1436 if (mergeActive) leaf.setValuesOn();
1443 template <
typename TreeT>
1448 assert(mBackground);
1449 return *mBackground;
1458 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 1460 #ifdef OPENVDB_INSTANTIATE_MERGE 1493 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 1500 #endif // OPENVDB_TOOLS_MERGE_HAS_BEEN_INCLUDED
ChildT * child
Definition: GridBuilder.h:1286
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#define OPENVDB_INSTANTIATE_STRUCT
Definition: version.h.in:144
Tag dispatch class that distinguishes constructors that steal.
Definition: Types.h:648
Implementation of a depth-first node visitor.
OPENVDB_IMPORT void initialize()
Global registration of basic types.
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Definition: Exceptions.h:63
Index32 Index
Definition: Types.h:54
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid.
Definition: NanoVDB.h:520
Tag dispatch class that distinguishes constructors that deep copy.
Definition: Types.h:646
void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
uint32_t Index32
Definition: Types.h:52
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
Definition: NodeManager.h:36
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202