37 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 40 #include <openvdb/Platform.h> 41 #include <openvdb/math/Operators.h> 42 #include <openvdb/tree/ValueAccessor.h> 43 #include <openvdb/util/Util.h> 45 #include <boost/integer_traits.hpp> 46 #include <boost/scoped_array.hpp> 48 #include <tbb/blocked_range.h> 49 #include <tbb/parallel_for.h> 50 #include <tbb/parallel_reduce.h> 51 #include <tbb/task_scheduler_init.h> 57 #include <type_traits> 81 template<
typename Gr
idType>
85 std::vector<Vec3s>& points,
86 std::vector<Vec4I>& quads,
87 double isovalue = 0.0);
102 template<
typename Gr
idType>
105 const GridType& grid,
106 std::vector<Vec3s>& points,
107 std::vector<Vec3I>& triangles,
108 std::vector<Vec4I>& quads,
109 double isovalue = 0.0,
110 double adaptivity = 0.0,
127 inline PolygonPool(
const size_t numQuads,
const size_t numTriangles);
131 inline void resetQuads(
size_t size);
132 inline void clearQuads();
134 inline void resetTriangles(
size_t size);
135 inline void clearTriangles();
140 const size_t&
numQuads()
const {
return mNumQuads; }
155 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
164 inline bool trimQuads(
const size_t n,
bool reallocate =
false);
165 inline bool trimTrinagles(
const size_t n,
bool reallocate =
false);
171 size_t mNumQuads, mNumTriangles;
172 boost::scoped_array<openvdb::Vec4I> mQuads;
173 boost::scoped_array<openvdb::Vec3I> mTriangles;
174 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
212 const std::vector<uint8_t>&
pointFlags()
const {
return mPointFlags; }
221 template<
typename InputGr
idType>
222 void operator()(
const InputGridType&);
275 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
276 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
283 bool mInvertSurfaceMask, mRelaxDisorientedTriangles;
285 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
286 std::vector<uint8_t> mPointFlags;
300 const std::vector<Vec3d>& points,
301 const std::vector<Vec3d>& normals)
307 if (points.empty())
return avgPos;
309 for (
size_t n = 0, N = points.size(); n < N; ++n) {
313 avgPos /= double(points.size());
317 double m00=0,m01=0,m02=0,
324 for (
size_t n = 0, N = points.size(); n < N; ++n) {
326 const Vec3d& n_ref = normals[n];
329 m00 += n_ref[0] * n_ref[0];
330 m11 += n_ref[1] * n_ref[1];
331 m22 += n_ref[2] * n_ref[2];
333 m01 += n_ref[0] * n_ref[1];
334 m02 += n_ref[0] * n_ref[2];
335 m12 += n_ref[1] * n_ref[2];
338 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
363 Mat3d D = Mat3d::identity();
366 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
367 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
371 for (
int i = 0; i < 3; ++i ) {
372 if (std::abs(eigenValues[i]) < tolerance) {
376 D[i][i] = 1.0 / eigenValues[i];
383 return avgPos + pseudoInv * rhs;
397 namespace volume_to_mesh_internal {
399 template<
typename ValueType>
402 FillArray(ValueType* array,
const ValueType& v) : mArray(array), mValue(v) { }
404 void operator()(
const tbb::blocked_range<size_t>& range)
const {
405 const ValueType v = mValue;
406 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
416 template<
typename ValueType>
418 fillArray(ValueType* array,
const ValueType& val,
const size_t length)
420 const auto grainSize = std::max<size_t>(
421 length / tbb::task_scheduler_init::default_num_threads(), 1024);
422 const tbb::blocked_range<size_t> range(0, length, grainSize);
434 1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,
435 1,0,1,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,0,1,
436 1,0,0,0,1,0,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
437 1,0,1,1,1,0,1,1,0,0,0,0,1,0,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,1,
438 1,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,0,1,0,0,0,0,1,1,0,1,1,1,0,1,
439 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,1,0,0,0,1,
440 1,0,0,0,1,0,1,0,1,1,0,0,1,1,1,1,1,1,0,0,1,0,0,0,1,1,0,0,1,1,0,1,
441 1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1};
446 0,0,0,0,0,5,0,0,0,0,5,0,0,0,0,0,0,0,1,0,0,5,1,0,4,0,0,0,4,0,0,0,
447 0,1,0,0,2,0,0,0,0,1,5,0,2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0,
448 0,0,2,2,0,5,0,0,3,3,0,0,0,0,0,0,6,6,0,0,6,0,0,0,0,0,0,0,0,0,0,0,
449 0,1,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
450 0,4,0,4,3,0,3,0,0,0,5,0,0,0,0,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,
451 6,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
452 0,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
453 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
460 {0,0,0,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,0,0,0,0,1,0,0,0},{1,1,1,0,0,0,0,0,0,0,1,0,0},
461 {1,0,1,0,1,0,0,0,0,1,1,0,0},{1,0,1,1,0,0,0,0,0,0,0,1,0},{1,1,1,1,1,0,0,0,0,1,0,1,0},
462 {1,1,0,1,0,0,0,0,0,0,1,1,0},{1,0,0,1,1,0,0,0,0,1,1,1,0},{1,0,0,1,1,0,0,0,0,0,0,0,1},
463 {1,1,0,1,0,0,0,0,0,1,0,0,1},{1,1,1,1,1,0,0,0,0,0,1,0,1},{1,0,1,1,0,0,0,0,0,1,1,0,1},
464 {1,0,1,0,1,0,0,0,0,0,0,1,1},{1,1,1,0,0,0,0,0,0,1,0,1,1},{1,1,0,0,1,0,0,0,0,0,1,1,1},
465 {1,0,0,0,0,0,0,0,0,1,1,1,1},{1,0,0,0,0,1,0,0,1,1,0,0,0},{1,1,0,0,1,1,0,0,1,0,0,0,0},
466 {1,1,1,0,0,1,0,0,1,1,1,0,0},{1,0,1,0,1,1,0,0,1,0,1,0,0},{2,0,1,1,0,2,0,0,2,2,0,1,0},
467 {1,1,1,1,1,1,0,0,1,0,0,1,0},{1,1,0,1,0,1,0,0,1,1,1,1,0},{1,0,0,1,1,1,0,0,1,0,1,1,0},
468 {1,0,0,1,1,1,0,0,1,1,0,0,1},{1,1,0,1,0,1,0,0,1,0,0,0,1},{2,2,1,1,2,1,0,0,1,2,1,0,1},
469 {1,0,1,1,0,1,0,0,1,0,1,0,1},{1,0,1,0,1,1,0,0,1,1,0,1,1},{1,1,1,0,0,1,0,0,1,0,0,1,1},
470 {2,1,0,0,1,2,0,0,2,1,2,2,2},{1,0,0,0,0,1,0,0,1,0,1,1,1},{1,0,0,0,0,1,1,0,0,0,1,0,0},
471 {1,1,0,0,1,1,1,0,0,1,1,0,0},{1,1,1,0,0,1,1,0,0,0,0,0,0},{1,0,1,0,1,1,1,0,0,1,0,0,0},
472 {1,0,1,1,0,1,1,0,0,0,1,1,0},{2,2,2,1,1,1,1,0,0,1,2,1,0},{1,1,0,1,0,1,1,0,0,0,0,1,0},
473 {1,0,0,1,1,1,1,0,0,1,0,1,0},{2,0,0,2,2,1,1,0,0,0,1,0,2},{1,1,0,1,0,1,1,0,0,1,1,0,1},
474 {1,1,1,1,1,1,1,0,0,0,0,0,1},{1,0,1,1,0,1,1,0,0,1,0,0,1},{1,0,1,0,1,1,1,0,0,0,1,1,1},
475 {2,1,1,0,0,2,2,0,0,2,1,2,2},{1,1,0,0,1,1,1,0,0,0,0,1,1},{1,0,0,0,0,1,1,0,0,1,0,1,1},
476 {1,0,0,0,0,0,1,0,1,1,1,0,0},{1,1,0,0,1,0,1,0,1,0,1,0,0},{1,1,1,0,0,0,1,0,1,1,0,0,0},
477 {1,0,1,0,1,0,1,0,1,0,0,0,0},{1,0,1,1,0,0,1,0,1,1,1,1,0},{2,1,1,2,2,0,2,0,2,0,1,2,0},
478 {1,1,0,1,0,0,1,0,1,1,0,1,0},{1,0,0,1,1,0,1,0,1,0,0,1,0},{1,0,0,1,1,0,1,0,1,1,1,0,1},
479 {1,1,0,1,0,0,1,0,1,0,1,0,1},{2,1,2,2,1,0,2,0,2,1,0,0,2},{1,0,1,1,0,0,1,0,1,0,0,0,1},
480 {2,0,2,0,2,0,1,0,1,2,2,1,1},{2,2,2,0,0,0,1,0,1,0,2,1,1},{2,2,0,0,2,0,1,0,1,2,0,1,1},
481 {1,0,0,0,0,0,1,0,1,0,0,1,1},{1,0,0,0,0,0,1,1,0,0,0,1,0},{2,1,0,0,1,0,2,2,0,1,0,2,0},
482 {1,1,1,0,0,0,1,1,0,0,1,1,0},{1,0,1,0,1,0,1,1,0,1,1,1,0},{1,0,1,1,0,0,1,1,0,0,0,0,0},
483 {1,1,1,1,1,0,1,1,0,1,0,0,0},{1,1,0,1,0,0,1,1,0,0,1,0,0},{1,0,0,1,1,0,1,1,0,1,1,0,0},
484 {1,0,0,1,1,0,1,1,0,0,0,1,1},{1,1,0,1,0,0,1,1,0,1,0,1,1},{2,1,2,2,1,0,1,1,0,0,1,2,1},
485 {2,0,1,1,0,0,2,2,0,2,2,1,2},{1,0,1,0,1,0,1,1,0,0,0,0,1},{1,1,1,0,0,0,1,1,0,1,0,0,1},
486 {1,1,0,0,1,0,1,1,0,0,1,0,1},{1,0,0,0,0,0,1,1,0,1,1,0,1},{1,0,0,0,0,1,1,1,1,1,0,1,0},
487 {1,1,0,0,1,1,1,1,1,0,0,1,0},{2,1,1,0,0,2,2,1,1,1,2,1,0},{2,0,2,0,2,1,1,2,2,0,1,2,0},
488 {1,0,1,1,0,1,1,1,1,1,0,0,0},{2,2,2,1,1,2,2,1,1,0,0,0,0},{2,2,0,2,0,1,1,2,2,2,1,0,0},
489 {2,0,0,1,1,2,2,1,1,0,2,0,0},{2,0,0,1,1,1,1,2,2,1,0,1,2},{2,2,0,2,0,2,2,1,1,0,0,2,1},
490 {4,3,2,2,3,4,4,1,1,3,4,2,1},{3,0,2,2,0,1,1,3,3,0,1,2,3},{2,0,2,0,2,2,2,1,1,2,0,0,1},
491 {2,1,1,0,0,1,1,2,2,0,0,0,2},{3,1,0,0,1,2,2,3,3,1,2,0,3},{2,0,0,0,0,1,1,2,2,0,1,0,2},
492 {1,0,0,0,0,1,0,1,0,0,1,1,0},{1,1,0,0,1,1,0,1,0,1,1,1,0},{1,1,1,0,0,1,0,1,0,0,0,1,0},
493 {1,0,1,0,1,1,0,1,0,1,0,1,0},{1,0,1,1,0,1,0,1,0,0,1,0,0},{2,1,1,2,2,2,0,2,0,2,1,0,0},
494 {1,1,0,1,0,1,0,1,0,0,0,0,0},{1,0,0,1,1,1,0,1,0,1,0,0,0},{1,0,0,1,1,1,0,1,0,0,1,1,1},
495 {2,2,0,2,0,1,0,1,0,1,2,2,1},{2,2,1,1,2,2,0,2,0,0,0,1,2},{2,0,2,2,0,1,0,1,0,1,0,2,1},
496 {1,0,1,0,1,1,0,1,0,0,1,0,1},{2,2,2,0,0,1,0,1,0,1,2,0,1},{1,1,0,0,1,1,0,1,0,0,0,0,1},
497 {1,0,0,0,0,1,0,1,0,1,0,0,1},{1,0,0,0,0,0,0,1,1,1,1,1,0},{1,1,0,0,1,0,0,1,1,0,1,1,0},
498 {1,1,1,0,0,0,0,1,1,1,0,1,0},{1,0,1,0,1,0,0,1,1,0,0,1,0},{1,0,1,1,0,0,0,1,1,1,1,0,0},
499 {2,2,2,1,1,0,0,1,1,0,2,0,0},{1,1,0,1,0,0,0,1,1,1,0,0,0},{1,0,0,1,1,0,0,1,1,0,0,0,0},
500 {2,0,0,2,2,0,0,1,1,2,2,2,1},{2,1,0,1,0,0,0,2,2,0,1,1,2},{3,2,1,1,2,0,0,3,3,2,0,1,3},
501 {2,0,1,1,0,0,0,2,2,0,0,1,2},{2,0,1,0,1,0,0,2,2,1,1,0,2},{2,1,1,0,0,0,0,2,2,0,1,0,2},
502 {2,1,0,0,1,0,0,2,2,1,0,0,2},{1,0,0,0,0,0,0,1,1,0,0,0,1},{1,0,0,0,0,0,0,1,1,0,0,0,1},
503 {1,1,0,0,1,0,0,1,1,1,0,0,1},{2,1,1,0,0,0,0,2,2,0,1,0,2},{1,0,1,0,1,0,0,1,1,1,1,0,1},
504 {1,0,1,1,0,0,0,1,1,0,0,1,1},{2,1,1,2,2,0,0,1,1,1,0,1,2},{1,1,0,1,0,0,0,1,1,0,1,1,1},
505 {2,0,0,1,1,0,0,2,2,2,2,2,1},{1,0,0,1,1,0,0,1,1,0,0,0,0},{1,1,0,1,0,0,0,1,1,1,0,0,0},
506 {1,1,1,1,1,0,0,1,1,0,1,0,0},{1,0,1,1,0,0,0,1,1,1,1,0,0},{1,0,1,0,1,0,0,1,1,0,0,1,0},
507 {1,1,1,0,0,0,0,1,1,1,0,1,0},{1,1,0,0,1,0,0,1,1,0,1,1,0},{1,0,0,0,0,0,0,1,1,1,1,1,0},
508 {1,0,0,0,0,1,0,1,0,1,0,0,1},{1,1,0,0,1,1,0,1,0,0,0,0,1},{1,1,1,0,0,1,0,1,0,1,1,0,1},
509 {1,0,1,0,1,1,0,1,0,0,1,0,1},{1,0,1,1,0,1,0,1,0,1,0,1,1},{2,2,2,1,1,2,0,2,0,0,0,2,1},
510 {2,1,0,1,0,2,0,2,0,1,2,2,1},{2,0,0,2,2,1,0,1,0,0,1,1,2},{1,0,0,1,1,1,0,1,0,1,0,0,0},
511 {1,1,0,1,0,1,0,1,0,0,0,0,0},{2,1,2,2,1,2,0,2,0,1,2,0,0},{1,0,1,1,0,1,0,1,0,0,1,0,0},
512 {1,0,1,0,1,1,0,1,0,1,0,1,0},{1,1,1,0,0,1,0,1,0,0,0,1,0},{2,2,0,0,2,1,0,1,0,2,1,1,0},
513 {1,0,0,0,0,1,0,1,0,0,1,1,0},{1,0,0,0,0,1,1,1,1,0,1,0,1},{2,1,0,0,1,2,1,1,2,2,1,0,1},
514 {1,1,1,0,0,1,1,1,1,0,0,0,1},{2,0,2,0,2,1,2,2,1,1,0,0,2},{2,0,1,1,0,1,2,2,1,0,1,2,1},
515 {4,1,1,3,3,2,4,4,2,2,1,4,3},{2,2,0,2,0,2,1,1,2,0,0,1,2},{3,0,0,1,1,2,3,3,2,2,0,3,1},
516 {1,0,0,1,1,1,1,1,1,0,1,0,0},{2,2,0,2,0,1,2,2,1,1,2,0,0},{2,2,1,1,2,2,1,1,2,0,0,0,0},
517 {2,0,1,1,0,2,1,1,2,2,0,0,0},{2,0,2,0,2,2,1,1,2,0,2,1,0},{3,1,1,0,0,3,2,2,3,3,1,2,0},
518 {2,1,0,0,1,1,2,2,1,0,0,2,0},{2,0,0,0,0,2,1,1,2,2,0,1,0},{1,0,0,0,0,0,1,1,0,1,1,0,1},
519 {1,1,0,0,1,0,1,1,0,0,1,0,1},{1,1,1,0,0,0,1,1,0,1,0,0,1},{1,0,1,0,1,0,1,1,0,0,0,0,1},
520 {2,0,2,2,0,0,1,1,0,2,2,1,2},{3,1,1,2,2,0,3,3,0,0,1,3,2},{2,1,0,1,0,0,2,2,0,1,0,2,1},
521 {2,0,0,1,1,0,2,2,0,0,0,2,1},{1,0,0,1,1,0,1,1,0,1,1,0,0},{1,1,0,1,0,0,1,1,0,0,1,0,0},
522 {2,2,1,1,2,0,1,1,0,2,0,0,0},{1,0,1,1,0,0,1,1,0,0,0,0,0},{2,0,1,0,1,0,2,2,0,1,1,2,0},
523 {2,1,1,0,0,0,2,2,0,0,1,2,0},{2,1,0,0,1,0,2,2,0,1,0,2,0},{1,0,0,0,0,0,1,1,0,0,0,1,0},
524 {1,0,0,0,0,0,1,0,1,0,0,1,1},{1,1,0,0,1,0,1,0,1,1,0,1,1},{1,1,1,0,0,0,1,0,1,0,1,1,1},
525 {2,0,2,0,2,0,1,0,1,1,1,2,2},{1,0,1,1,0,0,1,0,1,0,0,0,1},{2,2,2,1,1,0,2,0,2,2,0,0,1},
526 {1,1,0,1,0,0,1,0,1,0,1,0,1},{2,0,0,2,2,0,1,0,1,1,1,0,2},{1,0,0,1,1,0,1,0,1,0,0,1,0},
527 {1,1,0,1,0,0,1,0,1,1,0,1,0},{2,2,1,1,2,0,2,0,2,0,2,1,0},{2,0,2,2,0,0,1,0,1,1,1,2,0},
528 {1,0,1,0,1,0,1,0,1,0,0,0,0},{1,1,1,0,0,0,1,0,1,1,0,0,0},{1,1,0,0,1,0,1,0,1,0,1,0,0},
529 {1,0,0,0,0,0,1,0,1,1,1,0,0},{1,0,0,0,0,1,1,0,0,1,0,1,1},{1,1,0,0,1,1,1,0,0,0,0,1,1},
530 {2,2,2,0,0,1,1,0,0,2,1,2,2},{2,0,1,0,1,2,2,0,0,0,2,1,1},{1,0,1,1,0,1,1,0,0,1,0,0,1},
531 {2,1,1,2,2,1,1,0,0,0,0,0,2},{2,1,0,1,0,2,2,0,0,1,2,0,1},{2,0,0,2,2,1,1,0,0,0,1,0,2},
532 {1,0,0,1,1,1,1,0,0,1,0,1,0},{1,1,0,1,0,1,1,0,0,0,0,1,0},{3,1,2,2,1,3,3,0,0,1,3,2,0},
533 {2,0,1,1,0,2,2,0,0,0,2,1,0},{1,0,1,0,1,1,1,0,0,1,0,0,0},{1,1,1,0,0,1,1,0,0,0,0,0,0},
534 {2,2,0,0,2,1,1,0,0,2,1,0,0},{1,0,0,0,0,1,1,0,0,0,1,0,0},{1,0,0,0,0,1,0,0,1,0,1,1,1},
535 {2,2,0,0,2,1,0,0,1,1,2,2,2},{1,1,1,0,0,1,0,0,1,0,0,1,1},{2,0,1,0,1,2,0,0,2,2,0,1,1},
536 {1,0,1,1,0,1,0,0,1,0,1,0,1},{3,1,1,3,3,2,0,0,2,2,1,0,3},{1,1,0,1,0,1,0,0,1,0,0,0,1},
537 {2,0,0,2,2,1,0,0,1,1,0,0,2},{1,0,0,1,1,1,0,0,1,0,1,1,0},{2,1,0,1,0,2,0,0,2,2,1,1,0},
538 {2,1,2,2,1,1,0,0,1,0,0,2,0},{2,0,1,1,0,2,0,0,2,2,0,1,0},{1,0,1,0,1,1,0,0,1,0,1,0,0},
539 {2,1,1,0,0,2,0,0,2,2,1,0,0},{1,1,0,0,1,1,0,0,1,0,0,0,0},{1,0,0,0,0,1,0,0,1,1,0,0,0},
540 {1,0,0,0,0,0,0,0,0,1,1,1,1},{1,1,0,0,1,0,0,0,0,0,1,1,1},{1,1,1,0,0,0,0,0,0,1,0,1,1},
541 {1,0,1,0,1,0,0,0,0,0,0,1,1},{1,0,1,1,0,0,0,0,0,1,1,0,1},{2,1,1,2,2,0,0,0,0,0,1,0,2},
542 {1,1,0,1,0,0,0,0,0,1,0,0,1},{1,0,0,1,1,0,0,0,0,0,0,0,1},{1,0,0,1,1,0,0,0,0,1,1,1,0},
543 {1,1,0,1,0,0,0,0,0,0,1,1,0},{2,1,2,2,1,0,0,0,0,1,0,2,0},{1,0,1,1,0,0,0,0,0,0,0,1,0},
544 {1,0,1,0,1,0,0,0,0,1,1,0,0},{1,1,1,0,0,0,0,0,0,0,1,0,0},{1,1,0,0,1,0,0,0,0,1,0,0,0},
545 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
554 double epsilon = 0.001)
557 Vec3d normal = (p2-p0).cross(p1-p3);
559 const Vec3d centroid = (p0 + p1 + p2 + p3);
560 const double d = centroid.
dot(normal) * 0.25;
564 double absDist = std::abs(p0.dot(normal) - d);
565 if (absDist > epsilon)
return false;
567 absDist = std::abs(p1.dot(normal) - d);
568 if (absDist > epsilon)
return false;
570 absDist = std::abs(p2.dot(normal) - d);
571 if (absDist > epsilon)
return false;
573 absDist = std::abs(p3.dot(normal) - d);
574 if (absDist > epsilon)
return false;
598 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
599 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
614 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
616 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
640 template<
typename AccessorT>
645 values[0] = accessor.getValue(ijk);
647 values[1] = accessor.getValue(ijk);
649 values[2] = accessor.getValue(ijk);
651 values[3] = accessor.getValue(ijk);
653 values[4] = accessor.getValue(ijk);
655 values[5] = accessor.getValue(ijk);
657 values[6] = accessor.getValue(ijk);
659 values[7] = accessor.getValue(ijk);
663 template<
typename LeafT>
668 values[0] = leaf.getValue(offset);
669 values[3] = leaf.getValue(offset + 1);
670 values[4] = leaf.getValue(offset + LeafT::DIM);
671 values[7] = leaf.getValue(offset + LeafT::DIM + 1);
672 values[1] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM));
673 values[2] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1);
674 values[5] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM);
675 values[6] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1);
679 template<
typename ValueType>
692 return uint8_t(signs);
698 template<
typename AccessorT>
704 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 1u;
706 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 2u;
708 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 4u;
710 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 8u;
711 coord[1] += 1; coord[2] = ijk[2];
712 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 16u;
714 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 32u;
716 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 64u;
718 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 128u;
719 return uint8_t(signs);
725 template<
typename LeafT>
735 if (
isInsideValue(leaf.getValue(offset + 1), iso)) signs |= 8u;
738 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM), iso)) signs |= 16u;
741 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM + 1), iso)) signs |= 128u;
744 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ), iso)) signs |= 2u;
747 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1), iso)) signs |= 4u;
750 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM), iso)) signs |= 32u;
753 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1), iso)) signs |= 64u;
755 return uint8_t(signs);
761 template<
class AccessorT>
764 const AccessorT& acc,
Coord ijk,
typename AccessorT::ValueType iso)
769 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 3) signs = uint8_t(~signs);
773 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 4) signs = uint8_t(~signs);
777 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 1) signs = uint8_t(~signs);
781 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 2) signs = uint8_t(~signs);
785 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 6) signs = uint8_t(~signs);
789 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 5) signs = uint8_t(~signs);
797 template<
class AccessorT>
800 typename AccessorT::ValueType isovalue,
const int dim)
813 coord[1] += dim; coord[2] = ijk[2];
824 if (p[0]) signs |= 1u;
825 if (p[1]) signs |= 2u;
826 if (p[2]) signs |= 4u;
827 if (p[3]) signs |= 8u;
828 if (p[4]) signs |= 16u;
829 if (p[5]) signs |= 32u;
830 if (p[6]) signs |= 64u;
831 if (p[7]) signs |= 128u;
832 if (!sAdaptable[signs])
return true;
837 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
838 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
839 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
842 coord.
reset(ip, j, k);
844 if (p[0] != m && p[1] != m)
return true;
847 coord.reset(ipp, j, kp);
849 if (p[1] != m && p[2] != m)
return true;
852 coord.reset(ip, j, kpp);
854 if (p[2] != m && p[3] != m)
return true;
857 coord.reset(i, j, kp);
859 if (p[0] != m && p[3] != m)
return true;
862 coord.reset(ip, jpp, k);
864 if (p[4] != m && p[5] != m)
return true;
867 coord.reset(ipp, jpp, kp);
869 if (p[5] != m && p[6] != m)
return true;
872 coord.reset(ip, jpp, kpp);
874 if (p[6] != m && p[7] != m)
return true;
877 coord.reset(i, jpp, kp);
879 if (p[7] != m && p[4] != m)
return true;
882 coord.reset(i, jp, k);
884 if (p[0] != m && p[4] != m)
return true;
887 coord.reset(ipp, jp, k);
889 if (p[1] != m && p[5] != m)
return true;
892 coord.reset(ipp, jp, kpp);
894 if (p[2] != m && p[6] != m)
return true;
898 coord.reset(i, jp, kpp);
900 if (p[3] != m && p[7] != m)
return true;
906 coord.reset(ip, jp, k);
908 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
911 coord.reset(ipp, jp, kp);
913 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
916 coord.reset(ip, jp, kpp);
918 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
921 coord.reset(i, jp, kp);
923 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
926 coord.reset(ip, j, kp);
928 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
931 coord.reset(ip, jpp, kp);
933 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
936 coord.reset(ip, jp, kp);
938 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
939 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
948 template <
class LeafType>
952 Coord ijk, end = start;
957 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
958 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
959 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
960 leaf.setValueOnly(ijk, regionId);
969 template <
class LeafType>
972 typename LeafType::ValueType::value_type adaptivity)
974 if (adaptivity < 1e-6)
return false;
976 using VecT =
typename LeafType::ValueType;
977 Coord ijk, end = start;
982 std::vector<VecT> norms;
983 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
984 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
985 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
987 if(!leaf.isValueOn(ijk))
continue;
988 norms.push_back(leaf.getValue(ijk));
993 size_t N = norms.size();
994 for (
size_t ni = 0; ni < N; ++ni) {
995 VecT n_i = norms[ni];
996 for (
size_t nj = 0; nj < N; ++nj) {
997 VecT n_j = norms[nj];
998 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
1009 inline double evalZeroCrossing(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1013 template<
typename LeafT>
1017 values[0] = double(leaf.getValue(offset));
1018 values[3] = double(leaf.getValue(offset + 1));
1019 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1020 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1021 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1022 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1023 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1024 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1029 template<
typename AccessorT>
1034 values[0] = double(acc.getValue(coord));
1037 values[1] = double(acc.getValue(coord));
1040 values[2] = double(acc.getValue(coord));
1043 values[3] = double(acc.getValue(coord));
1045 coord[1] += 1; coord[2] = ijk[2];
1046 values[4] = double(acc.getValue(coord));
1049 values[5] = double(acc.getValue(coord));
1052 values[6] = double(acc.getValue(coord));
1055 values[7] = double(acc.getValue(coord));
1062 unsigned char edgeGroup,
double iso)
1064 Vec3d avg(0.0, 0.0, 0.0);
1067 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1072 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1078 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1084 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1089 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1095 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1102 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1109 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1115 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1120 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1126 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1133 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1140 double w = 1.0 / double(samples);
1154 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1156 avg =
Vec3d(0.0, 0.0, 0.0);
1159 if (sEdgeGroupTable[signs][1] == edgeGroup
1160 && sEdgeGroupTable[signsMask][1] == 0) {
1165 if (sEdgeGroupTable[signs][2] == edgeGroup
1166 && sEdgeGroupTable[signsMask][2] == 0) {
1172 if (sEdgeGroupTable[signs][3] == edgeGroup
1173 && sEdgeGroupTable[signsMask][3] == 0) {
1179 if (sEdgeGroupTable[signs][4] == edgeGroup
1180 && sEdgeGroupTable[signsMask][4] == 0) {
1185 if (sEdgeGroupTable[signs][5] == edgeGroup
1186 && sEdgeGroupTable[signsMask][5] == 0) {
1192 if (sEdgeGroupTable[signs][6] == edgeGroup
1193 && sEdgeGroupTable[signsMask][6] == 0) {
1200 if (sEdgeGroupTable[signs][7] == edgeGroup
1201 && sEdgeGroupTable[signsMask][7] == 0) {
1208 if (sEdgeGroupTable[signs][8] == edgeGroup
1209 && sEdgeGroupTable[signsMask][8] == 0) {
1215 if (sEdgeGroupTable[signs][9] == edgeGroup
1216 && sEdgeGroupTable[signsMask][9] == 0) {
1221 if (sEdgeGroupTable[signs][10] == edgeGroup
1222 && sEdgeGroupTable[signsMask][10] == 0) {
1228 if (sEdgeGroupTable[signs][11] == edgeGroup
1229 && sEdgeGroupTable[signsMask][11] == 0) {
1236 if (sEdgeGroupTable[signs][12] == edgeGroup
1237 && sEdgeGroupTable[signsMask][12] == 0) {
1244 double w = 1.0 / double(samples);
1258 unsigned char signs,
unsigned char edgeGroup,
double iso)
1260 std::vector<Vec3d> samples;
1263 std::vector<double> weights;
1266 Vec3d avg(0.0, 0.0, 0.0);
1268 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1273 samples.push_back(avg);
1274 weights.push_back((avg-p).lengthSqr());
1277 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1282 samples.push_back(avg);
1283 weights.push_back((avg-p).lengthSqr());
1286 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1291 samples.push_back(avg);
1292 weights.push_back((avg-p).lengthSqr());
1295 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1300 samples.push_back(avg);
1301 weights.push_back((avg-p).lengthSqr());
1304 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1309 samples.push_back(avg);
1310 weights.push_back((avg-p).lengthSqr());
1313 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1318 samples.push_back(avg);
1319 weights.push_back((avg-p).lengthSqr());
1322 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1327 samples.push_back(avg);
1328 weights.push_back((avg-p).lengthSqr());
1331 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1336 samples.push_back(avg);
1337 weights.push_back((avg-p).lengthSqr());
1340 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1345 samples.push_back(avg);
1346 weights.push_back((avg-p).lengthSqr());
1349 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1354 samples.push_back(avg);
1355 weights.push_back((avg-p).lengthSqr());
1358 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1363 samples.push_back(avg);
1364 weights.push_back((avg-p).lengthSqr());
1367 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1372 samples.push_back(avg);
1373 weights.push_back((avg-p).lengthSqr());
1380 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1381 minWeight =
std::min(minWeight, weights[i]);
1382 maxWeight =
std::max(maxWeight, weights[i]);
1385 const double offset = maxWeight + minWeight * 0.1;
1386 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1387 weights[i] = offset - weights[i];
1391 double weightSum = 0.0;
1392 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1393 weightSum += weights[i];
1400 if (samples.size() > 1) {
1401 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1402 avg += samples[i] * (weights[i] / weightSum);
1405 avg = samples.front();
1416 const std::vector<double>& values,
unsigned char signs,
double iso)
1418 for (
size_t n = 1, N = sEdgeGroupTable[signs][0] + 1; n < N; ++n) {
1419 points.push_back(
computePoint(values, signs, uint8_t(n), iso));
1428 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1431 for (
size_t i = 1; i <= 12; ++i) {
1432 if (sEdgeGroupTable[lhsSigns][i] == groupId && sEdgeGroupTable[rhsSigns][i] != 0) {
1433 id = sEdgeGroupTable[rhsSigns][i];
1447 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1448 unsigned char lhsSigns,
unsigned char rhsSigns,
1449 double iso,
size_t pointIdx,
const uint32_t * seamPointArray)
1451 for (
size_t n = 1, N = sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1457 const unsigned char e = uint8_t(
id);
1458 const uint32_t& quantizedPoint = seamPointArray[pointIdx + (
id - 1)];
1463 weightedPointMask.push_back(
true);
1465 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1466 weightedPointMask.push_back(
false);
1470 points.push_back(
computePoint(lhsValues, lhsSigns, uint8_t(n), iso));
1471 weightedPointMask.push_back(
false);
1477 template <
typename InputTreeType>
1483 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1490 const InputTreeType& inputTree,
1491 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1492 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1493 const boost::scoped_array<Index32>& leafNodeOffsets,
1497 void setRefData(
const InputTreeType& refInputTree,
1500 const uint32_t * quantizedSeamLinePoints,
1501 uint8_t * seamLinePointsFlags);
1503 void operator()(
const tbb::blocked_range<size_t>&)
const;
1506 Vec3s *
const mPoints;
1507 InputTreeType
const *
const mInputTree;
1510 Index32 const *
const mNodeOffsets;
1512 double const mIsovalue;
1514 InputTreeType
const * mRefInputTree;
1517 uint32_t
const * mQuantizedSeamLinePoints;
1518 uint8_t * mSeamLinePointsFlags;
1522 template <
typename InputTreeType>
1525 const InputTreeType& inputTree,
1526 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1527 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1528 const boost::scoped_array<Index32>& leafNodeOffsets,
1531 : mPoints(pointArray)
1532 , mInputTree(&inputTree)
1533 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
1534 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1535 , mNodeOffsets(leafNodeOffsets.get())
1538 , mRefInputTree(nullptr)
1539 , mRefPointIndexTree(nullptr)
1540 , mRefSignFlagsTree(nullptr)
1541 , mQuantizedSeamLinePoints(nullptr)
1542 , mSeamLinePointsFlags(nullptr)
1546 template <
typename InputTreeType>
1549 const InputTreeType& refInputTree,
1552 const uint32_t * quantizedSeamLinePoints,
1553 uint8_t * seamLinePointsFlags)
1555 mRefInputTree = &refInputTree;
1556 mRefPointIndexTree = &refPointIndexTree;
1557 mRefSignFlagsTree = &refSignFlagsTree;
1558 mQuantizedSeamLinePoints = quantizedSeamLinePoints;
1559 mSeamLinePointsFlags = seamLinePointsFlags;
1562 template <
typename InputTreeType>
1570 using IndexType =
typename Index32TreeType::ValueType;
1572 using IndexArray = std::vector<Index>;
1573 using IndexArrayMap = std::map<IndexType, IndexArray>;
1575 InputTreeAccessor inputAcc(*mInputTree);
1579 std::vector<Vec3d> points(4);
1580 std::vector<bool> weightedPointMask(4);
1581 std::vector<double> values(8), refValues(8);
1582 const double iso = mIsovalue;
1586 std::unique_ptr<InputTreeAccessor> refInputAcc;
1587 std::unique_ptr<Index32TreeAccessor> refPointIndexAcc;
1588 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
1590 const bool hasReferenceData = mRefInputTree && mRefPointIndexTree && mRefSignFlagsTree;
1592 if (hasReferenceData) {
1593 refInputAcc.reset(
new InputTreeAccessor(*mRefInputTree));
1594 refPointIndexAcc.reset(
new Index32TreeAccessor(*mRefPointIndexTree));
1595 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
1598 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1601 const Coord& origin = pointIndexNode.origin();
1611 if (hasReferenceData) {
1612 refInputNode = refInputAcc->probeConstLeaf(origin);
1613 refPointIndexNode = refPointIndexAcc->probeConstLeaf(origin);
1614 refSignFlagsNode = refSignFlagsAcc->probeConstLeaf(origin);
1617 IndexType pointOffset = IndexType(mNodeOffsets[n]);
1618 IndexArrayMap regions;
1620 for (
auto it = pointIndexNode.beginValueOn(); it; ++it) {
1621 const Index offset = it.pos();
1623 const IndexType
id = it.getValue();
1626 regions[id].push_back(offset);
1631 pointIndexNode.setValueOnly(offset, pointOffset);
1633 const Int16 flags = signFlagsNode.getValue(offset);
1634 uint8_t signs = uint8_t(
SIGNS & flags);
1635 uint8_t refSigns = 0;
1637 if ((flags &
SEAM) && refPointIndexNode && refSignFlagsNode) {
1638 if (refSignFlagsNode->isValueOn(offset)) {
1639 refSigns = uint8_t(
SIGNS & refSignFlagsNode->getValue(offset));
1643 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1645 const bool inclusiveCell = inputNode &&
1646 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1647 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1648 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1656 weightedPointMask.clear();
1658 if (refSigns == 0) {
1663 if (inclusiveCell && refInputNode) {
1668 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1669 iso, refPointIndexNode->getValue(offset), mQuantizedSeamLinePoints);
1672 xyz[0] = double(ijk[0]);
1673 xyz[1] = double(ijk[1]);
1674 xyz[2] = double(ijk[2]);
1676 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1678 Vec3d& point = points[i];
1681 if (!std::isfinite(point[0]) ||
1682 !std::isfinite(point[1]) ||
1683 !std::isfinite(point[2]))
1686 "VolumeToMesh encountered NaNs or infs in the input VDB!" 1687 " Hint: Check the input and consider using the \"Diagnostics\" tool " 1688 "to detect and resolve the NaNs.");
1694 Vec3s& pos = mPoints[pointOffset];
1695 pos[0] = float(point[0]);
1696 pos[1] = float(point[1]);
1697 pos[2] = float(point[2]);
1699 if (mSeamLinePointsFlags && !weightedPointMask.empty() && weightedPointMask[i]) {
1700 mSeamLinePointsFlags[pointOffset] = uint8_t(1);
1708 for (
typename IndexArrayMap::iterator it = regions.begin(); it != regions.end(); ++it) {
1710 Vec3d avg(0.0), point(0.0);
1713 const IndexArray& voxels = it->second;
1714 for (
size_t i = 0, I = voxels.size(); i < I; ++i) {
1716 const Index offset = voxels[i];
1717 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1719 const bool inclusiveCell = inputNode &&
1720 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1721 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1722 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1726 pointIndexNode.setValueOnly(offset, pointOffset);
1728 uint8_t signs = uint8_t(
SIGNS & signFlagsNode.getValue(offset));
1736 avg[0] += double(ijk[0]) + points[0][0];
1737 avg[1] += double(ijk[1]) + points[0][1];
1738 avg[2] += double(ijk[2]) + points[0][2];
1744 double w = 1.0 / double(count);
1752 Vec3s& pos = mPoints[pointOffset];
1753 pos[0] = float(avg[0]);
1754 pos[1] = float(avg[1]);
1755 pos[2] = float(avg[2]);
1766 template <
typename InputTreeType>
1772 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1779 const InputTreeType& inputTree,
1782 uint32_t * quantizedPoints,
1784 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1785 , mInputTree(&inputTree)
1786 , mRefPointIndexTree(&refPointIndexTree)
1787 , mRefSignFlagsTree(&refSignFlagsTree)
1788 , mQuantizedPoints(quantizedPoints)
1799 std::vector<double> values(8);
1800 const double iso = double(mIsovalue);
1804 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1807 const Coord& origin = signFlagsNode.origin();
1810 if (!refSignNode)
continue;
1814 if (!refPointIndexNode)
continue;
1818 for (
typename Int16LeafNodeType::ValueOnCIter it = signFlagsNode.cbeginValueOn();
1821 const Index offset = it.pos();
1823 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1825 const bool inclusiveCell = inputNode &&
1826 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1827 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1828 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1832 if ((it.getValue() &
SEAM) && refSignNode->isValueOn(offset)) {
1834 uint8_t lhsSigns = uint8_t(
SIGNS & it.getValue());
1835 uint8_t rhsSigns = uint8_t(
SIGNS & refSignNode->getValue(offset));
1838 if (inclusiveCell) {
1845 for (
unsigned i = 1, I = sEdgeGroupTable[lhsSigns][0] + 1; i < I; ++i) {
1851 uint32_t& data = mQuantizedPoints[
1852 refPointIndexNode->getValue(offset) + (
id - 1)];
1857 pos, values, lhsSigns, rhsSigns, uint8_t(i), iso);
1875 InputTreeType
const *
const mInputTree;
1878 uint32_t *
const mQuantizedPoints;
1883 template <
typename TreeType>
1889 const TreeType& refSignFlagsTree)
1890 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1891 , mRefSignFlagsTree(&refSignFlagsTree)
1899 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1902 const Coord& origin = signFlagsNode.origin();
1905 if (!refSignNode)
continue;
1907 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
1908 const Index offset = it.pos();
1910 uint8_t rhsSigns = uint8_t(refSignNode->getValue(offset) &
SIGNS);
1912 if (sEdgeGroupTable[rhsSigns][0] > 0) {
1914 const typename LeafNodeType::ValueType value = it.getValue();
1915 uint8_t lhsSigns = uint8_t(value &
SIGNS);
1917 if (rhsSigns != lhsSigns) {
1918 signFlagsNode.setValueOnly(offset, value |
SEAM);
1929 TreeType
const *
const mRefSignFlagsTree;
1933 template <
typename BoolTreeType,
typename SignDataType>
1942 const BoolTreeType& maskTree)
1943 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1944 , mMaskTree(&maskTree)
1952 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1955 const Coord& origin = signFlagsNode.origin();
1958 if (!maskNode)
continue;
1960 using ValueOnCIter =
typename SignDataLeafNodeType::ValueOnCIter;
1962 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
1963 const Index offset = it.pos();
1965 if (maskNode->isValueOn(offset)) {
1966 signFlagsNode.setValueOnly(offset, it.getValue() |
SEAM);
1976 BoolTreeType
const *
const mMaskTree;
1980 template <
typename TreeType>
1984 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1987 const TreeType& signFlagsTree,
1989 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1990 , mSignFlagsTree(&signFlagsTree)
1997 : mSignFlagsNodes(rhs.mSignFlagsNodes)
1998 , mSignFlagsTree(rhs.mSignFlagsTree)
2008 using ValueOnCIter =
typename LeafNodeType::ValueOnCIter;
2009 using ValueType =
typename LeafNodeType::ValueType;
2015 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2020 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
2022 const ValueType flags = it.getValue();
2024 if (!(flags &
SEAM) && (flags &
EDGES)) {
2026 ijk = it.getCoord();
2028 bool isSeamLineVoxel =
false;
2030 if (flags &
XEDGE) {
2034 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2036 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2040 if (!isSeamLineVoxel && flags &
YEDGE) {
2042 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2044 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2046 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2050 if (!isSeamLineVoxel && flags &
ZEDGE) {
2052 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2054 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2056 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2060 if (isSeamLineVoxel) {
2061 maskAcc.
setValue(it.getCoord(),
true);
2071 TreeType
const *
const mSignFlagsTree;
2077 template<
typename SignDataTreeType>
2081 using SignDataType =
typename SignDataTreeType::ValueType;
2082 using SignDataLeafNodeType =
typename SignDataTreeType::LeafNodeType;
2083 using BoolTreeType =
typename SignDataTreeType::template ValueConverter<bool>::Type;
2085 std::vector<SignDataLeafNodeType*> signFlagsLeafNodes;
2086 signFlagsTree.getNodes(signFlagsLeafNodes);
2088 const tbb::blocked_range<size_t> nodeRange(0, signFlagsLeafNodes.size());
2090 tbb::parallel_for(nodeRange,
2093 BoolTreeType seamLineMaskTree(
false);
2096 maskSeamLine(signFlagsLeafNodes, signFlagsTree, seamLineMaskTree);
2098 tbb::parallel_reduce(nodeRange, maskSeamLine);
2100 tbb::parallel_for(nodeRange,
2108 template <
typename InputGr
idType>
2115 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
2119 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
2125 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2130 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2131 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2134 bool invertSurfaceOrientation);
2138 mSpatialAdaptivityTree = &grid.
tree();
2139 mSpatialAdaptivityTransform = &grid.
transform();
2149 mRefSignFlagsTree = &signFlagsData;
2150 mInternalAdaptivity = internalAdaptivity;
2153 void operator()(
const tbb::blocked_range<size_t>&)
const;
2164 float mSurfaceAdaptivity, mInternalAdaptivity;
2165 bool mInvertSurfaceOrientation;
2174 template <
typename InputGr
idType>
2176 const InputGridType& inputGrid,
2178 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2179 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2182 bool invertSurfaceOrientation)
2183 : mInputTree(&inputGrid.tree())
2184 , mInputTransform(&inputGrid.transform())
2185 , mPointIndexTree(&pointIndexTree)
2186 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
2187 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
2189 , mSurfaceAdaptivity(adaptivity)
2190 , mInternalAdaptivity(adaptivity)
2191 , mInvertSurfaceOrientation(invertSurfaceOrientation)
2192 , mSpatialAdaptivityTree(nullptr)
2193 , mMaskTree(nullptr)
2194 , mRefSignFlagsTree(nullptr)
2195 , mSpatialAdaptivityTransform(nullptr)
2200 template <
typename InputGr
idType>
2205 using Vec3sLeafNodeType =
typename InputLeafNodeType::template ValueConverter<Vec3sType>::Type;
2213 std::unique_ptr<FloatTreeAccessor> spatialAdaptivityAcc;
2214 if (mSpatialAdaptivityTree && mSpatialAdaptivityTransform) {
2215 spatialAdaptivityAcc.reset(
new FloatTreeAccessor(*mSpatialAdaptivityTree));
2218 std::unique_ptr<BoolTreeAccessor> maskAcc;
2220 maskAcc.reset(
new BoolTreeAccessor(*mMaskTree));
2223 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
2224 if (mRefSignFlagsTree) {
2225 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
2228 InputTreeAccessor inputAcc(*mInputTree);
2229 Index32TreeAccessor pointIndexAcc(*mPointIndexTree);
2233 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<InputValueType>();
2234 std::unique_ptr<Vec3sLeafNodeType> gradientNode;
2237 const int LeafDim = InputLeafNodeType::DIM;
2239 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2241 mask.setValuesOff();
2246 const Coord& origin = pointIndexNode.origin();
2248 end[0] = origin[0] + LeafDim;
2249 end[1] = origin[1] + LeafDim;
2250 end[2] = origin[2] + LeafDim;
2255 if (maskLeaf !=
nullptr) {
2256 for (
typename BoolLeafNodeType::ValueOnCIter it = maskLeaf->cbeginValueOn();
2259 mask.setActiveState(it.getCoord() & ~1u,
true);
2264 float adaptivity = (refSignFlagsAcc && !refSignFlagsAcc->probeConstLeaf(origin)) ?
2265 mInternalAdaptivity : mSurfaceAdaptivity;
2267 bool useGradients = adaptivity < 1.0f;
2272 if (spatialAdaptivityAcc) {
2273 useGradients =
false;
2274 for (
Index offset = 0; offset < FloatLeafNodeType::NUM_VALUES; ++offset) {
2275 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2278 float weight = spatialAdaptivityAcc->getValue(ijk);
2279 float adaptivityValue = weight * adaptivity;
2280 if (adaptivityValue < 1.0f) useGradients =
true;
2281 adaptivityLeaf.setValueOnly(offset, adaptivityValue);
2286 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2287 const Int16 flags = it.getValue();
2288 const unsigned char signs =
static_cast<unsigned char>(
SIGNS & int(flags));
2290 if ((flags &
SEAM) || !sAdaptable[signs] || sEdgeGroupTable[signs][0] > 1) {
2292 mask.setActiveState(it.getCoord() & ~1u,
true);
2294 }
else if (flags &
EDGES) {
2296 bool maskRegion =
false;
2298 ijk = it.getCoord();
2299 if (!pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2301 if (!maskRegion && flags &
XEDGE) {
2303 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2305 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2307 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2311 if (!maskRegion && flags &
YEDGE) {
2313 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2315 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2317 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2321 if (!maskRegion && flags &
ZEDGE) {
2323 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2325 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2327 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2332 mask.setActiveState(it.getCoord() & ~1u,
true);
2339 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2340 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2341 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2342 if (!mask.isValueOn(ijk) &
isNonManifold(inputAcc, ijk, mIsovalue, dim)) {
2343 mask.setActiveState(ijk,
true);
2354 gradientNode->setValuesOff();
2356 gradientNode.
reset(
new Vec3sLeafNodeType());
2359 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2360 ijk = it.getCoord();
2361 if (!mask.isValueOn(ijk & ~1u)) {
2365 if (invertGradientDir) {
2369 gradientNode->setValueOn(it.pos(), dir);
2376 for ( ; dim <= LeafDim; dim = dim << 1) {
2377 const unsigned coordMask = ~((dim << 1) - 1);
2378 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2379 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2380 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2382 adaptivity = adaptivityLeaf.getValue(ijk);
2384 if (mask.isValueOn(ijk)
2386 || (useGradients && !
isMergable(*gradientNode, ijk, dim, adaptivity)))
2388 mask.setActiveState(ijk & coordMask,
true);
2390 mergeVoxels(pointIndexNode, ijk, dim, regionId++);
2410 mPolygonPool = &quadPool;
2415 template<
typename IndexType>
2419 mPolygonPool->quad(mIdx) = verts;
2421 Vec4I& quad = mPolygonPool->quad(mIdx);
2427 mPolygonPool->quadFlags(mIdx) = flags;
2433 mPolygonPool->trimQuads(mIdx);
2449 mPolygonPool = &polygonPool;
2451 mPolygonPool->resetTriangles(upperBound);
2457 template<
typename IndexType>
2460 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2461 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2462 mPolygonPool->quadFlags(mQuadIdx) = flags;
2463 addQuad(verts, reverse);
2465 verts[0] == verts[3] &&
2466 verts[1] != verts[2] &&
2467 verts[1] != verts[0] &&
2468 verts[2] != verts[0]) {
2469 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2470 addTriangle(verts[0], verts[1], verts[2], reverse);
2472 verts[1] == verts[2] &&
2473 verts[0] != verts[3] &&
2474 verts[0] != verts[1] &&
2475 verts[3] != verts[1]) {
2476 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2477 addTriangle(verts[0], verts[1], verts[3], reverse);
2479 verts[0] == verts[1] &&
2480 verts[2] != verts[3] &&
2481 verts[2] != verts[0] &&
2482 verts[3] != verts[0]) {
2483 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2484 addTriangle(verts[0], verts[2], verts[3], reverse);
2486 verts[2] == verts[3] &&
2487 verts[0] != verts[1] &&
2488 verts[0] != verts[2] &&
2489 verts[1] != verts[2]) {
2490 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2491 addTriangle(verts[0], verts[1], verts[2], reverse);
2498 mPolygonPool->trimQuads(mQuadIdx,
true);
2499 mPolygonPool->trimTrinagles(mTriangleIdx,
true);
2504 template<
typename IndexType>
2508 mPolygonPool->quad(mQuadIdx) = verts;
2510 Vec4I& quad = mPolygonPool->quad(mQuadIdx);
2519 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2521 Vec3I& prim = mPolygonPool->triangle(mTriangleIdx);
2535 size_t mQuadIdx, mTriangleIdx;
2540 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2543 bool invertSurfaceOrientation,
2546 const Vec3i& offsets,
2548 const SignAccT& signAcc,
2549 const IdxAccT& idxAcc,
2550 PrimBuilder& mesher)
2552 using IndexType =
typename IdxAccT::ValueType;
2555 const bool isActive = idxAcc.probeValue(ijk, v0);
2562 bool isInside = flags &
INSIDE;
2564 isInside = invertSurfaceOrientation ? !isInside : isInside;
2569 if (flags &
XEDGE) {
2571 quad[0] = v0 + offsets[0];
2575 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2576 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2577 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][5] - 1 : 0;
2581 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2582 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2583 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][7] - 1 : 0;
2587 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2588 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2589 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][3] - 1 : 0;
2592 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2599 if (flags &
YEDGE) {
2601 quad[0] = v0 + offsets[1];
2605 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2606 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2607 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][12] - 1 : 0;
2611 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2612 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2613 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][11] - 1 : 0;
2617 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2618 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2619 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][10] - 1 : 0;
2622 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2629 if (flags &
ZEDGE) {
2631 quad[0] = v0 + offsets[2];
2635 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2636 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2637 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][8] - 1 : 0;
2641 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2642 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2643 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][6] - 1 : 0;
2647 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2648 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2649 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][2] - 1 : 0;
2652 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2661 template<
typename InputTreeType>
2665 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2670 : mInputTree(&inputTree)
2674 , mTileArray(tileArray)
2679 : mInputTree(rhs.mInputTree)
2680 , mIsovalue(rhs.mIsovalue)
2683 , mTileArray(rhs.mTileArray)
2689 void operator()(
const tbb::blocked_range<size_t>&);
2696 Vec4i const *
const mTileArray;
2700 template<
typename InputTreeType>
2709 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2711 const Vec4i& tile = mTileArray[n];
2713 bbox.
min()[0] = tile[0];
2714 bbox.
min()[1] = tile[1];
2715 bbox.
min()[2] = tile[2];
2730 bool processRegion =
true;
2735 if (processRegion) {
2738 region.
min()[0] = region.
max()[0] = ijk[0];
2739 mMask->fill(region,
false);
2746 processRegion =
true;
2748 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2752 if (processRegion) {
2755 region.
min()[0] = region.
max()[0] = ijk[0];
2756 mMask->fill(region,
false);
2766 processRegion =
true;
2771 if (processRegion) {
2774 region.
min()[1] = region.
max()[1] = ijk[1];
2775 mMask->fill(region,
false);
2782 processRegion =
true;
2784 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2788 if (processRegion) {
2791 region.
min()[1] = region.
max()[1] = ijk[1];
2792 mMask->fill(region,
false);
2802 processRegion =
true;
2807 if (processRegion) {
2810 region.
min()[2] = region.
max()[2] = ijk[2];
2811 mMask->fill(region,
false);
2817 processRegion =
true;
2819 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2823 if (processRegion) {
2826 region.
min()[2] = region.
max()[2] = ijk[2];
2827 mMask->fill(region,
false);
2833 template<
typename InputTreeType>
2836 typename InputTreeType::template ValueConverter<bool>::Type& mask)
2838 typename InputTreeType::ValueOnCIter tileIter(inputTree);
2839 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2841 size_t tileCount = 0;
2842 for ( ; tileIter; ++tileIter) {
2846 if (tileCount > 0) {
2847 boost::scoped_array<Vec4i> tiles(
new Vec4i[tileCount]);
2852 tileIter = inputTree.cbeginValueOn();
2853 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2855 for (; tileIter; ++tileIter) {
2856 Vec4i& tile = tiles[index++];
2857 tileIter.getBoundingBox(bbox);
2858 tile[0] = bbox.
min()[0];
2859 tile[1] = bbox.
min()[1];
2860 tile[2] = bbox.
min()[2];
2861 tile[3] = bbox.
max()[0] - bbox.
min()[0];
2865 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, tileCount), op);
2878 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
2884 for (
size_t n = range.begin(); n < range.end(); ++n) {
2885 mPointsOut[n] = mPointsIn[n];
2891 std::vector<Vec3s>& mPointsOut;
2903 template<
typename LeafNodeType>
2904 void constructOffsetList();
2942 IndexVector mCore, mMinX, mMaxX, mMinY, mMaxY, mMinZ, mMaxZ,
2943 mInternalNeighborsX, mInternalNeighborsY, mInternalNeighborsZ;
2947 template<
typename LeafNodeType>
2953 mCore.reserve((LeafNodeType::DIM - 2) * (LeafNodeType::DIM - 2));
2955 for (
Index x = 1; x < (LeafNodeType::DIM - 1); ++x) {
2956 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2957 for (
Index y = 1; y < (LeafNodeType::DIM - 1); ++y) {
2958 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2959 for (
Index z = 1; z < (LeafNodeType::DIM - 1); ++z) {
2960 mCore.push_back(offsetXY + z);
2966 mInternalNeighborsX.clear();
2967 mInternalNeighborsX.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2969 for (
Index x = 0; x < (LeafNodeType::DIM - 1); ++x) {
2970 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2971 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2972 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2973 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2974 mInternalNeighborsX.push_back(offsetXY + z);
2980 mInternalNeighborsY.clear();
2981 mInternalNeighborsY.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2983 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2984 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2985 for (
Index y = 0; y < (LeafNodeType::DIM - 1); ++y) {
2986 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2987 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2988 mInternalNeighborsY.push_back(offsetXY + z);
2994 mInternalNeighborsZ.clear();
2995 mInternalNeighborsZ.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2997 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2998 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2999 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3000 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3001 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3002 mInternalNeighborsZ.push_back(offsetXY + z);
3009 mMinX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3011 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3012 const Index offsetXY = (y << LeafNodeType::LOG2DIM);
3013 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3014 mMinX.push_back(offsetXY + z);
3021 mMaxX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3023 const Index offsetX = (LeafNodeType::DIM - 1) << (2 * LeafNodeType::LOG2DIM);
3024 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3025 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3026 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3027 mMaxX.push_back(offsetXY + z);
3034 mMinY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3036 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3037 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3038 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3039 mMinY.push_back(offsetX + z);
3046 mMaxY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3048 const Index offsetY = (LeafNodeType::DIM - 1) << LeafNodeType::LOG2DIM;
3049 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3050 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3051 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3052 mMaxY.push_back(offsetX + offsetY + z);
3059 mMinZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3061 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3062 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3063 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3064 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3065 mMinZ.push_back(offsetXY);
3072 mMaxZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3074 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3075 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3076 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3077 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3078 mMaxZ.push_back(offsetXY + (LeafNodeType::DIM - 1));
3089 template<
typename AccessorT,
int _AXIS>
3092 enum { AXIS = _AXIS };
3099 acc.setActiveState(ijk);
3101 acc.setActiveState(ijk);
3103 acc.setActiveState(ijk);
3105 acc.setActiveState(ijk);
3106 }
else if (_AXIS == 1) {
3107 acc.setActiveState(ijk);
3109 acc.setActiveState(ijk);
3111 acc.setActiveState(ijk);
3113 acc.setActiveState(ijk);
3115 acc.setActiveState(ijk);
3117 acc.setActiveState(ijk);
3119 acc.setActiveState(ijk);
3121 acc.setActiveState(ijk);
3130 template<
typename VoxelEdgeAcc,
typename LeafNode>
3138 if (VoxelEdgeAcc::AXIS == 0) {
3139 nvo = LeafNode::DIM * LeafNode::DIM;
3141 }
else if (VoxelEdgeAcc::AXIS == 1) {
3142 nvo = LeafNode::DIM;
3146 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3147 const Index& pos = (*offsets)[n];
3148 bool isActive = leafnode.isValueOn(pos) || leafnode.isValueOn(pos + nvo);
3149 if (isActive && (
isInsideValue(leafnode.getValue(pos), iso) !=
3151 edgeAcc.set(leafnode.offsetToGlobalCoord(pos));
3160 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3165 const std::vector<Index>* lhsOffsets = &voxels.
maxX();
3166 const std::vector<Index>* rhsOffsets = &voxels.
minX();
3167 Coord ijk = lhsNode.origin();
3169 if (VoxelEdgeAcc::AXIS == 0) {
3170 ijk[0] += LeafNode::DIM;
3171 }
else if (VoxelEdgeAcc::AXIS == 1) {
3172 ijk[1] += LeafNode::DIM;
3173 lhsOffsets = &voxels.
maxY();
3174 rhsOffsets = &voxels.
minY();
3175 }
else if (VoxelEdgeAcc::AXIS == 2) {
3176 ijk[2] += LeafNode::DIM;
3177 lhsOffsets = &voxels.
maxZ();
3178 rhsOffsets = &voxels.
minZ();
3181 typename LeafNode::ValueType value;
3182 const LeafNode* rhsNodePt = acc.probeConstLeaf(ijk);
3185 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3186 const Index& pos = (*lhsOffsets)[n];
3187 bool isActive = lhsNode.isValueOn(pos) || rhsNodePt->isValueOn((*rhsOffsets)[n]);
3188 if (isActive && (
isInsideValue(lhsNode.getValue(pos), iso) !=
3189 isInsideValue(rhsNodePt->getValue((*rhsOffsets)[n]), iso))) {
3190 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3193 }
else if (!acc.probeValue(ijk, value)) {
3195 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3196 const Index& pos = (*lhsOffsets)[n];
3197 if (lhsNode.isValueOn(pos) && (inside !=
isInsideValue(lhsNode.getValue(pos), iso))) {
3198 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3208 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3213 Coord ijk = leafnode.origin();
3214 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3215 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3216 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3218 typename LeafNode::ValueType value;
3219 if (!acc.probeConstLeaf(ijk) && !acc.probeValue(ijk, value)) {
3226 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3228 const Index& pos = (*offsets)[n];
3229 if (leafnode.isValueOn(pos)
3232 ijk = leafnode.offsetToGlobalCoord(pos);
3233 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3234 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3235 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3245 template<
typename InputTreeType>
3251 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3255 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3260 void operator()(
const tbb::blocked_range<size_t>&);
3262 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3279 template<
typename InputTreeType>
3282 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3285 : mInputAccessor(inputTree)
3286 , mInputNodes(inputLeafNodes.empty() ? nullptr : &inputLeafNodes.front())
3287 , mIntersectionTree(false)
3288 , mIntersectionAccessor(intersectionTree)
3290 , mOffsets(&mOffsetData)
3297 template<
typename InputTreeType>
3300 : mInputAccessor(rhs.mInputAccessor.tree())
3301 , mInputNodes(rhs.mInputNodes)
3302 , mIntersectionTree(false)
3303 , mIntersectionAccessor(mIntersectionTree)
3305 , mOffsets(rhs.mOffsets)
3306 , mIsovalue(rhs.mIsovalue)
3311 template<
typename InputTreeType>
3319 for (
size_t n = range.begin(); n != range.end(); ++n) {
3350 template<
typename InputTreeType>
3353 typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3354 const InputTreeType& inputTree,
3355 typename InputTreeType::ValueType isovalue)
3359 std::vector<const InputLeafNodeType*> inputLeafNodes;
3360 inputTree.getNodes(inputLeafNodes);
3363 inputTree, inputLeafNodes, intersectionTree, isovalue);
3365 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, inputLeafNodes.size()), op);
3374 template<
typename InputTreeType>
3380 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3384 const InputTreeType& inputTree,
3385 const std::vector<BoolLeafNodeType*>& nodes,
3390 void operator()(
const tbb::blocked_range<size_t>&);
3392 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3406 template<
typename InputTreeType>
3408 const InputTreeType& inputTree,
3409 const std::vector<BoolLeafNodeType*>& nodes,
3412 : mInputAccessor(inputTree)
3413 , mNodes(nodes.empty() ? nullptr : &nodes.front())
3414 , mIntersectionTree(false)
3415 , mIntersectionAccessor(intersectionTree)
3421 template<
typename InputTreeType>
3424 : mInputAccessor(rhs.mInputAccessor.tree())
3425 , mNodes(rhs.mNodes)
3426 , mIntersectionTree(false)
3427 , mIntersectionAccessor(mIntersectionTree)
3428 , mIsovalue(rhs.mIsovalue)
3433 template<
typename InputTreeType>
3444 for (
size_t n = range.begin(); n != range.end(); ++n) {
3448 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3450 if (!it.getValue()) {
3452 ijk = it.getCoord();
3473 template<
typename BoolTreeType>
3479 const std::vector<BoolLeafNodeType*>& maskNodes,
3481 : mMaskTree(&maskTree)
3482 , mMaskNodes(maskNodes.empty() ? nullptr : &maskNodes.front())
3483 , mTmpBorderTree(false)
3484 , mBorderTree(&borderTree)
3489 : mMaskTree(rhs.mMaskTree)
3490 , mMaskNodes(rhs.mMaskNodes)
3491 , mTmpBorderTree(false)
3492 , mBorderTree(&mTmpBorderTree)
3504 for (
size_t n = range.begin(); n != range.end(); ++n) {
3508 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3510 ijk = it.getCoord();
3512 const bool lhs = it.getValue();
3515 bool isEdgeVoxel =
false;
3518 isEdgeVoxel = (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3521 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3524 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3527 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3531 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3534 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3537 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3556 template<
typename BoolTreeType>
3562 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3569 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3573 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3580 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3581 const Index pos = it.pos();
3582 if (maskNode->getValue(pos)) {
3583 node.setValueOnly(pos,
true);
3599 template<
typename BoolTreeType>
3606 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3608 , mInputTransform(inputTransform)
3609 , mMaskTransform(maskTransform)
3610 , mInvertMask(invert)
3616 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3620 const bool matchingTransforms = mInputTransform == mMaskTransform;
3621 const bool maskState = mInvertMask;
3623 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3627 if (matchingTransforms) {
3633 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3634 const Index pos = it.pos();
3635 if (maskNode->isValueOn(pos) == maskState) {
3636 node.setValueOnly(pos,
true);
3642 if (maskTreeAcc.
isValueOn(node.origin()) == maskState) {
3643 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3644 node.setValueOnly(it.pos(),
true);
3654 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3656 ijk = mMaskTransform.worldToIndexCellCentered(
3657 mInputTransform.indexToWorld(it.getCoord()));
3659 if (maskTreeAcc.
isValueOn(ijk) == maskState) {
3660 node.setValueOnly(it.pos(),
true);
3673 bool const mInvertMask;
3677 template<
typename InputGr
idType>
3680 typename InputGridType::TreeType::template ValueConverter<bool>::Type& intersectionTree,
3681 typename InputGridType::TreeType::template ValueConverter<bool>::Type& borderTree,
3682 const InputGridType& inputGrid,
3685 typename InputGridType::ValueType isovalue)
3687 using InputTreeType =
typename InputGridType::TreeType;
3688 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3692 if (maskGrid && maskGrid->type() == BoolGridType::gridType()) {
3695 const InputTreeType& inputTree = inputGrid.tree();
3697 const BoolGridType * surfaceMask =
static_cast<const BoolGridType*
>(maskGrid.get());
3705 std::vector<BoolLeafNodeType*> intersectionLeafNodes;
3706 intersectionTree.getNodes(intersectionLeafNodes);
3708 tbb::parallel_for(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()),
3710 intersectionLeafNodes, maskTree, transform, maskTransform, invertMask));
3716 intersectionTree, intersectionLeafNodes, borderTree);
3717 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), borderOp);
3725 inputTree, intersectionLeafNodes, tmpIntersectionTree, isovalue);
3727 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3729 std::vector<BoolLeafNodeType*> tmpIntersectionLeafNodes;
3730 tmpIntersectionTree.getNodes(tmpIntersectionLeafNodes);
3732 tbb::parallel_for(tbb::blocked_range<size_t>(0, tmpIntersectionLeafNodes.size()),
3735 intersectionTree.clear();
3736 intersectionTree.merge(tmpIntersectionTree);
3744 template<
typename InputTreeType>
3752 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
3757 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3763 void operator()(
const tbb::blocked_range<size_t>&);
3765 mSignFlagsAccessor.tree().merge(rhs.mSignFlagsAccessor.
tree());
3766 mPointIndexAccessor.tree().merge(rhs.mPointIndexAccessor.
tree());
3782 template<
typename InputTreeType>
3784 const InputTreeType& inputTree,
3785 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3789 : mInputAccessor(inputTree)
3790 , mIntersectionNodes(&intersectionLeafNodes.front())
3792 , mSignFlagsAccessor(signFlagsTree)
3793 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3794 , mPointIndexAccessor(pointIndexTree)
3797 pointIndexTree.root().setBackground(boost::integer_traits<Index32>::const_max,
false);
3801 template<
typename InputTreeType>
3803 : mInputAccessor(rhs.mInputAccessor.tree())
3804 , mIntersectionNodes(rhs.mIntersectionNodes)
3806 , mSignFlagsAccessor(mSignFlagsTree)
3807 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3808 , mPointIndexAccessor(mPointIndexTree)
3809 , mIsovalue(rhs.mIsovalue)
3814 template<
typename InputTreeType>
3818 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
3822 typename std::unique_ptr<Int16LeafNodeType> signsNodePt(
new Int16LeafNodeType(ijk, 0));
3824 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3831 if (!signsNodePt.get()) signsNodePt.reset(
new Int16LeafNodeType(origin, 0));
3832 else signsNodePt->setOrigin(origin);
3834 bool updatedNode =
false;
3838 const Index pos = it.pos();
3852 if (signFlags != 0 && signFlags != 0xFF) {
3854 const bool inside = signFlags & 0x1;
3856 int edgeFlags = inside ?
INSIDE : 0;
3858 if (!it.getValue()) {
3859 edgeFlags |= inside != ((signFlags & 0x02) != 0) ?
XEDGE : 0;
3860 edgeFlags |= inside != ((signFlags & 0x10) != 0) ?
YEDGE : 0;
3861 edgeFlags |= inside != ((signFlags & 0x08) != 0) ?
ZEDGE : 0;
3864 const uint8_t ambiguousCellFlags = sAmbiguousFace[signFlags];
3865 if (ambiguousCellFlags != 0) {
3867 origin + ijk, mIsovalue);
3870 edgeFlags |= int(signFlags);
3872 signsNodePt->setValueOn(pos,
Int16(edgeFlags));
3878 typename Index32TreeType::LeafNodeType* idxNode = mPointIndexAccessor.
touchLeaf(origin);
3879 idxNode->topologyUnion(*signsNodePt);
3882 for (
auto it = idxNode->beginValueOn(); it; ++it) {
3883 idxNode->setValueOnly(it.pos(), 0);
3886 mSignFlagsAccessor.
addLeaf(signsNodePt.release());
3892 template<
typename InputTreeType>
3895 typename InputTreeType::template ValueConverter<Int16>::Type& signFlagsTree,
3896 typename InputTreeType::template ValueConverter<Index32>::Type& pointIndexTree,
3897 const typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3898 const InputTreeType& inputTree,
3899 typename InputTreeType::ValueType isovalue)
3901 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3904 std::vector<const BoolLeafNodeType*> intersectionLeafNodes;
3905 intersectionTree.getNodes(intersectionLeafNodes);
3908 inputTree, intersectionLeafNodes, signFlagsTree, pointIndexTree, isovalue);
3910 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3917 template<Index32 LeafNodeLog2Dim>
3923 boost::scoped_array<Index32>& leafNodeCount)
3924 : mLeafNodes(leafNodes.empty() ? nullptr : &leafNodes.front())
3925 , mData(leafNodeCount.get())
3931 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3935 Int16 const * p = mLeafNodes[n]->buffer().data();
3936 Int16 const *
const endP = p + Int16LeafNodeType::SIZE;
3953 template<
typename Po
intIndexLeafNode>
3959 const std::vector<Int16LeafNodeType*>& signDataNodes,
3960 boost::scoped_array<Index32>& leafNodeCount)
3961 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
3962 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
3963 , mData(leafNodeCount.get())
3971 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3978 std::set<IndexType> uniqueRegions;
3985 count += size_t(sEdgeGroupTable[(
SIGNS & signNode.
getValue(it.pos()))][0]);
3987 uniqueRegions.insert(
id);
3991 mData[n] =
Index32(count + uniqueRegions.size());
4002 template<
typename Po
intIndexLeafNode>
4007 MapPoints(
const std::vector<PointIndexLeafNode*>& pointIndexNodes,
4008 const std::vector<Int16LeafNodeType*>& signDataNodes,
4009 boost::scoped_array<Index32>& leafNodeCount)
4010 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
4011 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
4012 , mData(leafNodeCount.get())
4018 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
4023 Index32 pointOffset = mData[n];
4026 const Index pos = it.pos();
4029 pointOffset +=
Index32(sEdgeGroupTable[signs][0]);
4043 template<
typename TreeType,
typename PrimBuilder>
4054 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4058 bool invertSurfaceOrientation);
4062 void operator()(
const tbb::blocked_range<size_t>&)
const;
4070 bool const mInvertSurfaceOrientation;
4074 template<
typename TreeType,
typename PrimBuilder>
4076 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4080 bool invertSurfaceOrientation)
4081 : mSignFlagsLeafNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
4082 , mSignFlagsTree(&signFlagsTree)
4083 , mRefSignFlagsTree(nullptr)
4084 , mIndexTree(&idxTree)
4085 , mPolygonPoolList(&polygons)
4086 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4090 template<
typename InputTreeType,
typename PrimBuilder>
4095 Int16ValueAccessor signAcc(*mSignFlagsTree);
4099 const bool invertSurfaceOrientation = mInvertSurfaceOrientation;
4106 std::unique_ptr<Int16ValueAccessor> refSignAcc;
4107 if (mRefSignFlagsTree) refSignAcc.
reset(
new Int16ValueAccessor(*mRefSignFlagsTree));
4109 for (
size_t n = range.begin(); n != range.end(); ++n) {
4112 origin = node.origin();
4116 typename Int16LeafNodeType::ValueOnCIter iter = node.cbeginValueOn();
4117 for (; iter; ++iter) {
4118 if (iter.getValue() &
XEDGE) ++edgeCount;
4119 if (iter.getValue() &
YEDGE) ++edgeCount;
4120 if (iter.getValue() &
ZEDGE) ++edgeCount;
4123 if(edgeCount == 0)
continue;
4125 mesher.init(edgeCount, (*mPolygonPoolList)[n]);
4130 if (!signleafPt || !idxLeafPt)
continue;
4134 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
4138 for (iter = node.cbeginValueOn(); iter; ++iter) {
4139 ijk = iter.getCoord();
4141 Int16 flags = iter.getValue();
4143 if (!(flags & 0xE00))
continue;
4146 if (refSignLeafPt) {
4147 refFlags = refSignLeafPt->getValue(iter.pos());
4154 const uint8_t cell = uint8_t(
SIGNS & flags);
4156 if (sEdgeGroupTable[cell][0] > 1) {
4157 offsets[0] = (sEdgeGroupTable[cell][1] - 1);
4158 offsets[1] = (sEdgeGroupTable[cell][9] - 1);
4159 offsets[2] = (sEdgeGroupTable[cell][4] - 1);
4162 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
4164 flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher);
4167 flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher);
4180 template<
typename T>
4183 CopyArray(T * outputArray,
const T * inputArray,
size_t outputOffset = 0)
4184 : mOutputArray(outputArray), mInputArray(inputArray), mOutputOffset(outputOffset)
4188 void operator()(
const tbb::blocked_range<size_t>& inputArrayRange)
const 4190 const size_t offset = mOutputOffset;
4191 for (
size_t n = inputArrayRange.begin(), N = inputArrayRange.end(); n < N; ++n) {
4192 mOutputArray[offset + n] = mInputArray[n];
4197 T *
const mOutputArray;
4198 T
const *
const mInputArray;
4199 size_t const mOutputOffset;
4206 const std::vector<uint8_t>& pointFlags,
4207 boost::scoped_array<openvdb::Vec3s>& points,
4208 boost::scoped_array<unsigned>& numQuadsToDivide)
4209 : mPolygonPoolList(&polygons)
4210 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4211 , mPoints(points.get())
4212 , mNumQuadsToDivide(numQuadsToDivide.get())
4218 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4225 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4233 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4234 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4236 if (!edgePoly)
continue;
4238 const Vec3s& p0 = mPoints[quad[0]];
4239 const Vec3s& p1 = mPoints[quad[1]];
4240 const Vec3s& p2 = mPoints[quad[2]];
4241 const Vec3s& p3 = mPoints[quad[3]];
4250 mNumQuadsToDivide[n] = count;
4256 uint8_t
const *
const mPointFlags;
4257 Vec3s const *
const mPoints;
4258 unsigned *
const mNumQuadsToDivide;
4265 const boost::scoped_array<openvdb::Vec3s>& points,
4267 boost::scoped_array<openvdb::Vec3s>& centroids,
4268 boost::scoped_array<unsigned>& numQuadsToDivide,
4269 boost::scoped_array<unsigned>& centroidOffsets)
4270 : mPolygonPoolList(&polygons)
4271 , mPoints(points.get())
4272 , mCentroids(centroids.get())
4273 , mNumQuadsToDivide(numQuadsToDivide.get())
4274 , mCentroidOffsets(centroidOffsets.get())
4275 , mPointCount(pointCount)
4281 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4285 const size_t nonplanarCount = size_t(mNumQuadsToDivide[n]);
4287 if (nonplanarCount > 0) {
4293 size_t offset = mCentroidOffsets[n];
4295 size_t triangleIdx = 0;
4297 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4299 const char quadFlags = polygons.
quadFlags(i);
4302 unsigned newPointIdx = unsigned(offset + mPointCount);
4306 mCentroids[offset] = (mPoints[quad[0]] + mPoints[quad[1]] +
4307 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25f;
4314 triangle[0] = quad[0];
4315 triangle[1] = newPointIdx;
4316 triangle[2] = quad[3];
4326 triangle[0] = quad[0];
4327 triangle[1] = quad[1];
4328 triangle[2] = newPointIdx;
4338 triangle[0] = quad[1];
4339 triangle[1] = quad[2];
4340 triangle[2] = newPointIdx;
4351 triangle[0] = quad[2];
4352 triangle[1] = quad[3];
4353 triangle[2] = newPointIdx;
4364 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4371 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4375 tmpPolygons.
quad(quadIdx) = quad;
4381 polygons.
copy(tmpPolygons);
4388 Vec3s const *
const mPoints;
4389 Vec3s *
const mCentroids;
4390 unsigned *
const mNumQuadsToDivide;
4391 unsigned *
const mCentroidOffsets;
4392 size_t const mPointCount;
4399 size_t polygonPoolListSize,
4401 size_t& pointListSize,
4402 std::vector<uint8_t>& pointFlags)
4404 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4406 boost::scoped_array<unsigned> numQuadsToDivide(
new unsigned[polygonPoolListSize]);
4408 tbb::parallel_for(polygonPoolListRange,
4411 boost::scoped_array<unsigned> centroidOffsets(
new unsigned[polygonPoolListSize]);
4413 size_t centroidCount = 0;
4417 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4418 centroidOffsets[n] = sum;
4419 sum += numQuadsToDivide[n];
4421 centroidCount = size_t(sum);
4424 boost::scoped_array<Vec3s> centroidList(
new Vec3s[centroidCount]);
4426 tbb::parallel_for(polygonPoolListRange,
4428 centroidList, numQuadsToDivide, centroidOffsets));
4430 if (centroidCount > 0) {
4432 const size_t newPointListSize = centroidCount + pointListSize;
4434 boost::scoped_array<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointListSize]);
4436 tbb::parallel_for(tbb::blocked_range<size_t>(0, pointListSize),
4439 tbb::parallel_for(tbb::blocked_range<size_t>(0, newPointListSize - pointListSize),
4442 pointListSize = newPointListSize;
4443 pointList.swap(newPointList);
4444 pointFlags.resize(pointListSize, 0);
4452 const std::vector<uint8_t>& pointFlags)
4453 : mPolygonPoolList(&polygons)
4454 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4460 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4464 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4472 const bool hasSeamLinePoint =
4473 mPointFlags[verts[0]] || mPointFlags[verts[1]] ||
4474 mPointFlags[verts[2]] || mPointFlags[verts[3]];
4476 if (!hasSeamLinePoint) {
4477 flags &= ~POLYFLAG_FRACTURE_SEAM;
4482 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4490 const bool hasSeamLinePoint =
4491 mPointFlags[verts[0]] || mPointFlags[verts[1]] || mPointFlags[verts[2]];
4493 if (!hasSeamLinePoint) {
4494 flags &= ~POLYFLAG_FRACTURE_SEAM;
4505 uint8_t
const *
const mPointFlags;
4511 std::vector<uint8_t>& pointFlags)
4513 tbb::parallel_for(tbb::blocked_range<size_t>(0, polygonPoolListSize),
4521 template<
typename InputTreeType>
4525 const PointList& pointList, boost::scoped_array<uint8_t>& pointMask,
4527 : mInputTree(&inputTree)
4528 , mPolygonPoolList(&polygons)
4529 , mPointList(&pointList)
4530 , mPointMask(pointMask.get())
4531 , mTransform(transform)
4532 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4538 using ValueType =
typename InputTreeType::LeafNodeType::ValueType;
4541 Vec3s centroid, normal;
4544 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<ValueType>();
4546 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4548 const PolygonPool& polygons = (*mPolygonPoolList)[n];
4550 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4554 const Vec3s& v0 = (*mPointList)[verts[0]];
4555 const Vec3s& v1 = (*mPointList)[verts[1]];
4556 const Vec3s& v2 = (*mPointList)[verts[2]];
4558 normal = (v2 - v0).cross((v1 - v0));
4561 centroid = (v0 + v1 + v2) * (1.0f / 3.0f);
4562 ijk = mTransform.worldToIndexCellCentered(centroid);
4567 if (invertGradientDir) {
4572 if (dir.dot(normal) < -0.5f) {
4577 mPointMask[verts[0]] = 1;
4578 mPointMask[verts[1]] = 1;
4579 mPointMask[verts[2]] = 1;
4588 InputTreeType
const *
const mInputTree;
4591 uint8_t *
const mPointMask;
4593 bool const mInvertSurfaceOrientation;
4597 template<
typename InputTree>
4600 bool invertSurfaceOrientation,
4601 const InputTree& inputTree,
4604 size_t polygonPoolListSize,
4606 const size_t pointListSize)
4608 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4610 boost::scoped_array<uint8_t> pointMask(
new uint8_t[pointListSize]);
4611 fillArray(pointMask.get(), uint8_t(0), pointListSize);
4613 tbb::parallel_for(polygonPoolListRange,
4615 inputTree, polygonPoolList, pointList, pointMask, transform, invertSurfaceOrientation));
4617 boost::scoped_array<uint8_t> pointUpdates(
new uint8_t[pointListSize]);
4618 fillArray(pointUpdates.get(), uint8_t(0), pointListSize);
4620 boost::scoped_array<Vec3s> newPoints(
new Vec3s[pointListSize]);
4621 fillArray(newPoints.get(),
Vec3s(0.0f, 0.0f, 0.0f), pointListSize);
4623 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4627 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4630 for (
int v = 0; v < 4; ++v) {
4632 const unsigned pointIdx = verts[v];
4634 if (pointMask[pointIdx] == 1) {
4636 newPoints[pointIdx] +=
4637 pointList[verts[0]] + pointList[verts[1]] +
4638 pointList[verts[2]] + pointList[verts[3]];
4640 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 4);
4645 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4648 for (
int v = 0; v < 3; ++v) {
4650 const unsigned pointIdx = verts[v];
4652 if (pointMask[pointIdx] == 1) {
4653 newPoints[pointIdx] +=
4654 pointList[verts[0]] + pointList[verts[1]] + pointList[verts[2]];
4656 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 3);
4662 for (
size_t n = 0, N = pointListSize; n < N; ++n) {
4663 if (pointUpdates[n] > 0) {
4664 const double weight = 1.0 / double(pointUpdates[n]);
4665 pointList[n] = newPoints[n] * float(weight);
4682 , mTriangles(nullptr)
4683 , mQuadFlags(nullptr)
4684 , mTriangleFlags(nullptr)
4691 : mNumQuads(numQuads)
4692 , mNumTriangles(numTriangles)
4695 , mQuadFlags(new char[mNumQuads])
4696 , mTriangleFlags(new char[mNumTriangles])
4707 for (
size_t i = 0; i < mNumQuads; ++i) {
4708 mQuads[i] = rhs.mQuads[i];
4709 mQuadFlags[i] = rhs.mQuadFlags[i];
4712 for (
size_t i = 0; i < mNumTriangles; ++i) {
4713 mTriangles[i] = rhs.mTriangles[i];
4714 mTriangleFlags[i] = rhs.mTriangleFlags[i];
4724 mQuadFlags.reset(
new char[mNumQuads]);
4732 mQuads.reset(
nullptr);
4733 mQuadFlags.reset(
nullptr);
4740 mNumTriangles = size;
4742 mTriangleFlags.reset(
new char[mNumTriangles]);
4750 mTriangles.reset(
nullptr);
4751 mTriangleFlags.reset(
nullptr);
4758 if (!(n < mNumQuads))
return false;
4763 mQuads.reset(
nullptr);
4766 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
4767 boost::scoped_array<char> flags(
new char[n]);
4769 for (
size_t i = 0; i < n; ++i) {
4770 quads[i] = mQuads[i];
4771 flags[i] = mQuadFlags[i];
4775 mQuadFlags.swap(flags);
4787 if (!(n < mNumTriangles))
return false;
4792 mTriangles.reset(
nullptr);
4795 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
4796 boost::scoped_array<char> flags(
new char[n]);
4798 for (
size_t i = 0; i < n; ++i) {
4799 triangles[i] = mTriangles[i];
4800 flags[i] = mTriangleFlags[i];
4803 mTriangles.swap(triangles);
4804 mTriangleFlags.swap(flags);
4821 , mSeamPointListSize(0)
4822 , mPolygonPoolListSize(0)
4823 , mIsovalue(isovalue)
4824 , mPrimAdaptivity(adaptivity)
4825 , mSecAdaptivity(0.0)
4827 , mSurfaceMaskGrid(
GridBase::ConstPtr())
4828 , mAdaptivityGrid(
GridBase::ConstPtr())
4829 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
4832 , mInvertSurfaceMask(false)
4833 , mRelaxDisorientedTriangles(relaxDisorientedTriangles)
4834 , mQuantizedSeamPoints(nullptr)
4844 mSecAdaptivity = secAdaptivity;
4849 mSeamPointListSize = 0;
4850 mQuantizedSeamPoints.reset(
nullptr);
4857 mSurfaceMaskGrid = mask;
4858 mInvertSurfaceMask = invertMask;
4865 mAdaptivityGrid = grid;
4872 mAdaptivityMaskTree = tree;
4876 template<
typename InputGr
idType>
4882 using InputTreeType =
typename InputGridType::TreeType;
4883 using InputLeafNodeType =
typename InputTreeType::LeafNodeType;
4884 using InputValueType =
typename InputLeafNodeType::ValueType;
4888 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
4890 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
4891 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
4892 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
4893 using Index32TreeType =
typename InputTreeType::template ValueConverter<Index32>::Type;
4894 using Index32LeafNodeType =
typename Index32TreeType::LeafNodeType;
4899 mPolygonPoolListSize = 0;
4901 mPointFlags.clear();
4906 const InputValueType isovalue = InputValueType(mIsovalue);
4907 const float adaptivityThreshold = float(mPrimAdaptivity);
4908 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4914 const bool invertSurfaceOrientation = (!volume_to_mesh_internal::isBoolValue<InputValueType>()
4919 const InputTreeType& inputTree = inputGrid.tree();
4921 BoolTreeType intersectionTree(
false), adaptivityMask(
false);
4923 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeType::treeType()) {
4924 const BoolTreeType *refAdaptivityMask=
4925 static_cast<const BoolTreeType*
>(mAdaptivityMaskTree.get());
4926 adaptivityMask.topologyUnion(*refAdaptivityMask);
4929 Int16TreeType signFlagsTree(0);
4930 Index32TreeType pointIndexTree(boost::integer_traits<Index32>::const_max);
4936 intersectionTree, inputTree, isovalue);
4939 inputGrid, mSurfaceMaskGrid, mInvertSurfaceMask, isovalue);
4941 if (intersectionTree.empty())
return;
4944 signFlagsTree, pointIndexTree, intersectionTree, inputTree, isovalue);
4946 intersectionTree.clear();
4948 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
4949 pointIndexTree.getNodes(pointIndexLeafNodes);
4951 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
4952 signFlagsTree.getNodes(signFlagsLeafNodes);
4954 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
4959 Int16TreeType* refSignFlagsTree =
nullptr;
4960 Index32TreeType* refPointIndexTree =
nullptr;
4961 InputTreeType
const* refInputTree =
nullptr;
4963 if (mRefGrid && mRefGrid->type() == InputGridType::gridType()) {
4965 const InputGridType* refGrid =
static_cast<const InputGridType*
>(mRefGrid.get());
4966 refInputTree = &refGrid->tree();
4968 if (!mRefSignTree && !mRefIdxTree) {
4972 typename Int16TreeType::Ptr refSignFlagsTreePt(
new Int16TreeType(0));
4973 typename Index32TreeType::Ptr refPointIndexTreePt(
4974 new Index32TreeType(boost::integer_traits<Index32>::const_max));
4976 BoolTreeType refIntersectionTree(
false);
4979 refIntersectionTree, *refInputTree, isovalue);
4982 *refPointIndexTreePt, refIntersectionTree, *refInputTree, isovalue);
4984 mRefSignTree = refSignFlagsTreePt;
4985 mRefIdxTree = refPointIndexTreePt;
4988 if (mRefSignTree && mRefIdxTree) {
4992 refSignFlagsTree =
static_cast<Int16TreeType*
>(mRefSignTree.get());
4993 refPointIndexTree =
static_cast<Index32TreeType*
>(mRefIdxTree.get());
4997 if (refSignFlagsTree && refPointIndexTree) {
5003 if (mSeamPointListSize == 0) {
5007 std::vector<Int16LeafNodeType*> refSignFlagsLeafNodes;
5008 refSignFlagsTree->getNodes(refSignFlagsLeafNodes);
5010 boost::scoped_array<Index32> leafNodeOffsets(
5011 new Index32[refSignFlagsLeafNodes.size()]);
5013 tbb::parallel_for(tbb::blocked_range<size_t>(0, refSignFlagsLeafNodes.size()),
5015 refSignFlagsLeafNodes, leafNodeOffsets));
5019 for (
size_t n = 0, N = refSignFlagsLeafNodes.size(); n < N; ++n) {
5020 const Index32 tmp = leafNodeOffsets[n];
5021 leafNodeOffsets[n] = count;
5024 mSeamPointListSize = size_t(count);
5027 if (mSeamPointListSize != 0) {
5029 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
5031 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
5033 std::vector<Index32LeafNodeType*> refPointIndexLeafNodes;
5034 refPointIndexTree->getNodes(refPointIndexLeafNodes);
5036 tbb::parallel_for(tbb::blocked_range<size_t>(0, refPointIndexLeafNodes.size()),
5038 refPointIndexLeafNodes, refSignFlagsLeafNodes, leafNodeOffsets));
5042 if (mSeamPointListSize != 0) {
5044 tbb::parallel_for(auxiliaryLeafNodeRange,
5046 signFlagsLeafNodes, inputTree, *refPointIndexTree, *refSignFlagsTree,
5047 mQuantizedSeamPoints.get(), isovalue));
5052 const bool referenceMeshing = refSignFlagsTree && refPointIndexTree && refInputTree;
5057 boost::scoped_array<Index32> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
5061 inputGrid, pointIndexTree, pointIndexLeafNodes, signFlagsLeafNodes,
5062 isovalue, adaptivityThreshold, invertSurfaceOrientation);
5064 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridType::gridType()) {
5065 const FloatGridType* adaptivityGrid =
5066 static_cast<const FloatGridType*
>(mAdaptivityGrid.get());
5070 if (!adaptivityMask.empty()) {
5074 if (referenceMeshing) {
5078 tbb::parallel_for(auxiliaryLeafNodeRange, mergeOp);
5081 op(pointIndexLeafNodes, signFlagsLeafNodes, leafNodeOffsets);
5083 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5088 op(signFlagsLeafNodes, leafNodeOffsets);
5090 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5096 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
5097 const Index32 tmp = leafNodeOffsets[n];
5102 mPointListSize = size_t(pointCount);
5104 mPointFlags.clear();
5112 op(mPoints.get(), inputTree, pointIndexLeafNodes,
5113 signFlagsLeafNodes, leafNodeOffsets, transform, mIsovalue);
5115 if (referenceMeshing) {
5116 mPointFlags.resize(mPointListSize);
5117 op.setRefData(*refInputTree, *refPointIndexTree, *refSignFlagsTree,
5118 mQuantizedSeamPoints.get(), &mPointFlags.front());
5121 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5127 mPolygonPoolListSize = signFlagsLeafNodes.size();
5128 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
5135 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5136 mPolygons, invertSurfaceOrientation);
5138 if (referenceMeshing) {
5142 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5149 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5150 mPolygons, invertSurfaceOrientation);
5152 if (referenceMeshing) {
5156 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5160 signFlagsTree.clear();
5161 pointIndexTree.clear();
5164 if (adaptive && mRelaxDisorientedTriangles) {
5166 inputTree, transform, mPolygons, mPolygonPoolListSize, mPoints, mPointListSize);
5170 if (referenceMeshing) {
5172 mPolygons, mPolygonPoolListSize, mPoints, mPointListSize, mPointFlags);
5187 template<
typename Gr
idType>
5188 inline typename std::enable_if<std::is_scalar<typename GridType::ValueType>::value,
void>::type
5190 const GridType& grid,
5191 std::vector<Vec3s>& points,
5192 std::vector<Vec3I>& triangles,
5193 std::vector<Vec4I>& quads,
5198 VolumeToMesh mesher(isovalue, adaptivity, relaxDisorientedTriangles);
5207 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
5214 size_t numQuads = 0, numTriangles = 0;
5216 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5217 numTriangles += polygons.numTriangles();
5218 numQuads += polygons.numQuads();
5222 triangles.resize(numTriangles);
5224 quads.resize(numQuads);
5228 size_t qIdx = 0, tIdx = 0;
5230 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5232 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
5233 quads[qIdx++] = polygons.quad(i);
5236 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
5237 triangles[tIdx++] = polygons.triangle(i);
5243 template<
typename Gr
idType>
5244 inline typename std::enable_if<!std::is_scalar<typename GridType::ValueType>::value,
void>::type
5247 std::vector<Vec3s>&,
5248 std::vector<Vec3I>&,
5249 std::vector<Vec4I>&,
5261 template<
typename Gr
idType>
5264 const GridType& grid,
5265 std::vector<Vec3s>& points,
5266 std::vector<Vec3I>& triangles,
5267 std::vector<Vec4I>& quads,
5270 bool relaxDisorientedTriangles)
5272 doVolumeToMesh(grid, points, triangles, quads, isovalue, adaptivity, relaxDisorientedTriangles);
5276 template<
typename Gr
idType>
5279 const GridType& grid,
5280 std::vector<Vec3s>& points,
5281 std::vector<Vec4I>& quads,
5284 std::vector<Vec3I> triangles;
5285 doVolumeToMesh(grid, points, triangles, quads, isovalue, 0.0,
true);
5292 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:241
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:502
Abstract base class for typed grids.
Definition: Grid.h:104
Vec3< int32_t > Vec3i
Definition: Vec3.h:676
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
Coord & reset(Int32 x, Int32 y, Int32 z)
Reset all three coordinates with the specified arguments.
Definition: Coord.h:96
Definition: Exceptions.h:90
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:110
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:320
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:263
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:108
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:266
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:147
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:108
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:201
Gradient operators defined in index space of various orders.
Definition: Operators.h:123
Vec3< double > Vec3d
Definition: Vec3.h:679
SharedPtr< TreeBase > Ptr
Definition: Tree.h:65
const Coord & min() const
Definition: Coord.h:337
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1087
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:422
Base class for typed trees.
Definition: Tree.h:62
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:797
Mat3< double > Mat3d
Definition: Mat3.h:699
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
uint32_t Index32
Definition: Types.h:58
Index32 Index
Definition: Types.h:60
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
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:287
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:216
Definition: Exceptions.h:91
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
Definition: Exceptions.h:39
SharedPtr< const TreeBase > ConstPtr
Definition: Tree.h:66
Vec4< int32_t > Vec4i
Definition: Vec4.h:584
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:377
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118
Definition: LeafNode.h:236
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:275
int16_t Int16
Definition: Types.h:61
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:393
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1062
static const Index DIM
Definition: LeafNode.h:77
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:429
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:374
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
const Coord & max() const
Definition: Coord.h:338
Vec3< float > Vec3s
Definition: Vec3.h:678
bool diagonalizeSymmetricMatrix(const Mat3< T > &input, Mat3< T > &Q, Vec3< T > &D, unsigned int MAX_ITERATIONS=250)
Use Jacobi iterations to decompose a symmetric 3x3 matrix (diagonalize and compute eigenvectors) ...
Definition: Mat3.h:789
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:64
T & z()
Definition: Vec3.h:112
OPENVDB_API const Index32 INVALID_IDX