37 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 45 #include <boost/scoped_array.hpp> 47 #include <tbb/blocked_range.h> 48 #include <tbb/parallel_for.h> 49 #include <tbb/parallel_reduce.h> 50 #include <tbb/task_scheduler_init.h> 56 #include <type_traits> 80 template<
typename Gr
idType>
84 std::vector<Vec3s>& points,
85 std::vector<Vec4I>& quads,
86 double isovalue = 0.0);
101 template<
typename Gr
idType>
104 const GridType& grid,
105 std::vector<Vec3s>& points,
106 std::vector<Vec3I>& triangles,
107 std::vector<Vec4I>& quads,
108 double isovalue = 0.0,
109 double adaptivity = 0.0,
126 inline PolygonPool(
const size_t numQuads,
const size_t numTriangles);
130 inline void resetQuads(
size_t size);
131 inline void clearQuads();
133 inline void resetTriangles(
size_t size);
134 inline void clearTriangles();
139 const size_t&
numQuads()
const {
return mNumQuads; }
154 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
163 inline bool trimQuads(
const size_t n,
bool reallocate =
false);
164 inline bool trimTrinagles(
const size_t n,
bool reallocate =
false);
170 size_t mNumQuads, mNumTriangles;
171 boost::scoped_array<openvdb::Vec4I> mQuads;
172 boost::scoped_array<openvdb::Vec3I> mTriangles;
173 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
201 const size_t& pointListSize()
const;
204 const size_t& polygonPoolListSize()
const;
208 std::vector<uint8_t>& pointFlags();
209 const std::vector<uint8_t>& pointFlags()
const;
217 template<
typename InputGr
idType>
218 void operator()(
const InputGridType&);
271 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
272 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
279 bool mInvertSurfaceMask, mRelaxDisorientedTriangles;
281 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
282 std::vector<uint8_t> mPointFlags;
296 const std::vector<Vec3d>& points,
297 const std::vector<Vec3d>& normals)
303 if (points.empty())
return avgPos;
305 for (
size_t n = 0, N = points.size(); n < N; ++n) {
309 avgPos /= double(points.size());
313 double m00=0,m01=0,m02=0,
320 for (
size_t n = 0, N = points.size(); n < N; ++n) {
322 const Vec3d& n_ref = normals[n];
325 m00 += n_ref[0] * n_ref[0];
326 m11 += n_ref[1] * n_ref[1];
327 m22 += n_ref[2] * n_ref[2];
329 m01 += n_ref[0] * n_ref[1];
330 m02 += n_ref[0] * n_ref[2];
331 m12 += n_ref[1] * n_ref[2];
334 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
359 Mat3d D = Mat3d::identity();
362 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
363 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
367 for (
int i = 0; i < 3; ++i ) {
368 if (std::abs(eigenValues[i]) < tolerance) {
372 D[i][i] = 1.0 / eigenValues[i];
379 return avgPos + pseudoInv * rhs;
393 namespace volume_to_mesh_internal {
395 template<
typename ValueType>
398 FillArray(ValueType* array,
const ValueType& v) : mArray(array), mValue(v) { }
400 void operator()(
const tbb::blocked_range<size_t>& range)
const {
401 const ValueType v = mValue;
402 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
412 template<
typename ValueType>
414 fillArray(ValueType* array,
const ValueType& val,
const size_t length)
416 const auto grainSize = std::max<size_t>(
417 length / tbb::task_scheduler_init::default_num_threads(), 1024);
418 const tbb::blocked_range<size_t> range(0, length, grainSize);
430 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,
431 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,
432 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,
433 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,
434 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,
435 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,
436 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,
437 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};
442 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,
443 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,
444 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,
445 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,
446 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,
447 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,
448 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,
449 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};
456 {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},
457 {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},
458 {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},
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {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},
497 {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},
498 {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},
499 {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},
500 {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},
501 {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},
502 {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},
503 {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},
504 {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},
505 {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},
506 {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},
507 {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},
508 {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},
509 {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},
510 {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},
511 {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},
512 {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},
513 {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},
514 {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},
515 {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},
516 {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},
517 {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},
518 {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},
519 {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},
520 {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},
521 {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},
522 {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},
523 {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},
524 {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},
525 {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},
526 {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},
527 {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},
528 {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},
529 {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},
530 {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},
531 {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},
532 {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},
533 {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},
534 {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},
535 {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},
536 {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},
537 {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},
538 {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},
539 {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},
540 {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},
541 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
550 double epsilon = 0.001)
553 Vec3d normal = (p2-p0).cross(p1-p3);
555 const Vec3d centroid = (p0 + p1 + p2 + p3);
556 const double d = centroid.
dot(normal) * 0.25;
560 double absDist = std::abs(p0.dot(normal) - d);
561 if (absDist > epsilon)
return false;
563 absDist = std::abs(p1.dot(normal) - d);
564 if (absDist > epsilon)
return false;
566 absDist = std::abs(p2.dot(normal) - d);
567 if (absDist > epsilon)
return false;
569 absDist = std::abs(p3.dot(normal) - d);
570 if (absDist > epsilon)
return false;
594 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
595 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
610 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
612 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
636 template<
typename AccessorT>
641 values[0] = accessor.getValue(ijk);
643 values[1] = accessor.getValue(ijk);
645 values[2] = accessor.getValue(ijk);
647 values[3] = accessor.getValue(ijk);
649 values[4] = accessor.getValue(ijk);
651 values[5] = accessor.getValue(ijk);
653 values[6] = accessor.getValue(ijk);
655 values[7] = accessor.getValue(ijk);
659 template<
typename LeafT>
664 values[0] = leaf.getValue(offset);
665 values[3] = leaf.getValue(offset + 1);
666 values[4] = leaf.getValue(offset + LeafT::DIM);
667 values[7] = leaf.getValue(offset + LeafT::DIM + 1);
668 values[1] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM));
669 values[2] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1);
670 values[5] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM);
671 values[6] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1);
675 template<
typename ValueType>
688 return uint8_t(signs);
694 template<
typename AccessorT>
700 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 1u;
702 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 2u;
704 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 4u;
706 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 8u;
707 coord[1] += 1; coord[2] = ijk[2];
708 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 16u;
710 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 32u;
712 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 64u;
714 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 128u;
715 return uint8_t(signs);
721 template<
typename LeafT>
731 if (
isInsideValue(leaf.getValue(offset + 1), iso)) signs |= 8u;
734 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM), iso)) signs |= 16u;
737 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM + 1), iso)) signs |= 128u;
740 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ), iso)) signs |= 2u;
743 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1), iso)) signs |= 4u;
746 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM), iso)) signs |= 32u;
749 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1), iso)) signs |= 64u;
751 return uint8_t(signs);
757 template<
class AccessorT>
760 const AccessorT& acc,
Coord ijk,
typename AccessorT::ValueType iso)
765 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 3) signs = uint8_t(~signs);
769 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 4) signs = uint8_t(~signs);
773 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 1) signs = uint8_t(~signs);
777 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 2) signs = uint8_t(~signs);
781 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 6) signs = uint8_t(~signs);
785 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 5) signs = uint8_t(~signs);
793 template<
class AccessorT>
796 typename AccessorT::ValueType isovalue,
const int dim)
809 coord[1] += dim; coord[2] = ijk[2];
820 if (p[0]) signs |= 1u;
821 if (p[1]) signs |= 2u;
822 if (p[2]) signs |= 4u;
823 if (p[3]) signs |= 8u;
824 if (p[4]) signs |= 16u;
825 if (p[5]) signs |= 32u;
826 if (p[6]) signs |= 64u;
827 if (p[7]) signs |= 128u;
828 if (!sAdaptable[signs])
return true;
833 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
834 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
835 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
838 coord.
reset(ip, j, k);
840 if (p[0] != m && p[1] != m)
return true;
843 coord.reset(ipp, j, kp);
845 if (p[1] != m && p[2] != m)
return true;
848 coord.reset(ip, j, kpp);
850 if (p[2] != m && p[3] != m)
return true;
853 coord.reset(i, j, kp);
855 if (p[0] != m && p[3] != m)
return true;
858 coord.reset(ip, jpp, k);
860 if (p[4] != m && p[5] != m)
return true;
863 coord.reset(ipp, jpp, kp);
865 if (p[5] != m && p[6] != m)
return true;
868 coord.reset(ip, jpp, kpp);
870 if (p[6] != m && p[7] != m)
return true;
873 coord.reset(i, jpp, kp);
875 if (p[7] != m && p[4] != m)
return true;
878 coord.reset(i, jp, k);
880 if (p[0] != m && p[4] != m)
return true;
883 coord.reset(ipp, jp, k);
885 if (p[1] != m && p[5] != m)
return true;
888 coord.reset(ipp, jp, kpp);
890 if (p[2] != m && p[6] != m)
return true;
894 coord.reset(i, jp, kpp);
896 if (p[3] != m && p[7] != m)
return true;
902 coord.reset(ip, jp, k);
904 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
907 coord.reset(ipp, jp, kp);
909 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
912 coord.reset(ip, jp, kpp);
914 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
917 coord.reset(i, jp, kp);
919 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
922 coord.reset(ip, j, kp);
924 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
927 coord.reset(ip, jpp, kp);
929 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
932 coord.reset(ip, jp, kp);
934 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
935 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
944 template <
class LeafType>
948 Coord ijk, end = start;
953 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
954 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
955 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
956 leaf.setValueOnly(ijk, regionId);
965 template <
class LeafType>
968 typename LeafType::ValueType::value_type adaptivity)
970 if (adaptivity < 1e-6)
return false;
972 using VecT =
typename LeafType::ValueType;
973 Coord ijk, end = start;
978 std::vector<VecT> norms;
979 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
980 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
981 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
983 if(!leaf.isValueOn(ijk))
continue;
984 norms.push_back(leaf.getValue(ijk));
989 size_t N = norms.size();
990 for (
size_t ni = 0; ni < N; ++ni) {
991 VecT n_i = norms[ni];
992 for (
size_t nj = 0; nj < N; ++nj) {
993 VecT n_j = norms[nj];
994 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
1005 inline double evalZeroCrossing(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1009 template<
typename LeafT>
1013 values[0] = double(leaf.getValue(offset));
1014 values[3] = double(leaf.getValue(offset + 1));
1015 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1016 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1017 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1018 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1019 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1020 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1025 template<
typename AccessorT>
1030 values[0] = double(acc.getValue(coord));
1033 values[1] = double(acc.getValue(coord));
1036 values[2] = double(acc.getValue(coord));
1039 values[3] = double(acc.getValue(coord));
1041 coord[1] += 1; coord[2] = ijk[2];
1042 values[4] = double(acc.getValue(coord));
1045 values[5] = double(acc.getValue(coord));
1048 values[6] = double(acc.getValue(coord));
1051 values[7] = double(acc.getValue(coord));
1058 unsigned char edgeGroup,
double iso)
1060 Vec3d avg(0.0, 0.0, 0.0);
1063 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1068 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1074 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1080 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1085 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1091 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1098 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1105 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1111 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1116 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1122 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1129 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1136 double w = 1.0 / double(samples);
1150 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1152 avg =
Vec3d(0.0, 0.0, 0.0);
1155 if (sEdgeGroupTable[signs][1] == edgeGroup
1156 && sEdgeGroupTable[signsMask][1] == 0) {
1161 if (sEdgeGroupTable[signs][2] == edgeGroup
1162 && sEdgeGroupTable[signsMask][2] == 0) {
1168 if (sEdgeGroupTable[signs][3] == edgeGroup
1169 && sEdgeGroupTable[signsMask][3] == 0) {
1175 if (sEdgeGroupTable[signs][4] == edgeGroup
1176 && sEdgeGroupTable[signsMask][4] == 0) {
1181 if (sEdgeGroupTable[signs][5] == edgeGroup
1182 && sEdgeGroupTable[signsMask][5] == 0) {
1188 if (sEdgeGroupTable[signs][6] == edgeGroup
1189 && sEdgeGroupTable[signsMask][6] == 0) {
1196 if (sEdgeGroupTable[signs][7] == edgeGroup
1197 && sEdgeGroupTable[signsMask][7] == 0) {
1204 if (sEdgeGroupTable[signs][8] == edgeGroup
1205 && sEdgeGroupTable[signsMask][8] == 0) {
1211 if (sEdgeGroupTable[signs][9] == edgeGroup
1212 && sEdgeGroupTable[signsMask][9] == 0) {
1217 if (sEdgeGroupTable[signs][10] == edgeGroup
1218 && sEdgeGroupTable[signsMask][10] == 0) {
1224 if (sEdgeGroupTable[signs][11] == edgeGroup
1225 && sEdgeGroupTable[signsMask][11] == 0) {
1232 if (sEdgeGroupTable[signs][12] == edgeGroup
1233 && sEdgeGroupTable[signsMask][12] == 0) {
1240 double w = 1.0 / double(samples);
1254 unsigned char signs,
unsigned char edgeGroup,
double iso)
1256 std::vector<Vec3d> samples;
1259 std::vector<double> weights;
1262 Vec3d avg(0.0, 0.0, 0.0);
1264 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1269 samples.push_back(avg);
1270 weights.push_back((avg-p).lengthSqr());
1273 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1278 samples.push_back(avg);
1279 weights.push_back((avg-p).lengthSqr());
1282 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1287 samples.push_back(avg);
1288 weights.push_back((avg-p).lengthSqr());
1291 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1296 samples.push_back(avg);
1297 weights.push_back((avg-p).lengthSqr());
1300 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1305 samples.push_back(avg);
1306 weights.push_back((avg-p).lengthSqr());
1309 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1314 samples.push_back(avg);
1315 weights.push_back((avg-p).lengthSqr());
1318 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1323 samples.push_back(avg);
1324 weights.push_back((avg-p).lengthSqr());
1327 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1332 samples.push_back(avg);
1333 weights.push_back((avg-p).lengthSqr());
1336 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1341 samples.push_back(avg);
1342 weights.push_back((avg-p).lengthSqr());
1345 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1350 samples.push_back(avg);
1351 weights.push_back((avg-p).lengthSqr());
1354 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1359 samples.push_back(avg);
1360 weights.push_back((avg-p).lengthSqr());
1363 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1368 samples.push_back(avg);
1369 weights.push_back((avg-p).lengthSqr());
1376 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1377 minWeight =
std::min(minWeight, weights[i]);
1378 maxWeight =
std::max(maxWeight, weights[i]);
1381 const double offset = maxWeight + minWeight * 0.1;
1382 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1383 weights[i] = offset - weights[i];
1387 double weightSum = 0.0;
1388 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1389 weightSum += weights[i];
1396 if (samples.size() > 1) {
1397 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1398 avg += samples[i] * (weights[i] / weightSum);
1401 avg = samples.front();
1412 const std::vector<double>& values,
unsigned char signs,
double iso)
1414 for (
size_t n = 1, N = sEdgeGroupTable[signs][0] + 1; n < N; ++n) {
1415 points.push_back(
computePoint(values, signs, uint8_t(n), iso));
1424 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1427 for (
size_t i = 1; i <= 12; ++i) {
1428 if (sEdgeGroupTable[lhsSigns][i] == groupId && sEdgeGroupTable[rhsSigns][i] != 0) {
1429 id = sEdgeGroupTable[rhsSigns][i];
1443 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1444 unsigned char lhsSigns,
unsigned char rhsSigns,
1445 double iso,
size_t pointIdx,
const uint32_t * seamPointArray)
1447 for (
size_t n = 1, N = sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1453 const unsigned char e = uint8_t(
id);
1454 const uint32_t& quantizedPoint = seamPointArray[pointIdx + (
id - 1)];
1459 weightedPointMask.push_back(
true);
1461 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1462 weightedPointMask.push_back(
false);
1466 points.push_back(
computePoint(lhsValues, lhsSigns, uint8_t(n), iso));
1467 weightedPointMask.push_back(
false);
1473 template <
typename InputTreeType>
1479 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1486 const InputTreeType& inputTree,
1487 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1488 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1489 const boost::scoped_array<Index32>& leafNodeOffsets,
1493 void setRefData(
const InputTreeType& refInputTree,
1496 const uint32_t * quantizedSeamLinePoints,
1497 uint8_t * seamLinePointsFlags);
1499 void operator()(
const tbb::blocked_range<size_t>&)
const;
1502 Vec3s *
const mPoints;
1503 InputTreeType
const *
const mInputTree;
1506 Index32 const *
const mNodeOffsets;
1508 double const mIsovalue;
1510 InputTreeType
const * mRefInputTree;
1513 uint32_t
const * mQuantizedSeamLinePoints;
1514 uint8_t * mSeamLinePointsFlags;
1518 template <
typename InputTreeType>
1521 const InputTreeType& inputTree,
1522 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1523 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1524 const boost::scoped_array<Index32>& leafNodeOffsets,
1527 : mPoints(pointArray)
1528 , mInputTree(&inputTree)
1529 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
1530 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1531 , mNodeOffsets(leafNodeOffsets.get())
1534 , mRefInputTree(nullptr)
1535 , mRefPointIndexTree(nullptr)
1536 , mRefSignFlagsTree(nullptr)
1537 , mQuantizedSeamLinePoints(nullptr)
1538 , mSeamLinePointsFlags(nullptr)
1542 template <
typename InputTreeType>
1545 const InputTreeType& refInputTree,
1548 const uint32_t * quantizedSeamLinePoints,
1549 uint8_t * seamLinePointsFlags)
1551 mRefInputTree = &refInputTree;
1552 mRefPointIndexTree = &refPointIndexTree;
1553 mRefSignFlagsTree = &refSignFlagsTree;
1554 mQuantizedSeamLinePoints = quantizedSeamLinePoints;
1555 mSeamLinePointsFlags = seamLinePointsFlags;
1558 template <
typename InputTreeType>
1566 using IndexType =
typename Index32TreeType::ValueType;
1568 using IndexArray = std::vector<Index>;
1569 using IndexArrayMap = std::map<IndexType, IndexArray>;
1571 InputTreeAccessor inputAcc(*mInputTree);
1575 std::vector<Vec3d> points(4);
1576 std::vector<bool> weightedPointMask(4);
1577 std::vector<double> values(8), refValues(8);
1578 const double iso = mIsovalue;
1582 std::unique_ptr<InputTreeAccessor> refInputAcc;
1583 std::unique_ptr<Index32TreeAccessor> refPointIndexAcc;
1584 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
1586 const bool hasReferenceData = mRefInputTree && mRefPointIndexTree && mRefSignFlagsTree;
1588 if (hasReferenceData) {
1589 refInputAcc.reset(
new InputTreeAccessor(*mRefInputTree));
1590 refPointIndexAcc.reset(
new Index32TreeAccessor(*mRefPointIndexTree));
1591 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
1594 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1597 const Coord& origin = pointIndexNode.origin();
1607 if (hasReferenceData) {
1608 refInputNode = refInputAcc->probeConstLeaf(origin);
1609 refPointIndexNode = refPointIndexAcc->probeConstLeaf(origin);
1610 refSignFlagsNode = refSignFlagsAcc->probeConstLeaf(origin);
1613 IndexType pointOffset = IndexType(mNodeOffsets[n]);
1614 IndexArrayMap regions;
1616 for (
auto it = pointIndexNode.beginValueOn(); it; ++it) {
1617 const Index offset = it.pos();
1619 const IndexType
id = it.getValue();
1622 regions[id].push_back(offset);
1627 pointIndexNode.setValueOnly(offset, pointOffset);
1629 const Int16 flags = signFlagsNode.getValue(offset);
1630 uint8_t signs = uint8_t(
SIGNS & flags);
1631 uint8_t refSigns = 0;
1633 if ((flags &
SEAM) && refPointIndexNode && refSignFlagsNode) {
1634 if (refSignFlagsNode->isValueOn(offset)) {
1635 refSigns = uint8_t(
SIGNS & refSignFlagsNode->getValue(offset));
1639 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1641 const bool inclusiveCell = inputNode &&
1642 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1643 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1644 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1652 weightedPointMask.clear();
1654 if (refSigns == 0) {
1659 if (inclusiveCell && refInputNode) {
1664 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1665 iso, refPointIndexNode->getValue(offset), mQuantizedSeamLinePoints);
1668 xyz[0] = double(ijk[0]);
1669 xyz[1] = double(ijk[1]);
1670 xyz[2] = double(ijk[2]);
1672 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1674 Vec3d& point = points[i];
1677 if (!std::isfinite(point[0]) ||
1678 !std::isfinite(point[1]) ||
1679 !std::isfinite(point[2]))
1682 "VolumeToMesh encountered NaNs or infs in the input VDB!" 1683 " Hint: Check the input and consider using the \"Diagnostics\" tool " 1684 "to detect and resolve the NaNs.");
1690 Vec3s& pos = mPoints[pointOffset];
1691 pos[0] = float(point[0]);
1692 pos[1] = float(point[1]);
1693 pos[2] = float(point[2]);
1695 if (mSeamLinePointsFlags && !weightedPointMask.empty() && weightedPointMask[i]) {
1696 mSeamLinePointsFlags[pointOffset] = uint8_t(1);
1704 for (
typename IndexArrayMap::iterator it = regions.begin(); it != regions.end(); ++it) {
1706 Vec3d avg(0.0), point(0.0);
1709 const IndexArray& voxels = it->second;
1710 for (
size_t i = 0, I = voxels.size(); i < I; ++i) {
1712 const Index offset = voxels[i];
1713 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1715 const bool inclusiveCell = inputNode &&
1716 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1717 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1718 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1722 pointIndexNode.setValueOnly(offset, pointOffset);
1724 uint8_t signs = uint8_t(
SIGNS & signFlagsNode.getValue(offset));
1732 avg[0] += double(ijk[0]) + points[0][0];
1733 avg[1] += double(ijk[1]) + points[0][1];
1734 avg[2] += double(ijk[2]) + points[0][2];
1740 double w = 1.0 / double(count);
1748 Vec3s& pos = mPoints[pointOffset];
1749 pos[0] = float(avg[0]);
1750 pos[1] = float(avg[1]);
1751 pos[2] = float(avg[2]);
1762 template <
typename InputTreeType>
1768 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1775 const InputTreeType& inputTree,
1778 uint32_t * quantizedPoints,
1780 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1781 , mInputTree(&inputTree)
1782 , mRefPointIndexTree(&refPointIndexTree)
1783 , mRefSignFlagsTree(&refSignFlagsTree)
1784 , mQuantizedPoints(quantizedPoints)
1795 std::vector<double> values(8);
1796 const double iso = double(mIsovalue);
1800 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1803 const Coord& origin = signFlagsNode.origin();
1806 if (!refSignNode)
continue;
1810 if (!refPointIndexNode)
continue;
1814 for (
typename Int16LeafNodeType::ValueOnCIter it = signFlagsNode.cbeginValueOn();
1817 const Index offset = it.pos();
1819 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1821 const bool inclusiveCell = inputNode &&
1822 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1823 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1824 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1828 if ((it.getValue() &
SEAM) && refSignNode->isValueOn(offset)) {
1830 uint8_t lhsSigns = uint8_t(
SIGNS & it.getValue());
1831 uint8_t rhsSigns = uint8_t(
SIGNS & refSignNode->getValue(offset));
1834 if (inclusiveCell) {
1841 for (
unsigned i = 1, I = sEdgeGroupTable[lhsSigns][0] + 1; i < I; ++i) {
1847 uint32_t& data = mQuantizedPoints[
1848 refPointIndexNode->getValue(offset) + (
id - 1)];
1853 pos, values, lhsSigns, rhsSigns, uint8_t(i), iso);
1871 InputTreeType
const *
const mInputTree;
1874 uint32_t *
const mQuantizedPoints;
1879 template <
typename TreeType>
1885 const TreeType& refSignFlagsTree)
1886 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1887 , mRefSignFlagsTree(&refSignFlagsTree)
1895 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1898 const Coord& origin = signFlagsNode.origin();
1901 if (!refSignNode)
continue;
1903 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
1904 const Index offset = it.pos();
1906 uint8_t rhsSigns = uint8_t(refSignNode->getValue(offset) &
SIGNS);
1908 if (sEdgeGroupTable[rhsSigns][0] > 0) {
1910 const typename LeafNodeType::ValueType value = it.getValue();
1911 uint8_t lhsSigns = uint8_t(value &
SIGNS);
1913 if (rhsSigns != lhsSigns) {
1914 signFlagsNode.setValueOnly(offset, value |
SEAM);
1925 TreeType
const *
const mRefSignFlagsTree;
1929 template <
typename BoolTreeType,
typename SignDataType>
1938 const BoolTreeType& maskTree)
1939 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1940 , mMaskTree(&maskTree)
1948 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1951 const Coord& origin = signFlagsNode.origin();
1954 if (!maskNode)
continue;
1956 using ValueOnCIter =
typename SignDataLeafNodeType::ValueOnCIter;
1958 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
1959 const Index offset = it.pos();
1961 if (maskNode->isValueOn(offset)) {
1962 signFlagsNode.setValueOnly(offset, it.getValue() |
SEAM);
1972 BoolTreeType
const *
const mMaskTree;
1976 template <
typename TreeType>
1980 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1983 const TreeType& signFlagsTree,
1985 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1986 , mSignFlagsTree(&signFlagsTree)
1993 : mSignFlagsNodes(rhs.mSignFlagsNodes)
1994 , mSignFlagsTree(rhs.mSignFlagsTree)
2004 using ValueOnCIter =
typename LeafNodeType::ValueOnCIter;
2005 using ValueType =
typename LeafNodeType::ValueType;
2011 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2016 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
2018 const ValueType flags = it.getValue();
2020 if (!(flags &
SEAM) && (flags &
EDGES)) {
2022 ijk = it.getCoord();
2024 bool isSeamLineVoxel =
false;
2026 if (flags &
XEDGE) {
2030 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2032 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2036 if (!isSeamLineVoxel && flags &
YEDGE) {
2038 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2040 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2042 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2046 if (!isSeamLineVoxel && flags &
ZEDGE) {
2048 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2050 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2052 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2056 if (isSeamLineVoxel) {
2057 maskAcc.
setValue(it.getCoord(),
true);
2067 TreeType
const *
const mSignFlagsTree;
2073 template<
typename SignDataTreeType>
2077 using SignDataType =
typename SignDataTreeType::ValueType;
2078 using SignDataLeafNodeType =
typename SignDataTreeType::LeafNodeType;
2079 using BoolTreeType =
typename SignDataTreeType::template ValueConverter<bool>::Type;
2081 std::vector<SignDataLeafNodeType*> signFlagsLeafNodes;
2082 signFlagsTree.getNodes(signFlagsLeafNodes);
2084 const tbb::blocked_range<size_t> nodeRange(0, signFlagsLeafNodes.size());
2086 tbb::parallel_for(nodeRange,
2089 BoolTreeType seamLineMaskTree(
false);
2092 maskSeamLine(signFlagsLeafNodes, signFlagsTree, seamLineMaskTree);
2094 tbb::parallel_reduce(nodeRange, maskSeamLine);
2096 tbb::parallel_for(nodeRange,
2104 template <
typename InputGr
idType>
2111 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
2115 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
2121 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2126 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2127 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2130 bool invertSurfaceOrientation);
2134 mSpatialAdaptivityTree = &grid.
tree();
2135 mSpatialAdaptivityTransform = &grid.
transform();
2145 mRefSignFlagsTree = &signFlagsData;
2146 mInternalAdaptivity = internalAdaptivity;
2149 void operator()(
const tbb::blocked_range<size_t>&)
const;
2160 float mSurfaceAdaptivity, mInternalAdaptivity;
2161 bool mInvertSurfaceOrientation;
2170 template <
typename InputGr
idType>
2172 const InputGridType& inputGrid,
2174 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2175 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2178 bool invertSurfaceOrientation)
2179 : mInputTree(&inputGrid.tree())
2180 , mInputTransform(&inputGrid.transform())
2181 , mPointIndexTree(&pointIndexTree)
2182 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
2183 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
2185 , mSurfaceAdaptivity(adaptivity)
2186 , mInternalAdaptivity(adaptivity)
2187 , mInvertSurfaceOrientation(invertSurfaceOrientation)
2188 , mSpatialAdaptivityTree(nullptr)
2189 , mMaskTree(nullptr)
2190 , mRefSignFlagsTree(nullptr)
2191 , mSpatialAdaptivityTransform(nullptr)
2196 template <
typename InputGr
idType>
2201 using Vec3sLeafNodeType =
typename InputLeafNodeType::template ValueConverter<Vec3sType>::Type;
2209 std::unique_ptr<FloatTreeAccessor> spatialAdaptivityAcc;
2210 if (mSpatialAdaptivityTree && mSpatialAdaptivityTransform) {
2211 spatialAdaptivityAcc.reset(
new FloatTreeAccessor(*mSpatialAdaptivityTree));
2214 std::unique_ptr<BoolTreeAccessor> maskAcc;
2216 maskAcc.reset(
new BoolTreeAccessor(*mMaskTree));
2219 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
2220 if (mRefSignFlagsTree) {
2221 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
2224 InputTreeAccessor inputAcc(*mInputTree);
2225 Index32TreeAccessor pointIndexAcc(*mPointIndexTree);
2229 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<InputValueType>();
2230 std::unique_ptr<Vec3sLeafNodeType> gradientNode;
2233 const int LeafDim = InputLeafNodeType::DIM;
2235 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2237 mask.setValuesOff();
2242 const Coord& origin = pointIndexNode.origin();
2244 end[0] = origin[0] + LeafDim;
2245 end[1] = origin[1] + LeafDim;
2246 end[2] = origin[2] + LeafDim;
2251 if (maskLeaf !=
nullptr) {
2252 for (
typename BoolLeafNodeType::ValueOnCIter it = maskLeaf->cbeginValueOn();
2255 mask.setActiveState(it.getCoord() & ~1u,
true);
2260 float adaptivity = (refSignFlagsAcc && !refSignFlagsAcc->probeConstLeaf(origin)) ?
2261 mInternalAdaptivity : mSurfaceAdaptivity;
2263 bool useGradients = adaptivity < 1.0f;
2268 if (spatialAdaptivityAcc) {
2269 useGradients =
false;
2270 for (
Index offset = 0; offset < FloatLeafNodeType::NUM_VALUES; ++offset) {
2271 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2274 float weight = spatialAdaptivityAcc->getValue(ijk);
2275 float adaptivityValue = weight * adaptivity;
2276 if (adaptivityValue < 1.0f) useGradients =
true;
2277 adaptivityLeaf.setValueOnly(offset, adaptivityValue);
2282 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2283 const Int16 flags = it.getValue();
2284 const unsigned char signs =
static_cast<unsigned char>(
SIGNS & int(flags));
2286 if ((flags &
SEAM) || !sAdaptable[signs] || sEdgeGroupTable[signs][0] > 1) {
2288 mask.setActiveState(it.getCoord() & ~1u,
true);
2290 }
else if (flags &
EDGES) {
2292 bool maskRegion =
false;
2294 ijk = it.getCoord();
2295 if (!pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2297 if (!maskRegion && flags &
XEDGE) {
2299 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2301 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2303 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2307 if (!maskRegion && flags &
YEDGE) {
2309 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2311 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2313 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2317 if (!maskRegion && flags &
ZEDGE) {
2319 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2321 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2323 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2328 mask.setActiveState(it.getCoord() & ~1u,
true);
2335 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2336 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2337 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2338 if (!mask.isValueOn(ijk) &
isNonManifold(inputAcc, ijk, mIsovalue, dim)) {
2339 mask.setActiveState(ijk,
true);
2350 gradientNode->setValuesOff();
2352 gradientNode.
reset(
new Vec3sLeafNodeType());
2355 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2356 ijk = it.getCoord();
2357 if (!mask.isValueOn(ijk & ~1u)) {
2361 if (invertGradientDir) {
2365 gradientNode->setValueOn(it.pos(), dir);
2372 for ( ; dim <= LeafDim; dim = dim << 1) {
2373 const unsigned coordMask = ~((dim << 1) - 1);
2374 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2375 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2376 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2378 adaptivity = adaptivityLeaf.getValue(ijk);
2380 if (mask.isValueOn(ijk)
2382 || (useGradients && !
isMergable(*gradientNode, ijk, dim, adaptivity)))
2384 mask.setActiveState(ijk & coordMask,
true);
2386 mergeVoxels(pointIndexNode, ijk, dim, regionId++);
2406 mPolygonPool = &quadPool;
2411 template<
typename IndexType>
2415 mPolygonPool->quad(mIdx) = verts;
2417 Vec4I& quad = mPolygonPool->quad(mIdx);
2423 mPolygonPool->quadFlags(mIdx) = flags;
2429 mPolygonPool->trimQuads(mIdx);
2445 mPolygonPool = &polygonPool;
2447 mPolygonPool->resetTriangles(upperBound);
2453 template<
typename IndexType>
2456 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2457 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2458 mPolygonPool->quadFlags(mQuadIdx) = flags;
2459 addQuad(verts, reverse);
2461 verts[0] == verts[3] &&
2462 verts[1] != verts[2] &&
2463 verts[1] != verts[0] &&
2464 verts[2] != verts[0]) {
2465 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2466 addTriangle(verts[0], verts[1], verts[2], reverse);
2468 verts[1] == verts[2] &&
2469 verts[0] != verts[3] &&
2470 verts[0] != verts[1] &&
2471 verts[3] != verts[1]) {
2472 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2473 addTriangle(verts[0], verts[1], verts[3], reverse);
2475 verts[0] == verts[1] &&
2476 verts[2] != verts[3] &&
2477 verts[2] != verts[0] &&
2478 verts[3] != verts[0]) {
2479 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2480 addTriangle(verts[0], verts[2], verts[3], reverse);
2482 verts[2] == verts[3] &&
2483 verts[0] != verts[1] &&
2484 verts[0] != verts[2] &&
2485 verts[1] != verts[2]) {
2486 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2487 addTriangle(verts[0], verts[1], verts[2], reverse);
2494 mPolygonPool->trimQuads(mQuadIdx,
true);
2495 mPolygonPool->trimTrinagles(mTriangleIdx,
true);
2500 template<
typename IndexType>
2504 mPolygonPool->quad(mQuadIdx) = verts;
2506 Vec4I& quad = mPolygonPool->quad(mQuadIdx);
2515 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2517 Vec3I& prim = mPolygonPool->triangle(mTriangleIdx);
2531 size_t mQuadIdx, mTriangleIdx;
2536 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2539 bool invertSurfaceOrientation,
2542 const Vec3i& offsets,
2544 const SignAccT& signAcc,
2545 const IdxAccT& idxAcc,
2546 PrimBuilder& mesher)
2548 using IndexType =
typename IdxAccT::ValueType;
2551 const bool isActive = idxAcc.probeValue(ijk, v0);
2558 bool isInside = flags &
INSIDE;
2560 isInside = invertSurfaceOrientation ? !isInside : isInside;
2565 if (flags &
XEDGE) {
2567 quad[0] = v0 + offsets[0];
2571 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2572 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2573 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][5] - 1 : 0;
2577 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2578 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2579 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][7] - 1 : 0;
2583 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2584 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2585 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][3] - 1 : 0;
2588 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2595 if (flags &
YEDGE) {
2597 quad[0] = v0 + offsets[1];
2601 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2602 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2603 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][12] - 1 : 0;
2607 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2608 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2609 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][11] - 1 : 0;
2613 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2614 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2615 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][10] - 1 : 0;
2618 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2625 if (flags &
ZEDGE) {
2627 quad[0] = v0 + offsets[2];
2631 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2632 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2633 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][8] - 1 : 0;
2637 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2638 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2639 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][6] - 1 : 0;
2643 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2644 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2645 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][2] - 1 : 0;
2648 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2657 template<
typename InputTreeType>
2661 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2666 : mInputTree(&inputTree)
2670 , mTileArray(tileArray)
2675 : mInputTree(rhs.mInputTree)
2676 , mIsovalue(rhs.mIsovalue)
2679 , mTileArray(rhs.mTileArray)
2685 void operator()(
const tbb::blocked_range<size_t>&);
2692 Vec4i const *
const mTileArray;
2696 template<
typename InputTreeType>
2705 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2707 const Vec4i& tile = mTileArray[n];
2709 bbox.
min()[0] = tile[0];
2710 bbox.
min()[1] = tile[1];
2711 bbox.
min()[2] = tile[2];
2726 bool processRegion =
true;
2731 if (processRegion) {
2734 region.
min()[0] = region.
max()[0] = ijk[0];
2735 mMask->fill(region,
false);
2742 processRegion =
true;
2744 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2748 if (processRegion) {
2751 region.
min()[0] = region.
max()[0] = ijk[0];
2752 mMask->fill(region,
false);
2762 processRegion =
true;
2767 if (processRegion) {
2770 region.
min()[1] = region.
max()[1] = ijk[1];
2771 mMask->fill(region,
false);
2778 processRegion =
true;
2780 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2784 if (processRegion) {
2787 region.
min()[1] = region.
max()[1] = ijk[1];
2788 mMask->fill(region,
false);
2798 processRegion =
true;
2803 if (processRegion) {
2806 region.
min()[2] = region.
max()[2] = ijk[2];
2807 mMask->fill(region,
false);
2813 processRegion =
true;
2815 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2819 if (processRegion) {
2822 region.
min()[2] = region.
max()[2] = ijk[2];
2823 mMask->fill(region,
false);
2829 template<
typename InputTreeType>
2832 typename InputTreeType::template ValueConverter<bool>::Type& mask)
2834 typename InputTreeType::ValueOnCIter tileIter(inputTree);
2835 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2837 size_t tileCount = 0;
2838 for ( ; tileIter; ++tileIter) {
2842 if (tileCount > 0) {
2843 boost::scoped_array<Vec4i> tiles(
new Vec4i[tileCount]);
2848 tileIter = inputTree.cbeginValueOn();
2849 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2851 for (; tileIter; ++tileIter) {
2852 Vec4i& tile = tiles[index++];
2853 tileIter.getBoundingBox(bbox);
2854 tile[0] = bbox.
min()[0];
2855 tile[1] = bbox.
min()[1];
2856 tile[2] = bbox.
min()[2];
2857 tile[3] = bbox.
max()[0] - bbox.
min()[0];
2861 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, tileCount), op);
2874 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
2880 for (
size_t n = range.begin(); n < range.end(); ++n) {
2881 mPointsOut[n] = mPointsIn[n];
2887 std::vector<Vec3s>& mPointsOut;
2899 template<
typename LeafNodeType>
2900 void constructOffsetList();
2938 IndexVector mCore, mMinX, mMaxX, mMinY, mMaxY, mMinZ, mMaxZ,
2939 mInternalNeighborsX, mInternalNeighborsY, mInternalNeighborsZ;
2943 template<
typename LeafNodeType>
2949 mCore.reserve((LeafNodeType::DIM - 2) * (LeafNodeType::DIM - 2));
2951 for (
Index x = 1; x < (LeafNodeType::DIM - 1); ++x) {
2952 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2953 for (
Index y = 1; y < (LeafNodeType::DIM - 1); ++y) {
2954 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2955 for (
Index z = 1; z < (LeafNodeType::DIM - 1); ++z) {
2956 mCore.push_back(offsetXY + z);
2962 mInternalNeighborsX.clear();
2963 mInternalNeighborsX.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2965 for (
Index x = 0; x < (LeafNodeType::DIM - 1); ++x) {
2966 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2967 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2968 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2969 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2970 mInternalNeighborsX.push_back(offsetXY + z);
2976 mInternalNeighborsY.clear();
2977 mInternalNeighborsY.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2979 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2980 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2981 for (
Index y = 0; y < (LeafNodeType::DIM - 1); ++y) {
2982 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2983 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2984 mInternalNeighborsY.push_back(offsetXY + z);
2990 mInternalNeighborsZ.clear();
2991 mInternalNeighborsZ.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2993 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2994 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2995 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2996 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2997 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
2998 mInternalNeighborsZ.push_back(offsetXY + z);
3005 mMinX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3007 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3008 const Index offsetXY = (y << LeafNodeType::LOG2DIM);
3009 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3010 mMinX.push_back(offsetXY + z);
3017 mMaxX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3019 const Index offsetX = (LeafNodeType::DIM - 1) << (2 * LeafNodeType::LOG2DIM);
3020 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3021 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3022 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3023 mMaxX.push_back(offsetXY + z);
3030 mMinY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3032 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3033 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3034 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3035 mMinY.push_back(offsetX + z);
3042 mMaxY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3044 const Index offsetY = (LeafNodeType::DIM - 1) << LeafNodeType::LOG2DIM;
3045 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3046 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3047 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3048 mMaxY.push_back(offsetX + offsetY + z);
3055 mMinZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3057 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3058 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3059 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3060 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3061 mMinZ.push_back(offsetXY);
3068 mMaxZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3070 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3071 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3072 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3073 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3074 mMaxZ.push_back(offsetXY + (LeafNodeType::DIM - 1));
3085 template<
typename AccessorT,
int _AXIS>
3088 enum { AXIS = _AXIS };
3095 acc.setActiveState(ijk);
3097 acc.setActiveState(ijk);
3099 acc.setActiveState(ijk);
3101 acc.setActiveState(ijk);
3102 }
else if (_AXIS == 1) {
3103 acc.setActiveState(ijk);
3105 acc.setActiveState(ijk);
3107 acc.setActiveState(ijk);
3109 acc.setActiveState(ijk);
3111 acc.setActiveState(ijk);
3113 acc.setActiveState(ijk);
3115 acc.setActiveState(ijk);
3117 acc.setActiveState(ijk);
3126 template<
typename VoxelEdgeAcc,
typename LeafNode>
3134 if (VoxelEdgeAcc::AXIS == 0) {
3135 nvo = LeafNode::DIM * LeafNode::DIM;
3137 }
else if (VoxelEdgeAcc::AXIS == 1) {
3138 nvo = LeafNode::DIM;
3142 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3143 const Index& pos = (*offsets)[n];
3144 bool isActive = leafnode.isValueOn(pos) || leafnode.isValueOn(pos + nvo);
3145 if (isActive && (
isInsideValue(leafnode.getValue(pos), iso) !=
3147 edgeAcc.set(leafnode.offsetToGlobalCoord(pos));
3156 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3161 const std::vector<Index>* lhsOffsets = &voxels.
maxX();
3162 const std::vector<Index>* rhsOffsets = &voxels.
minX();
3163 Coord ijk = lhsNode.origin();
3165 if (VoxelEdgeAcc::AXIS == 0) {
3166 ijk[0] += LeafNode::DIM;
3167 }
else if (VoxelEdgeAcc::AXIS == 1) {
3168 ijk[1] += LeafNode::DIM;
3169 lhsOffsets = &voxels.
maxY();
3170 rhsOffsets = &voxels.
minY();
3171 }
else if (VoxelEdgeAcc::AXIS == 2) {
3172 ijk[2] += LeafNode::DIM;
3173 lhsOffsets = &voxels.
maxZ();
3174 rhsOffsets = &voxels.
minZ();
3177 typename LeafNode::ValueType value;
3178 const LeafNode* rhsNodePt = acc.probeConstLeaf(ijk);
3181 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3182 const Index& pos = (*lhsOffsets)[n];
3183 bool isActive = lhsNode.isValueOn(pos) || rhsNodePt->isValueOn((*rhsOffsets)[n]);
3184 if (isActive && (
isInsideValue(lhsNode.getValue(pos), iso) !=
3185 isInsideValue(rhsNodePt->getValue((*rhsOffsets)[n]), iso))) {
3186 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3189 }
else if (!acc.probeValue(ijk, value)) {
3191 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3192 const Index& pos = (*lhsOffsets)[n];
3193 if (lhsNode.isValueOn(pos) && (inside !=
isInsideValue(lhsNode.getValue(pos), iso))) {
3194 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3204 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3209 Coord ijk = leafnode.origin();
3210 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3211 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3212 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3214 typename LeafNode::ValueType value;
3215 if (!acc.probeConstLeaf(ijk) && !acc.probeValue(ijk, value)) {
3222 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3224 const Index& pos = (*offsets)[n];
3225 if (leafnode.isValueOn(pos)
3228 ijk = leafnode.offsetToGlobalCoord(pos);
3229 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3230 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3231 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3241 template<
typename InputTreeType>
3247 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3251 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3256 void operator()(
const tbb::blocked_range<size_t>&);
3258 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3275 template<
typename InputTreeType>
3278 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3281 : mInputAccessor(inputTree)
3282 , mInputNodes(inputLeafNodes.empty() ? nullptr : &inputLeafNodes.front())
3283 , mIntersectionTree(false)
3284 , mIntersectionAccessor(intersectionTree)
3286 , mOffsets(&mOffsetData)
3293 template<
typename InputTreeType>
3296 : mInputAccessor(rhs.mInputAccessor.tree())
3297 , mInputNodes(rhs.mInputNodes)
3298 , mIntersectionTree(false)
3299 , mIntersectionAccessor(mIntersectionTree)
3301 , mOffsets(rhs.mOffsets)
3302 , mIsovalue(rhs.mIsovalue)
3307 template<
typename InputTreeType>
3315 for (
size_t n = range.begin(); n != range.end(); ++n) {
3346 template<
typename InputTreeType>
3349 typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3350 const InputTreeType& inputTree,
3351 typename InputTreeType::ValueType isovalue)
3355 std::vector<const InputLeafNodeType*> inputLeafNodes;
3356 inputTree.getNodes(inputLeafNodes);
3359 inputTree, inputLeafNodes, intersectionTree, isovalue);
3361 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, inputLeafNodes.size()), op);
3370 template<
typename InputTreeType>
3376 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3380 const InputTreeType& inputTree,
3381 const std::vector<BoolLeafNodeType*>& nodes,
3386 void operator()(
const tbb::blocked_range<size_t>&);
3388 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3402 template<
typename InputTreeType>
3404 const InputTreeType& inputTree,
3405 const std::vector<BoolLeafNodeType*>& nodes,
3408 : mInputAccessor(inputTree)
3409 , mNodes(nodes.empty() ? nullptr : &nodes.front())
3410 , mIntersectionTree(false)
3411 , mIntersectionAccessor(intersectionTree)
3417 template<
typename InputTreeType>
3420 : mInputAccessor(rhs.mInputAccessor.tree())
3421 , mNodes(rhs.mNodes)
3422 , mIntersectionTree(false)
3423 , mIntersectionAccessor(mIntersectionTree)
3424 , mIsovalue(rhs.mIsovalue)
3429 template<
typename InputTreeType>
3440 for (
size_t n = range.begin(); n != range.end(); ++n) {
3444 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3446 if (!it.getValue()) {
3448 ijk = it.getCoord();
3469 template<
typename BoolTreeType>
3475 const std::vector<BoolLeafNodeType*>& maskNodes,
3477 : mMaskTree(&maskTree)
3478 , mMaskNodes(maskNodes.empty() ? nullptr : &maskNodes.front())
3479 , mTmpBorderTree(false)
3480 , mBorderTree(&borderTree)
3485 : mMaskTree(rhs.mMaskTree)
3486 , mMaskNodes(rhs.mMaskNodes)
3487 , mTmpBorderTree(false)
3488 , mBorderTree(&mTmpBorderTree)
3500 for (
size_t n = range.begin(); n != range.end(); ++n) {
3504 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3506 ijk = it.getCoord();
3508 const bool lhs = it.getValue();
3511 bool isEdgeVoxel =
false;
3514 isEdgeVoxel = (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3517 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3520 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3523 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3527 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3530 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3533 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3552 template<
typename BoolTreeType>
3558 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3565 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3569 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3576 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3577 const Index pos = it.pos();
3578 if (maskNode->getValue(pos)) {
3579 node.setValueOnly(pos,
true);
3595 template<
typename BoolTreeType>
3602 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3604 , mInputTransform(inputTransform)
3605 , mMaskTransform(maskTransform)
3606 , mInvertMask(invert)
3612 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3616 const bool matchingTransforms = mInputTransform == mMaskTransform;
3617 const bool maskState = mInvertMask;
3619 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3623 if (matchingTransforms) {
3629 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3630 const Index pos = it.pos();
3631 if (maskNode->isValueOn(pos) == maskState) {
3632 node.setValueOnly(pos,
true);
3638 if (maskTreeAcc.
isValueOn(node.origin()) == maskState) {
3639 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3640 node.setValueOnly(it.pos(),
true);
3650 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3652 ijk = mMaskTransform.worldToIndexCellCentered(
3653 mInputTransform.indexToWorld(it.getCoord()));
3655 if (maskTreeAcc.
isValueOn(ijk) == maskState) {
3656 node.setValueOnly(it.pos(),
true);
3669 bool const mInvertMask;
3673 template<
typename InputGr
idType>
3676 typename InputGridType::TreeType::template ValueConverter<bool>::Type& intersectionTree,
3677 typename InputGridType::TreeType::template ValueConverter<bool>::Type& borderTree,
3678 const InputGridType& inputGrid,
3681 typename InputGridType::ValueType isovalue)
3683 using InputTreeType =
typename InputGridType::TreeType;
3684 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3688 if (maskGrid && maskGrid->type() == BoolGridType::gridType()) {
3691 const InputTreeType& inputTree = inputGrid.tree();
3693 const BoolGridType * surfaceMask =
static_cast<const BoolGridType*
>(maskGrid.get());
3701 std::vector<BoolLeafNodeType*> intersectionLeafNodes;
3702 intersectionTree.getNodes(intersectionLeafNodes);
3704 tbb::parallel_for(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()),
3706 intersectionLeafNodes, maskTree, transform, maskTransform, invertMask));
3712 intersectionTree, intersectionLeafNodes, borderTree);
3713 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), borderOp);
3721 inputTree, intersectionLeafNodes, tmpIntersectionTree, isovalue);
3723 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3725 std::vector<BoolLeafNodeType*> tmpIntersectionLeafNodes;
3726 tmpIntersectionTree.getNodes(tmpIntersectionLeafNodes);
3728 tbb::parallel_for(tbb::blocked_range<size_t>(0, tmpIntersectionLeafNodes.size()),
3731 intersectionTree.clear();
3732 intersectionTree.merge(tmpIntersectionTree);
3740 template<
typename InputTreeType>
3748 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
3753 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3759 void operator()(
const tbb::blocked_range<size_t>&);
3761 mSignFlagsAccessor.tree().merge(rhs.mSignFlagsAccessor.
tree());
3762 mPointIndexAccessor.tree().merge(rhs.mPointIndexAccessor.
tree());
3778 template<
typename InputTreeType>
3780 const InputTreeType& inputTree,
3781 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3785 : mInputAccessor(inputTree)
3786 , mIntersectionNodes(&intersectionLeafNodes.front())
3788 , mSignFlagsAccessor(signFlagsTree)
3789 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3790 , mPointIndexAccessor(pointIndexTree)
3793 pointIndexTree.root().setBackground(boost::integer_traits<Index32>::const_max,
false);
3797 template<
typename InputTreeType>
3799 : mInputAccessor(rhs.mInputAccessor.tree())
3800 , mIntersectionNodes(rhs.mIntersectionNodes)
3802 , mSignFlagsAccessor(mSignFlagsTree)
3803 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3804 , mPointIndexAccessor(mPointIndexTree)
3805 , mIsovalue(rhs.mIsovalue)
3810 template<
typename InputTreeType>
3814 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
3818 typename std::unique_ptr<Int16LeafNodeType> signsNodePt(
new Int16LeafNodeType(ijk, 0));
3820 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3827 if (!signsNodePt.get()) signsNodePt.reset(
new Int16LeafNodeType(origin, 0));
3828 else signsNodePt->setOrigin(origin);
3830 bool updatedNode =
false;
3834 const Index pos = it.pos();
3848 if (signFlags != 0 && signFlags != 0xFF) {
3850 const bool inside = signFlags & 0x1;
3852 int edgeFlags = inside ?
INSIDE : 0;
3854 if (!it.getValue()) {
3855 edgeFlags |= inside != ((signFlags & 0x02) != 0) ?
XEDGE : 0;
3856 edgeFlags |= inside != ((signFlags & 0x10) != 0) ?
YEDGE : 0;
3857 edgeFlags |= inside != ((signFlags & 0x08) != 0) ?
ZEDGE : 0;
3860 const uint8_t ambiguousCellFlags = sAmbiguousFace[signFlags];
3861 if (ambiguousCellFlags != 0) {
3863 origin + ijk, mIsovalue);
3866 edgeFlags |= int(signFlags);
3868 signsNodePt->setValueOn(pos,
Int16(edgeFlags));
3874 typename Index32TreeType::LeafNodeType* idxNode = mPointIndexAccessor.
touchLeaf(origin);
3875 idxNode->topologyUnion(*signsNodePt);
3878 for (
auto it = idxNode->beginValueOn(); it; ++it) {
3879 idxNode->setValueOnly(it.pos(), 0);
3882 mSignFlagsAccessor.
addLeaf(signsNodePt.release());
3888 template<
typename InputTreeType>
3891 typename InputTreeType::template ValueConverter<Int16>::Type& signFlagsTree,
3892 typename InputTreeType::template ValueConverter<Index32>::Type& pointIndexTree,
3893 const typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3894 const InputTreeType& inputTree,
3895 typename InputTreeType::ValueType isovalue)
3897 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3900 std::vector<const BoolLeafNodeType*> intersectionLeafNodes;
3901 intersectionTree.getNodes(intersectionLeafNodes);
3904 inputTree, intersectionLeafNodes, signFlagsTree, pointIndexTree, isovalue);
3906 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3913 template<Index32 LeafNodeLog2Dim>
3919 boost::scoped_array<Index32>& leafNodeCount)
3920 : mLeafNodes(leafNodes.empty() ? nullptr : &leafNodes.front())
3921 , mData(leafNodeCount.get())
3927 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3931 Int16 const * p = mLeafNodes[n]->buffer().data();
3932 Int16 const *
const endP = p + Int16LeafNodeType::SIZE;
3949 template<
typename Po
intIndexLeafNode>
3955 const std::vector<Int16LeafNodeType*>& signDataNodes,
3956 boost::scoped_array<Index32>& leafNodeCount)
3957 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
3958 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
3959 , mData(leafNodeCount.get())
3967 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3974 std::set<IndexType> uniqueRegions;
3981 count += size_t(sEdgeGroupTable[(
SIGNS & signNode.
getValue(it.pos()))][0]);
3983 uniqueRegions.insert(
id);
3987 mData[n] =
Index32(count + uniqueRegions.size());
3998 template<
typename Po
intIndexLeafNode>
4003 MapPoints(
const std::vector<PointIndexLeafNode*>& pointIndexNodes,
4004 const std::vector<Int16LeafNodeType*>& signDataNodes,
4005 boost::scoped_array<Index32>& leafNodeCount)
4006 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
4007 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
4008 , mData(leafNodeCount.get())
4014 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
4019 Index32 pointOffset = mData[n];
4022 const Index pos = it.pos();
4025 pointOffset +=
Index32(sEdgeGroupTable[signs][0]);
4039 template<
typename TreeType,
typename PrimBuilder>
4050 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4054 bool invertSurfaceOrientation);
4058 void operator()(
const tbb::blocked_range<size_t>&)
const;
4066 bool const mInvertSurfaceOrientation;
4070 template<
typename TreeType,
typename PrimBuilder>
4072 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4076 bool invertSurfaceOrientation)
4077 : mSignFlagsLeafNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
4078 , mSignFlagsTree(&signFlagsTree)
4079 , mRefSignFlagsTree(nullptr)
4080 , mIndexTree(&idxTree)
4081 , mPolygonPoolList(&polygons)
4082 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4086 template<
typename InputTreeType,
typename PrimBuilder>
4091 Int16ValueAccessor signAcc(*mSignFlagsTree);
4095 const bool invertSurfaceOrientation = mInvertSurfaceOrientation;
4102 std::unique_ptr<Int16ValueAccessor> refSignAcc;
4103 if (mRefSignFlagsTree) refSignAcc.
reset(
new Int16ValueAccessor(*mRefSignFlagsTree));
4105 for (
size_t n = range.begin(); n != range.end(); ++n) {
4108 origin = node.origin();
4112 typename Int16LeafNodeType::ValueOnCIter iter = node.cbeginValueOn();
4113 for (; iter; ++iter) {
4114 if (iter.getValue() &
XEDGE) ++edgeCount;
4115 if (iter.getValue() &
YEDGE) ++edgeCount;
4116 if (iter.getValue() &
ZEDGE) ++edgeCount;
4119 if(edgeCount == 0)
continue;
4121 mesher.init(edgeCount, (*mPolygonPoolList)[n]);
4126 if (!signleafPt || !idxLeafPt)
continue;
4130 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
4134 for (iter = node.cbeginValueOn(); iter; ++iter) {
4135 ijk = iter.getCoord();
4137 Int16 flags = iter.getValue();
4139 if (!(flags & 0xE00))
continue;
4142 if (refSignLeafPt) {
4143 refFlags = refSignLeafPt->getValue(iter.pos());
4150 const uint8_t cell = uint8_t(
SIGNS & flags);
4152 if (sEdgeGroupTable[cell][0] > 1) {
4153 offsets[0] = (sEdgeGroupTable[cell][1] - 1);
4154 offsets[1] = (sEdgeGroupTable[cell][9] - 1);
4155 offsets[2] = (sEdgeGroupTable[cell][4] - 1);
4158 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
4160 flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher);
4163 flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher);
4176 template<
typename T>
4179 CopyArray(T * outputArray,
const T * inputArray,
size_t outputOffset = 0)
4180 : mOutputArray(outputArray), mInputArray(inputArray), mOutputOffset(outputOffset)
4184 void operator()(
const tbb::blocked_range<size_t>& inputArrayRange)
const 4186 const size_t offset = mOutputOffset;
4187 for (
size_t n = inputArrayRange.begin(), N = inputArrayRange.end(); n < N; ++n) {
4188 mOutputArray[offset + n] = mInputArray[n];
4193 T *
const mOutputArray;
4194 T
const *
const mInputArray;
4195 size_t const mOutputOffset;
4202 const std::vector<uint8_t>& pointFlags,
4203 boost::scoped_array<openvdb::Vec3s>& points,
4204 boost::scoped_array<unsigned>& numQuadsToDivide)
4205 : mPolygonPoolList(&polygons)
4206 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4207 , mPoints(points.get())
4208 , mNumQuadsToDivide(numQuadsToDivide.get())
4214 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4221 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4229 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4230 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4232 if (!edgePoly)
continue;
4234 const Vec3s& p0 = mPoints[quad[0]];
4235 const Vec3s& p1 = mPoints[quad[1]];
4236 const Vec3s& p2 = mPoints[quad[2]];
4237 const Vec3s& p3 = mPoints[quad[3]];
4246 mNumQuadsToDivide[n] = count;
4252 uint8_t
const *
const mPointFlags;
4253 Vec3s const *
const mPoints;
4254 unsigned *
const mNumQuadsToDivide;
4261 const boost::scoped_array<openvdb::Vec3s>& points,
4263 boost::scoped_array<openvdb::Vec3s>& centroids,
4264 boost::scoped_array<unsigned>& numQuadsToDivide,
4265 boost::scoped_array<unsigned>& centroidOffsets)
4266 : mPolygonPoolList(&polygons)
4267 , mPoints(points.get())
4268 , mCentroids(centroids.get())
4269 , mNumQuadsToDivide(numQuadsToDivide.get())
4270 , mCentroidOffsets(centroidOffsets.get())
4271 , mPointCount(pointCount)
4277 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4281 const size_t nonplanarCount = size_t(mNumQuadsToDivide[n]);
4283 if (nonplanarCount > 0) {
4289 size_t offset = mCentroidOffsets[n];
4291 size_t triangleIdx = 0;
4293 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4295 const char quadFlags = polygons.
quadFlags(i);
4298 unsigned newPointIdx = unsigned(offset + mPointCount);
4302 mCentroids[offset] = (mPoints[quad[0]] + mPoints[quad[1]] +
4303 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25f;
4310 triangle[0] = quad[0];
4311 triangle[1] = newPointIdx;
4312 triangle[2] = quad[3];
4322 triangle[0] = quad[0];
4323 triangle[1] = quad[1];
4324 triangle[2] = newPointIdx;
4334 triangle[0] = quad[1];
4335 triangle[1] = quad[2];
4336 triangle[2] = newPointIdx;
4347 triangle[0] = quad[2];
4348 triangle[1] = quad[3];
4349 triangle[2] = newPointIdx;
4360 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4367 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4371 tmpPolygons.
quad(quadIdx) = quad;
4377 polygons.
copy(tmpPolygons);
4384 Vec3s const *
const mPoints;
4385 Vec3s *
const mCentroids;
4386 unsigned *
const mNumQuadsToDivide;
4387 unsigned *
const mCentroidOffsets;
4388 size_t const mPointCount;
4395 size_t polygonPoolListSize,
4397 size_t& pointListSize,
4398 std::vector<uint8_t>& pointFlags)
4400 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4402 boost::scoped_array<unsigned> numQuadsToDivide(
new unsigned[polygonPoolListSize]);
4404 tbb::parallel_for(polygonPoolListRange,
4407 boost::scoped_array<unsigned> centroidOffsets(
new unsigned[polygonPoolListSize]);
4409 size_t centroidCount = 0;
4413 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4414 centroidOffsets[n] = sum;
4415 sum += numQuadsToDivide[n];
4417 centroidCount = size_t(sum);
4420 boost::scoped_array<Vec3s> centroidList(
new Vec3s[centroidCount]);
4422 tbb::parallel_for(polygonPoolListRange,
4424 centroidList, numQuadsToDivide, centroidOffsets));
4426 if (centroidCount > 0) {
4428 const size_t newPointListSize = centroidCount + pointListSize;
4430 boost::scoped_array<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointListSize]);
4432 tbb::parallel_for(tbb::blocked_range<size_t>(0, pointListSize),
4435 tbb::parallel_for(tbb::blocked_range<size_t>(0, newPointListSize - pointListSize),
4438 pointListSize = newPointListSize;
4439 pointList.swap(newPointList);
4440 pointFlags.resize(pointListSize, 0);
4448 const std::vector<uint8_t>& pointFlags)
4449 : mPolygonPoolList(&polygons)
4450 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4456 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4460 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4468 const bool hasSeamLinePoint =
4469 mPointFlags[verts[0]] || mPointFlags[verts[1]] ||
4470 mPointFlags[verts[2]] || mPointFlags[verts[3]];
4472 if (!hasSeamLinePoint) {
4473 flags &= ~POLYFLAG_FRACTURE_SEAM;
4478 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4486 const bool hasSeamLinePoint =
4487 mPointFlags[verts[0]] || mPointFlags[verts[1]] || mPointFlags[verts[2]];
4489 if (!hasSeamLinePoint) {
4490 flags &= ~POLYFLAG_FRACTURE_SEAM;
4501 uint8_t
const *
const mPointFlags;
4507 std::vector<uint8_t>& pointFlags)
4509 tbb::parallel_for(tbb::blocked_range<size_t>(0, polygonPoolListSize),
4517 template<
typename InputTreeType>
4521 const PointList& pointList, boost::scoped_array<uint8_t>& pointMask,
4523 : mInputTree(&inputTree)
4524 , mPolygonPoolList(&polygons)
4525 , mPointList(&pointList)
4526 , mPointMask(pointMask.get())
4527 , mTransform(transform)
4528 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4534 using ValueType =
typename InputTreeType::LeafNodeType::ValueType;
4537 Vec3s centroid, normal;
4540 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<ValueType>();
4542 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4544 const PolygonPool& polygons = (*mPolygonPoolList)[n];
4546 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4550 const Vec3s& v0 = (*mPointList)[verts[0]];
4551 const Vec3s& v1 = (*mPointList)[verts[1]];
4552 const Vec3s& v2 = (*mPointList)[verts[2]];
4554 normal = (v2 - v0).cross((v1 - v0));
4557 centroid = (v0 + v1 + v2) * (1.0f / 3.0f);
4558 ijk = mTransform.worldToIndexCellCentered(centroid);
4563 if (invertGradientDir) {
4568 if (dir.dot(normal) < -0.5f) {
4573 mPointMask[verts[0]] = 1;
4574 mPointMask[verts[1]] = 1;
4575 mPointMask[verts[2]] = 1;
4584 InputTreeType
const *
const mInputTree;
4587 uint8_t *
const mPointMask;
4589 bool const mInvertSurfaceOrientation;
4593 template<
typename InputTree>
4596 bool invertSurfaceOrientation,
4597 const InputTree& inputTree,
4600 size_t polygonPoolListSize,
4602 const size_t pointListSize)
4604 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4606 boost::scoped_array<uint8_t> pointMask(
new uint8_t[pointListSize]);
4607 fillArray(pointMask.get(), uint8_t(0), pointListSize);
4609 tbb::parallel_for(polygonPoolListRange,
4611 inputTree, polygonPoolList, pointList, pointMask, transform, invertSurfaceOrientation));
4613 boost::scoped_array<uint8_t> pointUpdates(
new uint8_t[pointListSize]);
4614 fillArray(pointUpdates.get(), uint8_t(0), pointListSize);
4616 boost::scoped_array<Vec3s> newPoints(
new Vec3s[pointListSize]);
4617 fillArray(newPoints.get(),
Vec3s(0.0f, 0.0f, 0.0f), pointListSize);
4619 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4623 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4626 for (
int v = 0; v < 4; ++v) {
4628 const unsigned pointIdx = verts[v];
4630 if (pointMask[pointIdx] == 1) {
4632 newPoints[pointIdx] +=
4633 pointList[verts[0]] + pointList[verts[1]] +
4634 pointList[verts[2]] + pointList[verts[3]];
4636 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 4);
4641 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4644 for (
int v = 0; v < 3; ++v) {
4646 const unsigned pointIdx = verts[v];
4648 if (pointMask[pointIdx] == 1) {
4649 newPoints[pointIdx] +=
4650 pointList[verts[0]] + pointList[verts[1]] + pointList[verts[2]];
4652 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 3);
4658 for (
size_t n = 0, N = pointListSize; n < N; ++n) {
4659 if (pointUpdates[n] > 0) {
4660 const double weight = 1.0 / double(pointUpdates[n]);
4661 pointList[n] = newPoints[n] * float(weight);
4678 , mTriangles(nullptr)
4679 , mQuadFlags(nullptr)
4680 , mTriangleFlags(nullptr)
4687 : mNumQuads(numQuads)
4688 , mNumTriangles(numTriangles)
4691 , mQuadFlags(new char[mNumQuads])
4692 , mTriangleFlags(new char[mNumTriangles])
4703 for (
size_t i = 0; i < mNumQuads; ++i) {
4704 mQuads[i] = rhs.mQuads[i];
4705 mQuadFlags[i] = rhs.mQuadFlags[i];
4708 for (
size_t i = 0; i < mNumTriangles; ++i) {
4709 mTriangles[i] = rhs.mTriangles[i];
4710 mTriangleFlags[i] = rhs.mTriangleFlags[i];
4720 mQuadFlags.reset(
new char[mNumQuads]);
4728 mQuads.reset(
nullptr);
4729 mQuadFlags.reset(
nullptr);
4736 mNumTriangles = size;
4738 mTriangleFlags.reset(
new char[mNumTriangles]);
4746 mTriangles.reset(
nullptr);
4747 mTriangleFlags.reset(
nullptr);
4754 if (!(n < mNumQuads))
return false;
4759 mQuads.reset(
nullptr);
4762 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
4763 boost::scoped_array<char> flags(
new char[n]);
4765 for (
size_t i = 0; i < n; ++i) {
4766 quads[i] = mQuads[i];
4767 flags[i] = mQuadFlags[i];
4771 mQuadFlags.swap(flags);
4783 if (!(n < mNumTriangles))
return false;
4788 mTriangles.reset(
nullptr);
4791 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
4792 boost::scoped_array<char> flags(
new char[n]);
4794 for (
size_t i = 0; i < n; ++i) {
4795 triangles[i] = mTriangles[i];
4796 flags[i] = mTriangleFlags[i];
4799 mTriangles.swap(triangles);
4800 mTriangleFlags.swap(flags);
4817 , mSeamPointListSize(0)
4818 , mPolygonPoolListSize(0)
4819 , mIsovalue(isovalue)
4820 , mPrimAdaptivity(adaptivity)
4821 , mSecAdaptivity(0.0)
4823 , mSurfaceMaskGrid(
GridBase::ConstPtr())
4824 , mAdaptivityGrid(
GridBase::ConstPtr())
4825 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
4828 , mInvertSurfaceMask(false)
4829 , mRelaxDisorientedTriangles(relaxDisorientedTriangles)
4830 , mQuantizedSeamPoints(nullptr)
4843 inline const size_t&
4846 return mPointListSize;
4864 inline const size_t&
4867 return mPolygonPoolListSize;
4875 mSecAdaptivity = secAdaptivity;
4880 mSeamPointListSize = 0;
4881 mQuantizedSeamPoints.reset(
nullptr);
4888 mSurfaceMaskGrid = mask;
4889 mInvertSurfaceMask = invertMask;
4896 mAdaptivityGrid = grid;
4903 mAdaptivityMaskTree = tree;
4907 inline std::vector<uint8_t>&
4914 inline const std::vector<uint8_t>&
4921 template<
typename InputGr
idType>
4927 using InputTreeType =
typename InputGridType::TreeType;
4928 using InputLeafNodeType =
typename InputTreeType::LeafNodeType;
4929 using InputValueType =
typename InputLeafNodeType::ValueType;
4933 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
4935 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
4936 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
4937 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
4938 using Index32TreeType =
typename InputTreeType::template ValueConverter<Index32>::Type;
4939 using Index32LeafNodeType =
typename Index32TreeType::LeafNodeType;
4944 mPolygonPoolListSize = 0;
4946 mPointFlags.clear();
4951 const InputValueType isovalue = InputValueType(mIsovalue);
4952 const float adaptivityThreshold = float(mPrimAdaptivity);
4953 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4959 const bool invertSurfaceOrientation = (!volume_to_mesh_internal::isBoolValue<InputValueType>()
4964 const InputTreeType& inputTree = inputGrid.tree();
4966 BoolTreeType intersectionTree(
false), adaptivityMask(
false);
4968 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeType::treeType()) {
4969 const BoolTreeType *refAdaptivityMask=
4970 static_cast<const BoolTreeType*
>(mAdaptivityMaskTree.get());
4971 adaptivityMask.topologyUnion(*refAdaptivityMask);
4974 Int16TreeType signFlagsTree(0);
4975 Index32TreeType pointIndexTree(boost::integer_traits<Index32>::const_max);
4981 intersectionTree, inputTree, isovalue);
4984 inputGrid, mSurfaceMaskGrid, mInvertSurfaceMask, isovalue);
4986 if (intersectionTree.empty())
return;
4989 signFlagsTree, pointIndexTree, intersectionTree, inputTree, isovalue);
4991 intersectionTree.clear();
4993 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
4994 pointIndexTree.getNodes(pointIndexLeafNodes);
4996 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
4997 signFlagsTree.getNodes(signFlagsLeafNodes);
4999 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
5004 Int16TreeType* refSignFlagsTree =
nullptr;
5005 Index32TreeType* refPointIndexTree =
nullptr;
5006 InputTreeType
const* refInputTree =
nullptr;
5008 if (mRefGrid && mRefGrid->type() == InputGridType::gridType()) {
5010 const InputGridType* refGrid =
static_cast<const InputGridType*
>(mRefGrid.get());
5011 refInputTree = &refGrid->tree();
5013 if (!mRefSignTree && !mRefIdxTree) {
5017 typename Int16TreeType::Ptr refSignFlagsTreePt(
new Int16TreeType(0));
5018 typename Index32TreeType::Ptr refPointIndexTreePt(
5019 new Index32TreeType(boost::integer_traits<Index32>::const_max));
5021 BoolTreeType refIntersectionTree(
false);
5024 refIntersectionTree, *refInputTree, isovalue);
5027 *refPointIndexTreePt, refIntersectionTree, *refInputTree, isovalue);
5029 mRefSignTree = refSignFlagsTreePt;
5030 mRefIdxTree = refPointIndexTreePt;
5033 if (mRefSignTree && mRefIdxTree) {
5037 refSignFlagsTree =
static_cast<Int16TreeType*
>(mRefSignTree.get());
5038 refPointIndexTree =
static_cast<Index32TreeType*
>(mRefIdxTree.get());
5042 if (refSignFlagsTree && refPointIndexTree) {
5048 if (mSeamPointListSize == 0) {
5052 std::vector<Int16LeafNodeType*> refSignFlagsLeafNodes;
5053 refSignFlagsTree->getNodes(refSignFlagsLeafNodes);
5055 boost::scoped_array<Index32> leafNodeOffsets(
5056 new Index32[refSignFlagsLeafNodes.size()]);
5058 tbb::parallel_for(tbb::blocked_range<size_t>(0, refSignFlagsLeafNodes.size()),
5060 refSignFlagsLeafNodes, leafNodeOffsets));
5064 for (
size_t n = 0, N = refSignFlagsLeafNodes.size(); n < N; ++n) {
5065 const Index32 tmp = leafNodeOffsets[n];
5066 leafNodeOffsets[n] = count;
5069 mSeamPointListSize = size_t(count);
5072 if (mSeamPointListSize != 0) {
5074 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
5076 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
5078 std::vector<Index32LeafNodeType*> refPointIndexLeafNodes;
5079 refPointIndexTree->getNodes(refPointIndexLeafNodes);
5081 tbb::parallel_for(tbb::blocked_range<size_t>(0, refPointIndexLeafNodes.size()),
5083 refPointIndexLeafNodes, refSignFlagsLeafNodes, leafNodeOffsets));
5087 if (mSeamPointListSize != 0) {
5089 tbb::parallel_for(auxiliaryLeafNodeRange,
5091 signFlagsLeafNodes, inputTree, *refPointIndexTree, *refSignFlagsTree,
5092 mQuantizedSeamPoints.get(), isovalue));
5097 const bool referenceMeshing = refSignFlagsTree && refPointIndexTree && refInputTree;
5102 boost::scoped_array<Index32> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
5106 inputGrid, pointIndexTree, pointIndexLeafNodes, signFlagsLeafNodes,
5107 isovalue, adaptivityThreshold, invertSurfaceOrientation);
5109 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridType::gridType()) {
5110 const FloatGridType* adaptivityGrid =
5111 static_cast<const FloatGridType*
>(mAdaptivityGrid.get());
5115 if (!adaptivityMask.empty()) {
5119 if (referenceMeshing) {
5123 tbb::parallel_for(auxiliaryLeafNodeRange, mergeOp);
5126 op(pointIndexLeafNodes, signFlagsLeafNodes, leafNodeOffsets);
5128 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5133 op(signFlagsLeafNodes, leafNodeOffsets);
5135 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5141 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
5142 const Index32 tmp = leafNodeOffsets[n];
5147 mPointListSize = size_t(pointCount);
5149 mPointFlags.clear();
5157 op(mPoints.get(), inputTree, pointIndexLeafNodes,
5158 signFlagsLeafNodes, leafNodeOffsets, transform, mIsovalue);
5160 if (referenceMeshing) {
5161 mPointFlags.resize(mPointListSize);
5162 op.setRefData(*refInputTree, *refPointIndexTree, *refSignFlagsTree,
5163 mQuantizedSeamPoints.get(), &mPointFlags.front());
5166 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5172 mPolygonPoolListSize = signFlagsLeafNodes.size();
5173 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
5180 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5181 mPolygons, invertSurfaceOrientation);
5183 if (referenceMeshing) {
5187 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5194 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5195 mPolygons, invertSurfaceOrientation);
5197 if (referenceMeshing) {
5201 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5205 signFlagsTree.clear();
5206 pointIndexTree.clear();
5209 if (adaptive && mRelaxDisorientedTriangles) {
5211 inputTree, transform, mPolygons, mPolygonPoolListSize, mPoints, mPointListSize);
5215 if (referenceMeshing) {
5217 mPolygons, mPolygonPoolListSize, mPoints, mPointListSize, mPointFlags);
5229 template<
typename Gr
idType>
5230 inline typename std::enable_if<std::is_scalar<typename GridType::ValueType>::value,
void>::type
5232 const GridType& grid,
5233 std::vector<Vec3s>& points,
5234 std::vector<Vec3I>& triangles,
5235 std::vector<Vec4I>& quads,
5240 VolumeToMesh mesher(isovalue, adaptivity, relaxDisorientedTriangles);
5249 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
5256 size_t numQuads = 0, numTriangles = 0;
5258 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5259 numTriangles += polygons.numTriangles();
5260 numQuads += polygons.numQuads();
5264 triangles.resize(numTriangles);
5266 quads.resize(numQuads);
5270 size_t qIdx = 0, tIdx = 0;
5272 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5274 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
5275 quads[qIdx++] = polygons.quad(i);
5278 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
5279 triangles[tIdx++] = polygons.triangle(i);
5285 template<
typename Gr
idType>
5286 inline typename std::enable_if<!std::is_scalar<typename GridType::ValueType>::value,
void>::type
5289 std::vector<Vec3s>&,
5290 std::vector<Vec3I>&,
5291 std::vector<Vec4I>&,
5300 template<
typename Gr
idType>
5303 const GridType& grid,
5304 std::vector<Vec3s>& points,
5305 std::vector<Vec3I>& triangles,
5306 std::vector<Vec4I>& quads,
5311 doVolumeToMesh(grid, points, triangles, quads, isovalue, adaptivity, relaxDisorientedTriangles);
5315 template<
typename Gr
idType>
5318 const GridType& grid,
5319 std::vector<Vec3s>& points,
5320 std::vector<Vec4I>& quads,
5323 std::vector<Vec3I> triangles;
5324 doVolumeToMesh(grid, points, triangles, quads, isovalue, 0.0,
true);
5331 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:508
Vec3< float > Vec3s
Definition: Vec3.h:707
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
uint32_t Index32
Definition: Types.h:55
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:275
Definition: LeafNode.h:233
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1059
SharedPtr< const TreeBase > ConstPtr
Definition: Tree.h:68
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:266
Abstract base class for typed grids.
Definition: Grid.h:103
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:215
Vec3< int32_t > Vec3i
Definition: Vec3.h:705
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:266
T & z()
Definition: Vec3.h:111
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
Gradient operators defined in index space of various orders.
Definition: Operators.h:122
Mat3< double > Mat3d
Definition: Mat3.h:708
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:346
SharedPtr< TreeBase > Ptr
Definition: Tree.h:67
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:408
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:796
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:61
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:198
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Vec3< double > Vec3d
Definition: Vec3.h:708
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
Definition: Exceptions.h:91
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:107
const Coord & max() const
Definition: Coord.h:340
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:376
Definition: Exceptions.h:39
Vec4< int32_t > Vec4i
Definition: Vec4.h:621
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:263
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
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1084
Definition: Exceptions.h:92
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:317
Coord & reset(Int32 x, Int32 y, Int32 z)
Reset all three coordinates with the specified arguments.
Definition: Coord.h:93
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:198
int16_t Int16
Definition: Types.h:58
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:794
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
const Coord & min() const
Definition: Coord.h:339
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:147
Index32 Index
Definition: Types.h:57
Base class for typed trees.
Definition: Tree.h:64
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
static const Index DIM
Definition: LeafNode.h:74
OPENVDB_API const Index32 INVALID_IDX
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:107
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
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:115