31 #ifndef OPENVDB_TOOLS_MESH_TO_VOLUME_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_MESH_TO_VOLUME_HAS_BEEN_INCLUDED
34 #include <openvdb/Types.h>
35 #include <openvdb/math/FiniteDifference.h>
36 #include <openvdb/math/Operators.h>
37 #include <openvdb/math/Proximity.h>
38 #include <openvdb/tools/Morphology.h>
39 #include <openvdb/util/NullInterrupter.h>
40 #include <openvdb/util/Util.h>
45 #include <tbb/blocked_range.h>
46 #include <tbb/parallel_for.h>
47 #include <tbb/parallel_reduce.h>
49 #include <boost/math/special_functions/fpclassify.hpp>
82 template<
typename Gr
idType>
83 inline typename GridType::Ptr
85 const openvdb::math::Transform& xform,
86 const std::vector<Vec3s>& points,
87 const std::vector<Vec3I>& triangles,
106 template<
typename Gr
idType>
107 inline typename GridType::Ptr
109 const openvdb::math::Transform& xform,
110 const std::vector<Vec3s>& points,
111 const std::vector<Vec4I>& quads,
131 template<
typename Gr
idType>
132 inline typename GridType::Ptr
134 const openvdb::math::Transform& xform,
135 const std::vector<Vec3s>& points,
136 const std::vector<Vec3I>& triangles,
137 const std::vector<Vec4I>& quads,
159 template<
typename Gr
idType>
160 inline typename GridType::Ptr
162 const openvdb::math::Transform& xform,
163 const std::vector<Vec3s>& points,
164 const std::vector<Vec3I>& triangles,
165 const std::vector<Vec4I>& quads,
184 template<
typename Gr
idType>
185 inline typename GridType::Ptr
187 const openvdb::math::Transform& xform,
188 const std::vector<Vec3s>& points,
189 const std::vector<Vec3I>& triangles,
190 const std::vector<Vec4I>& quads,
202 template<
typename FloatGr
idT,
typename InterruptT = util::NullInterrupter>
210 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
213 MeshToVolume(openvdb::math::Transform::Ptr&,
int conversionFlags = 0,
214 InterruptT *interrupter = NULL,
int signSweeps = 1);
227 void convertToLevelSet(
228 const std::vector<Vec3s>& pointList,
229 const std::vector<Vec4I>& polygonList,
241 void convertToUnsignedDistanceField(
const std::vector<Vec3s>& pointList,
242 const std::vector<Vec4I>& polygonList, FloatValueT exBandWidth);
247 typename FloatGridT::Ptr
distGridPtr()
const {
return mDistGrid; }
257 void doConvert(
const std::vector<Vec3s>&,
const std::vector<Vec4I>&,
258 FloatValueT exBandWidth, FloatValueT inBandWidth,
bool unsignedDistField =
false);
261 return mInterrupter && mInterrupter->wasInterrupted(percent);
264 openvdb::math::Transform::Ptr mTransform;
265 int mConversionFlags, mSignSweeps;
267 typename FloatGridT::Ptr mDistGrid;
268 typename IntGridT::Ptr mIndexGrid;
269 typename BoolGridT::Ptr mIntersectingVoxelsGrid;
271 InterruptT *mInterrupter;
288 : mXDist(dist), mYDist(dist), mZDist(dist)
331 void convert(
const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList);
336 void getEdgeData(Accessor& acc,
const Coord& ijk,
337 std::vector<Vec3d>& points, std::vector<Index32>& primitives);
362 PointTransform(
const std::vector<Vec3s>& pointsIn, std::vector<Vec3s>& pointsOut,
364 : mPointsIn(pointsIn)
365 , mPointsOut(&pointsOut)
370 void run(
bool threaded =
true)
373 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPointsOut->size()), *
this);
375 (*this)(tbb::blocked_range<size_t>(0, mPointsOut->size()));
379 inline void operator()(
const tbb::blocked_range<size_t>& range)
const
381 for (
size_t n = range.begin(); n < range.end(); ++n) {
382 (*mPointsOut)[n] =
Vec3s(mXform.worldToIndex(mPointsIn[n]));
387 const std::vector<Vec3s>& mPointsIn;
388 std::vector<Vec3s> *
const mPointsOut;
393 template<
typename ValueType>
396 static ValueType
epsilon() {
return ValueType(1e-7); }
401 template<
typename FloatTreeT,
typename IntTreeT>
403 combine(FloatTreeT& lhsDist, IntTreeT& lhsIndex, FloatTreeT& rhsDist, IntTreeT& rhsIndex)
405 typedef typename FloatTreeT::ValueType FloatValueT;
409 typename FloatTreeT::LeafCIter iter = rhsDist.cbeginLeaf();
411 FloatValueT rhsValue;
414 for ( ; iter; ++iter) {
415 typename FloatTreeT::LeafNodeType::ValueOnCIter it = iter->cbeginValueOn();
420 rhsValue = it.getValue();
421 FloatValueT& lhsValue =
const_cast<FloatValueT&
>(lhsDistAccessor.
getValue(ijk));
423 if (-rhsValue < std::abs(lhsValue)) {
442 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
452 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
458 const std::vector<Vec4I>& polygonList, InterruptT *interrupter = NULL);
462 void run(
bool threaded =
true);
465 void operator() (
const tbb::blocked_range<size_t> &range);
475 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
477 bool evalVoxel(
const Coord& ijk,
const Int32 polyIdx);
479 const std::vector<Vec3s>& mPointList;
480 const std::vector<Vec4I>& mPolygonList;
482 FloatTreeT mSqrDistTree;
483 FloatAccessorT mSqrDistAccessor;
485 IntTreeT mPrimIndexTree;
486 IntAccessorT mPrimIndexAccessor;
488 BoolTreeT mIntersectionTree;
489 BoolAccessorT mIntersectionAccessor;
492 IntTreeT mLastPrimTree;
493 IntAccessorT mLastPrimAccessor;
495 InterruptT *mInterrupter;
498 struct Primitive {
Vec3d a, b, c, d;
Int32 index; };
500 template<
bool IsQuad>
501 bool evalPrimitive(
const Coord&,
const Primitive&);
503 template<
bool IsQuad>
504 void voxelize(
const Primitive&);
508 template<
typename FloatTreeT,
typename InterruptT>
513 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPolygonList.size()), *
this);
515 (*this)(tbb::blocked_range<size_t>(0, mPolygonList.size()));
519 template<
typename FloatTreeT,
typename InterruptT>
521 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
522 InterruptT *interrupter)
523 : mPointList(pointList)
524 , mPolygonList(polygonList)
525 , mSqrDistTree(std::numeric_limits<FloatValueT>::
max())
526 , mSqrDistAccessor(mSqrDistTree)
528 , mPrimIndexAccessor(mPrimIndexTree)
529 , mIntersectionTree(false)
530 , mIntersectionAccessor(mIntersectionTree)
532 , mLastPrimAccessor(mLastPrimTree)
533 , mInterrupter(interrupter)
537 template<
typename FloatTreeT,
typename InterruptT>
540 : mPointList(rhs.mPointList)
541 , mPolygonList(rhs.mPolygonList)
542 , mSqrDistTree(std::numeric_limits<FloatValueT>::
max())
543 , mSqrDistAccessor(mSqrDistTree)
545 , mPrimIndexAccessor(mPrimIndexTree)
546 , mIntersectionTree(false)
547 , mIntersectionAccessor(mIntersectionTree)
549 , mLastPrimAccessor(mLastPrimTree)
550 , mInterrupter(rhs.mInterrupter)
555 template<
typename FloatTreeT,
typename InterruptT>
561 for (
size_t n = range.begin(); n < range.end(); ++n) {
563 if (mInterrupter && mInterrupter->wasInterrupted()) {
564 tbb::task::self().cancel_group_execution();
568 const Vec4I& verts = mPolygonList[n];
570 prim.index =
Int32(n);
571 prim.a =
Vec3d(mPointList[verts[0]]);
572 prim.b =
Vec3d(mPointList[verts[1]]);
573 prim.c =
Vec3d(mPointList[verts[2]]);
576 prim.d =
Vec3d(mPointList[verts[3]]);
577 voxelize<true>(prim);
579 voxelize<false>(prim);
585 template<
typename FloatTreeT,
typename InterruptT>
586 template<
bool IsQuad>
590 std::deque<Coord> coordList;
594 coordList.push_back(ijk);
596 evalPrimitive<IsQuad>(ijk, prim);
598 while (!coordList.empty()) {
601 ijk = coordList.back();
602 coordList.pop_back();
604 mIntersectionAccessor.setActiveState(ijk,
true);
606 for (
Int32 i = 0; i < 26; ++i) {
608 if (prim.index != mLastPrimAccessor.getValue(nijk)) {
609 mLastPrimAccessor.setValue(nijk, prim.index);
610 if(evalPrimitive<IsQuad>(nijk, prim)) coordList.push_back(nijk);
617 template<
typename FloatTreeT,
typename InterruptT>
618 template<
bool IsQuad>
620 MeshVoxelizer<FloatTreeT, InterruptT>::evalPrimitive(
const Coord& ijk,
const Primitive& prim)
622 Vec3d uvw, voxelCenter(ijk[0], ijk[1], ijk[2]);
625 FloatValueT dist = FloatValueT((voxelCenter -
630 FloatValueT secondDist = FloatValueT((voxelCenter -
633 if (secondDist < dist) dist = secondDist;
636 FloatValueT oldDist = std::abs(mSqrDistAccessor.getValue(ijk));
638 if (dist < oldDist) {
639 mSqrDistAccessor.setValue(ijk, -dist);
640 mPrimIndexAccessor.setValue(ijk, prim.index);
644 mPrimIndexAccessor.setValue(ijk,
std::min(prim.index, mPrimIndexAccessor.getValue(ijk)));
647 return (dist < 0.86602540378443861);
651 template<
typename FloatTreeT,
typename InterruptT>
655 typedef typename FloatTreeT::RootNodeType FloatRootNodeT;
656 typedef typename FloatRootNodeT::NodeChainType FloatNodeChainT;
657 BOOST_STATIC_ASSERT(boost::mpl::size<FloatNodeChainT>::value > 1);
658 typedef typename boost::mpl::at<FloatNodeChainT, boost::mpl::int_<1> >::type FloatInternalNodeT;
660 typedef typename IntTreeT::RootNodeType IntRootNodeT;
661 typedef typename IntRootNodeT::NodeChainType IntNodeChainT;
662 BOOST_STATIC_ASSERT(boost::mpl::size<IntNodeChainT>::value > 1);
663 typedef typename boost::mpl::at<IntNodeChainT, boost::mpl::int_<1> >::type IntInternalNodeT;
670 rhs.mSqrDistTree.clearAllAccessors();
671 rhs.mPrimIndexTree.clearAllAccessors();
673 typename FloatTreeT::LeafIter leafIt = rhs.mSqrDistTree.beginLeaf();
674 for ( ; leafIt; ++leafIt) {
676 ijk = leafIt->origin();
677 FloatLeafT* lhsDistLeafPt = mSqrDistAccessor.probeLeaf(ijk);
679 if (!lhsDistLeafPt) {
685 mSqrDistAccessor.addLeaf(rhs.mSqrDistAccessor.probeLeaf(ijk));
686 FloatInternalNodeT* floatNode =
687 rhs.mSqrDistAccessor.template getNode<FloatInternalNodeT>();
688 floatNode->template stealNode<FloatLeafT>(ijk, background,
false);
690 mPrimIndexAccessor.addLeaf(rhs.mPrimIndexAccessor.probeLeaf(ijk));
691 IntInternalNodeT* intNode =
692 rhs.mPrimIndexAccessor.template getNode<IntInternalNodeT>();
697 IntLeafT* lhsIdxLeafPt = mPrimIndexAccessor.probeLeaf(ijk);
698 IntLeafT* rhsIdxLeafPt = rhs.mPrimIndexAccessor.probeLeaf(ijk);
699 FloatValueT lhsValue, rhsValue;
701 typename FloatLeafT::ValueOnCIter it = leafIt->cbeginValueOn();
706 lhsValue = std::abs(lhsDistLeafPt->getValue(offset));
707 rhsValue = std::abs(it.getValue());
709 if (rhsValue < lhsValue) {
710 lhsDistLeafPt->setValueOn(offset, it.getValue());
711 lhsIdxLeafPt->setValueOn(offset, rhsIdxLeafPt->getValue(offset));
713 lhsIdxLeafPt->setValueOn(offset,
714 std::min(lhsIdxLeafPt->getValue(offset), rhsIdxLeafPt->getValue(offset)));
720 mIntersectionTree.merge(rhs.mIntersectionTree);
722 rhs.mSqrDistTree.clear();
723 rhs.mPrimIndexTree.clear();
724 rhs.mIntersectionTree.clear();
734 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
740 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
743 ContourTracer(FloatTreeT&,
const BoolTreeT&, InterruptT *interrupter = NULL);
746 void run(
bool threaded =
true);
749 void operator()(
const tbb::blocked_range<int> &range)
const;
754 int sparseScan(
int slice)
const;
756 FloatTreeT& mDistTree;
757 DistAccessorT mDistAccessor;
759 const BoolTreeT& mIntersectionTree;
760 BoolAccessorT mIntersectionAccessor;
765 std::vector<Index> mStepSize;
767 InterruptT *mInterrupter;
771 template<
typename FloatTreeT,
typename InterruptT>
776 tbb::parallel_for(tbb::blocked_range<int>(mBBox.min()[0], mBBox.max()[0]+1), *
this);
778 (*this)(tbb::blocked_range<int>(mBBox.min()[0], mBBox.max()[0]+1));
783 template<
typename FloatTreeT,
typename InterruptT>
785 FloatTreeT& distTree,
const BoolTreeT& intersectionTree, InterruptT *interrupter)
786 : mDistTree(distTree)
787 , mDistAccessor(mDistTree)
788 , mIntersectionTree(intersectionTree)
789 , mIntersectionAccessor(mIntersectionTree)
792 , mInterrupter(interrupter)
795 std::vector<Index> dims;
796 mDistTree.getNodeLog2Dims(dims);
798 mStepSize.resize(dims.size()+1, 1);
800 for (
int idx = static_cast<int>(dims.size()) - 1; idx > -1; --idx) {
801 exponent += dims[idx];
802 mStepSize[idx] = 1 << exponent;
805 mDistTree.evalLeafBoundingBox(mBBox);
808 const int tileDim = mStepSize[0];
810 for (
size_t i = 0; i < 3; ++i) {
813 double diff = std::abs(
double(mBBox.min()[i])) / double(tileDim);
815 if (mBBox.min()[i] <= tileDim) {
816 n = int(std::ceil(diff));
817 mBBox.min()[i] = - n * tileDim;
819 n = int(std::floor(diff));
820 mBBox.min()[i] = n * tileDim;
823 n = int(std::ceil(std::abs(
double(mBBox.max()[i] - mBBox.min()[i])) / double(tileDim)));
824 mBBox.max()[i] = mBBox.min()[i] + n * tileDim;
829 template<
typename FloatTreeT,
typename InterruptT>
832 : mDistTree(rhs.mDistTree)
833 , mDistAccessor(mDistTree)
834 , mIntersectionTree(rhs.mIntersectionTree)
835 , mIntersectionAccessor(mIntersectionTree)
837 , mStepSize(rhs.mStepSize)
838 , mInterrupter(rhs.mInterrupter)
843 template<
typename FloatTreeT,
typename InterruptT>
849 for (
int n = range.begin(); n < range.end(); n += iStep) {
851 if (mInterrupter && mInterrupter->wasInterrupted()) {
852 tbb::task::self().cancel_group_execution();
856 iStep = sparseScan(n);
861 template<
typename FloatTreeT,
typename InterruptT>
865 bool lastVoxelWasOut =
true;
866 int last_k = mBBox.min()[2];
868 Coord ijk(slice, mBBox.min()[1], mBBox.min()[2]);
869 Coord step(mStepSize[mDistAccessor.getValueDepth(ijk) + 1]);
872 for (ijk[1] = mBBox.min()[1]; ijk[1] <= mBBox.max()[1]; ijk[1] += step[1]) {
874 if (mInterrupter && mInterrupter->wasInterrupted()) {
878 step[1] = mStepSize[mDistAccessor.getValueDepth(ijk) + 1];
879 step[0] =
std::min(step[0], step[1]);
881 for (ijk[2] = mBBox.min()[2]; ijk[2] <= mBBox.max()[2]; ijk[2] += step[2]) {
883 step[2] = mStepSize[mDistAccessor.getValueDepth(ijk) + 1];
884 step[1] =
std::min(step[1], step[2]);
885 step[0] =
std::min(step[0], step[2]);
888 if (mDistAccessor.isValueOn(ijk)) {
891 if (mIntersectionAccessor.isValueOn(ijk)) {
893 lastVoxelWasOut =
false;
896 }
else if (lastVoxelWasOut) {
898 FloatValueT& val =
const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
904 for (
Int32 n = 3; n < 6; n += 2) {
905 n_ijk = ijk + util::COORD_OFFSETS[n];
907 if (mDistAccessor.probeValue(n_ijk, val) && val > 0) {
908 lastVoxelWasOut =
true;
913 if (lastVoxelWasOut) {
915 FloatValueT& v =
const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
918 const int tmp_k = ijk[2];
921 for (--ijk[2]; ijk[2] >= last_k; --ijk[2]) {
922 if (mIntersectionAccessor.isValueOn(ijk))
break;
924 const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
925 if (vb < FloatValueT(0.0)) vb = -vb;
948 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
956 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
962 SignMask(
const FloatLeafManager&,
const FloatTreeT&,
const BoolTreeT&,
963 InterruptT *interrupter = NULL);
967 void run(
bool threaded =
true);
970 void operator() (
const tbb::blocked_range<size_t> &range);
978 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
980 const FloatLeafManager& mDistLeafs;
981 const FloatTreeT& mDistTree;
982 const BoolTreeT& mIntersectionTree;
984 BoolTreeT mSignMaskTree;
986 InterruptT *mInterrupter;
990 template<
typename FloatTreeT,
typename InterruptT>
992 const FloatLeafManager& distLeafs,
const FloatTreeT& distTree,
993 const BoolTreeT& intersectionTree, InterruptT *interrupter)
994 : mDistLeafs(distLeafs)
995 , mDistTree(distTree)
996 , mIntersectionTree(intersectionTree)
997 , mSignMaskTree(false)
998 , mInterrupter(interrupter)
1003 template<
typename FloatTreeT,
typename InterruptT>
1006 : mDistLeafs(rhs.mDistLeafs)
1007 , mDistTree(rhs.mDistTree)
1008 , mIntersectionTree(rhs.mIntersectionTree)
1009 , mSignMaskTree(false)
1010 , mInterrupter(rhs.mInterrupter)
1015 template<
typename FloatTreeT,
typename InterruptT>
1019 if (threaded) tbb::parallel_reduce(mDistLeafs.getRange(), *
this);
1020 else (*
this)(mDistLeafs.getRange());
1024 template<
typename FloatTreeT,
typename InterruptT>
1028 FloatAccessorT distAcc(mDistTree);
1029 BoolConstAccessorT intersectionAcc(mIntersectionTree);
1030 BoolAccessorT maskAcc(mSignMaskTree);
1034 Coord& maxCoord = bbox.max();
1035 Coord& minCoord = bbox.min();
1037 const int extent = BoolLeafT::DIM - 1;
1039 for (
size_t n = range.begin(); n < range.end(); ++n) {
1041 const FloatLeafT& distLeaf = mDistLeafs.leaf(n);
1043 minCoord = distLeaf.origin();
1044 maxCoord[0] = minCoord[0] + extent;
1045 maxCoord[1] = minCoord[1] + extent;
1046 maxCoord[2] = minCoord[2] + extent;
1048 const BoolLeafT* intersectionLeaf = intersectionAcc.
probeConstLeaf(minCoord);
1050 BoolLeafT* maskLeafPt =
new BoolLeafT(minCoord,
false);
1051 BoolLeafT& maskLeaf = *maskLeafPt;
1052 bool addLeaf =
false;
1056 typename FloatLeafT::ValueOnCIter it = distLeaf.cbeginValueOn();
1058 if (intersectionLeaf && intersectionLeaf->isValueOn(it.pos()))
continue;
1059 if (it.getValue() < FloatValueT(0.0)) {
1060 ijk = it.getCoord();
1061 if (bbox.isInside(ijk)) {
1062 for (
size_t i = 0; i < 6; ++i) {
1063 if (distLeaf.probeValue(ijk+util::COORD_OFFSETS[i], value) && value>0.0) {
1064 maskLeaf.setValueOn(ijk);
1070 for (
size_t i = 0; i < 6; ++i) {
1071 if (distAcc.
probeValue(ijk+util::COORD_OFFSETS[i], value) && value>0.0) {
1072 maskLeaf.setValueOn(ijk);
1081 if (addLeaf) maskAcc.
addLeaf(maskLeafPt);
1082 else delete maskLeafPt;
1087 template<
typename FloatTreeT,
typename InterruptT>
1091 mSignMaskTree.merge(rhs.mSignMaskTree);
1099 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
1106 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1112 PropagateSign(BoolLeafManager&, FloatTreeT&,
const BoolTreeT&, InterruptT *interrupter = NULL);
1116 void run(
bool threaded =
true);
1119 void operator() (
const tbb::blocked_range<size_t> &range);
1127 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
1129 BoolLeafManager& mOldSignMaskLeafs;
1130 FloatTreeT& mDistTree;
1131 const BoolTreeT& mIntersectionTree;
1133 BoolTreeT mSignMaskTree;
1134 InterruptT *mInterrupter;
1138 template<
typename FloatTreeT,
typename InterruptT>
1140 FloatTreeT& distTree,
const BoolTreeT& intersectionTree, InterruptT *interrupter)
1141 : mOldSignMaskLeafs(signMaskLeafs)
1142 , mDistTree(distTree)
1143 , mIntersectionTree(intersectionTree)
1144 , mSignMaskTree(false)
1145 , mInterrupter(interrupter)
1150 template<
typename FloatTreeT,
typename InterruptT>
1153 : mOldSignMaskLeafs(rhs.mOldSignMaskLeafs)
1154 , mDistTree(rhs.mDistTree)
1155 , mIntersectionTree(rhs.mIntersectionTree)
1156 , mSignMaskTree(false)
1157 , mInterrupter(rhs.mInterrupter)
1162 template<
typename FloatTreeT,
typename InterruptT>
1166 if (threaded) tbb::parallel_reduce(mOldSignMaskLeafs.getRange(), *
this);
1167 else (*
this)(mOldSignMaskLeafs.getRange());
1171 template<
typename FloatTreeT,
typename InterruptT>
1175 FloatAccessorT distAcc(mDistTree);
1176 BoolConstAccessorT intersectionAcc(mIntersectionTree);
1177 BoolAccessorT maskAcc(mSignMaskTree);
1179 std::deque<Coord> coordList;
1183 Coord& maxCoord = bbox.max();
1184 Coord& minCoord = bbox.min();
1186 const int extent = BoolLeafT::DIM - 1;
1188 for (
size_t n = range.begin(); n < range.end(); ++n) {
1189 BoolLeafT& oldMaskLeaf = mOldSignMaskLeafs.leaf(n);
1191 minCoord = oldMaskLeaf.origin();
1192 maxCoord[0] = minCoord[0] + extent;
1193 maxCoord[1] = minCoord[1] + extent;
1194 maxCoord[2] = minCoord[2] + extent;
1196 FloatLeafT& distLeaf = *distAcc.
probeLeaf(minCoord);
1197 const BoolLeafT* intersectionLeaf = intersectionAcc.
probeConstLeaf(minCoord);
1199 typename BoolLeafT::ValueOnCIter it = oldMaskLeaf.cbeginValueOn();
1201 coordList.push_back(it.getCoord());
1203 while (!coordList.empty()) {
1205 ijk = coordList.back();
1206 coordList.pop_back();
1208 FloatValueT& dist =
const_cast<FloatValueT&
>(distLeaf.getValue(ijk));
1209 if (dist < FloatValueT(0.0)) {
1212 for (
size_t i = 0; i < 6; ++i) {
1213 nijk = ijk + util::COORD_OFFSETS[i];
1214 if (bbox.isInside(nijk)) {
1215 if (intersectionLeaf && intersectionLeaf->isValueOn(nijk))
continue;
1217 if (distLeaf.probeValue(nijk, value) && value < 0.0) {
1218 coordList.push_back(nijk);
1223 distAcc.
probeValue(nijk, value) && value < 0.0) {
1235 template<
typename FloatTreeT,
typename InterruptT>
1239 mSignMaskTree.merge(rhs.mSignMaskTree);
1250 template<
typename FloatTreeT>
1258 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1263 const std::vector<Vec3s>& pointList,
1264 const std::vector<Vec4I>& polygonList,
1265 FloatTreeT& distTree,
1266 IntTreeT& indexTree,
1267 BoolTreeT& intersectionTree,
1268 BoolLeafManager& leafs);
1272 void run(
bool threaded =
true);
1275 void operator()(
const tbb::blocked_range<size_t>&)
const;
1280 Vec3d getClosestPoint(
const Coord& ijk,
const Vec4I& prim)
const;
1282 std::vector<Vec3s>
const *
const mPointList;
1283 std::vector<Vec4I>
const *
const mPolygonList;
1285 FloatTreeT& mDistTree;
1286 IntTreeT& mIndexTree;
1287 BoolTreeT& mIntersectionTree;
1289 BoolLeafManager& mLeafs;
1293 template<
typename FloatTreeT>
1297 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1298 else (*
this)(mLeafs.getRange());
1302 template<
typename FloatTreeT>
1304 const std::vector<Vec3s>& pointList,
1305 const std::vector<Vec4I>& polygonList,
1306 FloatTreeT& distTree,
1307 IntTreeT& indexTree,
1308 BoolTreeT& intersectionTree,
1309 BoolLeafManager& leafs)
1310 : mPointList(&pointList)
1311 , mPolygonList(&polygonList)
1312 , mDistTree(distTree)
1313 , mIndexTree(indexTree)
1314 , mIntersectionTree(intersectionTree)
1320 template<
typename FloatTreeT>
1323 : mPointList(rhs.mPointList)
1324 , mPolygonList(rhs.mPolygonList)
1325 , mDistTree(rhs.mDistTree)
1326 , mIndexTree(rhs.mIndexTree)
1327 , mIntersectionTree(rhs.mIntersectionTree)
1328 , mLeafs(rhs.mLeafs)
1333 template<
typename FloatTreeT>
1336 const tbb::blocked_range<size_t>& range)
const
1340 FloatAccessorT distAcc(mDistTree);
1341 BoolAccessorT maskAcc(mIntersectionTree);
1342 IntAccessorT idxAcc(mIndexTree);
1344 FloatValueT tmpValue;
1347 typename BoolTreeT::LeafNodeType::ValueOnCIter iter;
1348 for (
size_t n = range.begin(); n < range.end(); ++n) {
1349 iter = mLeafs.leaf(n).cbeginValueOn();
1350 for (; iter; ++iter) {
1352 ijk = iter.getCoord();
1354 FloatValueT value = distAcc.
getValue(ijk);
1356 if (!(value < FloatValueT(0.0)))
continue;
1358 center =
Vec3d(ijk[0], ijk[1], ijk[2]);
1360 for (
Int32 i = 0; i < 26; ++i) {
1361 nijk = ijk + util::COORD_OFFSETS[i];
1364 if (tmpValue < FloatValueT(0.0))
continue;
1368 cpt = getClosestPoint(nijk, prim);
1370 dir1 = center -
cpt;
1373 dir2 =
Vec3d(nijk[0], nijk[1], nijk[2]) -
cpt;
1376 if (dir2.dot(dir1) > 0.0) {
1387 template<
typename FloatTreeT>
1391 Vec3d voxelCenter(ijk[0], ijk[1], ijk[2]);
1394 const Vec3d a((*mPointList)[prim[0]]);
1395 const Vec3d b((*mPointList)[prim[1]]);
1396 const Vec3d c((*mPointList)[prim[2]]);
1404 Vec3d diff1 = voxelCenter - cpt1;
1406 const Vec3d d((*mPointList)[prim[3]]);
1409 Vec3d diff2 = voxelCenter - cpt2;
1411 if (diff2.lengthSqr() < diff1.lengthSqr()) {
1426 template<
typename FloatTreeT>
1436 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1442 BoolTreeT& intersectionTree, BoolLeafManager& leafs);
1446 void run(
bool threaded =
true);
1449 void operator()(
const tbb::blocked_range<size_t>&)
const;
1454 FloatTreeT& mDistTree;
1455 IntTreeT& mIndexTree;
1456 BoolTreeT& mIntersectionTree;
1457 BoolLeafManager& mLeafs;
1461 template<
typename FloatTreeT>
1465 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1466 else (*
this)(mLeafs.getRange());
1472 template<
typename FloatTreeT>
1474 FloatTreeT& distTree,
1475 IntTreeT& indexTree,
1476 BoolTreeT& intersectionTree,
1477 BoolLeafManager& leafs)
1478 : mDistTree(distTree)
1479 , mIndexTree(indexTree)
1480 , mIntersectionTree(intersectionTree)
1486 template<
typename FloatTreeT>
1489 : mDistTree(rhs.mDistTree)
1490 , mIndexTree(rhs.mIndexTree)
1491 , mIntersectionTree(rhs.mIntersectionTree)
1492 , mLeafs(rhs.mLeafs)
1497 template<
typename FloatTreeT>
1500 const tbb::blocked_range<size_t>& range)
const
1507 typename BoolLeafT::ValueOnCIter iter;
1509 IntAccessorT indexAcc(mIndexTree);
1511 BoolAccessorT maskAcc(mIntersectionTree);
1513 for (
size_t n = range.begin(); n < range.end(); ++n) {
1515 BoolLeafT& maskLeaf = mLeafs.leaf(n);
1517 ijk = maskLeaf.origin();
1521 iter = maskLeaf.cbeginValueOn();
1522 for (; iter; ++iter) {
1524 offset = iter.pos();
1526 if(distLeaf->getValue(offset) > 0.0)
continue;
1528 ijk = iter.getCoord();
1530 for (
Int32 m = 0; m < 26; ++m) {
1531 m_ijk = ijk + util::COORD_OFFSETS[m];
1541 maskLeaf.setValueOff(offset);
1542 distLeaf->setValueOn(offset, FloatValueT(-0.86602540378443861));
1556 template<
typename FloatTreeT>
1567 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1572 BoolTreeT& intersectionTree);
1576 void run(
bool threaded =
true);
1579 void operator()(
const tbb::blocked_range<size_t>&)
const;
1584 FloatTreeT& mDistTree;
1586 IntTreeT& mIndexTree;
1587 BoolTreeT& mIntersectionTree;
1591 template<
typename FloatTreeT>
1595 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1596 else (*
this)(mLeafs.getRange());
1603 template<
typename FloatTreeT>
1605 FloatTreeT& distTree,
1607 IntTreeT& indexTree,
1608 BoolTreeT& intersectionTree)
1609 : mDistTree(distTree)
1611 , mIndexTree(indexTree)
1612 , mIntersectionTree(intersectionTree)
1617 template<
typename FloatTreeT>
1620 : mDistTree(rhs.mDistTree)
1621 , mLeafs(rhs.mLeafs)
1622 , mIndexTree(rhs.mIndexTree)
1623 , mIntersectionTree(rhs.mIntersectionTree)
1628 template<
typename FloatTreeT>
1631 const tbb::blocked_range<size_t>& range)
const
1638 typename DistLeafT::ValueOnCIter iter;
1639 const FloatValueT distBG = mDistTree.background();
1640 const Int32 indexBG = mIntersectionTree.background();
1642 IntAccessorT indexAcc(mIndexTree);
1644 BoolAccessorT maskAcc(mIntersectionTree);
1647 for (
size_t n = range.begin(); n < range.end(); ++n) {
1651 ijk = distLeaf.origin();
1654 IntLeafT& indexLeaf = *indexAcc.
probeLeaf(ijk);
1656 iter = distLeaf.cbeginValueOn();
1657 for (; iter; ++iter) {
1659 value = iter.getValue();
1660 if(value > 0.0)
continue;
1662 offset = iter.pos();
1663 if (maskLeaf && maskLeaf->isValueOn(offset))
continue;
1665 ijk = iter.getCoord();
1667 for (
Int32 m = 0; m < 26; ++m) {
1668 m_ijk = ijk + util::COORD_OFFSETS[m];
1676 distLeaf.setValueOff(offset, distBG);
1677 indexLeaf.setValueOff(offset, indexBG);
1687 template<
typename TreeType>
1694 template <
typename LeafNodeType>
1697 LeafNodeType* rhsLeaf =
const_cast<LeafNodeType*
>(mAcc.
probeLeaf(leaf.origin()));
1698 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
1699 for (; iter; ++iter) {
1700 rhsLeaf->setValueOnly(iter.pos(), iter.getValue());
1712 template<
typename FloatTreeT>
1722 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1728 FloatTreeT& distTree, IntTreeT& indexTree, BoolTreeT& maskTree,
1729 FloatValueT exteriorBandWidth, FloatValueT interiorBandWidth, FloatValueT voxelSize,
1730 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList);
1732 void run(
bool threaded =
true);
1734 void operator()(
const tbb::blocked_range<size_t>&);
1742 double evalVoxelDist(
const Coord&, FloatAccessorT&, IntAccessorT&,
1743 BoolAccessorT&, std::vector<Int32>&,
Int32&)
const;
1745 double evalVoxelDist(
const Coord&, FloatLeafT&, IntLeafT&,
1746 BoolLeafT&, std::vector<Int32>&,
Int32&)
const;
1748 double closestPrimDist(
const Coord&, std::vector<Int32>&,
Int32&)
const;
1750 BoolLeafManager& mMaskLeafs;
1752 FloatTreeT& mDistTree;
1753 IntTreeT& mIndexTree;
1754 BoolTreeT& mMaskTree;
1756 const FloatValueT mExteriorBandWidth, mInteriorBandWidth, mVoxelSize;
1757 const std::vector<Vec3s>& mPointList;
1758 const std::vector<Vec4I>& mPolygonList;
1760 FloatTreeT mNewDistTree;
1761 IntTreeT mNewIndexTree;
1762 BoolTreeT mNewMaskTree;
1766 template<
typename FloatTreeT>
1768 BoolLeafManager& leafs,
1769 FloatTreeT& distTree,
1770 IntTreeT& indexTree,
1771 BoolTreeT& maskTree,
1772 FloatValueT exteriorBandWidth,
1773 FloatValueT interiorBandWidth,
1774 FloatValueT voxelSize,
1775 const std::vector<Vec3s>& pointList,
1776 const std::vector<Vec4I>& polygonList)
1778 , mDistTree(distTree)
1779 , mIndexTree(indexTree)
1780 , mMaskTree(maskTree)
1781 , mExteriorBandWidth(exteriorBandWidth)
1782 , mInteriorBandWidth(interiorBandWidth)
1783 , mVoxelSize(voxelSize)
1784 , mPointList(pointList)
1785 , mPolygonList(polygonList)
1786 , mNewDistTree(std::numeric_limits<FloatValueT>::
max())
1788 , mNewMaskTree(false)
1793 template<
typename FloatTreeT>
1795 : mMaskLeafs(rhs.mMaskLeafs)
1796 , mDistTree(rhs.mDistTree)
1797 , mIndexTree(rhs.mIndexTree)
1798 , mMaskTree(rhs.mMaskTree)
1799 , mExteriorBandWidth(rhs.mExteriorBandWidth)
1800 , mInteriorBandWidth(rhs.mInteriorBandWidth)
1801 , mVoxelSize(rhs.mVoxelSize)
1802 , mPointList(rhs.mPointList)
1803 , mPolygonList(rhs.mPolygonList)
1804 , mNewDistTree(std::numeric_limits<FloatValueT>::
max())
1806 , mNewMaskTree(false)
1811 template<
typename FloatTreeT>
1815 if (threaded) tbb::parallel_reduce(mMaskLeafs.getRange(), *
this);
1816 else (*
this)(mMaskLeafs.getRange());
1820 mDistTree.topologyUnion(mNewDistTree);
1824 mIndexTree.merge(mNewIndexTree);
1827 mMaskTree.merge(mNewMaskTree);
1832 template<
typename FloatTreeT>
1837 Int32 closestPrim = 0;
1839 FloatValueT distance;
1842 FloatAccessorT newDistAcc(mNewDistTree);
1843 IntAccessorT newIndexAcc(mNewIndexTree);
1844 BoolAccessorT newMaskAcc(mNewMaskTree);
1846 FloatAccessorT distAcc(mDistTree);
1847 IntAccessorT indexAcc(mIndexTree);
1848 BoolAccessorT maskAcc(mMaskTree);
1851 std::vector<Int32> primitives(18);
1853 for (
size_t n = range.begin(); n < range.end(); ++n) {
1855 BoolLeafT& maskLeaf = mMaskLeafs.leaf(n);
1857 if (maskLeaf.isEmpty())
continue;
1859 ijk = maskLeaf.origin();
1861 FloatLeafT* distLeafPt = distAcc.
probeLeaf(ijk);
1864 distLeafPt =
new FloatLeafT(ijk, distAcc.
getValue(ijk));
1865 newDistAcc.
addLeaf(distLeafPt);
1868 IntLeafT* indexLeafPt = indexAcc.
probeLeaf(ijk);
1869 if (!indexLeafPt) indexLeafPt = newIndexAcc.
touchLeaf(ijk);
1871 bbox = maskLeaf.getNodeBoundingBox();
1874 typename BoolLeafT::ValueOnIter iter = maskLeaf.beginValueOn();
1875 for (; iter; ++iter) {
1877 ijk = iter.getCoord();
1879 if (bbox.isInside(ijk)) {
1880 distance = FloatValueT(evalVoxelDist(ijk, *distLeafPt, *indexLeafPt, maskLeaf,
1881 primitives, closestPrim));
1883 distance = FloatValueT(evalVoxelDist(ijk, distAcc, indexAcc, maskAcc,
1884 primitives, closestPrim));
1889 inside = distLeafPt->getValue(pos) < FloatValueT(0.0);
1891 if (!inside && distance < mExteriorBandWidth) {
1892 distLeafPt->setValueOn(pos, distance);
1893 indexLeafPt->setValueOn(pos, closestPrim);
1894 }
else if (inside && distance < mInteriorBandWidth) {
1895 distLeafPt->setValueOn(pos, -distance);
1896 indexLeafPt->setValueOn(pos, closestPrim);
1901 for (
Int32 i = 0; i < 6; ++i) {
1902 newMaskAcc.
setValueOn(ijk + util::COORD_OFFSETS[i]);
1909 template<
typename FloatTreeT>
1913 FloatAccessorT& distAcc,
1914 IntAccessorT& indexAcc,
1915 BoolAccessorT& maskAcc,
1916 std::vector<Int32>& prims,
1917 Int32& closestPrim)
const
1924 for (
Int32 n = 0; n < 18; ++n) {
1925 n_ijk = ijk + util::COORD_OFFSETS[n];
1926 if (!maskAcc.isValueOn(n_ijk) && distAcc.probeValue(n_ijk, tmpDist)) {
1927 prims.push_back(indexAcc.getValue(n_ijk));
1928 tmpDist = std::abs(tmpDist);
1929 if (tmpDist < minDist) minDist = tmpDist;
1934 tmpDist = FloatValueT(closestPrimDist(ijk, prims, closestPrim));
1938 return tmpDist > minDist ? tmpDist : minDist + mVoxelSize;
1943 template<
typename FloatTreeT>
1945 ExpandNB<FloatTreeT>::evalVoxelDist(
1947 FloatLeafT& distLeaf,
1948 IntLeafT& indexLeaf,
1949 BoolLeafT& maskLeaf,
1950 std::vector<Int32>& prims,
1951 Int32& closestPrim)
const
1957 for (
Int32 n = 0; n < 18; ++n) {
1958 pos = FloatLeafT::coordToOffset(ijk + util::COORD_OFFSETS[n]);
1959 if (!maskLeaf.isValueOn(pos) && distLeaf.probeValue(pos, tmpDist)) {
1960 prims.push_back(indexLeaf.getValue(pos));
1961 tmpDist = std::abs(tmpDist);
1962 if (tmpDist < minDist) minDist = tmpDist;
1966 tmpDist = FloatValueT(closestPrimDist(ijk, prims, closestPrim));
1967 return tmpDist > minDist ? tmpDist : minDist + mVoxelSize;
1971 template<
typename FloatTreeT>
1973 ExpandNB<FloatTreeT>::closestPrimDist(
const Coord& ijk,
1974 std::vector<Int32>& prims,
Int32& closestPrim)
const
1976 std::sort(prims.begin(), prims.end());
1978 Int32 lastPrim = -1;
1979 Vec3d uvw, voxelCenter(ijk[0], ijk[1], ijk[2]);
1982 for (
size_t n = 0, N = prims.size(); n < N; ++n) {
1983 if (prims[n] == lastPrim)
continue;
1985 lastPrim = prims[n];
1987 const Vec4I& verts = mPolygonList[lastPrim];
1990 const Vec3d a(mPointList[verts[0]]);
1991 const Vec3d b(mPointList[verts[1]]);
1992 const Vec3d c(mPointList[verts[2]]);
1994 primDist = (voxelCenter -
1999 const Vec3d d(mPointList[verts[3]]);
2001 tmpDist = (voxelCenter -
2004 if (tmpDist < primDist) primDist = tmpDist;
2007 if (primDist < dist) {
2009 closestPrim = lastPrim;
2013 return std::sqrt(dist) * double(mVoxelSize);
2017 template<
typename FloatTreeT>
2021 mNewDistTree.merge(rhs.mNewDistTree);
2022 mNewIndexTree.merge(rhs.mNewIndexTree);
2023 mNewMaskTree.merge(rhs.mNewMaskTree);
2030 template<
typename ValueType>
2034 : mVoxelSize(voxelSize)
2035 , mUnsigned(unsignedDist)
2039 template <
typename LeafNodeType>
2046 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2047 for (; iter; ++iter) {
2048 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2049 val = w[!mUnsigned && int(val < ValueType(0.0))] * std::sqrt(std::abs(val));
2054 ValueType mVoxelSize;
2055 const bool mUnsigned;
2059 template<
typename ValueType>
2063 : mExBandWidth(exBandWidth)
2064 , mInBandWidth(inBandWidth)
2068 template <
typename LeafNodeType>
2071 ValueType bgValues[2];
2072 bgValues[0] = mExBandWidth;
2073 bgValues[1] = -mInBandWidth;
2075 typename LeafNodeType::ValueOffIter iter = leaf.beginValueOff();
2077 for (; iter; ++iter) {
2078 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2079 val = bgValues[int(val < ValueType(0.0))];
2084 ValueType mExBandWidth, mInBandWidth;
2088 template<
typename ValueType>
2091 TrimOp(ValueType exBandWidth, ValueType inBandWidth)
2092 : mExBandWidth(exBandWidth)
2093 , mInBandWidth(inBandWidth)
2097 template <
typename LeafNodeType>
2100 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2102 for (; iter; ++iter) {
2103 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2104 const bool inside = val < ValueType(0.0);
2106 if (inside && !(val > -mInBandWidth)) {
2107 val = -mInBandWidth;
2109 }
else if (!inside && !(val < mExBandWidth)) {
2117 ValueType mExBandWidth, mInBandWidth;
2121 template<
typename ValueType>
2128 template <
typename LeafNodeType>
2131 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2132 for (; iter; ++iter) {
2133 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2143 template<
typename Gr
idType,
typename ValueType>
2147 typedef typename Scheme::template ISStencil<GridType>::StencilType
Stencil;
2151 RenormOp(GridType& grid, LeafManagerType& leafs, ValueType voxelSize, ValueType cfl = 1.0)
2154 , mVoxelSize(voxelSize)
2161 template <
typename LeafNodeType>
2164 const ValueType dt = mCFL * mVoxelSize, one(1.0), invDx = one / mVoxelSize;
2165 Stencil stencil(mGrid);
2166 BufferType& buffer = mLeafs.
getBuffer(leafIndex, 1);
2168 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2169 for (; iter; ++iter) {
2170 stencil.moveTo(iter);
2172 const ValueType normSqGradPhi =
2175 const ValueType phi0 = iter.getValue();
2176 const ValueType diff =
math::Sqrt(normSqGradPhi) * invDx - one;
2179 buffer.setValue(iter.pos(), phi0 - dt * S * diff);
2185 LeafManagerType& mLeafs;
2186 ValueType mVoxelSize, mCFL;
2190 template<
typename TreeType,
typename ValueType>
2196 MinOp(LeafManagerType& leafs): mLeafs(leafs) {}
2198 template <
typename LeafNodeType>
2201 BufferType& buffer = mLeafs.
getBuffer(leafIndex, 1);
2202 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2204 for (; iter; ++iter) {
2205 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2206 val =
std::min(val, buffer.getValue(iter.pos()));
2211 LeafManagerType& mLeafs;
2215 template<
typename TreeType,
typename ValueType>
2223 , mBufferIndex(bufferIndex)
2227 template <
typename LeafNodeType>
2230 BufferType& buffer = mLeafs.
getBuffer(leafIndex, mBufferIndex);
2231 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2234 for (; iter; ++iter) {
2235 offset = iter.pos();
2236 leaf.setValueOnly(offset, buffer.getValue(offset));
2241 LeafManagerType& mLeafs;
2242 const size_t mBufferIndex;
2246 template<
typename TreeType>
2254 template <
typename LeafNodeType>
2258 if (rhsLeaf) leaf.topologyDifference(*rhsLeaf,
false);
2273 template<
typename FloatGr
idT,
typename InterruptT>
2275 openvdb::math::Transform::Ptr& transform,
int conversionFlags,
2276 InterruptT *interrupter,
int signSweeps)
2277 : mTransform(transform)
2278 , mConversionFlags(conversionFlags)
2279 , mSignSweeps(signSweeps)
2280 , mInterrupter(interrupter)
2283 mSignSweeps =
std::min(mSignSweeps, 1);
2287 template<
typename FloatGr
idT,
typename InterruptT>
2293 mIntersectingVoxelsGrid = BoolGridT::create(
false);
2297 template<
typename FloatGr
idT,
typename InterruptT>
2300 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2301 FloatValueT exBandWidth, FloatValueT inBandWidth)
2306 const FloatValueT vs = FloatValueT(mTransform->voxelSize()[0]);
2315 doConvert(pointList, polygonList, exBandWidth, inBandWidth);
2320 template<
typename FloatGr
idT,
typename InterruptT>
2323 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2324 FloatValueT exBandWidth)
2328 const FloatValueT vs = FloatValueT(mTransform->voxelSize()[0]);
2329 doConvert(pointList, polygonList, vs * exBandWidth, 0.0,
true);
2334 template<
typename FloatGr
idT,
typename InterruptT>
2337 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2338 FloatValueT exBandWidth, FloatValueT inBandWidth,
bool unsignedDistField)
2340 mDistGrid->setTransform(mTransform);
2341 mIndexGrid->setTransform(mTransform);
2345 if (!boost::math::isfinite(exBandWidth) || boost::math::isnan(inBandWidth)) {
2346 std::stringstream msg;
2347 msg <<
"Illegal narrow band width: exterior = " << exBandWidth
2348 <<
", interior = " << inBandWidth;
2361 internal::MeshVoxelizer<FloatTreeT, InterruptT>
2362 voxelizer(pointList, polygonList, mInterrupter);
2368 mDistGrid->tree().merge(voxelizer.sqrDistTree());
2369 mIndexGrid->tree().merge(voxelizer.primIndexTree());
2370 mIntersectingVoxelsGrid->tree().merge(voxelizer.intersectionTree());
2373 if (!unsignedDistField) {
2377 internal::ContourTracer<FloatTreeT, InterruptT> trace(
2378 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2379 for (
int i = 0; i < mSignSweeps; ++i) {
2388 BoolTreeT signMaskTree(
false);
2391 internal::SignMask<FloatTreeT, InterruptT> signMaskOp(leafs,
2392 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2394 signMaskTree.merge(signMaskOp.signMaskTree());
2400 tree::LeafManager<BoolTreeT> leafs(signMaskTree);
2401 if(leafs.leafCount() == 0)
break;
2403 internal::PropagateSign<FloatTreeT, InterruptT> sign(leafs,
2404 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2408 signMaskTree.clear();
2409 signMaskTree.merge(sign.signMaskTree());
2417 tree::LeafManager<BoolTreeT> leafs(mIntersectingVoxelsGrid->tree());
2420 internal::IntersectingVoxelSign<FloatTreeT> sign(pointList, polygonList,
2421 mDistGrid->tree(), mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2429 internal::IntersectingVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2430 mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2437 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2439 internal::ShellVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2440 leafs, mIndexGrid->tree(), mIntersectingVoxelsGrid->tree());
2448 inBandWidth = FloatValueT(0.0);
2451 if (mDistGrid->activeVoxelCount() == 0) {
2456 mIntersectingVoxelsGrid->clear();
2457 const FloatValueT voxelSize = FloatValueT(mTransform->voxelSize()[0]);
2460 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2461 leafs.foreach(internal::SqrtAndScaleOp<FloatValueT>(voxelSize, unsignedDistField));
2466 if (!unsignedDistField) {
2467 mDistGrid->tree().root().setBackground(exBandWidth,
false);
2474 const FloatValueT minWidth = FloatValueT(voxelSize * 2.0);
2475 if (inBandWidth > minWidth || exBandWidth > minWidth) {
2478 BoolTreeT maskTree(
false);
2479 maskTree.topologyUnion(mDistGrid->tree());
2483 internal::LeafTopologyDiffOp<FloatTreeT> diffOp(mDistGrid->tree());
2487 float progress = 48, step = 0.0;
2490 2.0 * std::ceil((
std::max(inBandWidth, exBandWidth) - minWidth) / voxelSize);
2491 if (estimated <
double(maxIterations)) {
2492 maxIterations = unsigned(estimated);
2493 step = 42.f / float(maxIterations);
2501 tree::LeafManager<BoolTreeT> leafs(maskTree);
2503 if (leafs.leafCount() == 0)
break;
2505 leafs.foreach(diffOp);
2507 internal::ExpandNB<FloatTreeT> expand(
2508 leafs, mDistGrid->tree(), mIndexGrid->tree(), maskTree,
2509 exBandWidth, inBandWidth, voxelSize, pointList, polygonList);
2513 if ((++count) >= maxIterations)
break;
2524 if (!unsignedDistField && !rawData) {
2528 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree(), 1);
2530 const FloatValueT offset = FloatValueT(0.8 * voxelSize);
2533 internal::OffsetOp<FloatValueT> offsetOp(-offset);
2535 leafs.foreach(offsetOp);
2539 leafs.foreach(internal::RenormOp<FloatGridT, FloatValueT>(*mDistGrid, leafs, voxelSize));
2541 leafs.foreach(internal::MinOp<FloatTreeT, FloatValueT>(leafs));
2545 offsetOp.resetOffset(offset - internal::Tolerance<FloatValueT>::epsilon());
2546 leafs.foreach(offsetOp);
2551 const FloatValueT minTrimWidth = FloatValueT(voxelSize * 4.0);
2552 if (inBandWidth < minTrimWidth || exBandWidth < minTrimWidth) {
2558 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2559 leafs.foreach(internal::TrimOp<FloatValueT>(
2560 exBandWidth, unsignedDistField ? exBandWidth : inBandWidth));
2562 tools::pruneLevelSet(mDistGrid->tree(), exBandWidth, unsignedDistField ? -exBandWidth : -inBandWidth);
2571 template<
typename Gr
idType>
2572 inline typename boost::enable_if<boost::is_floating_point<typename GridType::ValueType>,
2573 typename GridType::Ptr>::type
2575 const openvdb::math::Transform& xform,
2576 const std::vector<Vec3s>& points,
2577 const std::vector<Vec3I>& triangles,
2578 const std::vector<Vec4I>& quads,
2581 bool unsignedDistanceField =
false)
2583 std::vector<Vec3s> indexSpacePoints(points.size());
2591 std::vector<Vec4I> primitives(triangles.size() + quads.size());
2593 for (
size_t n = 0, N = triangles.size(); n < N; ++n) {
2594 Vec4I& prim = primitives[n];
2595 const Vec3I& triangle = triangles[n];
2596 prim[0] = triangle[0];
2597 prim[1] = triangle[1];
2598 prim[2] = triangle[2];
2602 for (
size_t n = 0, N = quads.size(); n < N; ++n) {
2603 primitives[n + triangles.size()] = quads[n];
2606 typename GridType::ValueType exWidth(exBandWidth);
2607 typename GridType::ValueType inWidth(inBandWidth);
2613 if (!unsignedDistanceField) {
2625 template<
typename Gr
idType>
2626 inline typename boost::disable_if<boost::is_floating_point<typename GridType::ValueType>,
2627 typename GridType::Ptr>::type
2630 const std::vector<Vec3s>& ,
2631 const std::vector<Vec3I>& ,
2632 const std::vector<Vec4I>& ,
2638 "mesh to volume conversion is supported only for scalar, floating-point grids");
2645 template<
typename Gr
idType>
2646 inline typename GridType::Ptr
2648 const openvdb::math::Transform& xform,
2649 const std::vector<Vec3s>& points,
2650 const std::vector<Vec3I>& triangles,
2653 std::vector<Vec4I> quads(0);
2654 return doMeshConversion<GridType>(xform, points, triangles, quads,
2655 halfWidth, halfWidth);
2659 template<
typename Gr
idType>
2660 inline typename GridType::Ptr
2662 const openvdb::math::Transform& xform,
2663 const std::vector<Vec3s>& points,
2664 const std::vector<Vec4I>& quads,
2667 std::vector<Vec3I> triangles(0);
2668 return doMeshConversion<GridType>(xform, points, triangles, quads,
2669 halfWidth, halfWidth);
2673 template<
typename Gr
idType>
2674 inline typename GridType::Ptr
2676 const openvdb::math::Transform& xform,
2677 const std::vector<Vec3s>& points,
2678 const std::vector<Vec3I>& triangles,
2679 const std::vector<Vec4I>& quads,
2682 return doMeshConversion<GridType>(xform, points, triangles, quads,
2683 halfWidth, halfWidth);
2687 template<
typename Gr
idType>
2688 inline typename GridType::Ptr
2690 const openvdb::math::Transform& xform,
2691 const std::vector<Vec3s>& points,
2692 const std::vector<Vec3I>& triangles,
2693 const std::vector<Vec4I>& quads,
2697 return doMeshConversion<GridType>(xform, points, triangles,
2698 quads, exBandWidth, inBandWidth);
2702 template<
typename Gr
idType>
2703 inline typename GridType::Ptr
2705 const openvdb::math::Transform& xform,
2706 const std::vector<Vec3s>& points,
2707 const std::vector<Vec3I>& triangles,
2708 const std::vector<Vec4I>& quads,
2711 return doMeshConversion<GridType>(xform, points, triangles, quads,
2712 bandWidth, bandWidth,
true);
2720 inline std::ostream&
2723 ostr <<
"{[ " << rhs.
mXPrim <<
", " << rhs.
mXDist <<
"]";
2724 ostr <<
" [ " << rhs.
mYPrim <<
", " << rhs.
mYDist <<
"]";
2725 ostr <<
" [ " << rhs.
mZPrim <<
", " << rhs.
mZDist <<
"]}";
2730 inline MeshToVoxelEdgeData::EdgeData
2745 const std::vector<Vec3s>& pointList,
2746 const std::vector<Vec4I>& polygonList);
2748 void run(
bool threaded =
true);
2751 inline void operator() (
const tbb::blocked_range<size_t> &range);
2759 struct Primitive {
Vec3d a, b, c, d;
Int32 index; };
2761 template<
bool IsQuad>
2762 inline void voxelize(
const Primitive&);
2764 template<
bool IsQuad>
2765 inline bool evalPrimitive(
const Coord&,
const Primitive&);
2767 inline bool rayTriangleIntersection(
const Vec3d& origin,
const Vec3d& dir,
2774 const std::vector<Vec3s>& mPointList;
2775 const std::vector<Vec4I>& mPolygonList;
2779 IntTreeT mLastPrimTree;
2786 const std::vector<Vec3s>& pointList,
2787 const std::vector<Vec4I>& polygonList)
2790 , mPointList(pointList)
2791 , mPolygonList(polygonList)
2793 , mLastPrimAccessor(mLastPrimTree)
2802 , mPointList(rhs.mPointList)
2803 , mPolygonList(rhs.mPolygonList)
2805 , mLastPrimAccessor(mLastPrimTree)
2814 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPolygonList.size()), *
this);
2816 (*this)(tbb::blocked_range<size_t>(0, mPolygonList.size()));
2825 typedef RootNodeType::NodeChainType NodeChainType;
2826 BOOST_STATIC_ASSERT(boost::mpl::size<NodeChainType>::value > 1);
2827 typedef boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
2835 for ( ; leafIt; ++leafIt) {
2836 ijk = leafIt->origin();
2842 mAccessor.addLeaf(rhs.mAccessor.
probeLeaf(ijk));
2843 InternalNodeType* node = rhs.mAccessor.
getNode<InternalNodeType>();
2845 rhs.mAccessor.
clear();
2855 if (!lhsLeafPt->isValueOn(offset)) {
2856 lhsLeafPt->setValueOn(offset, rhsValue);
2888 for (
size_t n = range.begin(); n < range.end(); ++n) {
2890 const Vec4I& verts = mPolygonList[n];
2892 prim.index =
Int32(n);
2893 prim.a =
Vec3d(mPointList[verts[0]]);
2894 prim.b =
Vec3d(mPointList[verts[1]]);
2895 prim.c =
Vec3d(mPointList[verts[2]]);
2898 prim.d =
Vec3d(mPointList[verts[3]]);
2899 voxelize<true>(prim);
2901 voxelize<false>(prim);
2907 template<
bool IsQuad>
2909 MeshToVoxelEdgeData::GenEdgeData::voxelize(
const Primitive& prim)
2911 std::deque<Coord> coordList;
2915 coordList.push_back(ijk);
2917 evalPrimitive<IsQuad>(ijk, prim);
2919 while (!coordList.empty()) {
2921 ijk = coordList.back();
2922 coordList.pop_back();
2924 for (
Int32 i = 0; i < 26; ++i) {
2925 nijk = ijk + util::COORD_OFFSETS[i];
2927 if (prim.index != mLastPrimAccessor.getValue(nijk)) {
2928 mLastPrimAccessor.setValue(nijk, prim.index);
2929 if(evalPrimitive<IsQuad>(nijk, prim)) coordList.push_back(nijk);
2936 template<
bool IsQuad>
2938 MeshToVoxelEdgeData::GenEdgeData::evalPrimitive(
const Coord& ijk,
const Primitive& prim)
2940 Vec3d uvw, org(ijk[0], ijk[1], ijk[2]);
2941 bool intersecting =
false;
2945 mAccessor.probeValue(ijk, edgeData);
2948 double dist = (org -
2951 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.c, prim.b, t)) {
2952 if (t < edgeData.mXDist) {
2953 edgeData.mXDist = float(t);
2954 edgeData.mXPrim = prim.index;
2955 intersecting =
true;
2959 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.c, prim.b, t)) {
2960 if (t < edgeData.mYDist) {
2961 edgeData.mYDist = float(t);
2962 edgeData.mYPrim = prim.index;
2963 intersecting =
true;
2967 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.c, prim.b, t)) {
2968 if (t < edgeData.mZDist) {
2969 edgeData.mZDist = float(t);
2970 edgeData.mZPrim = prim.index;
2971 intersecting =
true;
2977 double secondDist = (org -
2980 if (secondDist < dist) dist = secondDist;
2982 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.d, prim.c, t)) {
2983 if (t < edgeData.mXDist) {
2984 edgeData.mXDist = float(t);
2985 edgeData.mXPrim = prim.index;
2986 intersecting =
true;
2990 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.d, prim.c, t)) {
2991 if (t < edgeData.mYDist) {
2992 edgeData.mYDist = float(t);
2993 edgeData.mYPrim = prim.index;
2994 intersecting =
true;
2998 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.d, prim.c, t)) {
2999 if (t < edgeData.mZDist) {
3000 edgeData.mZDist = float(t);
3001 edgeData.mZPrim = prim.index;
3002 intersecting =
true;
3007 if (intersecting) mAccessor.setValue(ijk, edgeData);
3009 return (dist < 0.86602540378443861);
3014 MeshToVoxelEdgeData::GenEdgeData::rayTriangleIntersection(
3025 double divisor = s1.
dot(e1);
3026 if (!(std::abs(divisor) > 0.0))
return false;
3030 double inv_divisor = 1.0 / divisor;
3031 Vec3d d = origin - a;
3032 double b1 = d.
dot(s1) * inv_divisor;
3034 if (b1 < 0.0 || b1 > 1.0)
return false;
3037 double b2 = dir.
dot(s2) * inv_divisor;
3039 if (b2 < 0.0 || (b1 + b2) > 1.0)
return false;
3043 t = e2.dot(s2) * inv_divisor;
3044 return (t < 0.0) ?
false :
true;
3060 const std::vector<Vec3s>& pointList,
3061 const std::vector<Vec4I>& polygonList)
3075 std::vector<Vec3d>& points,
3076 std::vector<Index32>& primitives)
3086 point[0] = double(coord[0]) + data.
mXDist;
3087 point[1] = double(coord[1]);
3088 point[2] = double(coord[2]);
3090 points.push_back(point);
3091 primitives.push_back(data.
mXPrim);
3095 point[0] = double(coord[0]);
3096 point[1] = double(coord[1]) + data.
mYDist;
3097 point[2] = double(coord[2]);
3099 points.push_back(point);
3100 primitives.push_back(data.
mYPrim);
3104 point[0] = double(coord[0]);
3105 point[1] = double(coord[1]);
3106 point[2] = double(coord[2]) + data.
mZDist;
3108 points.push_back(point);
3109 primitives.push_back(data.
mZPrim);
3119 point[0] = double(coord[0]);
3120 point[1] = double(coord[1]) + data.
mYDist;
3121 point[2] = double(coord[2]);
3123 points.push_back(point);
3124 primitives.push_back(data.
mYPrim);
3128 point[0] = double(coord[0]);
3129 point[1] = double(coord[1]);
3130 point[2] = double(coord[2]) + data.
mZDist;
3132 points.push_back(point);
3133 primitives.push_back(data.
mZPrim);
3141 point[0] = double(coord[0]);
3142 point[1] = double(coord[1]) + data.
mYDist;
3143 point[2] = double(coord[2]);
3145 points.push_back(point);
3146 primitives.push_back(data.
mYPrim);
3155 point[0] = double(coord[0]) + data.
mXDist;
3156 point[1] = double(coord[1]);
3157 point[2] = double(coord[2]);
3159 points.push_back(point);
3160 primitives.push_back(data.
mXPrim);
3164 point[0] = double(coord[0]);
3165 point[1] = double(coord[1]) + data.
mYDist;
3166 point[2] = double(coord[2]);
3168 points.push_back(point);
3169 primitives.push_back(data.
mYPrim);
3179 point[0] = double(coord[0]) + data.
mXDist;
3180 point[1] = double(coord[1]);
3181 point[2] = double(coord[2]);
3183 points.push_back(point);
3184 primitives.push_back(data.
mXPrim);
3193 point[0] = double(coord[0]) + data.
mXDist;
3194 point[1] = double(coord[1]);
3195 point[2] = double(coord[2]);
3197 points.push_back(point);
3198 primitives.push_back(data.
mXPrim);
3202 point[0] = double(coord[0]);
3203 point[1] = double(coord[1]);
3204 point[2] = double(coord[2]) + data.
mZDist;
3206 points.push_back(point);
3207 primitives.push_back(data.
mZPrim);
3216 point[0] = double(coord[0]);
3217 point[1] = double(coord[1]);
3218 point[2] = double(coord[2]) + data.
mZDist;
3220 points.push_back(point);
3221 primitives.push_back(data.
mZPrim);
3231 #endif // OPENVDB_TOOLS_MESH_TO_VOLUME_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:328
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:378
static Accessor::ValueType result(const Accessor &grid, const Coord &ijk)
Definition: Operators.h:260
OPENVDB_API const Index32 INVALID_IDX
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:303
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:170
_RootNodeType RootNodeType
Definition: Tree.h:209
math::Vec4< Index32 > Vec4I
Definition: Types.h:91
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Efficient multi-threaded replacement of the background values in tree.
Type Pow2(Type x)
Return .
Definition: Math.h:498
Definition: Operators.h:152
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
int32_t Int32
Definition: Types.h:61
const ValueT & getValue() const
Return the tile or voxel value to which this iterator is currently pointing.
Definition: TreeIterator.h:734
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:246
Defined various multi-threaded utility functions for trees.
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:476
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:485
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:693
#define OPENVDB_VERSION_NAME
Definition: version.h:43
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:217
Index32 Index
Definition: Types.h:59
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:216
Definition: Exceptions.h:87
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1228
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:383
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:203
Tree< typename RootNodeType::template ValueConverter< Int32 >::Type > Type
Definition: Tree.h:223
Definition: Exceptions.h:39
BufferType & getBuffer(size_t leafIdx, size_t bufferIdx) const
Return the leaf or auxiliary buffer for the leaf node at index leafIdx. If bufferIdx is zero...
Definition: LeafManager.h:330
void clear()
Remove all tiles from this tree and all nodes other than the root node.
Definition: Tree.h:580
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Vec3< double > Vec3d
Definition: Vec3.h:629
void clearAllAccessors()
Clear all registered accessors.
Definition: Tree.h:1435
virtual void clear()
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:392
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:158
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:347
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: Util.h:56
Definition: Exceptions.h:88
Base class for tree-traversal iterators over tile and voxel values.
Definition: TreeIterator.h:658
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1100
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:391
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition: Tree.h:1731
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: Tree.h:1622
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
uint32_t Index32
Definition: Types.h:57
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Vec3< float > Vec3s
Definition: Vec3.h:628
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:120
OPENVDB_API Vec3d closestPointOnTriangleToPoint(const Vec3d &a, const Vec3d &b, const Vec3d &c, const Vec3d &p, Vec3d &uvw)
Closest Point on Triangle to Point. Given a triangle abc and a point p, return the point on abc close...
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:241
RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:211
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
Definition: Vec3.h:232