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>
42 #include <tbb/blocked_range.h>
43 #include <tbb/parallel_for.h>
44 #include <tbb/parallel_reduce.h>
75 template<
typename Gr
idType>
76 inline typename GridType::Ptr
78 const openvdb::math::Transform& xform,
79 const std::vector<Vec3s>& points,
80 const std::vector<Vec3I>& triangles,
99 template<
typename Gr
idType>
100 inline typename GridType::Ptr
102 const openvdb::math::Transform& xform,
103 const std::vector<Vec3s>& points,
104 const std::vector<Vec4I>& quads,
124 template<
typename Gr
idType>
125 inline typename GridType::Ptr
127 const openvdb::math::Transform& xform,
128 const std::vector<Vec3s>& points,
129 const std::vector<Vec3I>& triangles,
130 const std::vector<Vec4I>& quads,
152 template<
typename Gr
idType>
153 inline typename GridType::Ptr
155 const openvdb::math::Transform& xform,
156 const std::vector<Vec3s>& points,
157 const std::vector<Vec3I>& triangles,
158 const std::vector<Vec4I>& quads,
177 template<
typename Gr
idType>
178 inline typename GridType::Ptr
180 const openvdb::math::Transform& xform,
181 const std::vector<Vec3s>& points,
182 const std::vector<Vec3I>& triangles,
183 const std::vector<Vec4I>& quads,
195 template<
typename FloatGr
idT,
typename InterruptT = util::NullInterrupter>
203 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
206 MeshToVolume(openvdb::math::Transform::Ptr&,
int conversionFlags = 0,
207 InterruptT *interrupter = NULL,
int signSweeps = 1);
220 void convertToLevelSet(
221 const std::vector<Vec3s>& pointList,
222 const std::vector<Vec4I>& polygonList,
234 void convertToUnsignedDistanceField(
const std::vector<Vec3s>& pointList,
235 const std::vector<Vec4I>& polygonList,
FloatValueT exBandWidth);
240 typename FloatGridT::Ptr
distGridPtr()
const {
return mDistGrid; }
250 void doConvert(
const std::vector<Vec3s>&,
const std::vector<Vec4I>&,
251 FloatValueT exBandWidth, FloatValueT inBandWidth,
bool unsignedDistField =
false);
254 return mInterrupter && mInterrupter->wasInterrupted(percent);
257 openvdb::math::Transform::Ptr mTransform;
258 int mConversionFlags, mSignSweeps;
260 typename FloatGridT::Ptr mDistGrid;
261 typename IntGridT::Ptr mIndexGrid;
262 typename BoolGridT::Ptr mIntersectingVoxelsGrid;
264 InterruptT *mInterrupter;
281 : mXDist(dist), mYDist(dist), mZDist(dist)
324 void convert(
const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList);
329 void getEdgeData(
Accessor& acc,
const Coord& ijk,
330 std::vector<Vec3d>& points, std::vector<Index32>& primitives);
355 PointTransform(
const std::vector<Vec3s>& pointsIn, std::vector<Vec3s>& pointsOut,
357 : mPointsIn(pointsIn)
358 , mPointsOut(&pointsOut)
363 void run(
bool threaded =
true)
366 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPointsOut->size()), *
this);
368 (*this)(tbb::blocked_range<size_t>(0, mPointsOut->size()));
372 inline void operator()(
const tbb::blocked_range<size_t>& range)
const
374 for (
size_t n = range.begin(); n < range.end(); ++n) {
375 (*mPointsOut)[n] = mXform.worldToIndex(mPointsIn[n]);
380 const std::vector<Vec3s>& mPointsIn;
381 std::vector<Vec3s> *
const mPointsOut;
386 template<
typename ValueType>
389 static ValueType
epsilon() {
return ValueType(1e-7); }
394 template<
typename FloatTreeT,
typename IntTreeT>
396 combine(FloatTreeT& lhsDist, IntTreeT& lhsIndex, FloatTreeT& rhsDist, IntTreeT& rhsIndex)
398 typedef typename FloatTreeT::ValueType FloatValueT;
402 typename FloatTreeT::LeafCIter iter = rhsDist.cbeginLeaf();
404 FloatValueT rhsValue;
407 for ( ; iter; ++iter) {
408 typename FloatTreeT::LeafNodeType::ValueOnCIter it = iter->cbeginValueOn();
413 rhsValue = it.getValue();
414 FloatValueT& lhsValue =
const_cast<FloatValueT&
>(lhsDistAccessor.
getValue(ijk));
416 if (-rhsValue < std::abs(lhsValue)) {
435 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
445 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
451 const std::vector<Vec4I>& polygonList, InterruptT *interrupter = NULL);
455 void run(
bool threaded =
true);
458 void operator() (
const tbb::blocked_range<size_t> &range);
468 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
470 bool evalVoxel(
const Coord& ijk,
const Int32 polyIdx);
472 const std::vector<Vec3s>& mPointList;
473 const std::vector<Vec4I>& mPolygonList;
475 FloatTreeT mSqrDistTree;
476 FloatAccessorT mSqrDistAccessor;
478 IntTreeT mPrimIndexTree;
479 IntAccessorT mPrimIndexAccessor;
481 BoolTreeT mIntersectionTree;
482 BoolAccessorT mIntersectionAccessor;
485 IntTreeT mLastPrimTree;
486 IntAccessorT mLastPrimAccessor;
488 InterruptT *mInterrupter;
491 struct Primitive {
Vec3d a, b, c, d;
Int32 index; };
493 template<
bool IsQuad>
494 bool evalPrimitive(
const Coord&,
const Primitive&);
496 template<
bool IsQuad>
497 void voxelize(
const Primitive&);
501 template<
typename FloatTreeT,
typename InterruptT>
506 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPolygonList.size()), *
this);
508 (*this)(tbb::blocked_range<size_t>(0, mPolygonList.size()));
512 template<
typename FloatTreeT,
typename InterruptT>
514 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
515 InterruptT *interrupter)
516 : mPointList(pointList)
517 , mPolygonList(polygonList)
519 , mSqrDistAccessor(mSqrDistTree)
521 , mPrimIndexAccessor(mPrimIndexTree)
522 , mIntersectionTree(false)
523 , mIntersectionAccessor(mIntersectionTree)
525 , mLastPrimAccessor(mLastPrimTree)
526 , mInterrupter(interrupter)
530 template<
typename FloatTreeT,
typename InterruptT>
533 : mPointList(rhs.mPointList)
534 , mPolygonList(rhs.mPolygonList)
536 , mSqrDistAccessor(mSqrDistTree)
538 , mPrimIndexAccessor(mPrimIndexTree)
539 , mIntersectionTree(false)
540 , mIntersectionAccessor(mIntersectionTree)
542 , mLastPrimAccessor(mLastPrimTree)
543 , mInterrupter(rhs.mInterrupter)
548 template<
typename FloatTreeT,
typename InterruptT>
554 for (
size_t n = range.begin(); n < range.end(); ++n) {
556 if (mInterrupter && mInterrupter->wasInterrupted()) {
557 tbb::task::self().cancel_group_execution();
561 const Vec4I& verts = mPolygonList[n];
563 prim.index =
Int32(n);
564 prim.a =
Vec3d(mPointList[verts[0]]);
565 prim.b =
Vec3d(mPointList[verts[1]]);
566 prim.c =
Vec3d(mPointList[verts[2]]);
569 prim.d =
Vec3d(mPointList[verts[3]]);
570 voxelize<true>(prim);
572 voxelize<false>(prim);
578 template<
typename FloatTreeT,
typename InterruptT>
579 template<
bool IsQuad>
583 std::deque<Coord> coordList;
587 coordList.push_back(ijk);
589 evalPrimitive<IsQuad>(ijk, prim);
591 while (!coordList.empty()) {
594 ijk = coordList.back();
595 coordList.pop_back();
597 mIntersectionAccessor.setActiveState(ijk,
true);
599 for (
Int32 i = 0; i < 26; ++i) {
601 if (prim.index != mLastPrimAccessor.getValue(nijk)) {
602 mLastPrimAccessor.setValue(nijk, prim.index);
603 if(evalPrimitive<IsQuad>(nijk, prim)) coordList.push_back(nijk);
610 template<
typename FloatTreeT,
typename InterruptT>
611 template<
bool IsQuad>
613 MeshVoxelizer<FloatTreeT, InterruptT>::evalPrimitive(
const Coord& ijk,
const Primitive& prim)
615 Vec3d uvw, voxelCenter(ijk[0], ijk[1], ijk[2]);
618 FloatValueT dist = FloatValueT((voxelCenter -
623 FloatValueT secondDist = FloatValueT((voxelCenter -
626 if (secondDist < dist) dist = secondDist;
629 FloatValueT oldDist = std::abs(mSqrDistAccessor.getValue(ijk));
631 if (dist < oldDist) {
632 mSqrDistAccessor.setValue(ijk, -dist);
633 mPrimIndexAccessor.setValue(ijk, prim.index);
637 mPrimIndexAccessor.setValue(ijk,
std::min(prim.index, mPrimIndexAccessor.getValue(ijk)));
640 return (dist < 0.86602540378443861);
644 template<
typename FloatTreeT,
typename InterruptT>
648 typedef typename FloatTreeT::RootNodeType FloatRootNodeT;
649 typedef typename FloatRootNodeT::NodeChainType FloatNodeChainT;
650 BOOST_STATIC_ASSERT(boost::mpl::size<FloatNodeChainT>::value > 1);
651 typedef typename boost::mpl::at<FloatNodeChainT, boost::mpl::int_<1> >::type FloatInternalNodeT;
653 typedef typename IntTreeT::RootNodeType IntRootNodeT;
654 typedef typename IntRootNodeT::NodeChainType IntNodeChainT;
655 BOOST_STATIC_ASSERT(boost::mpl::size<IntNodeChainT>::value > 1);
656 typedef typename boost::mpl::at<IntNodeChainT, boost::mpl::int_<1> >::type IntInternalNodeT;
663 rhs.mSqrDistTree.clearAllAccessors();
664 rhs.mPrimIndexTree.clearAllAccessors();
666 typename FloatTreeT::LeafIter leafIt = rhs.mSqrDistTree.beginLeaf();
667 for ( ; leafIt; ++leafIt) {
669 ijk = leafIt->origin();
670 FloatLeafT* lhsDistLeafPt = mSqrDistAccessor.probeLeaf(ijk);
672 if (!lhsDistLeafPt) {
678 mSqrDistAccessor.addLeaf(rhs.mSqrDistAccessor.probeLeaf(ijk));
679 FloatInternalNodeT* floatNode =
680 rhs.mSqrDistAccessor.template getNode<FloatInternalNodeT>();
681 floatNode->template stealNode<FloatLeafT>(ijk, background,
false);
683 mPrimIndexAccessor.addLeaf(rhs.mPrimIndexAccessor.probeLeaf(ijk));
684 IntInternalNodeT* intNode =
685 rhs.mPrimIndexAccessor.template getNode<IntInternalNodeT>();
690 IntLeafT* lhsIdxLeafPt = mPrimIndexAccessor.probeLeaf(ijk);
691 IntLeafT* rhsIdxLeafPt = rhs.mPrimIndexAccessor.probeLeaf(ijk);
694 typename FloatLeafT::ValueOnCIter it = leafIt->cbeginValueOn();
699 lhsValue = std::abs(lhsDistLeafPt->getValue(offset));
700 rhsValue = std::abs(it.getValue());
702 if (rhsValue < lhsValue) {
703 lhsDistLeafPt->setValueOn(offset, it.getValue());
704 lhsIdxLeafPt->setValueOn(offset, rhsIdxLeafPt->getValue(offset));
706 lhsIdxLeafPt->setValueOn(offset,
707 std::min(lhsIdxLeafPt->getValue(offset), rhsIdxLeafPt->getValue(offset)));
713 mIntersectionTree.merge(rhs.mIntersectionTree);
715 rhs.mSqrDistTree.clear();
716 rhs.mPrimIndexTree.clear();
717 rhs.mIntersectionTree.clear();
727 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
733 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
739 void run(
bool threaded =
true);
742 void operator()(
const tbb::blocked_range<int> &range)
const;
747 int sparseScan(
int slice)
const;
749 FloatTreeT& mDistTree;
758 std::vector<Index> mStepSize;
760 InterruptT *mInterrupter;
764 template<
typename FloatTreeT,
typename InterruptT>
769 tbb::parallel_for(tbb::blocked_range<int>(mBBox.min()[0], mBBox.max()[0]+1), *
this);
771 (*this)(tbb::blocked_range<int>(mBBox.min()[0], mBBox.max()[0]+1));
776 template<
typename FloatTreeT,
typename InterruptT>
778 FloatTreeT& distTree,
const BoolTreeT& intersectionTree, InterruptT *interrupter)
779 : mDistTree(distTree)
780 , mDistAccessor(mDistTree)
781 , mIntersectionTree(intersectionTree)
782 , mIntersectionAccessor(mIntersectionTree)
785 , mInterrupter(interrupter)
788 std::vector<Index> dims;
789 mDistTree.getNodeLog2Dims(dims);
791 mStepSize.resize(dims.size()+1, 1);
793 for (
int idx = static_cast<int>(dims.size()) - 1; idx > -1; --idx) {
794 exponent += dims[idx];
795 mStepSize[idx] = 1 << exponent;
798 mDistTree.evalLeafBoundingBox(mBBox);
801 const int tileDim = mStepSize[0];
803 for (
size_t i = 0; i < 3; ++i) {
806 double diff = std::abs(
double(mBBox.min()[i])) / double(tileDim);
808 if (mBBox.min()[i] <= tileDim) {
809 n = int(std::ceil(diff));
810 mBBox.min()[i] = - n * tileDim;
812 n = int(std::floor(diff));
813 mBBox.min()[i] = n * tileDim;
816 n = int(std::ceil(std::abs(
double(mBBox.max()[i] - mBBox.min()[i])) / double(tileDim)));
817 mBBox.max()[i] = mBBox.min()[i] + n * tileDim;
822 template<
typename FloatTreeT,
typename InterruptT>
825 : mDistTree(rhs.mDistTree)
826 , mDistAccessor(mDistTree)
827 , mIntersectionTree(rhs.mIntersectionTree)
828 , mIntersectionAccessor(mIntersectionTree)
830 , mStepSize(rhs.mStepSize)
831 , mInterrupter(rhs.mInterrupter)
836 template<
typename FloatTreeT,
typename InterruptT>
842 for (
int n = range.begin(); n < range.end(); n += iStep) {
844 if (mInterrupter && mInterrupter->wasInterrupted()) {
845 tbb::task::self().cancel_group_execution();
849 iStep = sparseScan(n);
854 template<
typename FloatTreeT,
typename InterruptT>
858 bool lastVoxelWasOut =
true;
861 Coord ijk(slice, mBBox.min()[1], mBBox.min()[2]);
862 Coord step(mStepSize[mDistAccessor.getValueDepth(ijk) + 1]);
865 for (ijk[1] = mBBox.min()[1]; ijk[1] <= mBBox.max()[1]; ijk[1] += step[1]) {
867 if (mInterrupter && mInterrupter->wasInterrupted()) {
871 step[1] = mStepSize[mDistAccessor.getValueDepth(ijk) + 1];
872 step[0] =
std::min(step[0], step[1]);
874 for (ijk[2] = mBBox.min()[2]; ijk[2] <= mBBox.max()[2]; ijk[2] += step[2]) {
876 step[2] = mStepSize[mDistAccessor.getValueDepth(ijk) + 1];
877 step[1] =
std::min(step[1], step[2]);
878 step[0] =
std::min(step[0], step[2]);
881 if (mDistAccessor.isValueOn(ijk)) {
884 if (mIntersectionAccessor.isValueOn(ijk)) {
886 lastVoxelWasOut =
false;
889 }
else if (lastVoxelWasOut) {
891 FloatValueT& val =
const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
897 for (
Int32 n = 3; n < 6; n += 2) {
898 n_ijk = ijk + util::COORD_OFFSETS[n];
900 if (mDistAccessor.probeValue(n_ijk, val) && val > 0) {
901 lastVoxelWasOut =
true;
906 if (lastVoxelWasOut) {
908 FloatValueT& v =
const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
911 const int tmp_k = ijk[2];
914 for (--ijk[2]; ijk[2] >= last_k; --ijk[2]) {
915 if (mIntersectionAccessor.isValueOn(ijk))
break;
917 const_cast<FloatValueT&
>(mDistAccessor.getValue(ijk));
918 if (vb < FloatValueT(0.0)) vb = -vb;
941 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
949 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
956 InterruptT *interrupter = NULL);
960 void run(
bool threaded =
true);
963 void operator() (
const tbb::blocked_range<size_t> &range);
971 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
974 const FloatTreeT& mDistTree;
979 InterruptT *mInterrupter;
983 template<
typename FloatTreeT,
typename InterruptT>
986 const BoolTreeT& intersectionTree, InterruptT *interrupter)
987 : mDistLeafs(distLeafs)
988 , mDistTree(distTree)
989 , mIntersectionTree(intersectionTree)
990 , mSignMaskTree(false)
991 , mInterrupter(interrupter)
996 template<
typename FloatTreeT,
typename InterruptT>
999 : mDistLeafs(rhs.mDistLeafs)
1000 , mDistTree(rhs.mDistTree)
1001 , mIntersectionTree(rhs.mIntersectionTree)
1002 , mSignMaskTree(false)
1003 , mInterrupter(rhs.mInterrupter)
1008 template<
typename FloatTreeT,
typename InterruptT>
1012 if (threaded) tbb::parallel_reduce(mDistLeafs.getRange(), *
this);
1013 else (*
this)(mDistLeafs.getRange());
1017 template<
typename FloatTreeT,
typename InterruptT>
1027 Coord& maxCoord = bbox.max();
1028 Coord& minCoord = bbox.min();
1030 const int extent = BoolLeafT::DIM - 1;
1032 for (
size_t n = range.begin(); n < range.end(); ++n) {
1034 const FloatLeafT& distLeaf = mDistLeafs.leaf(n);
1036 minCoord = distLeaf.origin();
1037 maxCoord[0] = minCoord[0] + extent;
1038 maxCoord[1] = minCoord[1] + extent;
1039 maxCoord[2] = minCoord[2] + extent;
1045 bool addLeaf =
false;
1049 typename FloatLeafT::ValueOnCIter it = distLeaf.cbeginValueOn();
1051 if (intersectionLeaf && intersectionLeaf->isValueOn(it.pos()))
continue;
1053 ijk = it.getCoord();
1054 if (bbox.isInside(ijk)) {
1055 for (
size_t i = 0; i < 6; ++i) {
1056 if (distLeaf.probeValue(ijk+util::COORD_OFFSETS[i], value) && value>0.0) {
1057 maskLeaf.setValueOn(ijk);
1063 for (
size_t i = 0; i < 6; ++i) {
1064 if (distAcc.
probeValue(ijk+util::COORD_OFFSETS[i], value) && value>0.0) {
1065 maskLeaf.setValueOn(ijk);
1074 if (addLeaf) maskAcc.
addLeaf(maskLeafPt);
1075 else delete maskLeafPt;
1080 template<
typename FloatTreeT,
typename InterruptT>
1084 mSignMaskTree.merge(rhs.mSignMaskTree);
1092 template<
typename FloatTreeT,
typename InterruptT = util::NullInterrupter>
1099 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1109 void run(
bool threaded =
true);
1112 void operator() (
const tbb::blocked_range<size_t> &range);
1120 bool wasInterrupted()
const {
return mInterrupter && mInterrupter->wasInterrupted(); }
1123 FloatTreeT& mDistTree;
1127 InterruptT *mInterrupter;
1131 template<
typename FloatTreeT,
typename InterruptT>
1133 FloatTreeT& distTree,
const BoolTreeT& intersectionTree, InterruptT *interrupter)
1134 : mOldSignMaskLeafs(signMaskLeafs)
1135 , mDistTree(distTree)
1136 , mIntersectionTree(intersectionTree)
1137 , mSignMaskTree(false)
1138 , mInterrupter(interrupter)
1143 template<
typename FloatTreeT,
typename InterruptT>
1146 : mOldSignMaskLeafs(rhs.mOldSignMaskLeafs)
1147 , mDistTree(rhs.mDistTree)
1148 , mIntersectionTree(rhs.mIntersectionTree)
1149 , mSignMaskTree(false)
1150 , mInterrupter(rhs.mInterrupter)
1155 template<
typename FloatTreeT,
typename InterruptT>
1159 if (threaded) tbb::parallel_reduce(mOldSignMaskLeafs.getRange(), *
this);
1160 else (*
this)(mOldSignMaskLeafs.getRange());
1164 template<
typename FloatTreeT,
typename InterruptT>
1172 std::deque<Coord> coordList;
1176 Coord& maxCoord = bbox.max();
1177 Coord& minCoord = bbox.min();
1179 const int extent = BoolLeafT::DIM - 1;
1181 for (
size_t n = range.begin(); n < range.end(); ++n) {
1182 BoolLeafT& oldMaskLeaf = mOldSignMaskLeafs.leaf(n);
1184 minCoord = oldMaskLeaf.origin();
1185 maxCoord[0] = minCoord[0] + extent;
1186 maxCoord[1] = minCoord[1] + extent;
1187 maxCoord[2] = minCoord[2] + extent;
1192 typename BoolLeafT::ValueOnCIter it = oldMaskLeaf.cbeginValueOn();
1194 coordList.push_back(it.getCoord());
1196 while (!coordList.empty()) {
1198 ijk = coordList.back();
1199 coordList.pop_back();
1205 for (
size_t i = 0; i < 6; ++i) {
1206 nijk = ijk + util::COORD_OFFSETS[i];
1207 if (bbox.isInside(nijk)) {
1208 if (intersectionLeaf && intersectionLeaf->isValueOn(nijk))
continue;
1210 if (distLeaf.probeValue(nijk, value) && value < 0.0) {
1211 coordList.push_back(nijk);
1216 distAcc.
probeValue(nijk, value) && value < 0.0) {
1228 template<
typename FloatTreeT,
typename InterruptT>
1232 mSignMaskTree.merge(rhs.mSignMaskTree);
1243 template<
typename FloatTreeT>
1251 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1256 const std::vector<Vec3s>& pointList,
1257 const std::vector<Vec4I>& polygonList,
1258 FloatTreeT& distTree,
1265 void run(
bool threaded =
true);
1268 void operator()(
const tbb::blocked_range<size_t>&)
const;
1273 Vec3d getClosestPoint(
const Coord& ijk,
const Vec4I& prim)
const;
1275 std::vector<Vec3s>
const *
const mPointList;
1276 std::vector<Vec4I>
const *
const mPolygonList;
1278 FloatTreeT& mDistTree;
1286 template<
typename FloatTreeT>
1290 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1291 else (*
this)(mLeafs.getRange());
1295 template<
typename FloatTreeT>
1297 const std::vector<Vec3s>& pointList,
1298 const std::vector<Vec4I>& polygonList,
1299 FloatTreeT& distTree,
1303 : mPointList(&pointList)
1304 , mPolygonList(&polygonList)
1305 , mDistTree(distTree)
1306 , mIndexTree(indexTree)
1307 , mIntersectionTree(intersectionTree)
1313 template<
typename FloatTreeT>
1316 : mPointList(rhs.mPointList)
1317 , mPolygonList(rhs.mPolygonList)
1318 , mDistTree(rhs.mDistTree)
1319 , mIndexTree(rhs.mIndexTree)
1320 , mIntersectionTree(rhs.mIntersectionTree)
1321 , mLeafs(rhs.mLeafs)
1326 template<
typename FloatTreeT>
1329 const tbb::blocked_range<size_t>& range)
const
1340 typename BoolTreeT::LeafNodeType::ValueOnCIter iter;
1341 for (
size_t n = range.begin(); n < range.end(); ++n) {
1342 iter = mLeafs.leaf(n).cbeginValueOn();
1343 for (; iter; ++iter) {
1345 ijk = iter.getCoord();
1351 center =
Vec3d(ijk[0], ijk[1], ijk[2]);
1353 for (
Int32 i = 0; i < 26; ++i) {
1354 nijk = ijk + util::COORD_OFFSETS[i];
1361 cpt = getClosestPoint(nijk, prim);
1363 dir1 = center -
cpt;
1366 dir2 =
Vec3d(nijk[0], nijk[1], nijk[2]) -
cpt;
1369 if (dir2.dot(dir1) > 0.0) {
1380 template<
typename FloatTreeT>
1384 Vec3d voxelCenter(ijk[0], ijk[1], ijk[2]);
1387 const Vec3d a((*mPointList)[prim[0]]);
1388 const Vec3d b((*mPointList)[prim[1]]);
1389 const Vec3d c((*mPointList)[prim[2]]);
1397 Vec3d diff1 = voxelCenter - cpt1;
1399 const Vec3d d((*mPointList)[prim[3]]);
1402 Vec3d diff2 = voxelCenter - cpt2;
1404 if (diff2.lengthSqr() < diff1.lengthSqr()) {
1419 template<
typename FloatTreeT>
1429 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1439 void run(
bool threaded =
true);
1442 void operator()(
const tbb::blocked_range<size_t>&)
const;
1447 FloatTreeT& mDistTree;
1454 template<
typename FloatTreeT>
1458 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1459 else (*
this)(mLeafs.getRange());
1461 mIntersectionTree.pruneInactive();
1465 template<
typename FloatTreeT>
1467 FloatTreeT& distTree,
1471 : mDistTree(distTree)
1472 , mIndexTree(indexTree)
1473 , mIntersectionTree(intersectionTree)
1479 template<
typename FloatTreeT>
1482 : mDistTree(rhs.mDistTree)
1483 , mIndexTree(rhs.mIndexTree)
1484 , mIntersectionTree(rhs.mIntersectionTree)
1485 , mLeafs(rhs.mLeafs)
1490 template<
typename FloatTreeT>
1493 const tbb::blocked_range<size_t>& range)
const
1500 typename BoolLeafT::ValueOnCIter iter;
1506 for (
size_t n = range.begin(); n < range.end(); ++n) {
1510 ijk = maskLeaf.origin();
1514 iter = maskLeaf.cbeginValueOn();
1515 for (; iter; ++iter) {
1517 offset = iter.pos();
1519 if(distLeaf->getValue(offset) > 0.1)
continue;
1521 ijk = iter.getCoord();
1523 for (
Int32 m = 0; m < 26; ++m) {
1524 m_ijk = ijk + util::COORD_OFFSETS[m];
1534 maskLeaf.setValueOff(offset);
1535 distLeaf->setValueOn(offset, -0.86602540378443861);
1549 template<
typename FloatTreeT>
1560 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1569 void run(
bool threaded =
true);
1572 void operator()(
const tbb::blocked_range<size_t>&)
const;
1577 FloatTreeT& mDistTree;
1584 template<
typename FloatTreeT>
1588 if (threaded) tbb::parallel_for(mLeafs.getRange(), *
this);
1589 else (*
this)(mLeafs.getRange());
1591 mDistTree.pruneInactive();
1592 mIndexTree.pruneInactive();
1596 template<
typename FloatTreeT>
1598 FloatTreeT& distTree,
1602 : mDistTree(distTree)
1604 , mIndexTree(indexTree)
1605 , mIntersectionTree(intersectionTree)
1610 template<
typename FloatTreeT>
1613 : mDistTree(rhs.mDistTree)
1614 , mLeafs(rhs.mLeafs)
1615 , mIndexTree(rhs.mIndexTree)
1616 , mIntersectionTree(rhs.mIntersectionTree)
1621 template<
typename FloatTreeT>
1624 const tbb::blocked_range<size_t>& range)
const
1631 typename DistLeafT::ValueOnCIter iter;
1632 const FloatValueT distBG = mDistTree.background();
1633 const Int32 indexBG = mIntersectionTree.background();
1640 for (
size_t n = range.begin(); n < range.end(); ++n) {
1644 ijk = distLeaf.origin();
1649 iter = distLeaf.cbeginValueOn();
1650 for (; iter; ++iter) {
1652 value = iter.getValue();
1653 if(value > 0.0)
continue;
1655 offset = iter.pos();
1656 if (maskLeaf && maskLeaf->isValueOn(offset))
continue;
1658 ijk = iter.getCoord();
1660 for (
Int32 m = 0; m < 18; ++m) {
1661 m_ijk = ijk + util::COORD_OFFSETS[m];
1669 distLeaf.setValueOff(offset, distBG);
1670 indexLeaf.setValueOff(offset, indexBG);
1683 template<
typename FloatTreeT>
1693 typedef typename FloatTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1701 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList);
1703 void run(
bool threaded =
true);
1705 void operator()(
const tbb::blocked_range<size_t>&);
1719 double closestPrimDist(
const Coord&, std::vector<Int32>&,
Int32&)
const;
1723 FloatTreeT& mDistTree;
1727 const FloatValueT mExteriorBandWidth, mInteriorBandWidth, mVoxelSize;
1728 const std::vector<Vec3s>& mPointList;
1729 const std::vector<Vec4I>& mPolygonList;
1731 FloatTreeT mNewDistTree;
1737 template<
typename FloatTreeT>
1740 FloatTreeT& distTree,
1746 const std::vector<Vec3s>& pointList,
1747 const std::vector<Vec4I>& polygonList)
1749 , mDistTree(distTree)
1750 , mIndexTree(indexTree)
1751 , mMaskTree(maskTree)
1752 , mExteriorBandWidth(exteriorBandWidth)
1753 , mInteriorBandWidth(interiorBandWidth)
1754 , mVoxelSize(voxelSize)
1755 , mPointList(pointList)
1756 , mPolygonList(polygonList)
1759 , mNewMaskTree(false)
1764 template<
typename FloatTreeT>
1766 : mMaskLeafs(rhs.mMaskLeafs)
1767 , mDistTree(rhs.mDistTree)
1768 , mIndexTree(rhs.mIndexTree)
1769 , mMaskTree(rhs.mMaskTree)
1770 , mExteriorBandWidth(rhs.mExteriorBandWidth)
1771 , mInteriorBandWidth(rhs.mInteriorBandWidth)
1772 , mVoxelSize(rhs.mVoxelSize)
1773 , mPointList(rhs.mPointList)
1774 , mPolygonList(rhs.mPolygonList)
1777 , mNewMaskTree(false)
1782 template<
typename FloatTreeT>
1786 if (threaded) tbb::parallel_reduce(mMaskLeafs.getRange(), *
this);
1787 else (*
this)(mMaskLeafs.getRange());
1789 mDistTree.merge(mNewDistTree);
1790 mIndexTree.merge(mNewIndexTree);
1793 mMaskTree.merge(mNewMaskTree);
1797 template<
typename FloatTreeT>
1802 Int32 closestPrim = 0;
1816 std::vector<Int32> primitives(18);
1818 for (
size_t n = range.begin(); n < range.end(); ++n) {
1820 BoolLeafT& maskLeaf = mMaskLeafs.leaf(n);
1822 if (maskLeaf.isEmpty())
continue;
1824 ijk = maskLeaf.origin();
1829 newDistAcc.
addLeaf(distLeafPt);
1833 if (!indexLeafPt) indexLeafPt = newIndexAcc.
touchLeaf(ijk);
1835 bbox = maskLeaf.getNodeBoundingBox();
1838 typename BoolLeafT::ValueOnIter iter = maskLeaf.beginValueOn();
1839 for (; iter; ++iter) {
1841 ijk = iter.getCoord();
1843 if (bbox.isInside(ijk)) {
1844 distance = evalVoxelDist(ijk, *distLeafPt, *indexLeafPt, maskLeaf,
1845 primitives, closestPrim);
1847 distance = evalVoxelDist(ijk, distAcc, indexAcc, maskAcc,
1848 primitives, closestPrim);
1853 inside = distLeafPt->getValue(pos) <
FloatValueT(0.0);
1855 if (!inside && distance < mExteriorBandWidth) {
1856 distLeafPt->setValueOn(pos, distance);
1857 indexLeafPt->setValueOn(pos, closestPrim);
1858 }
else if (inside && distance < mInteriorBandWidth) {
1859 distLeafPt->setValueOn(pos, -distance);
1860 indexLeafPt->setValueOn(pos, closestPrim);
1865 for (
Int32 i = 0; i < 6; ++i) {
1866 newMaskAcc.
setValueOn(ijk + util::COORD_OFFSETS[i]);
1873 template<
typename FloatTreeT>
1877 FloatAccessorT& distAcc,
1878 IntAccessorT& indexAcc,
1879 BoolAccessorT& maskAcc,
1880 std::vector<Int32>& prims,
1881 Int32& closestPrim)
const
1888 for (
Int32 n = 0; n < 18; ++n) {
1889 n_ijk = ijk + util::COORD_OFFSETS[n];
1890 if (!maskAcc.isValueOn(n_ijk) && distAcc.probeValue(n_ijk, tmpDist)) {
1891 prims.push_back(indexAcc.getValue(n_ijk));
1892 tmpDist = std::abs(tmpDist);
1893 if (tmpDist < minDist) minDist = tmpDist;
1898 tmpDist = FloatValueT(closestPrimDist(ijk, prims, closestPrim));
1902 return tmpDist > minDist ? tmpDist : minDist + mVoxelSize;
1907 template<
typename FloatTreeT>
1909 ExpandNB<FloatTreeT>::evalVoxelDist(
1911 FloatLeafT& distLeaf,
1912 IntLeafT& indexLeaf,
1913 BoolLeafT& maskLeaf,
1914 std::vector<Int32>& prims,
1915 Int32& closestPrim)
const
1921 for (
Int32 n = 0; n < 18; ++n) {
1922 pos = FloatLeafT::coordToOffset(ijk + util::COORD_OFFSETS[n]);
1923 if (!maskLeaf.isValueOn(pos) && distLeaf.probeValue(pos, tmpDist)) {
1924 prims.push_back(indexLeaf.getValue(pos));
1925 tmpDist = std::abs(tmpDist);
1926 if (tmpDist < minDist) minDist = tmpDist;
1930 tmpDist = FloatValueT(closestPrimDist(ijk, prims, closestPrim));
1931 return tmpDist > minDist ? tmpDist : minDist + mVoxelSize;
1935 template<
typename FloatTreeT>
1937 ExpandNB<FloatTreeT>::closestPrimDist(
const Coord& ijk,
1938 std::vector<Int32>& prims,
Int32& closestPrim)
const
1940 std::sort(prims.begin(), prims.end());
1942 Int32 lastPrim = -1;
1943 Vec3d uvw, voxelCenter(ijk[0], ijk[1], ijk[2]);
1946 for (
size_t n = 0, N = prims.size(); n < N; ++n) {
1947 if (prims[n] == lastPrim)
continue;
1949 lastPrim = prims[n];
1951 const Vec4I& verts = mPolygonList[lastPrim];
1954 const Vec3d a(mPointList[verts[0]]);
1955 const Vec3d b(mPointList[verts[1]]);
1956 const Vec3d c(mPointList[verts[2]]);
1958 primDist = (voxelCenter -
1963 const Vec3d d(mPointList[verts[3]]);
1965 tmpDist = (voxelCenter -
1968 if (tmpDist < primDist) primDist = tmpDist;
1971 if (primDist < dist) {
1973 closestPrim = lastPrim;
1977 return std::sqrt(dist) * double(mVoxelSize);
1981 template<
typename FloatTreeT>
1985 mNewDistTree.merge(rhs.mNewDistTree);
1986 mNewIndexTree.merge(rhs.mNewIndexTree);
1987 mNewMaskTree.merge(rhs.mNewMaskTree);
1994 template<
typename ValueType>
1998 : mVoxelSize(voxelSize)
1999 , mUnsigned(unsignedDist)
2003 template <
typename LeafNodeType>
2010 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2011 for (; iter; ++iter) {
2012 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2013 val = w[!mUnsigned && int(val < ValueType(0.0))] * std::sqrt(std::abs(val));
2018 ValueType mVoxelSize;
2019 const bool mUnsigned;
2023 template<
typename ValueType>
2027 : mExBandWidth(exBandWidth)
2028 , mInBandWidth(inBandWidth)
2032 template <
typename LeafNodeType>
2035 ValueType bgValues[2];
2036 bgValues[0] = mExBandWidth;
2037 bgValues[1] = -mInBandWidth;
2039 typename LeafNodeType::ValueOffIter iter = leaf.beginValueOff();
2041 for (; iter; ++iter) {
2042 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2043 val = bgValues[int(val < ValueType(0.0))];
2048 ValueType mExBandWidth, mInBandWidth;
2052 template<
typename ValueType>
2055 TrimOp(ValueType exBandWidth, ValueType inBandWidth)
2056 : mExBandWidth(exBandWidth)
2057 , mInBandWidth(inBandWidth)
2061 template <
typename LeafNodeType>
2064 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2066 for (; iter; ++iter) {
2067 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2068 const bool inside = val < ValueType(0.0);
2070 if (inside && !(val > -mInBandWidth)) {
2071 val = -mInBandWidth;
2073 }
else if (!inside && !(val < mExBandWidth)) {
2081 ValueType mExBandWidth, mInBandWidth;
2085 template<
typename ValueType>
2092 template <
typename LeafNodeType>
2095 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2096 for (; iter; ++iter) {
2097 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2107 template<
typename Gr
idType,
typename ValueType>
2111 typedef typename Scheme::template ISStencil<GridType>::StencilType
Stencil;
2118 , mVoxelSize(voxelSize)
2125 template <
typename LeafNodeType>
2128 const ValueType dt = mCFL * mVoxelSize, one(1.0), invDx = one / mVoxelSize;
2132 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2133 for (; iter; ++iter) {
2134 stencil.moveTo(iter);
2136 const ValueType normSqGradPhi =
2139 const ValueType phi0 = iter.getValue();
2140 const ValueType diff =
math::Sqrt(normSqGradPhi) * invDx - one;
2143 buffer.setValue(iter.pos(), phi0 - dt * S * diff);
2150 ValueType mVoxelSize, mCFL;
2154 template<
typename TreeType,
typename ValueType>
2162 template <
typename LeafNodeType>
2166 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2168 for (; iter; ++iter) {
2169 ValueType& val =
const_cast<ValueType&
>(iter.getValue());
2170 val =
std::min(val, buffer.getValue(iter.pos()));
2179 template<
typename TreeType,
typename ValueType>
2187 , mBufferIndex(bufferIndex)
2191 template <
typename LeafNodeType>
2195 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
2198 for (; iter; ++iter) {
2199 offset = iter.pos();
2200 leaf.setValueOnly(offset, buffer.getValue(offset));
2206 const size_t mBufferIndex;
2210 template<
typename TreeType>
2218 template <
typename LeafNodeType>
2222 if (rhsLeaf) leaf.topologyDifference(*rhsLeaf,
false);
2238 template<
typename FloatGr
idT,
typename InterruptT>
2240 openvdb::math::Transform::Ptr& transform,
int conversionFlags,
2241 InterruptT *interrupter,
int signSweeps)
2242 : mTransform(transform)
2243 , mConversionFlags(conversionFlags)
2244 , mSignSweeps(signSweeps)
2245 , mInterrupter(interrupter)
2248 mSignSweeps =
std::min(mSignSweeps, 1);
2252 template<
typename FloatGr
idT,
typename InterruptT>
2258 mIntersectingVoxelsGrid = BoolGridT::create(
false);
2262 template<
typename FloatGr
idT,
typename InterruptT>
2265 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2271 const FloatValueT vs = mTransform->voxelSize()[0];
2272 doConvert(pointList, polygonList, vs * exBandWidth, vs * inBandWidth);
2277 template<
typename FloatGr
idT,
typename InterruptT>
2280 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2285 const FloatValueT vs = mTransform->voxelSize()[0];
2286 doConvert(pointList, polygonList, vs * exBandWidth, 0.0,
true);
2291 template<
typename FloatGr
idT,
typename InterruptT>
2294 const std::vector<Vec3s>& pointList,
const std::vector<Vec4I>& polygonList,
2295 FloatValueT exBandWidth, FloatValueT inBandWidth,
bool unsignedDistField)
2297 mDistGrid->setTransform(mTransform);
2298 mIndexGrid->setTransform(mTransform);
2310 voxelizer(pointList, polygonList, mInterrupter);
2316 mDistGrid->tree().merge(voxelizer.sqrDistTree());
2317 mIndexGrid->tree().merge(voxelizer.primIndexTree());
2318 mIntersectingVoxelsGrid->tree().merge(voxelizer.intersectionTree());
2322 if (!unsignedDistField) {
2326 internal::ContourTracer<FloatTreeT, InterruptT> trace(
2327 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2328 for (
int i = 0; i < mSignSweeps; ++i) {
2337 BoolTreeT signMaskTree(
false);
2340 internal::SignMask<FloatTreeT, InterruptT> signMaskOp(leafs,
2341 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2343 signMaskTree.merge(signMaskOp.signMaskTree());
2350 if(leafs.leafCount() == 0)
break;
2352 internal::PropagateSign<FloatTreeT, InterruptT> sign(leafs,
2353 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2355 signMaskTree.clear();
2357 signMaskTree.merge(sign.signMaskTree());
2366 tree::LeafManager<BoolTreeT> leafs(mIntersectingVoxelsGrid->tree());
2369 internal::IntersectingVoxelSign<FloatTreeT> sign(pointList, polygonList,
2370 mDistGrid->tree(), mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2379 internal::IntersectingVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2380 mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2389 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2391 internal::ShellVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2392 leafs, mIndexGrid->tree(), mIntersectingVoxelsGrid->tree());
2400 inBandWidth = FloatValueT(0.0);
2403 if (mDistGrid->activeVoxelCount() == 0)
return;
2405 mIntersectingVoxelsGrid->clear();
2406 const FloatValueT voxelSize(mTransform->voxelSize()[0]);
2409 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2410 leafs.foreach(internal::SqrtAndScaleOp<FloatValueT>(voxelSize, unsignedDistField));
2415 if (!unsignedDistField) {
2416 mDistGrid->tree().getRootNode().setBackground(exBandWidth,
false);
2417 mDistGrid->tree().signedFloodFill(exBandWidth, -inBandWidth);
2423 const FloatValueT minWidth = voxelSize * 2.0;
2424 if (inBandWidth > minWidth || exBandWidth > minWidth) {
2427 BoolTreeT maskTree(
false);
2428 maskTree.topologyUnion(mDistGrid->tree());
2432 internal::LeafTopologyDiffOp<FloatTreeT> diffOp(mDistGrid->tree());
2436 float progress = 48, step = 0.0;
2439 2.0 * std::ceil((
std::max(inBandWidth, exBandWidth) - minWidth) / voxelSize);
2440 if (estimated <
double(maxIterations)) {
2441 maxIterations = unsigned(estimated);
2442 step = 42.0 / float(maxIterations);
2450 tree::LeafManager<BoolTreeT> leafs(maskTree);
2452 if (leafs.leafCount() == 0)
break;
2454 leafs.foreach(diffOp);
2456 internal::ExpandNB<FloatTreeT> expand(
2457 leafs, mDistGrid->tree(), mIndexGrid->tree(), maskTree,
2458 exBandWidth, inBandWidth, voxelSize, pointList, polygonList);
2462 if ((++count) >= maxIterations)
break;
2474 if (!unsignedDistField && !rawData) {
2476 mDistGrid->tree().pruneLevelSet();
2477 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree(), 1);
2479 const FloatValueT offset = 0.8 * voxelSize;
2482 internal::OffsetOp<FloatValueT> offsetOp(-offset);
2484 leafs.foreach(offsetOp);
2488 leafs.foreach(internal::RenormOp<FloatGridT, FloatValueT>(*mDistGrid, leafs, voxelSize));
2490 leafs.foreach(internal::MinOp<FloatTreeT, FloatValueT>(leafs));
2494 offsetOp.resetOffset(offset - internal::Tolerance<FloatValueT>::epsilon());
2495 leafs.foreach(offsetOp);
2500 const FloatValueT minTrimWidth = voxelSize * 4.0;
2501 if (inBandWidth < minTrimWidth || exBandWidth < minTrimWidth) {
2507 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2508 leafs.foreach(internal::TrimOp<FloatValueT>(
2509 exBandWidth, unsignedDistField ? exBandWidth : inBandWidth));
2514 mDistGrid->tree().pruneLevelSet();
2515 mDistGrid->tree().signedFloodFill(exBandWidth, -inBandWidth);
2523 template<
typename Gr
idType>
2524 inline typename boost::enable_if<boost::is_floating_point<typename GridType::ValueType>,
2525 typename GridType::Ptr>::type
2527 const openvdb::math::Transform& xform,
2528 const std::vector<Vec3s>& points,
2529 const std::vector<Vec3I>& triangles,
2530 const std::vector<Vec4I>& quads,
2533 bool unsignedDistanceField =
false)
2535 std::vector<Vec3s> indexSpacePoints(points.size());
2543 std::vector<Vec4I> primitives(triangles.size() + quads.size());
2545 for (
size_t n = 0, N = triangles.size(); n < N; ++n) {
2546 Vec4I& prim = primitives[n];
2547 const Vec3I& triangle = triangles[n];
2548 prim[0] = triangle[0];
2549 prim[1] = triangle[1];
2550 prim[2] = triangle[2];
2554 for (
size_t n = 0, N = quads.size(); n < N; ++n) {
2555 primitives[n + triangles.size()] = quads[n];
2558 typename GridType::ValueType exWidth(exBandWidth);
2559 typename GridType::ValueType inWidth(inBandWidth);
2565 if (!unsignedDistanceField) {
2577 template<
typename Gr
idType>
2578 inline typename boost::disable_if<boost::is_floating_point<typename GridType::ValueType>,
2579 typename GridType::Ptr>::type
2582 const std::vector<Vec3s>& ,
2583 const std::vector<Vec3I>& ,
2584 const std::vector<Vec4I>& ,
2587 bool unsignedDistanceField =
false)
2590 "mesh to volume conversion is supported only for scalar, floating-point grids");
2597 template<
typename Gr
idType>
2598 inline typename GridType::Ptr
2600 const openvdb::math::Transform& xform,
2601 const std::vector<Vec3s>& points,
2602 const std::vector<Vec3I>& triangles,
2605 std::vector<Vec4I> quads(0);
2606 return doMeshConversion<GridType>(xform, points, triangles, quads,
2607 halfWidth, halfWidth);
2611 template<
typename Gr
idType>
2612 inline typename GridType::Ptr
2614 const openvdb::math::Transform& xform,
2615 const std::vector<Vec3s>& points,
2616 const std::vector<Vec4I>& quads,
2619 std::vector<Vec3I> triangles(0);
2620 return doMeshConversion<GridType>(xform, points, triangles, quads,
2621 halfWidth, halfWidth);
2625 template<
typename Gr
idType>
2626 inline typename GridType::Ptr
2628 const openvdb::math::Transform& xform,
2629 const std::vector<Vec3s>& points,
2630 const std::vector<Vec3I>& triangles,
2631 const std::vector<Vec4I>& quads,
2634 return doMeshConversion<GridType>(xform, points, triangles, quads,
2635 halfWidth, halfWidth);
2639 template<
typename Gr
idType>
2640 inline typename GridType::Ptr
2642 const openvdb::math::Transform& xform,
2643 const std::vector<Vec3s>& points,
2644 const std::vector<Vec3I>& triangles,
2645 const std::vector<Vec4I>& quads,
2649 return doMeshConversion<GridType>(xform, points, triangles,
2650 quads, exBandWidth, inBandWidth);
2654 template<
typename Gr
idType>
2655 inline typename GridType::Ptr
2657 const openvdb::math::Transform& xform,
2658 const std::vector<Vec3s>& points,
2659 const std::vector<Vec3I>& triangles,
2660 const std::vector<Vec4I>& quads,
2663 return doMeshConversion<GridType>(xform, points, triangles, quads,
2664 bandWidth, bandWidth,
true);
2672 inline std::ostream&
2675 ostr <<
"{[ " << rhs.
mXPrim <<
", " << rhs.
mXDist <<
"]";
2676 ostr <<
" [ " << rhs.
mYPrim <<
", " << rhs.
mYDist <<
"]";
2677 ostr <<
" [ " << rhs.
mZPrim <<
", " << rhs.
mZDist <<
"]}";
2682 inline MeshToVoxelEdgeData::EdgeData
2697 const std::vector<Vec3s>& pointList,
2698 const std::vector<Vec4I>& polygonList);
2700 void run(
bool threaded =
true);
2703 inline void operator() (
const tbb::blocked_range<size_t> &range);
2711 struct Primitive {
Vec3d a, b, c, d;
Int32 index; };
2713 template<
bool IsQuad>
2714 inline void voxelize(
const Primitive&);
2716 template<
bool IsQuad>
2717 inline bool evalPrimitive(
const Coord&,
const Primitive&);
2719 inline bool rayTriangleIntersection(
const Vec3d& origin,
const Vec3d& dir,
2726 const std::vector<Vec3s>& mPointList;
2727 const std::vector<Vec4I>& mPolygonList;
2731 IntTreeT mLastPrimTree;
2738 const std::vector<Vec3s>& pointList,
2739 const std::vector<Vec4I>& polygonList)
2742 , mPointList(pointList)
2743 , mPolygonList(polygonList)
2745 , mLastPrimAccessor(mLastPrimTree)
2754 , mPointList(rhs.mPointList)
2755 , mPolygonList(rhs.mPolygonList)
2757 , mLastPrimAccessor(mLastPrimTree)
2766 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPolygonList.size()), *
this);
2768 (*this)(tbb::blocked_range<size_t>(0, mPolygonList.size()));
2777 typedef RootNodeType::NodeChainType NodeChainType;
2778 BOOST_STATIC_ASSERT(boost::mpl::size<NodeChainType>::value > 1);
2779 typedef boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
2787 for ( ; leafIt; ++leafIt) {
2788 ijk = leafIt->origin();
2794 mAccessor.addLeaf(rhs.mAccessor.
probeLeaf(ijk));
2795 InternalNodeType* node = rhs.mAccessor.
getNode<InternalNodeType>();
2797 rhs.mAccessor.
clear();
2807 if (!lhsLeafPt->isValueOn(offset)) {
2808 lhsLeafPt->setValueOn(offset, rhsValue);
2840 for (
size_t n = range.begin(); n < range.end(); ++n) {
2842 const Vec4I& verts = mPolygonList[n];
2844 prim.index =
Int32(n);
2845 prim.a =
Vec3d(mPointList[verts[0]]);
2846 prim.b =
Vec3d(mPointList[verts[1]]);
2847 prim.c =
Vec3d(mPointList[verts[2]]);
2850 prim.d =
Vec3d(mPointList[verts[3]]);
2851 voxelize<true>(prim);
2853 voxelize<false>(prim);
2859 template<
bool IsQuad>
2861 MeshToVoxelEdgeData::GenEdgeData::voxelize(
const Primitive& prim)
2863 std::deque<Coord> coordList;
2867 coordList.push_back(ijk);
2869 evalPrimitive<IsQuad>(ijk, prim);
2871 while (!coordList.empty()) {
2873 ijk = coordList.back();
2874 coordList.pop_back();
2876 for (
Int32 i = 0; i < 26; ++i) {
2877 nijk = ijk + util::COORD_OFFSETS[i];
2879 if (prim.index != mLastPrimAccessor.getValue(nijk)) {
2880 mLastPrimAccessor.setValue(nijk, prim.index);
2881 if(evalPrimitive<IsQuad>(nijk, prim)) coordList.push_back(nijk);
2888 template<
bool IsQuad>
2890 MeshToVoxelEdgeData::GenEdgeData::evalPrimitive(
const Coord& ijk,
const Primitive& prim)
2892 Vec3d uvw, org(ijk[0], ijk[1], ijk[2]);
2893 bool intersecting =
false;
2897 mAccessor.probeValue(ijk, edgeData);
2900 double dist = (org -
2903 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.c, prim.b, t)) {
2904 if (t < edgeData.mXDist) {
2905 edgeData.mXDist = t;
2906 edgeData.mXPrim = prim.index;
2907 intersecting =
true;
2911 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.c, prim.b, t)) {
2912 if (t < edgeData.mYDist) {
2913 edgeData.mYDist = t;
2914 edgeData.mYPrim = prim.index;
2915 intersecting =
true;
2919 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.c, prim.b, t)) {
2920 if (t < edgeData.mZDist) {
2921 edgeData.mZDist = t;
2922 edgeData.mZPrim = prim.index;
2923 intersecting =
true;
2929 double secondDist = (org -
2932 if (secondDist < dist) dist = secondDist;
2934 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.d, prim.c, t)) {
2935 if (t < edgeData.mXDist) {
2936 edgeData.mXDist = t;
2937 edgeData.mXPrim = prim.index;
2938 intersecting =
true;
2942 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.d, prim.c, t)) {
2943 if (t < edgeData.mYDist) {
2944 edgeData.mYDist = t;
2945 edgeData.mYPrim = prim.index;
2946 intersecting =
true;
2950 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.d, prim.c, t)) {
2951 if (t < edgeData.mZDist) {
2952 edgeData.mZDist = t;
2953 edgeData.mZPrim = prim.index;
2954 intersecting =
true;
2959 if (intersecting) mAccessor.setValue(ijk, edgeData);
2961 return (dist < 0.86602540378443861);
2966 MeshToVoxelEdgeData::GenEdgeData::rayTriangleIntersection(
2977 double divisor = s1.
dot(e1);
2978 if (!(std::abs(divisor) > 0.0))
return false;
2982 double inv_divisor = 1.0 / divisor;
2983 Vec3d d = origin - a;
2984 double b1 = d.
dot(s1) * inv_divisor;
2986 if (b1 < 0.0 || b1 > 1.0)
return false;
2989 double b2 = dir.
dot(s2) * inv_divisor;
2991 if (b2 < 0.0 || (b1 + b2) > 1.0)
return false;
2995 t = e2.dot(s2) * inv_divisor;
2996 return (t < 0.0) ?
false :
true;
3012 const std::vector<Vec3s>& pointList,
3013 const std::vector<Vec4I>& polygonList)
3027 std::vector<Vec3d>& points,
3028 std::vector<Index32>& primitives)
3038 point[0] = double(coord[0]) + data.
mXDist;
3039 point[1] = double(coord[1]);
3040 point[2] = double(coord[2]);
3042 points.push_back(point);
3043 primitives.push_back(data.
mXPrim);
3047 point[0] = double(coord[0]);
3048 point[1] = double(coord[1]) + data.
mYDist;
3049 point[2] = double(coord[2]);
3051 points.push_back(point);
3052 primitives.push_back(data.
mYPrim);
3056 point[0] = double(coord[0]);
3057 point[1] = double(coord[1]);
3058 point[2] = double(coord[2]) + data.
mZDist;
3060 points.push_back(point);
3061 primitives.push_back(data.
mZPrim);
3071 point[0] = double(coord[0]);
3072 point[1] = double(coord[1]) + data.
mYDist;
3073 point[2] = double(coord[2]);
3075 points.push_back(point);
3076 primitives.push_back(data.
mYPrim);
3080 point[0] = double(coord[0]);
3081 point[1] = double(coord[1]);
3082 point[2] = double(coord[2]) + data.
mZDist;
3084 points.push_back(point);
3085 primitives.push_back(data.
mZPrim);
3093 point[0] = double(coord[0]);
3094 point[1] = double(coord[1]) + data.
mYDist;
3095 point[2] = double(coord[2]);
3097 points.push_back(point);
3098 primitives.push_back(data.
mYPrim);
3107 point[0] = double(coord[0]) + data.
mXDist;
3108 point[1] = double(coord[1]);
3109 point[2] = double(coord[2]);
3111 points.push_back(point);
3112 primitives.push_back(data.
mXPrim);
3116 point[0] = double(coord[0]);
3117 point[1] = double(coord[1]) + data.
mYDist;
3118 point[2] = double(coord[2]);
3120 points.push_back(point);
3121 primitives.push_back(data.
mYPrim);
3131 point[0] = double(coord[0]) + data.
mXDist;
3132 point[1] = double(coord[1]);
3133 point[2] = double(coord[2]);
3135 points.push_back(point);
3136 primitives.push_back(data.
mXPrim);
3145 point[0] = double(coord[0]) + data.
mXDist;
3146 point[1] = double(coord[1]);
3147 point[2] = double(coord[2]);
3149 points.push_back(point);
3150 primitives.push_back(data.
mXPrim);
3154 point[0] = double(coord[0]);
3155 point[1] = double(coord[1]);
3156 point[2] = double(coord[2]) + data.
mZDist;
3158 points.push_back(point);
3159 primitives.push_back(data.
mZPrim);
3168 point[0] = double(coord[0]);
3169 point[1] = double(coord[1]);
3170 point[2] = double(coord[2]) + data.
mZDist;
3172 points.push_back(point);
3173 primitives.push_back(data.
mZPrim);
3183 #endif // OPENVDB_TOOLS_MESH_TO_VOLUME_HAS_BEEN_INCLUDED
OPENVDB_API const Index32 INVALID_IDX
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
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:303
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
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1021
void clear()
Remove all tiles from this tree and all nodes other than the root node.
Definition: Tree.h:517
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:143
virtual void clear()
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:392
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
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: util/Util.h:55
void clearAllAccessors()
Clear all registered accessors.
Definition: Tree.h:1327
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:117
Definition: Exceptions.h:87
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:170
Type Pow2(Type x)
Return .
Definition: Math.h:467
Index32 Index
Definition: Types.h:56
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
Definition: Vec3.h:228
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:655
Base class for tree-traversal iterators over tile and voxel values.
Definition: TreeIterator.h:658
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:461
Tree< typename RootNodeType::template ValueConverter< Int32 >::Type > Type
Definition: Tree.h:198
#define OPENVDB_VERSION_NAME
Definition: version.h:45
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:1559
const ValueT & getValue() const
Return the tile or voxel value to which this iterator is currently pointing.
Definition: TreeIterator.h:733
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
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
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:360
uint32_t Index32
Definition: Types.h:54
int32_t Int32
Definition: Types.h:58
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition: Tree.h:1650
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1211
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:158
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
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:317
Vec3< double > Vec3d
Definition: Vec3.h:605
RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:186
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, returns the point on abc clos...
Definition: Operators.h:152
math::Vec4< Index32 > Vec4I
Definition: Types.h:88
_RootNodeType RootNodeType
Definition: Tree.h:184
static Accessor::ValueType result(const Accessor &grid, const Coord &ijk)
Definition: Operators.h:260
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:217
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
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
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
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