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);
2309 voxelizer(pointList, polygonList, mInterrupter);
2315 mDistGrid->tree().merge(voxelizer.sqrDistTree());
2316 mIndexGrid->tree().merge(voxelizer.primIndexTree());
2317 mIntersectingVoxelsGrid->tree().merge(voxelizer.intersectionTree());
2320 if (!unsignedDistField) {
2324 internal::ContourTracer<FloatTreeT, InterruptT> trace(
2325 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2326 for (
int i = 0; i < mSignSweeps; ++i) {
2335 BoolTreeT signMaskTree(
false);
2338 internal::SignMask<FloatTreeT, InterruptT> signMaskOp(leafs,
2339 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2341 signMaskTree.merge(signMaskOp.signMaskTree());
2348 if(leafs.leafCount() == 0)
break;
2350 internal::PropagateSign<FloatTreeT, InterruptT> sign(leafs,
2351 mDistGrid->tree(), mIntersectingVoxelsGrid->tree(), mInterrupter);
2353 signMaskTree.clear();
2355 signMaskTree.merge(sign.signMaskTree());
2364 tree::LeafManager<BoolTreeT> leafs(mIntersectingVoxelsGrid->tree());
2367 internal::IntersectingVoxelSign<FloatTreeT> sign(pointList, polygonList,
2368 mDistGrid->tree(), mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2376 internal::IntersectingVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2377 mIndexGrid->tree(), mIntersectingVoxelsGrid->tree(), leafs);
2385 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2387 internal::ShellVoxelCleaner<FloatTreeT> cleaner(mDistGrid->tree(),
2388 leafs, mIndexGrid->tree(), mIntersectingVoxelsGrid->tree());
2396 inBandWidth = FloatValueT(0.0);
2399 if (mDistGrid->activeVoxelCount() == 0)
return;
2401 mIntersectingVoxelsGrid->clear();
2402 const FloatValueT voxelSize(mTransform->voxelSize()[0]);
2405 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2406 leafs.foreach(internal::SqrtAndScaleOp<FloatValueT>(voxelSize, unsignedDistField));
2411 if (!unsignedDistField) {
2412 mDistGrid->tree().getRootNode().setBackground(exBandWidth,
false);
2413 mDistGrid->tree().signedFloodFill(exBandWidth, -inBandWidth);
2419 const FloatValueT minWidth = voxelSize * 2.0;
2420 if (inBandWidth > minWidth || exBandWidth > minWidth) {
2423 BoolTreeT maskTree(
false);
2424 maskTree.topologyUnion(mDistGrid->tree());
2428 internal::LeafTopologyDiffOp<FloatTreeT> diffOp(mDistGrid->tree());
2432 float progress = 48, step = 0.0;
2435 2.0 * std::ceil((
std::max(inBandWidth, exBandWidth) - minWidth) / voxelSize);
2436 if (estimated <
double(maxIterations)) {
2437 maxIterations = unsigned(estimated);
2438 step = 42.0 / float(maxIterations);
2446 tree::LeafManager<BoolTreeT> leafs(maskTree);
2448 if (leafs.leafCount() == 0)
break;
2450 leafs.foreach(diffOp);
2452 internal::ExpandNB<FloatTreeT> expand(
2453 leafs, mDistGrid->tree(), mIndexGrid->tree(), maskTree,
2454 exBandWidth, inBandWidth, voxelSize, pointList, polygonList);
2458 if ((++count) >= maxIterations)
break;
2470 if (!unsignedDistField) {
2472 mDistGrid->tree().pruneLevelSet();
2473 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree(), 1);
2475 const FloatValueT offset = 0.8 * voxelSize;
2478 internal::OffsetOp<FloatValueT> offsetOp(-offset);
2480 leafs.foreach(offsetOp);
2484 leafs.foreach(internal::RenormOp<FloatGridT, FloatValueT>(*mDistGrid, leafs, voxelSize));
2486 leafs.foreach(internal::MinOp<FloatTreeT, FloatValueT>(leafs));
2490 offsetOp.resetOffset(offset - internal::Tolerance<FloatValueT>::epsilon());
2491 leafs.foreach(offsetOp);
2496 const FloatValueT minTrimWidth = voxelSize * 4.0;
2497 if (inBandWidth < minTrimWidth || exBandWidth < minTrimWidth) {
2503 tree::LeafManager<FloatTreeT> leafs(mDistGrid->tree());
2504 leafs.foreach(internal::TrimOp<FloatValueT>(
2505 exBandWidth, unsignedDistField ? exBandWidth : inBandWidth));
2510 mDistGrid->tree().pruneLevelSet();
2511 mDistGrid->tree().signedFloodFill(exBandWidth, -inBandWidth);
2519 template<
typename Gr
idType>
2520 inline typename boost::enable_if<boost::is_floating_point<typename GridType::ValueType>,
2521 typename GridType::Ptr>::type
2523 const openvdb::math::Transform& xform,
2524 const std::vector<Vec3s>& points,
2525 const std::vector<Vec3I>& triangles,
2526 const std::vector<Vec4I>& quads,
2529 bool unsignedDistanceField =
false)
2531 std::vector<Vec3s> indexSpacePoints(points.size());
2539 std::vector<Vec4I> primitives(triangles.size() + quads.size());
2541 for (
size_t n = 0, N = triangles.size(); n < N; ++n) {
2542 Vec4I& prim = primitives[n];
2543 const Vec3I& triangle = triangles[n];
2544 prim[0] = triangle[0];
2545 prim[1] = triangle[1];
2546 prim[2] = triangle[2];
2550 for (
size_t n = 0, N = quads.size(); n < N; ++n) {
2551 primitives[n + triangles.size()] = quads[n];
2554 typename GridType::ValueType exWidth(exBandWidth);
2555 typename GridType::ValueType inWidth(inBandWidth);
2561 if (!unsignedDistanceField) {
2573 template<
typename Gr
idType>
2574 inline typename boost::disable_if<boost::is_floating_point<typename GridType::ValueType>,
2575 typename GridType::Ptr>::type
2578 const std::vector<Vec3s>& ,
2579 const std::vector<Vec3I>& ,
2580 const std::vector<Vec4I>& ,
2583 bool unsignedDistanceField =
false)
2586 "mesh to volume conversion is supported only for scalar, floating-point grids");
2593 template<
typename Gr
idType>
2594 inline typename GridType::Ptr
2596 const openvdb::math::Transform& xform,
2597 const std::vector<Vec3s>& points,
2598 const std::vector<Vec3I>& triangles,
2601 std::vector<Vec4I> quads(0);
2602 return doMeshConversion<GridType>(xform, points, triangles, quads,
2603 halfWidth, halfWidth);
2607 template<
typename Gr
idType>
2608 inline typename GridType::Ptr
2610 const openvdb::math::Transform& xform,
2611 const std::vector<Vec3s>& points,
2612 const std::vector<Vec4I>& quads,
2615 std::vector<Vec3I> triangles(0);
2616 return doMeshConversion<GridType>(xform, points, triangles, quads,
2617 halfWidth, halfWidth);
2621 template<
typename Gr
idType>
2622 inline typename GridType::Ptr
2624 const openvdb::math::Transform& xform,
2625 const std::vector<Vec3s>& points,
2626 const std::vector<Vec3I>& triangles,
2627 const std::vector<Vec4I>& quads,
2630 return doMeshConversion<GridType>(xform, points, triangles, quads,
2631 halfWidth, halfWidth);
2635 template<
typename Gr
idType>
2636 inline typename GridType::Ptr
2638 const openvdb::math::Transform& xform,
2639 const std::vector<Vec3s>& points,
2640 const std::vector<Vec3I>& triangles,
2641 const std::vector<Vec4I>& quads,
2645 return doMeshConversion<GridType>(xform, points, triangles,
2646 quads, exBandWidth, inBandWidth);
2650 template<
typename Gr
idType>
2651 inline typename GridType::Ptr
2653 const openvdb::math::Transform& xform,
2654 const std::vector<Vec3s>& points,
2655 const std::vector<Vec3I>& triangles,
2656 const std::vector<Vec4I>& quads,
2659 return doMeshConversion<GridType>(xform, points, triangles, quads,
2660 bandWidth, bandWidth,
true);
2668 inline std::ostream&
2671 ostr <<
"{[ " << rhs.
mXPrim <<
", " << rhs.
mXDist <<
"]";
2672 ostr <<
" [ " << rhs.
mYPrim <<
", " << rhs.
mYDist <<
"]";
2673 ostr <<
" [ " << rhs.
mZPrim <<
", " << rhs.
mZDist <<
"]}";
2678 inline MeshToVoxelEdgeData::EdgeData
2693 const std::vector<Vec3s>& pointList,
2694 const std::vector<Vec4I>& polygonList);
2696 void run(
bool threaded =
true);
2699 inline void operator() (
const tbb::blocked_range<size_t> &range);
2707 struct Primitive {
Vec3d a, b, c, d;
Int32 index; };
2709 template<
bool IsQuad>
2710 inline void voxelize(
const Primitive&);
2712 template<
bool IsQuad>
2713 inline bool evalPrimitive(
const Coord&,
const Primitive&);
2715 inline bool rayTriangleIntersection(
const Vec3d& origin,
const Vec3d& dir,
2722 const std::vector<Vec3s>& mPointList;
2723 const std::vector<Vec4I>& mPolygonList;
2727 IntTreeT mLastPrimTree;
2734 const std::vector<Vec3s>& pointList,
2735 const std::vector<Vec4I>& polygonList)
2738 , mPointList(pointList)
2739 , mPolygonList(polygonList)
2741 , mLastPrimAccessor(mLastPrimTree)
2750 , mPointList(rhs.mPointList)
2751 , mPolygonList(rhs.mPolygonList)
2753 , mLastPrimAccessor(mLastPrimTree)
2762 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPolygonList.size()), *
this);
2764 (*this)(tbb::blocked_range<size_t>(0, mPolygonList.size()));
2773 typedef RootNodeType::NodeChainType NodeChainType;
2774 BOOST_STATIC_ASSERT(boost::mpl::size<NodeChainType>::value > 1);
2775 typedef boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
2783 for ( ; leafIt; ++leafIt) {
2784 ijk = leafIt->origin();
2790 mAccessor.addLeaf(rhs.mAccessor.
probeLeaf(ijk));
2791 InternalNodeType* node = rhs.mAccessor.
getNode<InternalNodeType>();
2793 rhs.mAccessor.
clear();
2803 if (!lhsLeafPt->isValueOn(offset)) {
2804 lhsLeafPt->setValueOn(offset, rhsValue);
2836 for (
size_t n = range.begin(); n < range.end(); ++n) {
2838 const Vec4I& verts = mPolygonList[n];
2840 prim.index =
Int32(n);
2841 prim.a =
Vec3d(mPointList[verts[0]]);
2842 prim.b =
Vec3d(mPointList[verts[1]]);
2843 prim.c =
Vec3d(mPointList[verts[2]]);
2846 prim.d =
Vec3d(mPointList[verts[3]]);
2847 voxelize<true>(prim);
2849 voxelize<false>(prim);
2855 template<
bool IsQuad>
2857 MeshToVoxelEdgeData::GenEdgeData::voxelize(
const Primitive& prim)
2859 std::deque<Coord> coordList;
2863 coordList.push_back(ijk);
2865 evalPrimitive<IsQuad>(ijk, prim);
2867 while (!coordList.empty()) {
2869 ijk = coordList.back();
2870 coordList.pop_back();
2872 for (
Int32 i = 0; i < 26; ++i) {
2873 nijk = ijk + util::COORD_OFFSETS[i];
2875 if (prim.index != mLastPrimAccessor.getValue(nijk)) {
2876 mLastPrimAccessor.setValue(nijk, prim.index);
2877 if(evalPrimitive<IsQuad>(nijk, prim)) coordList.push_back(nijk);
2884 template<
bool IsQuad>
2886 MeshToVoxelEdgeData::GenEdgeData::evalPrimitive(
const Coord& ijk,
const Primitive& prim)
2888 Vec3d uvw, org(ijk[0], ijk[1], ijk[2]);
2889 bool intersecting =
false;
2893 mAccessor.probeValue(ijk, edgeData);
2896 double dist = (org -
2899 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.c, prim.b, t)) {
2900 if (t < edgeData.mXDist) {
2901 edgeData.mXDist = t;
2902 edgeData.mXPrim = prim.index;
2903 intersecting =
true;
2907 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.c, prim.b, t)) {
2908 if (t < edgeData.mYDist) {
2909 edgeData.mYDist = t;
2910 edgeData.mYPrim = prim.index;
2911 intersecting =
true;
2915 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.c, prim.b, t)) {
2916 if (t < edgeData.mZDist) {
2917 edgeData.mZDist = t;
2918 edgeData.mZPrim = prim.index;
2919 intersecting =
true;
2925 double secondDist = (org -
2928 if (secondDist < dist) dist = secondDist;
2930 if (rayTriangleIntersection(org,
Vec3d(1.0, 0.0, 0.0), prim.a, prim.d, prim.c, t)) {
2931 if (t < edgeData.mXDist) {
2932 edgeData.mXDist = t;
2933 edgeData.mXPrim = prim.index;
2934 intersecting =
true;
2938 if (rayTriangleIntersection(org,
Vec3d(0.0, 1.0, 0.0), prim.a, prim.d, prim.c, t)) {
2939 if (t < edgeData.mYDist) {
2940 edgeData.mYDist = t;
2941 edgeData.mYPrim = prim.index;
2942 intersecting =
true;
2946 if (rayTriangleIntersection(org,
Vec3d(0.0, 0.0, 1.0), prim.a, prim.d, prim.c, t)) {
2947 if (t < edgeData.mZDist) {
2948 edgeData.mZDist = t;
2949 edgeData.mZPrim = prim.index;
2950 intersecting =
true;
2955 if (intersecting) mAccessor.setValue(ijk, edgeData);
2957 return (dist < 0.86602540378443861);
2962 MeshToVoxelEdgeData::GenEdgeData::rayTriangleIntersection(
2973 double divisor = s1.
dot(e1);
2974 if (!(std::abs(divisor) > 0.0))
return false;
2978 double inv_divisor = 1.0 / divisor;
2979 Vec3d d = origin - a;
2980 double b1 = d.
dot(s1) * inv_divisor;
2982 if (b1 < 0.0 || b1 > 1.0)
return false;
2985 double b2 = dir.
dot(s2) * inv_divisor;
2987 if (b2 < 0.0 || (b1 + b2) > 1.0)
return false;
2991 t = e2.dot(s2) * inv_divisor;
2992 return (t < 0.0) ?
false :
true;
3008 const std::vector<Vec3s>& pointList,
3009 const std::vector<Vec4I>& polygonList)
3023 std::vector<Vec3d>& points,
3024 std::vector<Index32>& primitives)
3034 point[0] = double(coord[0]) + data.
mXDist;
3035 point[1] = double(coord[1]);
3036 point[2] = double(coord[2]);
3038 points.push_back(point);
3039 primitives.push_back(data.
mXPrim);
3043 point[0] = double(coord[0]);
3044 point[1] = double(coord[1]) + data.
mYDist;
3045 point[2] = double(coord[2]);
3047 points.push_back(point);
3048 primitives.push_back(data.
mYPrim);
3052 point[0] = double(coord[0]);
3053 point[1] = double(coord[1]);
3054 point[2] = double(coord[2]) + data.
mZDist;
3056 points.push_back(point);
3057 primitives.push_back(data.
mZPrim);
3067 point[0] = double(coord[0]);
3068 point[1] = double(coord[1]) + data.
mYDist;
3069 point[2] = double(coord[2]);
3071 points.push_back(point);
3072 primitives.push_back(data.
mYPrim);
3076 point[0] = double(coord[0]);
3077 point[1] = double(coord[1]);
3078 point[2] = double(coord[2]) + data.
mZDist;
3080 points.push_back(point);
3081 primitives.push_back(data.
mZPrim);
3089 point[0] = double(coord[0]);
3090 point[1] = double(coord[1]) + data.
mYDist;
3091 point[2] = double(coord[2]);
3093 points.push_back(point);
3094 primitives.push_back(data.
mYPrim);
3103 point[0] = double(coord[0]) + data.
mXDist;
3104 point[1] = double(coord[1]);
3105 point[2] = double(coord[2]);
3107 points.push_back(point);
3108 primitives.push_back(data.
mXPrim);
3112 point[0] = double(coord[0]);
3113 point[1] = double(coord[1]) + data.
mYDist;
3114 point[2] = double(coord[2]);
3116 points.push_back(point);
3117 primitives.push_back(data.
mYPrim);
3127 point[0] = double(coord[0]) + data.
mXDist;
3128 point[1] = double(coord[1]);
3129 point[2] = double(coord[2]);
3131 points.push_back(point);
3132 primitives.push_back(data.
mXPrim);
3141 point[0] = double(coord[0]) + data.
mXDist;
3142 point[1] = double(coord[1]);
3143 point[2] = double(coord[2]);
3145 points.push_back(point);
3146 primitives.push_back(data.
mXPrim);
3150 point[0] = double(coord[0]);
3151 point[1] = double(coord[1]);
3152 point[2] = double(coord[2]) + data.
mZDist;
3154 points.push_back(point);
3155 primitives.push_back(data.
mZPrim);
3164 point[0] = double(coord[0]);
3165 point[1] = double(coord[1]);
3166 point[2] = double(coord[2]) + data.
mZDist;
3168 points.push_back(point);
3169 primitives.push_back(data.
mZPrim);
3179 #endif // OPENVDB_TOOLS_MESH_TO_VOLUME_HAS_BEEN_INCLUDED
RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:186
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.
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
const ValueT & getValue() const
Return the tile or voxel value to which this iterator is currently pointing.
Definition: TreeIterator.h:733
OPENVDB_API const Index32 INVALID_IDX
NodeType * getNode()
Return the cached node of type NodeType. [Mainly for internal use].
Definition: ValueAccessor.h:303
int32_t Int32
Definition: Types.h:58
math::Vec4< Index32 > Vec4I
Definition: Types.h:88
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
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1211
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
_RootNodeType RootNodeType
Definition: Tree.h:184
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:648
uint32_t Index32
Definition: Types.h:54
virtual void clear()
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:392
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
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
Type Pow2(Type x)
Return .
Definition: Math.h:460
static Accessor::ValueType result(const Accessor &grid, const Coord &ijk)
Definition: Operators.h:260
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
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...
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:461
#define OPENVDB_VERSION_NAME
Definition: version.h:45
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
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Tree< typename RootNodeType::template ValueConverter< Int32 >::Type > Type
Definition: Tree.h:198
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
void clear()
Remove all tiles from this tree and all nodes other than the root node.
Definition: Tree.h:517
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: util/Util.h:55
Vec3< double > Vec3d
Definition: Vec3.h:605
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:117
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:353
void clearAllAccessors()
Clear all registered accessors.
Definition: Tree.h:1327
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:143
Index32 Index
Definition: Types.h:56
Definition: Operators.h:152
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1021
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
Definition: Exceptions.h:87
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:56
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:158
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
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition: Tree.h:1650
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
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
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
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
Definition: Vec3.h:228
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:170