39 #ifndef OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED
40 #define OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED
48 #include <tbb/blocked_range.h>
49 #include <tbb/parallel_for.h>
50 #include <tbb/parallel_reduce.h>
63 template<
typename Gr
idType>
64 inline typename GridType::ValueType lsutilGridMax()
69 template<
typename Gr
idType>
70 inline typename GridType::ValueType lsutilGridZero()
72 return zeroVal<typename GridType::ValueType>();
95 template<
class Gr
idType>
99 typename GridType::ValueType cutoffDistance = lsutilGridMax<GridType>());
112 template<
class Gr
idOrTreeType>
113 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
115 const GridOrTreeType& volume,
116 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>());
139 template<
typename Gr
idOrTreeType>
140 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
142 typename GridOrTreeType::ValueType isovalue = lsutilGridZero<GridOrTreeType>(),
143 const typename TreeAdapter<GridOrTreeType>::TreeType::template ValueConverter<bool>::Type* fillMask = NULL);
154 namespace level_set_util_internal {
157 template<
typename LeafNodeType>
164 ValueType isovalue,
const LeafNodeType ** nodes, BoolLeafNodeType ** maskNodes)
165 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
169 void operator()(
const tbb::blocked_range<size_t>& range)
const {
171 BoolLeafNodeType * maskNodePt = NULL;
173 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
175 mMaskNodes[n] = NULL;
176 const LeafNodeType& node = *mNodes[n];
179 maskNodePt =
new BoolLeafNodeType(node.origin(),
false);
184 const ValueType* values = &node.getValue(0);
185 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
186 if (values[i] < mIsovalue) maskNodePt->
setValueOn(i,
true);
190 mMaskNodes[n] = maskNodePt;
195 if (maskNodePt)
delete maskNodePt;
198 LeafNodeType
const *
const *
const mNodes;
204 template<
typename TreeType,
typename InternalNodeType>
210 : mTree(&tree), mMaskNodes(maskNodes), mIsovalue(isovalue) { }
212 void operator()(
const tbb::blocked_range<size_t>& range)
const {
214 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
215 typename InternalNodeType::ValueAllIter it = mMaskNodes[n]->beginValueAll();
217 if (acc.
getValue(it.getCoord()) < mIsovalue) {
231 template<
typename TreeType>
238 const size_t * nodexIndexMap, ValueType background)
239 : mNewTree(background)
242 , mNodeIndexMap(nodexIndexMap)
247 : mNewTree(rhs.mNewTree.background())
250 , mNodeIndexMap(rhs.mNodeIndexMap)
258 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
259 for (
size_t i = mNodeIndexMap[n], I = mNodeIndexMap[n + 1]; i < I; ++i) {
260 if (mNodes[i] != NULL) acc.
addLeaf(mNodes[i]);
269 TreeType *
const mTreePt;
270 LeafNodeType **
const mNodes;
271 size_t const *
const mNodeIndexMap;
276 template<
typename LeafNodeType>
283 ValueType isovalue,
const LeafNodeType ** nodes, CharLeafNodeType ** maskNodes)
284 : mNodes(nodes), mMaskNodes(maskNodes), mIsovalue(isovalue)
288 void operator()(
const tbb::blocked_range<size_t>& range)
const {
290 CharLeafNodeType * maskNodePt = NULL;
292 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
294 mMaskNodes[n] = NULL;
295 const LeafNodeType& node = *mNodes[n];
298 maskNodePt =
new CharLeafNodeType(node.origin(), 1);
303 typename LeafNodeType::ValueOnCIter it;
304 for (it = node.cbeginValueOn(); it; ++it) {
305 maskNodePt->
setValueOn(it.pos(), ((*it - mIsovalue) < 0.0) ? 0 : 1);
309 mMaskNodes[n] = maskNodePt;
314 if (maskNodePt)
delete maskNodePt;
317 LeafNodeType
const *
const *
const mNodes;
323 template<
typename LeafNodeType>
329 void operator()(
const tbb::blocked_range<size_t>& range)
const {
330 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
331 ValueType* values =
const_cast<ValueType*
>(&mNodes[n]->getValue(0));
332 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
333 values[i] = values[i] < 0 ? 1 : -1;
342 template<
typename LeafNodeType>
348 : minValue(std::numeric_limits<ValueType>::
max())
354 : minValue(std::numeric_limits<ValueType>::
max())
360 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
361 const ValueType* data = mNodes[n]->buffer().data();
362 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
363 minValue =
std::min(minValue, data[i]);
372 LeafNodeType
const *
const *
const mNodes;
376 template<
typename InternalNodeType>
382 : minValue(std::numeric_limits<ValueType>::
max())
388 : minValue(std::numeric_limits<ValueType>::
max())
394 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
395 typename InternalNodeType::ValueAllCIter it = mNodes[n]->beginValueAll();
406 InternalNodeType
const *
const *
const mNodes;
410 template<
typename LeafNodeType>
416 : mNodes(nodes), mWeight(ValueType(1.0) / cutoffDistance)
420 void operator()(
const tbb::blocked_range<size_t>& range)
const {
422 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
424 LeafNodeType& node = *mNodes[n];
427 ValueType* values = node.buffer().data();
428 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
429 values[i] = values[i] > ValueType(0.0) ? ValueType(0.0) : values[i] * mWeight;
430 if (values[i] > ValueType(0.0)) node.setValueOn(i);
433 if (node.onVoxelCount() == 0) {
445 template<
typename TreeType,
typename InternalNodeType>
449 : mTree(&tree), mNodes(nodes) { }
451 void operator()(
const tbb::blocked_range<size_t>& range)
const {
453 typedef typename TreeType::ValueType ValueType;
456 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
457 typename InternalNodeType::ValueAllIter it = mNodes[n]->beginValueAll();
459 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
460 it.setValue(ValueType(1.0));
472 template<
typename TreeType>
477 typedef typename TreeType::template ValueConverter<bool>::Type
BoolTreeType;
481 const BoolLeafNodeType ** fillNodes, BoolLeafNodeType ** newNodes)
482 : mTree(&tree), mFillMask(&fillMask), mFillNodes(fillNodes), mNewNodes(newNodes), mIsovalue(isovalue)
486 void operator()(
const tbb::blocked_range<size_t>& range)
const {
491 boost::scoped_array<char> valueMask(
new char[BoolLeafNodeType::SIZE]);
493 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
496 const BoolLeafNodeType& node = *mFillNodes[n];
497 const Coord& origin = node.origin();
499 const bool denseNode = node.isDense();
504 int denseNeighbors = 0;
506 const BoolLeafNodeType* neighborNode = maskAcc.
probeConstLeaf(origin.offsetBy(-1, 0, 0));
507 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
509 neighborNode = maskAcc.
probeConstLeaf(origin.offsetBy(BoolLeafNodeType::DIM, 0, 0));
510 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
513 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
515 neighborNode = maskAcc.
probeConstLeaf(origin.offsetBy(0, BoolLeafNodeType::DIM, 0));
516 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
519 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
521 neighborNode = maskAcc.
probeConstLeaf(origin.offsetBy(0, 0, BoolLeafNodeType::DIM));
522 if (neighborNode && neighborNode->isDense()) ++denseNeighbors;
524 if (denseNeighbors == 6)
continue;
528 memset(valueMask.get(), 0,
sizeof(char) * BoolLeafNodeType::SIZE);
530 const typename TreeType::LeafNodeType* distNode = distAcc.
probeConstLeaf(origin);
534 bool earlyTermination =
false;
538 evalInternalNeighborsP(valueMask.get(), node, *distNode);
539 evalInternalNeighborsN(valueMask.get(), node, *distNode);
540 }
else if (distAcc.
getValue(origin) > mIsovalue) {
541 earlyTermination = evalInternalNeighborsP(valueMask.get(), node);
542 if (!earlyTermination) earlyTermination = evalInternalNeighborsN(valueMask.get(), node);
548 if (!earlyTermination) {
549 evalExternalNeighborsX<true>(valueMask.get(), node, maskAcc, distAcc);
550 evalExternalNeighborsX<false>(valueMask.get(), node, maskAcc, distAcc);
551 evalExternalNeighborsY<true>(valueMask.get(), node, maskAcc, distAcc);
552 evalExternalNeighborsY<false>(valueMask.get(), node, maskAcc, distAcc);
553 evalExternalNeighborsZ<true>(valueMask.get(), node, maskAcc, distAcc);
554 evalExternalNeighborsZ<false>(valueMask.get(), node, maskAcc, distAcc);
559 int numBoundaryValues = 0;
560 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
561 numBoundaryValues += valueMask[i] == 1;
564 if (numBoundaryValues > 0) {
565 mNewNodes[n] =
new BoolLeafNodeType(origin,
false);
566 for (
Index i = 0, I = BoolLeafNodeType::SIZE; i < I; ++i) {
567 if (valueMask[i] == 1) mNewNodes[n]->setValueOn(i);
577 void evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node,
const LeafNodeType& distNode)
const {
579 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
580 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
581 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
582 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
583 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
584 const Index pos = yPos + z;
586 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
588 if (!node.isValueOn(pos + 1) && distNode.getValue(pos + 1) > mIsovalue) {
595 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
596 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
597 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
598 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
599 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
600 const Index pos = yPos + z;
602 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
604 if (!node.isValueOn(pos + BoolLeafNodeType::DIM) &&
605 distNode.getValue(pos + BoolLeafNodeType::DIM) > mIsovalue) {
612 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
613 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
614 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
615 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
616 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
617 const Index pos = yPos + z;
619 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
621 if (!node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
622 distNode.getValue(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) > mIsovalue) {
630 bool evalInternalNeighborsP(
char* valueMask,
const BoolLeafNodeType& node)
const {
632 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
633 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
634 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
635 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
636 for (
Index z = 0; z < BoolLeafNodeType::DIM - 1; ++z) {
637 const Index pos = yPos + z;
639 if (node.isValueOn(pos) && !node.isValueOn(pos + 1)) {
647 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
648 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
649 for (
Index y = 0; y < BoolLeafNodeType::DIM - 1; ++y) {
650 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
651 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
652 const Index pos = yPos + z;
654 if (node.isValueOn(pos) && !node.isValueOn(pos + BoolLeafNodeType::DIM)) {
662 for (
Index x = 0; x < BoolLeafNodeType::DIM - 1; ++x) {
663 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
664 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
665 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
666 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
667 const Index pos = yPos + z;
669 if (node.isValueOn(pos) &&
670 !node.isValueOn(pos + BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
683 void evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node,
const LeafNodeType& distNode)
const {
685 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
686 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
687 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
688 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
689 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
690 const Index pos = yPos + z;
692 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
694 if (!node.isValueOn(pos - 1) && distNode.getValue(pos - 1) > mIsovalue) {
701 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
702 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
703 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
704 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
705 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
706 const Index pos = yPos + z;
708 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
710 if (!node.isValueOn(pos - BoolLeafNodeType::DIM) &&
711 distNode.getValue(pos - BoolLeafNodeType::DIM) > mIsovalue) {
718 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
719 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
720 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
721 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
722 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
723 const Index pos = yPos + z;
725 if (valueMask[pos] != 0 || !node.isValueOn(pos))
continue;
727 if (!node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) &&
728 distNode.getValue(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM) > mIsovalue) {
737 bool evalInternalNeighborsN(
char* valueMask,
const BoolLeafNodeType& node)
const {
739 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
740 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
741 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
742 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
743 for (
Index z = 1; z < BoolLeafNodeType::DIM; ++z) {
744 const Index pos = yPos + z;
746 if (node.isValueOn(pos) && !node.isValueOn(pos - 1)) {
754 for (
Index x = 0; x < BoolLeafNodeType::DIM; ++x) {
755 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
756 for (
Index y = 1; y < BoolLeafNodeType::DIM; ++y) {
757 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
758 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
759 const Index pos = yPos + z;
761 if (node.isValueOn(pos) && !node.isValueOn(pos - BoolLeafNodeType::DIM)) {
769 for (
Index x = 1; x < BoolLeafNodeType::DIM; ++x) {
770 const Index xPos = x << (2 * BoolLeafNodeType::LOG2DIM);
771 for (
Index y = 0; y < BoolLeafNodeType::DIM; ++y) {
772 const Index yPos = xPos + (y << BoolLeafNodeType::LOG2DIM);
773 for (
Index z = 0; z < BoolLeafNodeType::DIM; ++z) {
774 const Index pos = yPos + z;
776 if (node.isValueOn(pos) &&
777 !node.isValueOn(pos - BoolLeafNodeType::DIM * BoolLeafNodeType::DIM)) {
792 template<
bool UpWind>
793 void evalExternalNeighborsX(
char* valueMask,
const BoolLeafNodeType& node,
794 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
795 const tree::ValueAccessor<const TreeType>& distAcc)
const {
797 const Coord& origin = node.origin();
798 Coord ijk(0, 0, 0), nijk;
803 ijk[0] = int(BoolLeafNodeType::DIM) - 1;
806 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
808 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
809 const Index yPos = xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
811 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
812 const Index pos = yPos + ijk[2];
814 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
816 nijk = origin + ijk.offsetBy(step, 0, 0);
818 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
827 template<
bool UpWind>
828 void evalExternalNeighborsY(
char* valueMask,
const BoolLeafNodeType& node,
829 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
830 const tree::ValueAccessor<const TreeType>& distAcc)
const {
832 const Coord& origin = node.origin();
833 Coord ijk(0, 0, 0), nijk;
838 ijk[1] = int(BoolLeafNodeType::DIM) - 1;
841 const Index yPos = ijk[1] << int(BoolLeafNodeType::LOG2DIM);
843 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
844 const Index xPos = yPos + (ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM)));
846 for (ijk[2] = 0; ijk[2] < int(BoolLeafNodeType::DIM); ++ijk[2]) {
847 const Index pos = xPos + ijk[2];
849 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
851 nijk = origin + ijk.offsetBy(0, step, 0);
852 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
861 template<
bool UpWind>
862 void evalExternalNeighborsZ(
char* valueMask,
const BoolLeafNodeType& node,
863 const tree::ValueAccessor<const BoolTreeType>& maskAcc,
864 const tree::ValueAccessor<const TreeType>& distAcc)
const {
866 const Coord& origin = node.origin();
867 Coord ijk(0, 0, 0), nijk;
872 ijk[2] = int(BoolLeafNodeType::DIM) - 1;
875 for (ijk[0] = 0; ijk[0] < int(BoolLeafNodeType::DIM); ++ijk[0]) {
876 const Index xPos = ijk[0] << (2 * int(BoolLeafNodeType::LOG2DIM));
878 for (ijk[1] = 0; ijk[1] < int(BoolLeafNodeType::DIM); ++ijk[1]) {
879 const Index pos = ijk[2] + xPos + (ijk[1] << int(BoolLeafNodeType::LOG2DIM));
881 if (valueMask[pos] == 0 && node.isValueOn(pos)) {
883 nijk = origin + ijk.offsetBy(0, 0, step);
884 if (!maskAcc.isValueOn(nijk) && distAcc.getValue(nijk) > mIsovalue) {
894 TreeType
const *
const mTree;
895 BoolTreeType
const *
const mFillMask;
896 BoolLeafNodeType
const *
const *
const mFillNodes;
897 BoolLeafNodeType **
const mNewNodes;
898 ValueType
const mIsovalue;
904 template <
class TreeType>
905 inline typename TreeType::template ValueConverter<char>::Type::Ptr
907 const typename TreeType::template ValueConverter<bool>::Type* fillMask)
909 typedef typename TreeType::LeafNodeType LeafNodeType;
910 typedef typename TreeType::RootNodeType RootNodeType;
911 typedef typename RootNodeType::NodeChainType NodeChainType;
912 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
914 typedef typename TreeType::template ValueConverter<char>::Type CharTreeType;
915 typedef typename CharTreeType::LeafNodeType CharLeafNodeType;
916 typedef typename CharTreeType::RootNodeType CharRootNodeType;
917 typedef typename CharRootNodeType::NodeChainType CharNodeChainType;
919 typedef typename TreeType::template ValueConverter<bool>::Type BoolTreeType;
920 typedef typename BoolTreeType::LeafNodeType BoolLeafNodeType;
924 const TreeType* treePt = &tree;
926 size_t numLeafNodes = 0, numInternalNodes = 0;
928 std::vector<const LeafNodeType*> nodes;
929 std::vector<size_t> leafnodeCount;
933 std::vector<const InternalNodeType*> internalNodes;
934 treePt->getNodes(internalNodes);
936 numInternalNodes = internalNodes.size();
938 leafnodeCount.push_back(0);
939 for (
size_t n = 0; n < numInternalNodes; ++n) {
940 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
943 numLeafNodes = leafnodeCount.back();
946 nodes.reserve(numLeafNodes);
948 for (
size_t n = 0; n < numInternalNodes; ++n) {
949 internalNodes[n]->getNodes(nodes);
954 boost::scoped_array<CharLeafNodeType*> maskNodes(
new CharLeafNodeType*[numLeafNodes]);
956 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
960 typename CharTreeType::Ptr maskTree(
new CharTreeType(1));
963 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
967 std::vector<CharLeafNodeType*> extraMaskNodes;
971 std::vector<const BoolLeafNodeType*> fillMaskNodes;
972 fillMask->getNodes(fillMaskNodes);
974 boost::scoped_array<BoolLeafNodeType*> boundaryMaskNodes(
new BoolLeafNodeType*[fillMaskNodes.size()]);
976 tbb::parallel_for(tbb::blocked_range<size_t>(0, fillMaskNodes.size()),
981 for (
size_t n = 0, N = fillMaskNodes.size(); n < N; ++n) {
983 if (boundaryMaskNodes[n] == NULL)
continue;
985 const BoolLeafNodeType& boundaryNode = *boundaryMaskNodes[n];
986 const Coord& origin = boundaryNode.origin();
988 CharLeafNodeType* maskNodePt = maskAcc.
probeLeaf(origin);
992 extraMaskNodes.push_back(maskNodePt);
995 char* data = maskNodePt->buffer().data();
997 typename BoolLeafNodeType::ValueOnCIter it = boundaryNode.cbeginValueOn();
999 if (data[it.pos()] != 0) data[it.pos()] = -1;
1002 delete boundaryMaskNodes[n];
1010 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1013 if (!extraMaskNodes.empty()) {
1014 tbb::parallel_for(tbb::blocked_range<size_t>(0, extraMaskNodes.size()),
1025 template <
class TreeType>
1026 inline typename TreeType::template ValueConverter<bool>::Type::Ptr
1029 typedef typename TreeType::LeafNodeType LeafNodeType;
1030 typedef typename TreeType::RootNodeType RootNodeType;
1031 typedef typename RootNodeType::NodeChainType NodeChainType;
1032 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
1034 typedef typename TreeType::template ValueConverter<bool>::Type BoolTreeType;
1035 typedef typename BoolTreeType::LeafNodeType BoolLeafNodeType;
1036 typedef typename BoolTreeType::RootNodeType BoolRootNodeType;
1037 typedef typename BoolRootNodeType::NodeChainType BoolNodeChainType;
1038 typedef typename boost::mpl::at<BoolNodeChainType, boost::mpl::int_<1> >::type BoolInternalNodeType;
1041 size_t numLeafNodes = 0, numInternalNodes = 0;
1043 std::vector<const LeafNodeType*> nodes;
1044 std::vector<size_t> leafnodeCount;
1048 std::vector<const InternalNodeType*> internalNodes;
1049 tree.getNodes(internalNodes);
1051 numInternalNodes = internalNodes.size();
1053 leafnodeCount.push_back(0);
1054 for (
size_t n = 0; n < numInternalNodes; ++n) {
1055 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1058 numLeafNodes = leafnodeCount.back();
1061 nodes.reserve(numLeafNodes);
1063 for (
size_t n = 0; n < numInternalNodes; ++n) {
1064 internalNodes[n]->getNodes(nodes);
1069 boost::scoped_array<BoolLeafNodeType*> maskNodes(
new BoolLeafNodeType*[numLeafNodes]);
1071 tbb::parallel_for(tbb::blocked_range<size_t>(0, numLeafNodes),
1076 typename BoolTreeType::Ptr maskTree(
new BoolTreeType(
false));
1079 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1083 std::vector<BoolInternalNodeType*> internalMaskNodes;
1084 maskTree->getNodes(internalMaskNodes);
1086 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalMaskNodes.size()),
1091 typename BoolTreeType::ValueAllIter it(*maskTree);
1092 it.setMaxDepth(BoolTreeType::ValueAllIter::LEAF_DEPTH - 2);
1095 if (acc.getValue(it.getCoord()) < iso) {
1097 it.setActiveState(
true);
1105 template<
typename TreeType>
1109 static BoolTreePtrType
construct(
const TreeType&, BoolTreePtrType& maskTree) {
return maskTree; }
1113 template<
typename TreeType>
1118 typedef typename TreeType::template ValueConverter<bool>::Type
BoolTreeType;
1123 static BoolGridPtrType
construct(
const GridType& grid, BoolTreePtrType& maskTree) {
1124 BoolGridPtrType maskGrid(BoolGridType::create(maskTree));
1137 template <
class Gr
idType>
1141 typedef typename GridType::ValueType ValueType;
1142 typedef typename GridType::TreeType TreeType;
1143 typedef typename TreeType::LeafNodeType LeafNodeType;
1144 typedef typename TreeType::RootNodeType RootNodeType;
1145 typedef typename RootNodeType::NodeChainType NodeChainType;
1146 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
1150 TreeType& tree = grid.tree();
1152 size_t numLeafNodes = 0, numInternalNodes = 0;
1154 std::vector<LeafNodeType*> nodes;
1155 std::vector<size_t> leafnodeCount;
1159 std::vector<InternalNodeType*> internalNodes;
1160 tree.getNodes(internalNodes);
1162 numInternalNodes = internalNodes.size();
1164 leafnodeCount.push_back(0);
1165 for (
size_t n = 0; n < numInternalNodes; ++n) {
1166 leafnodeCount.push_back(leafnodeCount.back() + internalNodes[n]->leafCount());
1169 numLeafNodes = leafnodeCount.back();
1172 nodes.reserve(numLeafNodes);
1174 for (
size_t n = 0; n < numInternalNodes; ++n) {
1175 internalNodes[n]->stealNodes(nodes, tree.background(),
false);
1183 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), minOp);
1187 if (minSDFValue > ValueType(0.0)) {
1189 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), minOp);
1193 cutoffDistance = -std::abs(cutoffDistance);
1194 cutoffDistance = minSDFValue > cutoffDistance ? minSDFValue : cutoffDistance;
1200 tbb::parallel_for(tbb::blocked_range<size_t>(0, nodes.size()),
1204 typename TreeType::Ptr newTree(
new TreeType(ValueType(0.0)));
1207 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, numInternalNodes), populate);
1210 std::vector<InternalNodeType*> internalNodes;
1211 newTree->getNodes(internalNodes);
1213 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalNodes.size()),
1219 typename TreeType::ValueAllIter it(*newTree);
1220 it.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 2);
1223 if (acc.
getValue(it.getCoord()) < ValueType(0.0)) {
1224 it.setValue(ValueType(1.0));
1225 it.setActiveState(
true);
1233 typename TreeType::ValueAllIter it(tree);
1234 it.setMaxDepth(TreeType::ValueAllIter::ROOT_DEPTH);
1236 if (it.getValue() < ValueType(0.0)) {
1237 newTree->addTile(TreeType::ValueAllIter::ROOT_LEVEL, it.getCoord(), ValueType(1.0),
true);
1242 grid.setTree(newTree);
1250 template <
class Gr
idOrTreeType>
1251 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
1252 sdfInteriorMask(
const GridOrTreeType& volume,
typename GridOrTreeType::ValueType isovalue)
1257 typedef typename TreeType::template ValueConverter<bool>::Type::Ptr BoolTreePtrType;
1264 template<
typename Gr
idOrTreeType>
1265 inline typename GridOrTreeType::template ValueConverter<bool>::Type::Ptr
1267 typename GridOrTreeType::ValueType isovalue,
1273 typedef typename TreeType::template ValueConverter<char>::Type::Ptr CharTreePtrType;
1276 typedef typename TreeType::template ValueConverter<bool>::Type::Ptr BoolTreePtrType;
1287 #endif // OPENVDB_TOOLS_LEVEL_SET_UTIL_HAS_BEEN_INCLUDED
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.
Definition: ValueAccessor.h:374
Index32 Index
Definition: Types.h:58
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:424
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:712
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:485
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
_TreeType TreeType
Definition: Grid.h:882
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:429
Convert polygonal meshes that consist of quads and/or triangles into signed or unsigned distance fiel...
Definition: Exceptions.h:39
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:880
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.
Definition: ValueAccessor.h:393
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:438
static TreeType & tree(TreeType &t)
Definition: Grid.h:897
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:65
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:335
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNode.h:470