31 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
34 #include <openvdb/tree/ValueAccessor.h>
35 #include <openvdb/tools/ValueTransformer.h>
36 #include <openvdb/util/Util.h>
37 #include <openvdb/math/Operators.h>
39 #include <openvdb/tools/Morphology.h>
40 #include <boost/scoped_array.hpp>
41 #include <boost/intrusive/slist.hpp>
43 #include <tbb/mutex.h>
44 #include <tbb/tick_count.h>
45 #include <tbb/blocked_range.h>
49 #include <boost/scoped_ptr.hpp>
76 , mTriangleFlags(NULL)
80 void resetQuads(
size_t size)
84 mQuadFlags.reset(
new char[mNumQuads]);
91 mQuadFlags.reset(NULL);
94 void resetTriangles(
size_t size)
98 mTriangleFlags.reset(
new char[mNumTriangles]);
101 void clearTriangles()
104 mTriangles.reset(NULL);
105 mTriangleFlags.reset(NULL);
108 const size_t&
numQuads()
const {
return mNumQuads; }
120 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
126 size_t mNumQuads, mNumTriangles;
127 boost::scoped_array<openvdb::Vec4I> mQuads;
128 boost::scoped_array<openvdb::Vec3I> mTriangles;
129 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
150 VolumeToMesh(
double isovalue = 0,
double adaptivity = 0);
153 const size_t& pointListSize()
const;
157 const size_t& polygonPoolListSize()
const;
161 template<
typename Gr
idT>
162 void operator()(
const GridT&);
189 template<
typename Gr
idT>
197 size_t mPointListSize, mPolygonPoolListSize;
198 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
253 template<
class AccessorT>
255 typename AccessorT::ValueType isovalue,
int dim)
259 if (accessor.getValue(coord) < isovalue) signs |= 1u;
261 if (accessor.getValue(coord) < isovalue) signs |= 2u;
263 if (accessor.getValue(coord) < isovalue) signs |= 4u;
265 if (accessor.getValue(coord) < isovalue) signs |= 8u;
266 coord[1] += dim; coord[2] = ijk[2];
267 if (accessor.getValue(coord) < isovalue) signs |= 16u;
269 if (accessor.getValue(coord) < isovalue) signs |= 32u;
271 if (accessor.getValue(coord) < isovalue) signs |= 64u;
273 if (accessor.getValue(coord) < isovalue) signs |= 128u;
278 template<
class AccessorT>
281 typename AccessorT::ValueType isovalue,
const int dim)
287 p[0] = accessor.getValue(coord) < isovalue;
289 p[1] = accessor.getValue(coord) < isovalue;
291 p[2] = accessor.getValue(coord) < isovalue;
293 p[3] = accessor.getValue(coord) < isovalue;
294 coord[1] += dim; coord[2] = ijk[2];
295 p[4] = accessor.getValue(coord) < isovalue;
297 p[5] = accessor.getValue(coord) < isovalue;
299 p[6] = accessor.getValue(coord) < isovalue;
301 p[7] = accessor.getValue(coord) < isovalue;
305 if (p[0]) signs |= 1u;
306 if (p[1]) signs |= 2u;
307 if (p[2]) signs |= 4u;
308 if (p[3]) signs |= 8u;
309 if (p[4]) signs |= 16u;
310 if (p[5]) signs |= 32u;
311 if (p[6]) signs |= 64u;
312 if (p[7]) signs |= 128u;
318 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
319 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
320 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
323 coord.
reset(ip, j, k);
324 m = accessor.getValue(coord) < isovalue;
325 if (p[0] != m && p[1] != m)
return true;
328 coord.
reset(ipp, j, kp);
329 m = accessor.getValue(coord) < isovalue;
330 if (p[1] != m && p[2] != m)
return true;
333 coord.
reset(ip, j, kpp);
334 m = accessor.getValue(coord) < isovalue;
335 if (p[2] != m && p[3] != m)
return true;
338 coord.
reset(i, j, kp);
339 m = accessor.getValue(coord) < isovalue;
340 if (p[0] != m && p[3] != m)
return true;
343 coord.
reset(ip, jpp, k);
344 m = accessor.getValue(coord) < isovalue;
345 if (p[4] != m && p[5] != m)
return true;
348 coord.
reset(ipp, jpp, kp);
349 m = accessor.getValue(coord) < isovalue;
350 if (p[5] != m && p[6] != m)
return true;
353 coord.
reset(ip, jpp, kpp);
354 m = accessor.getValue(coord) < isovalue;
355 if (p[6] != m && p[7] != m)
return true;
358 coord.
reset(i, jpp, kp);
359 m = accessor.getValue(coord) < isovalue;
360 if (p[7] != m && p[4] != m)
return true;
363 coord.
reset(i, jp, k);
364 m = accessor.getValue(coord) < isovalue;
365 if (p[0] != m && p[4] != m)
return true;
368 coord.
reset(ipp, jp, k);
369 m = accessor.getValue(coord) < isovalue;
370 if (p[1] != m && p[5] != m)
return true;
373 coord.
reset(ipp, jp, kpp);
374 m = accessor.getValue(coord) < isovalue;
375 if (p[2] != m && p[6] != m)
return true;
379 coord.
reset(i, jp, kpp);
380 m = accessor.getValue(coord) < isovalue;
381 if (p[3] != m && p[7] != m)
return true;
387 coord.
reset(ip, jp, k);
388 m = accessor.getValue(coord) < isovalue;
389 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
392 coord.
reset(ipp, jp, kp);
393 m = accessor.getValue(coord) < isovalue;
394 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
397 coord.
reset(ip, jp, kpp);
398 m = accessor.getValue(coord) < isovalue;
399 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
402 coord.
reset(i, jp, kp);
403 m = accessor.getValue(coord) < isovalue;
404 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
407 coord.
reset(ip, j, kp);
408 m = accessor.getValue(coord) < isovalue;
409 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
412 coord.
reset(ip, jpp, kp);
413 m = accessor.getValue(coord) < isovalue;
414 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
417 coord.
reset(ip, jp, kp);
418 m = accessor.getValue(coord) < isovalue;
419 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
420 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
429 template <
class LeafType>
433 Coord ijk, end = start;
438 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
439 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
440 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
441 if(leaf.isValueOn(ijk)) leaf.setValue(ijk, regionId);
450 template <
class LeafType>
453 typename LeafType::ValueType::value_type adaptivity)
455 if (adaptivity < 1e-6)
return false;
457 typedef typename LeafType::ValueType VecT;
458 Coord ijk, end = start;
463 std::vector<VecT> norms;
464 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
465 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
466 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
468 if(!leaf.isValueOn(ijk))
continue;
469 norms.push_back(leaf.getValue(ijk));
474 size_t N = norms.size();
475 for (
size_t ni = 0; ni < N; ++ni) {
476 VecT n_i = norms[ni];
477 for (
size_t nj = 0; nj < N; ++nj) {
478 VecT n_j = norms[nj];
479 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
489 template <
class TreeT>
493 typedef std::vector<const typename TreeT::LeafNodeType *>
ListT;
497 mLeafNodes.reserve(tree.leafCount());
498 typename TreeT::LeafCIter iter = tree.cbeginLeaf();
499 for ( ; iter; ++iter) mLeafNodes.push_back(iter.getLeaf());
502 size_t size()
const {
return mLeafNodes.size(); }
504 const typename TreeT::LeafNodeType* operator[](
size_t n)
const
505 {
return mLeafNodes[n]; }
507 tbb::blocked_range<size_t> getRange()
const
508 {
return tbb::blocked_range<size_t>(0, mLeafNodes.size()); }
517 template <
class TreeT>
521 typedef std::vector<typename TreeT::LeafNodeType *>
ListT;
525 mLeafNodes.reserve(tree.leafCount());
526 typename TreeT::LeafIter iter = tree.beginLeaf();
527 for ( ; iter; ++iter) mLeafNodes.push_back(iter.getLeaf());
530 size_t size()
const {
return mLeafNodes.size(); }
532 typename TreeT::LeafNodeType* operator[](
size_t n)
const
533 {
return mLeafNodes[n]; }
535 tbb::blocked_range<size_t> getRange()
const
536 {
return tbb::blocked_range<size_t>(0, mLeafNodes.size()); }
548 template<
typename DistTreeT>
552 typedef typename DistTreeT::template ValueConverter<char>::Type
CharTreeT;
553 typedef typename DistTreeT::template ValueConverter<bool>::Type
BoolTreeT;
558 , mTopologyMaskTree(NULL)
559 , mSeamMaskTree(typename
BoolTreeT::Ptr())
566 return mDistTree && mEdgeTree && mTopologyMaskTree && mSeamMaskTree;
580 template <
class DistTreeT>
590 inline void operator()(
const tbb::blocked_range<size_t>&)
const;
593 std::vector<size_t>& mLeafRegionCount;
597 template <
class DistTreeT>
600 std::vector<size_t>& leafRegionCount)
602 , mLeafRegionCount(leafRegionCount)
607 template <
class DistTreeT>
610 : mLeafNodes(rhs.mLeafNodes)
611 , mLeafRegionCount(rhs.mLeafRegionCount)
616 template <
class DistTreeT>
620 tbb::parallel_for(mLeafNodes.getRange(), *
this);
624 template <
class DistTreeT>
628 (*this)(mLeafNodes.getRange());
632 template <
class DistTreeT>
636 for (
size_t n = range.begin(); n != range.end(); ++n) {
637 mLeafRegionCount[n] = size_t(mLeafNodes[n]->onVoxelCount());
645 template <
class DistTreeT>
650 typedef typename DistTreeT::template ValueConverter<bool>::Type
BoolTreeT;
651 typedef typename DistTreeT::template ValueConverter<int>::Type
IntTreeT;
654 const DistTreeT& distTree,
656 std::vector<size_t>& leafRegionCount,
667 void operator()(
const tbb::blocked_range<size_t>&)
const;
670 const DistTreeT& mDistTree;
672 std::vector<size_t>& mLeafRegionCount;
678 template <
class DistTreeT>
680 const DistTreeT& distTree,
682 std::vector<size_t>& leafRegionCount,
685 : mDistTree(distTree)
686 , mAuxLeafs(auxLeafs)
687 , mLeafRegionCount(leafRegionCount)
689 , mAdaptivity(adaptivity)
695 template <
class DistTreeT>
698 : mDistTree(rhs.mDistTree)
699 , mAuxLeafs(rhs.mAuxLeafs)
700 , mLeafRegionCount(rhs.mLeafRegionCount)
701 , mIsovalue(rhs.mIsovalue)
702 , mAdaptivity(rhs.mAdaptivity)
703 , mRefData(rhs.mRefData)
708 template <
class DistTreeT>
712 tbb::parallel_for(mAuxLeafs.getRange(), *
this);
716 template <
class DistTreeT>
720 (*this)(mAuxLeafs.getRange());
723 template <
class DistTreeT>
730 template <
class DistTreeT>
735 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
736 typedef typename IntTreeT::LeafNodeType IntLeafT;
737 typedef typename BoolLeafT::template ValueConverter<Vec3T>::Type Vec3LeafT;
739 typedef typename IntLeafT::ValueOnIter IntIterT;
740 typedef typename BoolLeafT::ValueOnCIter BoolCIterT;
745 boost::scoped_ptr<BoolTreeAccessorT> seamMaskAcc;
746 boost::scoped_ptr<BoolTreeCAccessorT> topologyMaskAcc;
747 if (mRefData && mRefData->isValid()) {
748 seamMaskAcc.reset(
new BoolTreeAccessorT(*mRefData->mSeamMaskTree.get()));
749 topologyMaskAcc.reset(
new BoolTreeCAccessorT(*mRefData->mTopologyMaskTree));
751 const bool hasRefData = seamMaskAcc && topologyMaskAcc;
753 const int LeafDim = BoolLeafT::DIM;
758 Vec3LeafT gradientBuffer;
759 Coord ijk, coord, end;
761 for (
size_t n = range.begin(); n != range.end(); ++n) {
764 IntLeafT& auxLeaf = *mAuxLeafs[n];
766 const Coord& origin = auxLeaf.getOrigin();
767 end[0] = origin[0] + LeafDim;
768 end[1] = origin[1] + LeafDim;
769 end[2] = origin[2] + LeafDim;
775 const BoolLeafT* seamMask = seamMaskAcc->probeConstLeaf(origin);
776 if (seamMask != NULL) {
777 for (BoolCIterT it = seamMask->cbeginValueOn(); it; ++it) {
779 coord[0] = ijk[0] - (ijk[0] % 2);
780 coord[1] = ijk[1] - (ijk[1] % 2);
781 coord[2] = ijk[2] - (ijk[2] % 2);
782 mask.setActiveState(coord,
true);
785 if (topologyMaskAcc->probeConstLeaf(origin) == NULL) {
786 adaptivity = mRefData->mInternalAdaptivity;
791 for (IntIterT it = auxLeaf.beginValueOn(); it; ++it) {
793 coord[0] = ijk[0] - (ijk[0] % 2);
794 coord[1] = ijk[1] - (ijk[1] % 2);
795 coord[2] = ijk[2] - (ijk[2] % 2);
796 if(mask.isValueOn(coord))
continue;
797 mask.setActiveState(coord,
isAmbiguous(distAcc, ijk, mIsovalue, 1));
802 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
803 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
804 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
806 mask.setActiveState(ijk,
true);
813 gradientBuffer.setValuesOff();
815 for (IntIterT it = auxLeaf.beginValueOn(); it; ++it) {
818 coord[0] = ijk[0] - (ijk[0] % dim);
819 coord[1] = ijk[1] - (ijk[1] % dim);
820 coord[2] = ijk[2] - (ijk[2] % dim);
821 if(mask.isValueOn(coord))
continue;
829 gradientBuffer.setValue(ijk, norm);
832 int regionId = 1, next_dim = dim << 1;
835 for (ijk[0] = 0; ijk[0] < LeafDim; ijk[0] += dim) {
836 coord[0] = ijk[0] - (ijk[0] % next_dim);
837 for (ijk[1] = 0; ijk[1] < LeafDim; ijk[1] += dim) {
838 coord[1] = ijk[1] - (ijk[1] % next_dim);
839 for (ijk[2] = 0; ijk[2] < LeafDim; ijk[2] += dim) {
840 coord[2] = ijk[2] - (ijk[2] % next_dim);
841 if(mask.isValueOn(ijk) || !
isMergable(gradientBuffer, ijk, dim, adaptivity)) {
842 mask.setActiveState(coord,
true);
852 for (dim = 4; dim < LeafDim; dim = dim << 1) {
854 coord[0] = ijk[0] - (ijk[0] % next_dim);
855 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
856 coord[1] = ijk[1] - (ijk[1] % next_dim);
857 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
858 coord[2] = ijk[2] - (ijk[2] % next_dim);
859 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
861 if (mask.isValueOn(ijk) ||
isNonManifold(distAcc, ijk, mIsovalue, dim) ||
862 !
isMergable(gradientBuffer, ijk, dim, adaptivity)) {
863 mask.setActiveState(coord,
true);
873 if (!(mask.isValueOn(origin) ||
isNonManifold(distAcc, origin, mIsovalue, LeafDim))
874 &&
isMergable(gradientBuffer, origin, LeafDim, adaptivity)) {
880 size_t numVoxels = 0;
881 IntLeafT tmpLeaf(auxLeaf);
882 for (IntIterT it = tmpLeaf.beginValueOn(); it; ++it) {
883 if(it.getValue() == 0) {
889 while (tmpLeaf.onVoxelCount() > 0) {
891 IntIterT it = tmpLeaf.beginValueOn();
892 regionId = it.getValue();
894 if (it.getValue() == regionId) it.setValueOff();
898 mLeafRegionCount[n] = numVoxels;
906 template <
class DistTreeT>
912 typedef typename DistTreeT::template ValueConverter<int>::Type
IntTreeT;
915 const DistTreeT& distTree,
917 std::vector<size_t>& leafIndices,
918 const openvdb::math::Transform& xform,
929 void operator()(
const tbb::blocked_range<size_t>&)
const;
932 const DistTreeT& mDistTree;
934 const std::vector<size_t>& mLeafIndices;
935 const openvdb::math::Transform& mTransform;
937 const double mIsovalue;
940 double root(
double v0,
double v1)
const {
return (mIsovalue - v0) / (v1 - v0); }
945 template <
class DistTreeT>
947 const DistTreeT& distTree,
949 std::vector<size_t>& leafIndices,
950 const openvdb::math::Transform& xform,
953 : mDistTree(distTree)
954 , mAuxLeafs(auxLeafs)
955 , mLeafIndices(leafIndices)
964 template <
class DistTreeT>
966 : mDistTree(rhs.mDistTree)
967 , mAuxLeafs(rhs.mAuxLeafs)
968 , mLeafIndices(rhs.mLeafIndices)
969 , mTransform(rhs.mTransform)
970 , mPoints(rhs.mPoints)
971 , mIsovalue(rhs.mIsovalue)
972 , mRefData(rhs.mRefData)
977 template <
class DistTreeT>
985 template <
class DistTreeT>
989 tbb::parallel_for(mAuxLeafs.getRange(), *
this);
993 template <
class DistTreeT>
997 (*this)(mAuxLeafs.getRange());
1001 template <
class DistTreeT>
1005 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
1009 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
1010 typedef typename IntTreeT::LeafNodeType IntLeafT;
1013 boost::scoped_ptr<DistTreeAccessorT> refDistAcc;
1014 boost::scoped_ptr<BoolTreeAccessorT> refMaskAcc;
1016 if (mRefData && mRefData->isValid()) {
1018 refMaskAcc.reset(
new BoolTreeAccessorT(*mRefData->mTopologyMaskTree));
1022 const bool hasRefData = refDistAcc && refMaskAcc;
1023 typename IntTreeT::LeafNodeType::ValueOnIter auxIter;
1029 for (
size_t n = range.begin(); n != range.end(); ++n) {
1031 size_t idx = mLeafIndices[n];
1032 IntLeafT& auxLeaf = *mAuxLeafs[n];
1034 const BoolLeafT* maskLeaf = NULL;
1036 maskLeaf = refMaskAcc->probeConstLeaf(auxLeaf.getOrigin());
1039 for (auxIter = auxLeaf.beginValueOn(); auxIter; ++auxIter) {
1041 if(auxIter.getValue() == 0) {
1043 auxIter.setValue(idx);
1044 auxIter.setValueOff();
1045 ijk = auxIter.getCoord();
1047 if (hasRefData && maskLeaf && maskLeaf->isValueOn(ijk)) {
1048 calcAvgPoint(*refDistAcc.get(), ijk, avg);
1050 calcAvgPoint(distAcc, ijk, avg);
1054 avg[0] += double(ijk[0]);
1055 avg[1] += double(ijk[1]);
1056 avg[2] += double(ijk[2]);
1058 avg = mTransform.indexToWorld(avg);
1061 ptn[0] = float(avg[0]);
1062 ptn[1] = float(avg[1]);
1063 ptn[2] = float(avg[2]);
1069 while(auxLeaf.onVoxelCount() > 0) {
1075 auxIter = auxLeaf.beginValueOn();
1076 int regionId = auxIter.getValue(), points = 0;
1078 for (; auxIter; ++auxIter) {
1079 if(auxIter.getValue() == regionId) {
1081 auxIter.setValue(idx);
1082 auxIter.setValueOff();
1083 ijk = auxIter.getCoord();
1085 if (hasRefData && maskLeaf && maskLeaf->isValueOn(ijk)) {
1086 calcAvgPoint(*refDistAcc.get(), ijk, tmp);
1088 calcAvgPoint(distAcc, ijk, tmp);
1092 tmp[0] += double(ijk[0]);
1093 tmp[1] += double(ijk[1]);
1094 tmp[2] += double(ijk[2]);
1096 avg += mTransform.indexToWorld(tmp);
1102 double w = 1.0 / double(points);
1109 ptn[0] = float(avg[0]);
1110 ptn[1] = float(avg[1]);
1111 ptn[2] = float(avg[2]);
1117 template <
class DistTreeT>
1128 values[0] = double(acc.getValue(coord));
1131 values[1] = double(acc.getValue(coord));
1134 values[2] = double(acc.getValue(coord));
1137 values[3] = double(acc.getValue(coord));
1139 coord[1] += 1; coord[2] = ijk[2];
1140 values[4] = double(acc.getValue(coord));
1143 values[5] = double(acc.getValue(coord));
1146 values[6] = double(acc.getValue(coord));
1149 values[7] = double(acc.getValue(coord));
1152 for (
int n = 0; n < 8; ++n) signMask[n] = (values[n] < mIsovalue);
1154 int samples = 0, edgeFlags = 0;
1159 if (signMask[0] != signMask[1]) {
1160 avg[0] += root(values[0], values[1]);
1165 if (signMask[1] != signMask[2]) {
1167 avg[2] += root(values[1], values[2]);
1172 if (signMask[3] != signMask[2]) {
1173 avg[0] += root(values[3], values[2]);
1179 if (signMask[0] != signMask[3]) {
1180 avg[2] += root(values[0], values[3]);
1185 if (signMask[4] != signMask[5]) {
1186 avg[0] += root(values[4], values[5]);
1192 if (signMask[5] != signMask[6]) {
1195 avg[2] += root(values[5], values[6]);
1200 if (signMask[7] != signMask[6]) {
1201 avg[0] += root(values[7], values[6]);
1208 if (signMask[4] != signMask[7]) {
1210 avg[2] += root(values[4], values[7]);
1215 if (signMask[0] != signMask[4]) {
1216 avg[1] += root(values[0], values[4]);
1221 if (signMask[1] != signMask[5]) {
1223 avg[1] += root(values[1], values[5]);
1228 if (signMask[2] != signMask[6]) {
1230 avg[1] += root(values[2], values[6]);
1236 if (signMask[3] != signMask[7]) {
1237 avg[1] += root(values[3], values[7]);
1244 double w = 1.0 / double(samples);
1263 mPolygonPool = &quadPool;
1271 mPolygonPool->
quad(mIdx) = verts;
1293 AdaptiveMeshOp(): mQuadIdx(0), mTriangleIdx(0), mPolygonPool(NULL), mTmpPolygonPool() {}
1297 mPolygonPool = &polygonPool;
1308 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
1309 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
1310 mTmpPolygonPool.
quadFlags(mQuadIdx) = flags;
1311 addQuad(verts, reverse);
1313 verts[0] == verts[3] &&
1314 verts[1] != verts[2] &&
1315 verts[1] != verts[0] &&
1316 verts[2] != verts[0]) {
1318 addTriangle(verts[0], verts[1], verts[2], reverse);
1320 verts[1] == verts[2] &&
1321 verts[0] != verts[3] &&
1322 verts[0] != verts[1] &&
1323 verts[3] != verts[1]) {
1325 addTriangle(verts[0], verts[1], verts[3], reverse);
1327 verts[0] == verts[1] &&
1328 verts[2] != verts[3] &&
1329 verts[2] != verts[0] &&
1330 verts[3] != verts[0]) {
1332 addTriangle(verts[0], verts[2], verts[3], reverse);
1334 verts[2] == verts[3] &&
1335 verts[0] != verts[1] &&
1336 verts[0] != verts[2] &&
1337 verts[1] != verts[2]) {
1339 addTriangle(verts[0], verts[1], verts[2], reverse);
1347 for (
size_t i = 0; i < mQuadIdx; ++i) {
1348 mPolygonPool->
quad(i) = mTmpPolygonPool.
quad(i);
1354 for (
size_t i = 0; i < mTriangleIdx; ++i) {
1363 void addQuad(
const Vec4I& verts,
bool reverse)
1366 mTmpPolygonPool.
quad(mQuadIdx) = verts;
1368 Vec4I& quad = mTmpPolygonPool.
quad(mQuadIdx);
1377 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
1393 size_t mQuadIdx, mTriangleIdx;
1394 PolygonPool *mPolygonPool;
1395 PolygonPool mTmpPolygonPool;
1402 template<
class DistTreeT,
class MeshingOp>
1406 typedef typename DistTreeT::template ValueConverter<char>::Type
CharTreeT;
1407 typedef typename DistTreeT::template ValueConverter<int>::Type
IntTreeT;
1417 void operator()(
const tbb::blocked_range<size_t>&)
const;
1428 template<
class DistTreeT,
class MeshingOp>
1431 : mEdgeLeafs(edgeLeafs)
1433 , mPolygonPoolList(polygonPoolList)
1439 template<
class DistTreeT,
class MeshingOp>
1441 : mEdgeLeafs(rhs.mEdgeLeafs)
1442 , mAuxTree(rhs.mAuxTree)
1443 , mPolygonPoolList(rhs.mPolygonPoolList)
1444 , mRefData(rhs.mRefData)
1449 template<
class DistTreeT,
class MeshingOp>
1454 mRefData = &refData;
1458 template<
class DistTreeT,
class MeshingOp>
1462 tbb::parallel_for(mEdgeLeafs.getRange(), *
this);
1466 template<
class DistTreeT,
class MeshingOp>
1470 (*this)(mEdgeLeafs.getRange());
1474 template<
class DistTreeT,
class MeshingOp>
1477 const tbb::blocked_range<size_t>& range)
const
1479 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
1480 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
1481 typedef typename CharTreeT::LeafNodeType CharLeafT;
1483 typedef openvdb::tree::ValueAccessor<const CharTreeT> CharTreeAccessorT;
1484 typedef openvdb::tree::ValueAccessor<const IntTreeT> IntTreeAccessorT;
1485 typedef openvdb::tree::ValueAccessor<const BoolTreeT> BoolTreeAccessorT;
1487 boost::scoped_ptr<CharTreeAccessorT> refEdgeAcc;
1488 boost::scoped_ptr<BoolTreeAccessorT> refMaskAcc;
1489 if (mRefData && mRefData->isValid()) {
1490 refEdgeAcc.reset(
new CharTreeAccessorT(*mRefData->mEdgeTree));
1491 refMaskAcc.reset(
new BoolTreeAccessorT(*mRefData->mSeamMaskTree.get()));
1493 const bool hasRefData = refEdgeAcc && refMaskAcc;
1496 typename CharTreeT::LeafNodeType::ValueOnCIter iter;
1497 IntTreeAccessorT auxAcc(mAuxTree);
1500 char refEdgeFlags, isSemLinePoly;
1507 for (
size_t n = range.begin(); n != range.end(); ++n) {
1509 const Coord origin = mEdgeLeafs[n]->getOrigin();
1513 iter = mEdgeLeafs[n]->cbeginValueOn();
1514 for (; iter; ++iter) {
1515 char edgeFlags = iter.getValue() >> 1;
1516 edgeCount += edgeFlags & 0x1;
1518 edgeFlags = edgeFlags >> 1;
1519 edgeCount += edgeFlags & 0x1;
1521 edgeFlags = edgeFlags >> 1;
1522 edgeCount += edgeFlags & 0x1;
1525 mesher.init(edgeCount, mPolygonPoolList[n]);
1527 const CharLeafT* refEdgeLeaf = NULL;
1528 const BoolLeafT* refMaskLeaf = NULL;
1531 refEdgeLeaf = refEdgeAcc->probeConstLeaf(origin);
1532 refMaskLeaf = refMaskAcc->probeConstLeaf(origin);
1535 iter = mEdgeLeafs[n]->cbeginValueOn();
1536 for (; iter; ++iter) {
1537 ijk = iter.getCoord();
1538 const char& edgeFlags = iter.getValue();
1540 const bool isInside = edgeFlags &
INSIDE;
1545 if(refEdgeLeaf) refEdgeFlags = refEdgeLeaf->getValue(ijk);
1546 if (refMaskLeaf && refMaskLeaf->isValueOn(ijk)) {
1552 int v0 = auxAcc.getValue(ijk);
1554 if (edgeFlags &
XEDGE) {
1557 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1558 quad[1] = auxAcc.getValue(coord);
1560 quad[2] = auxAcc.getValue(coord);
1562 quad[3] = auxAcc.getValue(coord);
1564 mesher.addPrim(quad, isInside,
1565 (isSemLinePoly | isExteriorPoly[
bool(refEdgeFlags & XEDGE)]));
1569 if (edgeFlags &
YEDGE) {
1572 coord[0] = ijk[0]; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1573 quad[1] = auxAcc.getValue(coord);
1575 quad[2] = auxAcc.getValue(coord);
1577 quad[3] = auxAcc.getValue(coord);
1579 mesher.addPrim(quad, isInside,
1580 (isSemLinePoly | isExteriorPoly[
bool(refEdgeFlags & YEDGE)]));
1583 if (edgeFlags &
ZEDGE) {
1586 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1587 quad[1] = auxAcc.getValue(coord);
1589 quad[2] = auxAcc.getValue(coord);
1591 quad[3] = auxAcc.getValue(coord);
1593 mesher.addPrim(quad, !isInside,
1594 (isSemLinePoly | isExteriorPoly[
bool(refEdgeFlags & ZEDGE)]));
1606 template<
class DistTreeT,
class AuxDataT =
int>
1611 typedef typename DistTreeT::ValueType
ValueT;
1613 typedef typename DistTreeT::template ValueConverter<char>::Type
CharTreeT;
1616 typedef typename DistTreeT::template ValueConverter<AuxDataT>::Type
AuxTreeT;
1620 double iso = 0.0,
bool extraCheck =
false);
1626 typename CharTreeT::Ptr
edgeTree()
const {
return mEdgeTree; }
1627 typename AuxTreeT::Ptr
auxTree()
const {
return mAuxTree; }
1629 void operator()(
const tbb::blocked_range<size_t>&);
1633 mEdgeTree->merge(*rhs.mEdgeTree);
1634 mAuxTree->merge(*rhs.mAuxTree);
1639 const DistTreeT& mSourceTree;
1642 typename CharTreeT::Ptr mEdgeTree;
1645 typename AuxTreeT::Ptr mAuxTree;
1648 const double mIsovalue;
1649 const bool mExtraCheck;
1651 int edgeCheck(
const Coord& ijk,
const bool thisInside);
1654 template<
class DistTreeT,
class AuxDataT>
1657 : mLeafNodes(leafNodes)
1659 , mSourceAccessor(mSourceTree)
1661 , mEdgeAccessor(*mEdgeTree)
1662 , mAuxTree(new
AuxTreeT(AuxDataT(0)))
1663 , mAuxAccessor(*mAuxTree)
1665 , mExtraCheck(extraCheck)
1669 template<
class DistTreeT,
class AuxDataT>
1671 : mLeafNodes(rhs.mLeafNodes)
1672 , mSourceTree(rhs.mSourceTree)
1673 , mSourceAccessor(mSourceTree)
1675 , mEdgeAccessor(*mEdgeTree)
1676 , mAuxTree(new
AuxTreeT(AuxDataT(0)))
1677 , mAuxAccessor(*mAuxTree)
1678 , mIsovalue(rhs.mIsovalue)
1679 , mExtraCheck(rhs.mExtraCheck)
1685 template<
class DistTreeT,
typename AuxDataT>
1689 tbb::parallel_reduce(mLeafNodes.getRange(), *
this);
1692 template<
class DistTreeT,
typename AuxDataT>
1696 (*this)(mLeafNodes.getRange());
1699 template<
class DistTreeT,
typename AuxDataT>
1703 typename DistTreeT::LeafNodeType::ValueOnCIter iter;
1710 for (
size_t n = range.begin(); n != range.end(); ++n) {
1711 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
1712 ijk = iter.getCoord();
1713 thisInside = iter.getValue() < mIsovalue;
1714 edgeFlags = edgeCheck(ijk, thisInside);
1716 if (edgeFlags != 0) {
1717 edgeFlags |= int(thisInside);
1718 mEdgeAccessor.setValue(ijk,
char(edgeFlags));
1723 for (
size_t n = range.begin(); n != range.end(); ++n) {
1724 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
1726 ijk = iter.getCoord();
1727 thisInside = iter.getValue() < mIsovalue;
1728 edgeFlags = edgeCheck(ijk, thisInside);
1730 if (edgeFlags != 0) {
1731 edgeFlags |= int(thisInside);
1732 mEdgeAccessor.setValue(ijk,
char(edgeFlags));
1736 if (!mSourceAccessor.probeValue(ijk, val)) {
1737 thisInside = val < mIsovalue;
1738 edgeFlags = edgeCheck(ijk, thisInside);
1740 if (edgeFlags != 0) {
1741 edgeFlags |= int(thisInside);
1742 mEdgeAccessor.setValue(ijk,
char(edgeFlags));
1748 if (!mSourceAccessor.probeValue(ijk, val)) {
1749 thisInside = val < mIsovalue;
1750 edgeFlags = edgeCheck(ijk, thisInside);
1752 if (edgeFlags != 0) {
1753 edgeFlags |= int(thisInside);
1754 mEdgeAccessor.setValue(ijk,
char(edgeFlags));
1760 if (!mSourceAccessor.probeValue(ijk, val)) {
1761 thisInside = val < mIsovalue;
1762 edgeFlags = edgeCheck(ijk, thisInside);
1764 if (edgeFlags != 0) {
1765 edgeFlags |= int(thisInside);
1766 mEdgeAccessor.setValue(ijk,
char(edgeFlags));
1774 template<
class DistTreeT,
typename AuxDataT>
1782 n_ijk = ijk; ++n_ijk[0];
1783 bool otherInside = (mSourceAccessor.getValue(n_ijk) < mIsovalue);
1784 if (otherInside != thisInside) {
1788 mAuxAccessor.setActiveState(ijk,
true);
1790 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1791 mAuxAccessor.setActiveState(coord,
true);
1793 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2]-1;
1794 mAuxAccessor.setActiveState(coord,
true);
1796 coord[0] = ijk[0]; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1797 mAuxAccessor.setActiveState(coord,
true);
1801 n_ijk[0] = ijk[0]; ++n_ijk[1];
1802 otherInside = (mSourceAccessor.getValue(n_ijk) < mIsovalue);
1803 if (otherInside != thisInside) {
1807 mAuxAccessor.setActiveState(ijk,
true);
1809 coord[0] = ijk[0]; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1810 mAuxAccessor.setActiveState(coord,
true);
1812 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2];
1813 mAuxAccessor.setActiveState(coord,
true);
1815 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1816 mAuxAccessor.setActiveState(coord,
true);
1820 n_ijk[1] = ijk[1]; ++n_ijk[2];
1821 otherInside = (mSourceAccessor.getValue(n_ijk) < mIsovalue);
1822 if (otherInside != thisInside) {
1826 mAuxAccessor.setActiveState(ijk,
true);
1828 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1829 mAuxAccessor.setActiveState(coord,
true);
1831 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2];
1832 mAuxAccessor.setActiveState(coord,
true);
1834 coord[0] = ijk[0]-1; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1835 mAuxAccessor.setActiveState(coord,
true);
1844 template <
class DistTreeT>
1848 typedef typename DistTreeT::template ValueConverter<bool>::Type
BoolTreeT;
1849 typedef typename DistTreeT::template ValueConverter<int>::Type
IntTreeT;
1861 void operator()(
const tbb::blocked_range<size_t>&)
const;
1872 template <
class DistTreeT>
1875 : mSeamMaskLeafs(seamMaskLeafs)
1876 , mTopologyMaskTree(topologyMaskTree)
1877 , mTopologyMaskAcc(mTopologyMaskTree)
1883 template <
class DistTreeT>
1885 : mSeamMaskLeafs(rhs.mSeamMaskLeafs)
1886 , mTopologyMaskTree(rhs.mTopologyMaskTree)
1887 , mTopologyMaskAcc(mTopologyMaskTree)
1888 , mAuxTree(rhs.mAuxTree)
1893 template <
class DistTreeT>
1897 tbb::parallel_for(mSeamMaskLeafs.getRange(), *
this);
1900 template <
class DistTreeT>
1904 (*this)(mSeamMaskLeafs.getRange());
1907 template <
class DistTreeT>
1911 typedef typename BoolTreeT::LeafNodeType::ValueOnIter ValueOnIterT;
1913 for (
size_t leafIdx = range.begin(); leafIdx != range.end(); ++leafIdx) {
1914 ValueOnIterT it = mSeamMaskLeafs[leafIdx]->beginValueOn();
1916 ijk = it.getCoord();
1917 if (!mTopologyMaskAcc.isValueOn(ijk)) {
1920 bool turnOff =
true;
1921 for (
size_t n = 0; n < 6; ++n) {
1923 if (!mAuxTree.isValueOn(n_ijk) && mTopologyMaskAcc.isValueOn(n_ijk)) {
1928 if (turnOff) it.setValueOff();
1938 template<
class CharAccessorT,
typename AuxAccessorT>
1943 : mEdgeAcc(edgeAcc), mAuxAcc(auxAcc) {}
1948 mEdgeAcc.setValue(ijk, edgeFlags |
XEDGE);
1950 mAuxAcc.setActiveState(ijk,
true);
1953 coord[1] = ijk[1]-1;
1954 mAuxAcc.setActiveState(coord,
true);
1956 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2]-1;
1957 mAuxAcc.setActiveState(coord,
true);
1959 coord[0] = ijk[0]; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1960 mAuxAcc.setActiveState(coord,
true);
1965 mEdgeAcc.setValue(ijk, edgeFlags |
YEDGE);
1967 mAuxAcc.setActiveState(ijk,
true);
1970 coord[2] = ijk[2]-1;
1971 mAuxAcc.setActiveState(coord,
true);
1973 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2];
1974 mAuxAcc.setActiveState(coord,
true);
1976 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
1977 mAuxAcc.setActiveState(coord,
true);
1982 mEdgeAcc.setValue(ijk, edgeFlags |
ZEDGE);
1984 mAuxAcc.setActiveState(ijk,
true);
1987 coord[1] = ijk[1]-1;
1988 mAuxAcc.setActiveState(coord,
true);
1990 coord[0] = ijk[0]-1; coord[1] = ijk[1]; coord[2] = ijk[2];
1991 mAuxAcc.setActiveState(coord,
true);
1993 coord[0] = ijk[0]-1; coord[1] = ijk[1]-1; coord[2] = ijk[2];
1994 mAuxAcc.setActiveState(coord,
true);
1998 CharAccessorT& mEdgeAcc;
1999 AuxAccessorT& mAuxAcc;
2006 template<
class DistTreeT,
class AuxTreeT,
class CharTreeT>
2009 const DistTreeT& distTree, CharTreeT& edgeTree, AuxTreeT& auxTree,
2016 typename DistTreeT::ValueType isoValue =
typename DistTreeT::ValueType(iso);
2018 DistAccessorT distAcc(distTree);
2019 CharTreeAccessorT edgeAcc(edgeTree);
2020 AuxTreeAccessorT auxAcc(auxTree);
2025 typename DistTreeT::ValueType value;
2027 bool processTileFace;
2029 typename DistTreeT::ValueOnCIter tileIter(distTree);
2030 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
2032 for ( ; tileIter; ++tileIter) {
2033 tileIter.getBoundingBox(bbox);
2035 const bool thisInside = (distAcc.getValue(bbox.
min()) < isoValue);
2036 const int thisDepth = distAcc.getValueDepth(bbox.
min());
2045 processTileFace =
true;
2046 if (thisDepth >= distAcc.getValueDepth(nijk)) {
2047 processTileFace = thisInside != (distAcc.getValue(nijk) < isoValue);
2050 if (processTileFace) {
2051 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
2053 for (ijk[2] = bbox.
min()[2]; ijk[2] <= bbox.
max()[2]; ++ijk[2]) {
2055 if ((distAcc.getValue(nijk) < isoValue) != thisInside) {
2056 auxData.
setXEdge(edgeAcc.getValue(ijk) | char(thisInside), ijk);
2065 processTileFace =
true;
2066 if (thisDepth >= distAcc.getValueDepth(ijk)) {
2067 processTileFace = !distAcc.probeValue(ijk, value) && thisInside != (value < isoValue);
2070 if (processTileFace) {
2071 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
2072 for (ijk[2] = bbox.
min()[2]; ijk[2] <= bbox.
max()[2]; ++ijk[2]) {
2073 if (!distAcc.probeValue(ijk, value) && (value < isoValue) != thisInside) {
2074 auxData.
setXEdge(edgeAcc.getValue(ijk) | char(!thisInside), ijk);
2087 processTileFace =
true;
2088 if (thisDepth >= distAcc.getValueDepth(nijk)) {
2089 processTileFace = thisInside != (distAcc.getValue(nijk) < isoValue);
2092 if (processTileFace) {
2093 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
2095 for (ijk[2] = bbox.
min()[2]; ijk[2] <= bbox.
max()[2]; ++ijk[2]) {
2098 if ((distAcc.getValue(nijk) < isoValue) != thisInside) {
2099 auxData.
setYEdge(edgeAcc.getValue(ijk) | char(thisInside), ijk);
2109 processTileFace =
true;
2110 if (thisDepth >= distAcc.getValueDepth(ijk)) {
2111 processTileFace = !distAcc.probeValue(ijk, value) && thisInside != (value < isoValue);
2114 if (processTileFace) {
2115 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
2116 for (ijk[2] = bbox.
min()[2]; ijk[2] <= bbox.
max()[2]; ++ijk[2]) {
2118 if (!distAcc.probeValue(ijk, value) && (value < isoValue) != thisInside) {
2119 auxData.
setYEdge(edgeAcc.getValue(ijk) | char(!thisInside), ijk);
2132 processTileFace =
true;
2133 if (thisDepth >= distAcc.getValueDepth(nijk)) {
2134 processTileFace = thisInside != (distAcc.getValue(nijk) < isoValue);
2137 if (processTileFace) {
2138 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
2140 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
2143 if ((distAcc.getValue(nijk) < isoValue) != thisInside) {
2144 auxData.
setZEdge(edgeAcc.getValue(ijk) | char(thisInside), ijk);
2153 processTileFace =
true;
2154 if (thisDepth >= distAcc.getValueDepth(ijk)) {
2155 processTileFace = !distAcc.probeValue(ijk, value) && thisInside != (value < isoValue);
2158 if (processTileFace) {
2159 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
2160 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
2162 if (!distAcc.probeValue(ijk, value) && (value < isoValue) != thisInside) {
2163 auxData.
setZEdge(edgeAcc.getValue(ijk) | char(!thisInside), ijk);
2180 , mPolygonPoolListSize(0)
2181 , mIsovalue(isovalue)
2182 , mPrimAdaptivity(adaptivity)
2183 , mSecAdaptivity(0.0)
2186 , mRefTopologyMaskTree(
TreeBase::Ptr())
2196 inline const size_t&
2199 return mPointListSize;
2217 inline const size_t&
2220 return mPolygonPoolListSize;
2228 mSecAdaptivity = secAdaptivity;
2235 template<
typename Gr
idT>
2239 typedef typename GridT::TreeType DistTreeT;
2240 typedef typename DistTreeT::ValueType DistValueT;
2242 typedef typename DistTreeT::template ValueConverter<char>::Type CharTreeT;
2243 typedef typename DistTreeT::template ValueConverter<int>::Type IntTreeT;
2244 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
2246 const bool noAdaptivity = mPrimAdaptivity < 1e-6 && mSecAdaptivity < 1e-6;
2248 const openvdb::math::Transform& transform = distGrid.transform();
2249 const DistTreeT& distTree = distGrid.tree();
2250 typename CharTreeT::Ptr edgeTree;
2251 typename IntTreeT::Ptr auxTree;
2253 const bool nonLevelSetGrid = distGrid.getGridClass() !=
GRID_LEVEL_SET;
2255 const bool extraSignCheck = nonLevelSetGrid ||
2256 (std::abs(mIsovalue -
double(distGrid.background())) < (1.5 * transform.voxelSize()[0]));
2268 if (nonLevelSetGrid) {
2276 const GridT* refGrid =
static_cast<const GridT*
>(mRefGrid.get());
2277 if (refGrid && refGrid->activeVoxelCount() > 0) {
2283 if (!mRefEdgeTree && !mRefTopologyMaskTree) {
2286 *refData.
mDistTree, leafs, mIsovalue, extraSignCheck);
2289 mRefTopologyMaskTree = op.
auxTree();
2292 if (mRefEdgeTree && mRefTopologyMaskTree) {
2293 refData.
mEdgeTree =
static_cast<CharTreeT*
>(mRefEdgeTree.get());
2294 refData.
mTopologyMaskTree =
static_cast<BoolTreeT*
>(mRefTopologyMaskTree.get());
2295 refData.
mSeamMaskTree =
typename BoolTreeT::Ptr(
new BoolTreeT(
false));
2317 std::vector<size_t> regions(auxLeafs.
size(), 0);
2325 regions, DistValueT(mIsovalue), DistValueT(mPrimAdaptivity));
2332 for (
size_t n = 0, N = regions.size(); n < N; ++n) {
2334 regions[n] = mPointListSize;
2335 mPointListSize += tmp;
2343 pointGen(distTree, auxLeafs, regions, transform, mPoints, mIsovalue);
2351 mPolygonPoolListSize = edgeLeafs.
size();
2352 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
2356 meshGen(edgeLeafs, *auxTree, mPolygons);
2361 meshGen(edgeLeafs, *auxTree, mPolygons);
2372 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED