37 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 45 #include <boost/integer_traits.hpp> 46 #include <boost/scoped_array.hpp> 48 #include <tbb/blocked_range.h> 49 #include <tbb/parallel_for.h> 50 #include <tbb/parallel_reduce.h> 51 #include <tbb/task_scheduler_init.h> 57 #include <type_traits> 81 template<
typename Gr
idType>
85 std::vector<Vec3s>& points,
86 std::vector<Vec4I>& quads,
87 double isovalue = 0.0);
102 template<
typename Gr
idType>
105 const GridType& grid,
106 std::vector<Vec3s>& points,
107 std::vector<Vec3I>& triangles,
108 std::vector<Vec4I>& quads,
109 double isovalue = 0.0,
110 double adaptivity = 0.0,
127 inline PolygonPool(
const size_t numQuads,
const size_t numTriangles);
131 inline void resetQuads(
size_t size);
132 inline void clearQuads();
134 inline void resetTriangles(
size_t size);
135 inline void clearTriangles();
140 const size_t&
numQuads()
const {
return mNumQuads; }
155 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
164 inline bool trimQuads(
const size_t n,
bool reallocate =
false);
165 inline bool trimTrinagles(
const size_t n,
bool reallocate =
false);
171 size_t mNumQuads, mNumTriangles;
172 boost::scoped_array<openvdb::Vec4I> mQuads;
173 boost::scoped_array<openvdb::Vec3I> mTriangles;
174 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
202 const size_t& pointListSize()
const;
205 const size_t& polygonPoolListSize()
const;
209 std::vector<uint8_t>& pointFlags();
210 const std::vector<uint8_t>& pointFlags()
const;
218 template<
typename InputGr
idType>
219 void operator()(
const InputGridType&);
272 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
273 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
280 bool mInvertSurfaceMask, mRelaxDisorientedTriangles;
282 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
283 std::vector<uint8_t> mPointFlags;
297 const std::vector<Vec3d>& points,
298 const std::vector<Vec3d>& normals)
304 if (points.empty())
return avgPos;
306 for (
size_t n = 0, N = points.size(); n < N; ++n) {
310 avgPos /= double(points.size());
314 double m00=0,m01=0,m02=0,
321 for (
size_t n = 0, N = points.size(); n < N; ++n) {
323 const Vec3d& n_ref = normals[n];
326 m00 += n_ref[0] * n_ref[0];
327 m11 += n_ref[1] * n_ref[1];
328 m22 += n_ref[2] * n_ref[2];
330 m01 += n_ref[0] * n_ref[1];
331 m02 += n_ref[0] * n_ref[2];
332 m12 += n_ref[1] * n_ref[2];
335 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
360 Mat3d D = Mat3d::identity();
363 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
364 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
368 for (
int i = 0;
i < 3; ++
i ) {
369 if (std::abs(eigenValues[
i]) < tolerance) {
373 D[
i][
i] = 1.0 / eigenValues[
i];
380 return avgPos + pseudoInv * rhs;
394 namespace volume_to_mesh_internal {
396 template<
typename ValueType>
399 FillArray(ValueType* array,
const ValueType& v) : mArray(array), mValue(v) { }
401 void operator()(
const tbb::blocked_range<size_t>& range)
const {
402 const ValueType v = mValue;
403 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
413 template<
typename ValueType>
415 fillArray(ValueType* array,
const ValueType& val,
const size_t length)
417 const auto grainSize = std::max<size_t>(
418 length / tbb::task_scheduler_init::default_num_threads(), 1024);
419 const tbb::blocked_range<size_t> range(0, length, grainSize);
431 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,
432 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,
433 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,
434 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,
435 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,
436 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,
437 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,
438 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};
443 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,
444 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,
445 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,
446 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,
447 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,
448 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,
449 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,
450 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};
457 {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},
458 {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},
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {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},
497 {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},
498 {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},
499 {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},
500 {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},
501 {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},
502 {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},
503 {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},
504 {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},
505 {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},
506 {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},
507 {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},
508 {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},
509 {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},
510 {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},
511 {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},
512 {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},
513 {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},
514 {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},
515 {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},
516 {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},
517 {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},
518 {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},
519 {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},
520 {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},
521 {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},
522 {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},
523 {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},
524 {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},
525 {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},
526 {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},
527 {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},
528 {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},
529 {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},
530 {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},
531 {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},
532 {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},
533 {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},
534 {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},
535 {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},
536 {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},
537 {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},
538 {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},
539 {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},
540 {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},
541 {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},
542 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
551 double epsilon = 0.001)
554 Vec3d normal = (p2-p0).cross(p1-p3);
556 const Vec3d centroid = (p0 + p1 + p2 + p3);
557 const double d = centroid.
dot(normal) * 0.25;
561 double absDist = std::abs(p0.dot(normal) - d);
562 if (absDist > epsilon)
return false;
564 absDist = std::abs(p1.dot(normal) - d);
565 if (absDist > epsilon)
return false;
567 absDist = std::abs(p2.dot(normal) - d);
568 if (absDist > epsilon)
return false;
570 absDist = std::abs(p3.dot(normal) - d);
571 if (absDist > epsilon)
return false;
595 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
596 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
611 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
613 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
637 template<
typename AccessorT>
642 values[0] = accessor.getValue(ijk);
644 values[1] = accessor.getValue(ijk);
646 values[2] = accessor.getValue(ijk);
648 values[3] = accessor.getValue(ijk);
650 values[4] = accessor.getValue(ijk);
652 values[5] = accessor.getValue(ijk);
654 values[6] = accessor.getValue(ijk);
656 values[7] = accessor.getValue(ijk);
660 template<
typename LeafT>
665 values[0] = leaf.getValue(offset);
666 values[3] = leaf.getValue(offset + 1);
667 values[4] = leaf.getValue(offset + LeafT::DIM);
668 values[7] = leaf.getValue(offset + LeafT::DIM + 1);
669 values[1] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM));
670 values[2] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1);
671 values[5] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM);
672 values[6] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1);
676 template<
typename ValueType>
689 return uint8_t(signs);
695 template<
typename AccessorT>
701 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 1u;
703 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 2u;
705 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 4u;
707 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 8u;
708 coord[1] += 1; coord[2] = ijk[2];
709 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 16u;
711 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 32u;
713 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 64u;
715 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 128u;
716 return uint8_t(signs);
722 template<
typename LeafT>
732 if (
isInsideValue(leaf.getValue(offset + 1), iso)) signs |= 8u;
735 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM), iso)) signs |= 16u;
738 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM + 1), iso)) signs |= 128u;
741 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ), iso)) signs |= 2u;
744 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1), iso)) signs |= 4u;
747 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM), iso)) signs |= 32u;
750 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1), iso)) signs |= 64u;
752 return uint8_t(signs);
758 template<
class AccessorT>
761 const AccessorT& acc,
Coord ijk,
typename AccessorT::ValueType iso)
766 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 3) signs = uint8_t(~signs);
770 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 4) signs = uint8_t(~signs);
774 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 1) signs = uint8_t(~signs);
778 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 2) signs = uint8_t(~signs);
782 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 6) signs = uint8_t(~signs);
786 if (sAmbiguousFace[
evalCellSigns(acc, ijk, iso)] == 5) signs = uint8_t(~signs);
794 template<
class AccessorT>
797 typename AccessorT::ValueType isovalue,
const int dim)
810 coord[1] += dim; coord[2] = ijk[2];
821 if (p[0]) signs |= 1u;
822 if (p[1]) signs |= 2u;
823 if (p[2]) signs |= 4u;
824 if (p[3]) signs |= 8u;
825 if (p[4]) signs |= 16u;
826 if (p[5]) signs |= 32u;
827 if (p[6]) signs |= 64u;
828 if (p[7]) signs |= 128u;
829 if (!sAdaptable[signs])
return true;
834 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
835 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
836 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
839 coord.
reset(ip, j, k);
841 if (p[0] != m && p[1] != m)
return true;
844 coord.reset(ipp, j, kp);
846 if (p[1] != m && p[2] != m)
return true;
849 coord.reset(ip, j, kpp);
851 if (p[2] != m && p[3] != m)
return true;
854 coord.reset(i, j, kp);
856 if (p[0] != m && p[3] != m)
return true;
859 coord.reset(ip, jpp, k);
861 if (p[4] != m && p[5] != m)
return true;
864 coord.reset(ipp, jpp, kp);
866 if (p[5] != m && p[6] != m)
return true;
869 coord.reset(ip, jpp, kpp);
871 if (p[6] != m && p[7] != m)
return true;
874 coord.reset(i, jpp, kp);
876 if (p[7] != m && p[4] != m)
return true;
879 coord.reset(i, jp, k);
881 if (p[0] != m && p[4] != m)
return true;
884 coord.reset(ipp, jp, k);
886 if (p[1] != m && p[5] != m)
return true;
889 coord.reset(ipp, jp, kpp);
891 if (p[2] != m && p[6] != m)
return true;
895 coord.reset(i, jp, kpp);
897 if (p[3] != m && p[7] != m)
return true;
903 coord.reset(ip, jp, k);
905 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
908 coord.reset(ipp, jp, kp);
910 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
913 coord.reset(ip, jp, kpp);
915 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
918 coord.reset(i, jp, kp);
920 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
923 coord.reset(ip, j, kp);
925 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
928 coord.reset(ip, jpp, kp);
930 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
933 coord.reset(ip, jp, kp);
935 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
936 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
945 template <
class LeafType>
949 Coord ijk, end = start;
954 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
955 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
956 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
957 leaf.setValueOnly(ijk, regionId);
966 template <
class LeafType>
969 typename LeafType::ValueType::value_type adaptivity)
971 if (adaptivity < 1e-6)
return false;
973 using VecT =
typename LeafType::ValueType;
974 Coord ijk, end = start;
979 std::vector<VecT> norms;
980 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
981 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
982 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
984 if(!leaf.isValueOn(ijk))
continue;
985 norms.push_back(leaf.getValue(ijk));
990 size_t N = norms.size();
991 for (
size_t ni = 0; ni < N; ++ni) {
992 VecT n_i = norms[ni];
993 for (
size_t nj = 0; nj < N; ++nj) {
994 VecT n_j = norms[nj];
995 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
1006 inline double evalZeroCrossing(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1010 template<
typename LeafT>
1014 values[0] = double(leaf.getValue(offset));
1015 values[3] = double(leaf.getValue(offset + 1));
1016 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1017 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1018 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1019 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1020 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1021 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1026 template<
typename AccessorT>
1031 values[0] = double(acc.getValue(coord));
1034 values[1] = double(acc.getValue(coord));
1037 values[2] = double(acc.getValue(coord));
1040 values[3] = double(acc.getValue(coord));
1042 coord[1] += 1; coord[2] = ijk[2];
1043 values[4] = double(acc.getValue(coord));
1046 values[5] = double(acc.getValue(coord));
1049 values[6] = double(acc.getValue(coord));
1052 values[7] = double(acc.getValue(coord));
1059 unsigned char edgeGroup,
double iso)
1061 Vec3d avg(0.0, 0.0, 0.0);
1064 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1069 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1075 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1081 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1086 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1092 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1099 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1106 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1112 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1117 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1123 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1130 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1137 double w = 1.0 / double(samples);
1151 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1153 avg =
Vec3d(0.0, 0.0, 0.0);
1156 if (sEdgeGroupTable[signs][1] == edgeGroup
1157 && sEdgeGroupTable[signsMask][1] == 0) {
1162 if (sEdgeGroupTable[signs][2] == edgeGroup
1163 && sEdgeGroupTable[signsMask][2] == 0) {
1169 if (sEdgeGroupTable[signs][3] == edgeGroup
1170 && sEdgeGroupTable[signsMask][3] == 0) {
1176 if (sEdgeGroupTable[signs][4] == edgeGroup
1177 && sEdgeGroupTable[signsMask][4] == 0) {
1182 if (sEdgeGroupTable[signs][5] == edgeGroup
1183 && sEdgeGroupTable[signsMask][5] == 0) {
1189 if (sEdgeGroupTable[signs][6] == edgeGroup
1190 && sEdgeGroupTable[signsMask][6] == 0) {
1197 if (sEdgeGroupTable[signs][7] == edgeGroup
1198 && sEdgeGroupTable[signsMask][7] == 0) {
1205 if (sEdgeGroupTable[signs][8] == edgeGroup
1206 && sEdgeGroupTable[signsMask][8] == 0) {
1212 if (sEdgeGroupTable[signs][9] == edgeGroup
1213 && sEdgeGroupTable[signsMask][9] == 0) {
1218 if (sEdgeGroupTable[signs][10] == edgeGroup
1219 && sEdgeGroupTable[signsMask][10] == 0) {
1225 if (sEdgeGroupTable[signs][11] == edgeGroup
1226 && sEdgeGroupTable[signsMask][11] == 0) {
1233 if (sEdgeGroupTable[signs][12] == edgeGroup
1234 && sEdgeGroupTable[signsMask][12] == 0) {
1241 double w = 1.0 / double(samples);
1255 unsigned char signs,
unsigned char edgeGroup,
double iso)
1257 std::vector<Vec3d> samples;
1260 std::vector<double> weights;
1263 Vec3d avg(0.0, 0.0, 0.0);
1265 if (sEdgeGroupTable[signs][1] == edgeGroup) {
1270 samples.push_back(avg);
1271 weights.push_back((avg-p).lengthSqr());
1274 if (sEdgeGroupTable[signs][2] == edgeGroup) {
1279 samples.push_back(avg);
1280 weights.push_back((avg-p).lengthSqr());
1283 if (sEdgeGroupTable[signs][3] == edgeGroup) {
1288 samples.push_back(avg);
1289 weights.push_back((avg-p).lengthSqr());
1292 if (sEdgeGroupTable[signs][4] == edgeGroup) {
1297 samples.push_back(avg);
1298 weights.push_back((avg-p).lengthSqr());
1301 if (sEdgeGroupTable[signs][5] == edgeGroup) {
1306 samples.push_back(avg);
1307 weights.push_back((avg-p).lengthSqr());
1310 if (sEdgeGroupTable[signs][6] == edgeGroup) {
1315 samples.push_back(avg);
1316 weights.push_back((avg-p).lengthSqr());
1319 if (sEdgeGroupTable[signs][7] == edgeGroup) {
1324 samples.push_back(avg);
1325 weights.push_back((avg-p).lengthSqr());
1328 if (sEdgeGroupTable[signs][8] == edgeGroup) {
1333 samples.push_back(avg);
1334 weights.push_back((avg-p).lengthSqr());
1337 if (sEdgeGroupTable[signs][9] == edgeGroup) {
1342 samples.push_back(avg);
1343 weights.push_back((avg-p).lengthSqr());
1346 if (sEdgeGroupTable[signs][10] == edgeGroup) {
1351 samples.push_back(avg);
1352 weights.push_back((avg-p).lengthSqr());
1355 if (sEdgeGroupTable[signs][11] == edgeGroup) {
1360 samples.push_back(avg);
1361 weights.push_back((avg-p).lengthSqr());
1364 if (sEdgeGroupTable[signs][12] == edgeGroup) {
1369 samples.push_back(avg);
1370 weights.push_back((avg-p).lengthSqr());
1377 for (
size_t i = 0, I = weights.size();
i < I; ++
i) {
1378 minWeight =
std::min(minWeight, weights[
i]);
1379 maxWeight =
std::max(maxWeight, weights[i]);
1382 const double offset = maxWeight + minWeight * 0.1;
1383 for (
size_t i = 0, I = weights.size();
i < I; ++
i) {
1384 weights[
i] = offset - weights[
i];
1388 double weightSum = 0.0;
1389 for (
size_t i = 0, I = weights.size();
i < I; ++
i) {
1390 weightSum += weights[
i];
1397 if (samples.size() > 1) {
1398 for (
size_t i = 0, I = samples.size();
i < I; ++
i) {
1399 avg += samples[
i] * (weights[
i] / weightSum);
1402 avg = samples.front();
1413 const std::vector<double>& values,
unsigned char signs,
double iso)
1415 for (
size_t n = 1, N = sEdgeGroupTable[signs][0] + 1; n < N; ++n) {
1416 points.push_back(
computePoint(values, signs, uint8_t(n), iso));
1425 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1428 for (
size_t i = 1;
i <= 12; ++
i) {
1429 if (sEdgeGroupTable[lhsSigns][
i] == groupId && sEdgeGroupTable[rhsSigns][
i] != 0) {
1430 id = sEdgeGroupTable[rhsSigns][
i];
1444 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1445 unsigned char lhsSigns,
unsigned char rhsSigns,
1446 double iso,
size_t pointIdx,
const uint32_t * seamPointArray)
1448 for (
size_t n = 1, N = sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1454 const unsigned char e = uint8_t(
id);
1455 const uint32_t& quantizedPoint = seamPointArray[pointIdx + (
id - 1)];
1460 weightedPointMask.push_back(
true);
1462 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1463 weightedPointMask.push_back(
false);
1467 points.push_back(
computePoint(lhsValues, lhsSigns, uint8_t(n), iso));
1468 weightedPointMask.push_back(
false);
1474 template <
typename InputTreeType>
1480 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1487 const InputTreeType& inputTree,
1488 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1489 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1490 const boost::scoped_array<Index32>& leafNodeOffsets,
1494 void setRefData(
const InputTreeType& refInputTree,
1497 const uint32_t * quantizedSeamLinePoints,
1498 uint8_t * seamLinePointsFlags);
1500 void operator()(
const tbb::blocked_range<size_t>&)
const;
1503 Vec3s *
const mPoints;
1504 InputTreeType
const *
const mInputTree;
1507 Index32 const *
const mNodeOffsets;
1509 double const mIsovalue;
1511 InputTreeType
const * mRefInputTree;
1514 uint32_t
const * mQuantizedSeamLinePoints;
1515 uint8_t * mSeamLinePointsFlags;
1519 template <
typename InputTreeType>
1522 const InputTreeType& inputTree,
1523 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1524 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1525 const boost::scoped_array<Index32>& leafNodeOffsets,
1528 : mPoints(pointArray)
1529 , mInputTree(&inputTree)
1530 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
1531 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1532 , mNodeOffsets(leafNodeOffsets.get())
1535 , mRefInputTree(nullptr)
1536 , mRefPointIndexTree(nullptr)
1537 , mRefSignFlagsTree(nullptr)
1538 , mQuantizedSeamLinePoints(nullptr)
1539 , mSeamLinePointsFlags(nullptr)
1543 template <
typename InputTreeType>
1546 const InputTreeType& refInputTree,
1549 const uint32_t * quantizedSeamLinePoints,
1550 uint8_t * seamLinePointsFlags)
1552 mRefInputTree = &refInputTree;
1553 mRefPointIndexTree = &refPointIndexTree;
1554 mRefSignFlagsTree = &refSignFlagsTree;
1555 mQuantizedSeamLinePoints = quantizedSeamLinePoints;
1556 mSeamLinePointsFlags = seamLinePointsFlags;
1559 template <
typename InputTreeType>
1567 using IndexType =
typename Index32TreeType::ValueType;
1569 using IndexArray = std::vector<Index>;
1570 using IndexArrayMap = std::map<IndexType, IndexArray>;
1572 InputTreeAccessor inputAcc(*mInputTree);
1576 std::vector<Vec3d> points(4);
1577 std::vector<bool> weightedPointMask(4);
1578 std::vector<double> values(8), refValues(8);
1579 const double iso = mIsovalue;
1583 std::unique_ptr<InputTreeAccessor> refInputAcc;
1584 std::unique_ptr<Index32TreeAccessor> refPointIndexAcc;
1585 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
1587 const bool hasReferenceData = mRefInputTree && mRefPointIndexTree && mRefSignFlagsTree;
1589 if (hasReferenceData) {
1590 refInputAcc.reset(
new InputTreeAccessor(*mRefInputTree));
1591 refPointIndexAcc.reset(
new Index32TreeAccessor(*mRefPointIndexTree));
1592 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
1595 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1598 const Coord& origin = pointIndexNode.origin();
1608 if (hasReferenceData) {
1609 refInputNode = refInputAcc->probeConstLeaf(origin);
1610 refPointIndexNode = refPointIndexAcc->probeConstLeaf(origin);
1611 refSignFlagsNode = refSignFlagsAcc->probeConstLeaf(origin);
1614 IndexType pointOffset = IndexType(mNodeOffsets[n]);
1615 IndexArrayMap regions;
1617 for (
auto it = pointIndexNode.beginValueOn(); it; ++it) {
1618 const Index offset = it.pos();
1620 const IndexType
id = it.getValue();
1623 regions[id].push_back(offset);
1628 pointIndexNode.setValueOnly(offset, pointOffset);
1630 const Int16 flags = signFlagsNode.getValue(offset);
1631 uint8_t signs = uint8_t(
SIGNS & flags);
1632 uint8_t refSigns = 0;
1634 if ((flags &
SEAM) && refPointIndexNode && refSignFlagsNode) {
1635 if (refSignFlagsNode->isValueOn(offset)) {
1636 refSigns = uint8_t(
SIGNS & refSignFlagsNode->getValue(offset));
1640 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1642 const bool inclusiveCell = inputNode &&
1643 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1644 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1645 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1653 weightedPointMask.clear();
1655 if (refSigns == 0) {
1660 if (inclusiveCell && refInputNode) {
1665 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1666 iso, refPointIndexNode->getValue(offset), mQuantizedSeamLinePoints);
1669 xyz[0] = double(ijk[0]);
1670 xyz[1] = double(ijk[1]);
1671 xyz[2] = double(ijk[2]);
1673 for (
size_t i = 0, I = points.size();
i < I; ++
i) {
1675 Vec3d& point = points[
i];
1678 if (!std::isfinite(point[0]) ||
1679 !std::isfinite(point[1]) ||
1680 !std::isfinite(point[2]))
1683 "VolumeToMesh encountered NaNs or infs in the input VDB!" 1684 " Hint: Check the input and consider using the \"Diagnostics\" tool " 1685 "to detect and resolve the NaNs.");
1691 Vec3s& pos = mPoints[pointOffset];
1692 pos[0] = float(point[0]);
1693 pos[1] = float(point[1]);
1694 pos[2] = float(point[2]);
1696 if (mSeamLinePointsFlags && !weightedPointMask.empty() && weightedPointMask[
i]) {
1697 mSeamLinePointsFlags[pointOffset] = uint8_t(1);
1705 for (
typename IndexArrayMap::iterator it = regions.begin(); it != regions.end(); ++it) {
1707 Vec3d avg(0.0), point(0.0);
1710 const IndexArray& voxels = it->second;
1711 for (
size_t i = 0, I = voxels.size();
i < I; ++
i) {
1713 const Index offset = voxels[
i];
1714 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1716 const bool inclusiveCell = inputNode &&
1717 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1718 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1719 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1723 pointIndexNode.setValueOnly(offset, pointOffset);
1725 uint8_t signs = uint8_t(
SIGNS & signFlagsNode.getValue(offset));
1733 avg[0] += double(ijk[0]) + points[0][0];
1734 avg[1] += double(ijk[1]) + points[0][1];
1735 avg[2] += double(ijk[2]) + points[0][2];
1741 double w = 1.0 / double(count);
1749 Vec3s& pos = mPoints[pointOffset];
1750 pos[0] = float(avg[0]);
1751 pos[1] = float(avg[1]);
1752 pos[2] = float(avg[2]);
1763 template <
typename InputTreeType>
1769 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1776 const InputTreeType& inputTree,
1779 uint32_t * quantizedPoints,
1781 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1782 , mInputTree(&inputTree)
1783 , mRefPointIndexTree(&refPointIndexTree)
1784 , mRefSignFlagsTree(&refSignFlagsTree)
1785 , mQuantizedPoints(quantizedPoints)
1796 std::vector<double> values(8);
1797 const double iso = double(mIsovalue);
1801 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1804 const Coord& origin = signFlagsNode.origin();
1807 if (!refSignNode)
continue;
1811 if (!refPointIndexNode)
continue;
1815 for (
typename Int16LeafNodeType::ValueOnCIter it = signFlagsNode.cbeginValueOn();
1818 const Index offset = it.pos();
1820 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1822 const bool inclusiveCell = inputNode &&
1823 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1824 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1825 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1829 if ((it.getValue() &
SEAM) && refSignNode->isValueOn(offset)) {
1831 uint8_t lhsSigns = uint8_t(
SIGNS & it.getValue());
1832 uint8_t rhsSigns = uint8_t(
SIGNS & refSignNode->getValue(offset));
1835 if (inclusiveCell) {
1842 for (
unsigned i = 1, I = sEdgeGroupTable[lhsSigns][0] + 1;
i < I; ++
i) {
1848 uint32_t&
data = mQuantizedPoints[
1849 refPointIndexNode->getValue(offset) + (
id - 1)];
1854 pos, values, lhsSigns, rhsSigns, uint8_t(
i), iso);
1872 InputTreeType
const *
const mInputTree;
1875 uint32_t *
const mQuantizedPoints;
1880 template <
typename TreeType>
1886 const TreeType& refSignFlagsTree)
1887 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1888 , mRefSignFlagsTree(&refSignFlagsTree)
1896 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1899 const Coord& origin = signFlagsNode.origin();
1902 if (!refSignNode)
continue;
1904 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
1905 const Index offset = it.pos();
1907 uint8_t rhsSigns = uint8_t(refSignNode->getValue(offset) &
SIGNS);
1909 if (sEdgeGroupTable[rhsSigns][0] > 0) {
1911 const typename LeafNodeType::ValueType value = it.getValue();
1912 uint8_t lhsSigns = uint8_t(value &
SIGNS);
1914 if (rhsSigns != lhsSigns) {
1915 signFlagsNode.setValueOnly(offset, value |
SEAM);
1926 TreeType
const *
const mRefSignFlagsTree;
1930 template <
typename BoolTreeType,
typename SignDataType>
1939 const BoolTreeType& maskTree)
1940 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1941 , mMaskTree(&maskTree)
1949 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1952 const Coord& origin = signFlagsNode.origin();
1955 if (!maskNode)
continue;
1957 using ValueOnCIter =
typename SignDataLeafNodeType::ValueOnCIter;
1959 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
1960 const Index offset = it.pos();
1962 if (maskNode->isValueOn(offset)) {
1963 signFlagsNode.setValueOnly(offset, it.getValue() |
SEAM);
1973 BoolTreeType
const *
const mMaskTree;
1977 template <
typename TreeType>
1981 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1984 const TreeType& signFlagsTree,
1986 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1987 , mSignFlagsTree(&signFlagsTree)
1994 : mSignFlagsNodes(rhs.mSignFlagsNodes)
1995 , mSignFlagsTree(rhs.mSignFlagsTree)
2005 using ValueOnCIter =
typename LeafNodeType::ValueOnCIter;
2006 using ValueType =
typename LeafNodeType::ValueType;
2012 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2017 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
2019 const ValueType flags = it.getValue();
2021 if (!(flags &
SEAM) && (flags &
EDGES)) {
2023 ijk = it.getCoord();
2025 bool isSeamLineVoxel =
false;
2027 if (flags &
XEDGE) {
2031 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2033 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2037 if (!isSeamLineVoxel && flags &
YEDGE) {
2039 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2041 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2043 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2047 if (!isSeamLineVoxel && flags &
ZEDGE) {
2049 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2051 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2053 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2057 if (isSeamLineVoxel) {
2058 maskAcc.
setValue(it.getCoord(),
true);
2068 TreeType
const *
const mSignFlagsTree;
2074 template<
typename SignDataTreeType>
2078 using SignDataType =
typename SignDataTreeType::ValueType;
2079 using SignDataLeafNodeType =
typename SignDataTreeType::LeafNodeType;
2080 using BoolTreeType =
typename SignDataTreeType::template ValueConverter<bool>::Type;
2082 std::vector<SignDataLeafNodeType*> signFlagsLeafNodes;
2083 signFlagsTree.getNodes(signFlagsLeafNodes);
2085 const tbb::blocked_range<size_t> nodeRange(0, signFlagsLeafNodes.size());
2087 tbb::parallel_for(nodeRange,
2090 BoolTreeType seamLineMaskTree(
false);
2093 maskSeamLine(signFlagsLeafNodes, signFlagsTree, seamLineMaskTree);
2095 tbb::parallel_reduce(nodeRange, maskSeamLine);
2097 tbb::parallel_for(nodeRange,
2105 template <
typename InputGr
idType>
2112 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
2116 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
2122 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2127 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2128 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2131 bool invertSurfaceOrientation);
2135 mSpatialAdaptivityTree = &grid.
tree();
2136 mSpatialAdaptivityTransform = &grid.
transform();
2146 mRefSignFlagsTree = &signFlagsData;
2147 mInternalAdaptivity = internalAdaptivity;
2150 void operator()(
const tbb::blocked_range<size_t>&)
const;
2161 float mSurfaceAdaptivity, mInternalAdaptivity;
2162 bool mInvertSurfaceOrientation;
2171 template <
typename InputGr
idType>
2173 const InputGridType& inputGrid,
2175 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2176 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2179 bool invertSurfaceOrientation)
2180 : mInputTree(&inputGrid.tree())
2181 , mInputTransform(&inputGrid.transform())
2182 , mPointIndexTree(&pointIndexTree)
2183 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
2184 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
2186 , mSurfaceAdaptivity(adaptivity)
2187 , mInternalAdaptivity(adaptivity)
2188 , mInvertSurfaceOrientation(invertSurfaceOrientation)
2189 , mSpatialAdaptivityTree(nullptr)
2190 , mMaskTree(nullptr)
2191 , mRefSignFlagsTree(nullptr)
2192 , mSpatialAdaptivityTransform(nullptr)
2197 template <
typename InputGr
idType>
2202 using Vec3sLeafNodeType =
typename InputLeafNodeType::template ValueConverter<Vec3sType>::Type;
2210 std::unique_ptr<FloatTreeAccessor> spatialAdaptivityAcc;
2211 if (mSpatialAdaptivityTree && mSpatialAdaptivityTransform) {
2212 spatialAdaptivityAcc.reset(
new FloatTreeAccessor(*mSpatialAdaptivityTree));
2215 std::unique_ptr<BoolTreeAccessor> maskAcc;
2217 maskAcc.reset(
new BoolTreeAccessor(*mMaskTree));
2220 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
2221 if (mRefSignFlagsTree) {
2222 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
2225 InputTreeAccessor inputAcc(*mInputTree);
2226 Index32TreeAccessor pointIndexAcc(*mPointIndexTree);
2230 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<InputValueType>();
2231 std::unique_ptr<Vec3sLeafNodeType> gradientNode;
2234 const int LeafDim = InputLeafNodeType::DIM;
2236 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2238 mask.setValuesOff();
2243 const Coord& origin = pointIndexNode.origin();
2245 end[0] = origin[0] + LeafDim;
2246 end[1] = origin[1] + LeafDim;
2247 end[2] = origin[2] + LeafDim;
2252 if (maskLeaf !=
nullptr) {
2253 for (
typename BoolLeafNodeType::ValueOnCIter it = maskLeaf->cbeginValueOn();
2256 mask.setActiveState(it.getCoord() & ~1u,
true);
2261 float adaptivity = (refSignFlagsAcc && !refSignFlagsAcc->probeConstLeaf(origin)) ?
2262 mInternalAdaptivity : mSurfaceAdaptivity;
2264 bool useGradients = adaptivity < 1.0f;
2269 if (spatialAdaptivityAcc) {
2270 useGradients =
false;
2271 for (
Index offset = 0; offset < FloatLeafNodeType::NUM_VALUES; ++offset) {
2272 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2275 float weight = spatialAdaptivityAcc->getValue(ijk);
2276 float adaptivityValue = weight * adaptivity;
2277 if (adaptivityValue < 1.0f) useGradients =
true;
2278 adaptivityLeaf.setValueOnly(offset, adaptivityValue);
2283 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2284 const Int16 flags = it.getValue();
2285 const unsigned char signs =
static_cast<unsigned char>(
SIGNS & int(flags));
2287 if ((flags &
SEAM) || !sAdaptable[signs] || sEdgeGroupTable[signs][0] > 1) {
2289 mask.setActiveState(it.getCoord() & ~1u,
true);
2291 }
else if (flags &
EDGES) {
2293 bool maskRegion =
false;
2295 ijk = it.getCoord();
2296 if (!pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2298 if (!maskRegion && flags &
XEDGE) {
2300 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2302 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2304 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2308 if (!maskRegion && flags &
YEDGE) {
2310 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2312 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2314 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2318 if (!maskRegion && flags &
ZEDGE) {
2320 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2322 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2324 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2329 mask.setActiveState(it.getCoord() & ~1u,
true);
2336 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2337 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2338 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2339 if (!mask.isValueOn(ijk) &
isNonManifold(inputAcc, ijk, mIsovalue, dim)) {
2340 mask.setActiveState(ijk,
true);
2351 gradientNode->setValuesOff();
2353 gradientNode.
reset(
new Vec3sLeafNodeType());
2356 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2357 ijk = it.getCoord();
2358 if (!mask.isValueOn(ijk & ~1u)) {
2362 if (invertGradientDir) {
2366 gradientNode->setValueOn(it.pos(), dir);
2373 for ( ; dim <= LeafDim; dim = dim << 1) {
2374 const unsigned coordMask = ~((dim << 1) - 1);
2375 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2376 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2377 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2379 adaptivity = adaptivityLeaf.getValue(ijk);
2381 if (mask.isValueOn(ijk)
2383 || (useGradients && !
isMergable(*gradientNode, ijk, dim, adaptivity)))
2385 mask.setActiveState(ijk & coordMask,
true);
2387 mergeVoxels(pointIndexNode, ijk, dim, regionId++);
2407 mPolygonPool = &quadPool;
2412 template<
typename IndexType>
2416 mPolygonPool->quad(mIdx) = verts;
2418 Vec4I& quad = mPolygonPool->quad(mIdx);
2424 mPolygonPool->quadFlags(mIdx) = flags;
2430 mPolygonPool->trimQuads(mIdx);
2446 mPolygonPool = &polygonPool;
2448 mPolygonPool->resetTriangles(upperBound);
2454 template<
typename IndexType>
2457 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2458 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2459 mPolygonPool->quadFlags(mQuadIdx) = flags;
2460 addQuad(verts, reverse);
2462 verts[0] == verts[3] &&
2463 verts[1] != verts[2] &&
2464 verts[1] != verts[0] &&
2465 verts[2] != verts[0]) {
2466 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2467 addTriangle(verts[0], verts[1], verts[2], reverse);
2469 verts[1] == verts[2] &&
2470 verts[0] != verts[3] &&
2471 verts[0] != verts[1] &&
2472 verts[3] != verts[1]) {
2473 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2474 addTriangle(verts[0], verts[1], verts[3], reverse);
2476 verts[0] == verts[1] &&
2477 verts[2] != verts[3] &&
2478 verts[2] != verts[0] &&
2479 verts[3] != verts[0]) {
2480 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2481 addTriangle(verts[0], verts[2], verts[3], reverse);
2483 verts[2] == verts[3] &&
2484 verts[0] != verts[1] &&
2485 verts[0] != verts[2] &&
2486 verts[1] != verts[2]) {
2487 mPolygonPool->triangleFlags(mTriangleIdx) = flags;
2488 addTriangle(verts[0], verts[1], verts[2], reverse);
2495 mPolygonPool->trimQuads(mQuadIdx,
true);
2496 mPolygonPool->trimTrinagles(mTriangleIdx,
true);
2501 template<
typename IndexType>
2505 mPolygonPool->quad(mQuadIdx) = verts;
2507 Vec4I& quad = mPolygonPool->quad(mQuadIdx);
2516 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2518 Vec3I& prim = mPolygonPool->triangle(mTriangleIdx);
2532 size_t mQuadIdx, mTriangleIdx;
2537 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2540 bool invertSurfaceOrientation,
2543 const Vec3i& offsets,
2545 const SignAccT& signAcc,
2546 const IdxAccT& idxAcc,
2547 PrimBuilder& mesher)
2549 using IndexType =
typename IdxAccT::ValueType;
2552 const bool isActive = idxAcc.probeValue(ijk, v0);
2559 bool isInside = flags &
INSIDE;
2561 isInside = invertSurfaceOrientation ? !isInside : isInside;
2566 if (flags &
XEDGE) {
2568 quad[0] = v0 + offsets[0];
2572 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2573 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2574 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][5] - 1 : 0;
2578 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2579 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2580 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][7] - 1 : 0;
2584 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2585 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2586 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][3] - 1 : 0;
2589 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2596 if (flags &
YEDGE) {
2598 quad[0] = v0 + offsets[1];
2602 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2603 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2604 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][12] - 1 : 0;
2608 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2609 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2610 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][11] - 1 : 0;
2614 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2615 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2616 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][10] - 1 : 0;
2619 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2626 if (flags &
ZEDGE) {
2628 quad[0] = v0 + offsets[2];
2632 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2633 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2634 quad[1] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][8] - 1 : 0;
2638 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2639 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2640 quad[2] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][6] - 1 : 0;
2644 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2645 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2646 quad[3] += sEdgeGroupTable[cell][0] > 1 ? sEdgeGroupTable[cell][2] - 1 : 0;
2649 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2658 template<
typename InputTreeType>
2662 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2667 : mInputTree(&inputTree)
2671 , mTileArray(tileArray)
2676 : mInputTree(rhs.mInputTree)
2677 , mIsovalue(rhs.mIsovalue)
2680 , mTileArray(rhs.mTileArray)
2686 void operator()(
const tbb::blocked_range<size_t>&);
2693 Vec4i const *
const mTileArray;
2697 template<
typename InputTreeType>
2706 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2708 const Vec4i& tile = mTileArray[n];
2710 bbox.
min()[0] = tile[0];
2711 bbox.
min()[1] = tile[1];
2712 bbox.
min()[2] = tile[2];
2727 bool processRegion =
true;
2732 if (processRegion) {
2735 region.
min()[0] = region.
max()[0] = ijk[0];
2736 mMask->fill(region,
false);
2743 processRegion =
true;
2745 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2749 if (processRegion) {
2752 region.
min()[0] = region.
max()[0] = ijk[0];
2753 mMask->fill(region,
false);
2763 processRegion =
true;
2768 if (processRegion) {
2771 region.
min()[1] = region.
max()[1] = ijk[1];
2772 mMask->fill(region,
false);
2779 processRegion =
true;
2781 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2785 if (processRegion) {
2788 region.
min()[1] = region.
max()[1] = ijk[1];
2789 mMask->fill(region,
false);
2799 processRegion =
true;
2804 if (processRegion) {
2807 region.
min()[2] = region.
max()[2] = ijk[2];
2808 mMask->fill(region,
false);
2814 processRegion =
true;
2816 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2820 if (processRegion) {
2823 region.
min()[2] = region.
max()[2] = ijk[2];
2824 mMask->fill(region,
false);
2830 template<
typename InputTreeType>
2833 typename InputTreeType::template ValueConverter<bool>::Type& mask)
2835 typename InputTreeType::ValueOnCIter tileIter(inputTree);
2836 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2838 size_t tileCount = 0;
2839 for ( ; tileIter; ++tileIter) {
2843 if (tileCount > 0) {
2844 boost::scoped_array<Vec4i> tiles(
new Vec4i[tileCount]);
2849 tileIter = inputTree.cbeginValueOn();
2850 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2852 for (; tileIter; ++tileIter) {
2853 Vec4i& tile = tiles[index++];
2854 tileIter.getBoundingBox(bbox);
2855 tile[0] = bbox.
min()[0];
2856 tile[1] = bbox.
min()[1];
2857 tile[2] = bbox.
min()[2];
2858 tile[3] = bbox.
max()[0] - bbox.
min()[0];
2862 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, tileCount), op);
2875 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
2881 for (
size_t n = range.begin(); n < range.end(); ++n) {
2882 mPointsOut[n] = mPointsIn[n];
2888 std::vector<Vec3s>& mPointsOut;
2900 template<
typename LeafNodeType>
2901 void constructOffsetList();
2939 IndexVector mCore, mMinX, mMaxX, mMinY, mMaxY, mMinZ, mMaxZ,
2940 mInternalNeighborsX, mInternalNeighborsY, mInternalNeighborsZ;
2944 template<
typename LeafNodeType>
2950 mCore.reserve((LeafNodeType::DIM - 2) * (LeafNodeType::DIM - 2));
2952 for (
Index x = 1; x < (LeafNodeType::DIM - 1); ++x) {
2953 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2954 for (
Index y = 1; y < (LeafNodeType::DIM - 1); ++y) {
2955 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2956 for (
Index z = 1; z < (LeafNodeType::DIM - 1); ++z) {
2957 mCore.push_back(offsetXY + z);
2963 mInternalNeighborsX.clear();
2964 mInternalNeighborsX.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2966 for (
Index x = 0; x < (LeafNodeType::DIM - 1); ++x) {
2967 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2968 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2969 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2970 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2971 mInternalNeighborsX.push_back(offsetXY + z);
2977 mInternalNeighborsY.clear();
2978 mInternalNeighborsY.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2980 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2981 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2982 for (
Index y = 0; y < (LeafNodeType::DIM - 1); ++y) {
2983 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2984 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2985 mInternalNeighborsY.push_back(offsetXY + z);
2991 mInternalNeighborsZ.clear();
2992 mInternalNeighborsZ.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2994 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2995 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2996 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2997 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2998 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
2999 mInternalNeighborsZ.push_back(offsetXY + z);
3006 mMinX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3008 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3009 const Index offsetXY = (y << LeafNodeType::LOG2DIM);
3010 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3011 mMinX.push_back(offsetXY + z);
3018 mMaxX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3020 const Index offsetX = (LeafNodeType::DIM - 1) << (2 * LeafNodeType::LOG2DIM);
3021 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3022 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3023 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3024 mMaxX.push_back(offsetXY + z);
3031 mMinY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3033 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3034 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3035 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3036 mMinY.push_back(offsetX + z);
3043 mMaxY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3045 const Index offsetY = (LeafNodeType::DIM - 1) << LeafNodeType::LOG2DIM;
3046 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3047 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3048 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3049 mMaxY.push_back(offsetX + offsetY + z);
3056 mMinZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3058 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3059 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3060 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3061 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3062 mMinZ.push_back(offsetXY);
3069 mMaxZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3071 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3072 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3073 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3074 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3075 mMaxZ.push_back(offsetXY + (LeafNodeType::DIM - 1));
3086 template<
typename AccessorT,
int _AXIS>
3089 enum { AXIS = _AXIS };
3096 acc.setActiveState(ijk);
3098 acc.setActiveState(ijk);
3100 acc.setActiveState(ijk);
3102 acc.setActiveState(ijk);
3103 }
else if (_AXIS == 1) {
3104 acc.setActiveState(ijk);
3106 acc.setActiveState(ijk);
3108 acc.setActiveState(ijk);
3110 acc.setActiveState(ijk);
3112 acc.setActiveState(ijk);
3114 acc.setActiveState(ijk);
3116 acc.setActiveState(ijk);
3118 acc.setActiveState(ijk);
3127 template<
typename VoxelEdgeAcc,
typename LeafNode>
3135 if (VoxelEdgeAcc::AXIS == 0) {
3136 nvo = LeafNode::DIM * LeafNode::DIM;
3138 }
else if (VoxelEdgeAcc::AXIS == 1) {
3139 nvo = LeafNode::DIM;
3143 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3144 const Index& pos = (*offsets)[n];
3145 bool isActive = leafnode.isValueOn(pos) || leafnode.isValueOn(pos + nvo);
3146 if (isActive && (
isInsideValue(leafnode.getValue(pos), iso) !=
3148 edgeAcc.set(leafnode.offsetToGlobalCoord(pos));
3157 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3162 const std::vector<Index>* lhsOffsets = &voxels.
maxX();
3163 const std::vector<Index>* rhsOffsets = &voxels.
minX();
3164 Coord ijk = lhsNode.origin();
3166 if (VoxelEdgeAcc::AXIS == 0) {
3167 ijk[0] += LeafNode::DIM;
3168 }
else if (VoxelEdgeAcc::AXIS == 1) {
3169 ijk[1] += LeafNode::DIM;
3170 lhsOffsets = &voxels.
maxY();
3171 rhsOffsets = &voxels.
minY();
3172 }
else if (VoxelEdgeAcc::AXIS == 2) {
3173 ijk[2] += LeafNode::DIM;
3174 lhsOffsets = &voxels.
maxZ();
3175 rhsOffsets = &voxels.
minZ();
3178 typename LeafNode::ValueType value;
3179 const LeafNode* rhsNodePt = acc.probeConstLeaf(ijk);
3182 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3183 const Index& pos = (*lhsOffsets)[n];
3184 bool isActive = lhsNode.isValueOn(pos) || rhsNodePt->isValueOn((*rhsOffsets)[n]);
3185 if (isActive && (
isInsideValue(lhsNode.getValue(pos), iso) !=
3186 isInsideValue(rhsNodePt->getValue((*rhsOffsets)[n]), iso))) {
3187 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3190 }
else if (!acc.probeValue(ijk, value)) {
3192 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3193 const Index& pos = (*lhsOffsets)[n];
3194 if (lhsNode.isValueOn(pos) && (inside !=
isInsideValue(lhsNode.getValue(pos), iso))) {
3195 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3205 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3210 Coord ijk = leafnode.origin();
3211 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3212 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3213 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3215 typename LeafNode::ValueType value;
3216 if (!acc.probeConstLeaf(ijk) && !acc.probeValue(ijk, value)) {
3223 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3225 const Index& pos = (*offsets)[n];
3226 if (leafnode.isValueOn(pos)
3229 ijk = leafnode.offsetToGlobalCoord(pos);
3230 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3231 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3232 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3242 template<
typename InputTreeType>
3248 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3252 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3257 void operator()(
const tbb::blocked_range<size_t>&);
3259 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3276 template<
typename InputTreeType>
3279 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3282 : mInputAccessor(inputTree)
3283 , mInputNodes(inputLeafNodes.empty() ? nullptr : &inputLeafNodes.front())
3284 , mIntersectionTree(false)
3285 , mIntersectionAccessor(intersectionTree)
3287 , mOffsets(&mOffsetData)
3294 template<
typename InputTreeType>
3297 : mInputAccessor(rhs.mInputAccessor.tree())
3298 , mInputNodes(rhs.mInputNodes)
3299 , mIntersectionTree(false)
3300 , mIntersectionAccessor(mIntersectionTree)
3302 , mOffsets(rhs.mOffsets)
3303 , mIsovalue(rhs.mIsovalue)
3308 template<
typename InputTreeType>
3316 for (
size_t n = range.begin(); n != range.end(); ++n) {
3347 template<
typename InputTreeType>
3350 typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3351 const InputTreeType& inputTree,
3352 typename InputTreeType::ValueType isovalue)
3356 std::vector<const InputLeafNodeType*> inputLeafNodes;
3357 inputTree.getNodes(inputLeafNodes);
3360 inputTree, inputLeafNodes, intersectionTree, isovalue);
3362 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, inputLeafNodes.size()), op);
3371 template<
typename InputTreeType>
3377 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3381 const InputTreeType& inputTree,
3382 const std::vector<BoolLeafNodeType*>& nodes,
3387 void operator()(
const tbb::blocked_range<size_t>&);
3389 mIntersectionAccessor.tree().merge(rhs.mIntersectionAccessor.
tree());
3403 template<
typename InputTreeType>
3405 const InputTreeType& inputTree,
3406 const std::vector<BoolLeafNodeType*>& nodes,
3409 : mInputAccessor(inputTree)
3410 , mNodes(nodes.empty() ? nullptr : &nodes.front())
3411 , mIntersectionTree(false)
3412 , mIntersectionAccessor(intersectionTree)
3418 template<
typename InputTreeType>
3421 : mInputAccessor(rhs.mInputAccessor.tree())
3422 , mNodes(rhs.mNodes)
3423 , mIntersectionTree(false)
3424 , mIntersectionAccessor(mIntersectionTree)
3425 , mIsovalue(rhs.mIsovalue)
3430 template<
typename InputTreeType>
3441 for (
size_t n = range.begin(); n != range.end(); ++n) {
3445 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3447 if (!it.getValue()) {
3449 ijk = it.getCoord();
3470 template<
typename BoolTreeType>
3476 const std::vector<BoolLeafNodeType*>& maskNodes,
3478 : mMaskTree(&maskTree)
3479 , mMaskNodes(maskNodes.empty() ? nullptr : &maskNodes.front())
3480 , mTmpBorderTree(false)
3481 , mBorderTree(&borderTree)
3486 : mMaskTree(rhs.mMaskTree)
3487 , mMaskNodes(rhs.mMaskNodes)
3488 , mTmpBorderTree(false)
3489 , mBorderTree(&mTmpBorderTree)
3501 for (
size_t n = range.begin(); n != range.end(); ++n) {
3505 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3507 ijk = it.getCoord();
3509 const bool lhs = it.getValue();
3512 bool isEdgeVoxel =
false;
3515 isEdgeVoxel = (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3518 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3521 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3524 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3528 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3531 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3534 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3553 template<
typename BoolTreeType>
3559 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3566 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3570 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3577 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3578 const Index pos = it.pos();
3579 if (maskNode->getValue(pos)) {
3580 node.setValueOnly(pos,
true);
3596 template<
typename BoolTreeType>
3603 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3605 , mInputTransform(inputTransform)
3606 , mMaskTransform(maskTransform)
3607 , mInvertMask(invert)
3613 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3617 const bool matchingTransforms = mInputTransform == mMaskTransform;
3618 const bool maskState = mInvertMask;
3620 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3624 if (matchingTransforms) {
3630 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3631 const Index pos = it.pos();
3632 if (maskNode->isValueOn(pos) == maskState) {
3633 node.setValueOnly(pos,
true);
3639 if (maskTreeAcc.
isValueOn(node.origin()) == maskState) {
3640 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3641 node.setValueOnly(it.pos(),
true);
3651 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3653 ijk = mMaskTransform.worldToIndexCellCentered(
3654 mInputTransform.indexToWorld(it.getCoord()));
3656 if (maskTreeAcc.
isValueOn(ijk) == maskState) {
3657 node.setValueOnly(it.pos(),
true);
3670 bool const mInvertMask;
3674 template<
typename InputGr
idType>
3677 typename InputGridType::TreeType::template ValueConverter<bool>::Type& intersectionTree,
3678 typename InputGridType::TreeType::template ValueConverter<bool>::Type& borderTree,
3679 const InputGridType& inputGrid,
3682 typename InputGridType::ValueType isovalue)
3684 using InputTreeType =
typename InputGridType::TreeType;
3685 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3689 if (maskGrid && maskGrid->type() == BoolGridType::gridType()) {
3692 const InputTreeType& inputTree = inputGrid.tree();
3694 const BoolGridType * surfaceMask =
static_cast<const BoolGridType*
>(maskGrid.get());
3702 std::vector<BoolLeafNodeType*> intersectionLeafNodes;
3703 intersectionTree.getNodes(intersectionLeafNodes);
3705 tbb::parallel_for(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()),
3707 intersectionLeafNodes, maskTree, transform, maskTransform, invertMask));
3713 intersectionTree, intersectionLeafNodes, borderTree);
3714 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), borderOp);
3722 inputTree, intersectionLeafNodes, tmpIntersectionTree, isovalue);
3724 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3726 std::vector<BoolLeafNodeType*> tmpIntersectionLeafNodes;
3727 tmpIntersectionTree.getNodes(tmpIntersectionLeafNodes);
3729 tbb::parallel_for(tbb::blocked_range<size_t>(0, tmpIntersectionLeafNodes.size()),
3732 intersectionTree.clear();
3733 intersectionTree.merge(tmpIntersectionTree);
3741 template<
typename InputTreeType>
3749 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
3754 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3760 void operator()(
const tbb::blocked_range<size_t>&);
3762 mSignFlagsAccessor.tree().merge(rhs.mSignFlagsAccessor.
tree());
3763 mPointIndexAccessor.tree().merge(rhs.mPointIndexAccessor.
tree());
3779 template<
typename InputTreeType>
3781 const InputTreeType& inputTree,
3782 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3786 : mInputAccessor(inputTree)
3787 , mIntersectionNodes(&intersectionLeafNodes.front())
3789 , mSignFlagsAccessor(signFlagsTree)
3790 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3791 , mPointIndexAccessor(pointIndexTree)
3794 pointIndexTree.root().setBackground(boost::integer_traits<Index32>::const_max,
false);
3798 template<
typename InputTreeType>
3800 : mInputAccessor(rhs.mInputAccessor.tree())
3801 , mIntersectionNodes(rhs.mIntersectionNodes)
3803 , mSignFlagsAccessor(mSignFlagsTree)
3804 , mPointIndexTree(boost::integer_traits<
Index32>::const_max)
3805 , mPointIndexAccessor(mPointIndexTree)
3806 , mIsovalue(rhs.mIsovalue)
3811 template<
typename InputTreeType>
3815 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
3819 typename std::unique_ptr<Int16LeafNodeType> signsNodePt(
new Int16LeafNodeType(ijk, 0));
3821 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3828 if (!signsNodePt.get()) signsNodePt.reset(
new Int16LeafNodeType(origin, 0));
3829 else signsNodePt->setOrigin(origin);
3831 bool updatedNode =
false;
3835 const Index pos = it.pos();
3849 if (signFlags != 0 && signFlags != 0xFF) {
3851 const bool inside = signFlags & 0x1;
3853 int edgeFlags = inside ?
INSIDE : 0;
3855 if (!it.getValue()) {
3856 edgeFlags |= inside != ((signFlags & 0x02) != 0) ?
XEDGE : 0;
3857 edgeFlags |= inside != ((signFlags & 0x10) != 0) ?
YEDGE : 0;
3858 edgeFlags |= inside != ((signFlags & 0x08) != 0) ?
ZEDGE : 0;
3861 const uint8_t ambiguousCellFlags = sAmbiguousFace[signFlags];
3862 if (ambiguousCellFlags != 0) {
3864 origin + ijk, mIsovalue);
3867 edgeFlags |= int(signFlags);
3869 signsNodePt->setValueOn(pos,
Int16(edgeFlags));
3875 typename Index32TreeType::LeafNodeType* idxNode = mPointIndexAccessor.
touchLeaf(origin);
3876 idxNode->topologyUnion(*signsNodePt);
3879 for (
auto it = idxNode->beginValueOn(); it; ++it) {
3880 idxNode->setValueOnly(it.pos(), 0);
3883 mSignFlagsAccessor.
addLeaf(signsNodePt.release());
3889 template<
typename InputTreeType>
3892 typename InputTreeType::template ValueConverter<Int16>::Type& signFlagsTree,
3893 typename InputTreeType::template ValueConverter<Index32>::Type& pointIndexTree,
3894 const typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3895 const InputTreeType& inputTree,
3896 typename InputTreeType::ValueType isovalue)
3898 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3901 std::vector<const BoolLeafNodeType*> intersectionLeafNodes;
3902 intersectionTree.getNodes(intersectionLeafNodes);
3905 inputTree, intersectionLeafNodes, signFlagsTree, pointIndexTree, isovalue);
3907 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3914 template<Index32 LeafNodeLog2Dim>
3920 boost::scoped_array<Index32>& leafNodeCount)
3921 : mLeafNodes(leafNodes.empty() ? nullptr : &leafNodes.front())
3922 , mData(leafNodeCount.get())
3928 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3932 Int16 const * p = mLeafNodes[n]->buffer().data();
3933 Int16 const *
const endP = p + Int16LeafNodeType::SIZE;
3950 template<
typename Po
intIndexLeafNode>
3956 const std::vector<Int16LeafNodeType*>& signDataNodes,
3957 boost::scoped_array<Index32>& leafNodeCount)
3958 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
3959 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
3960 , mData(leafNodeCount.get())
3968 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3975 std::set<IndexType> uniqueRegions;
3982 count += size_t(sEdgeGroupTable[(
SIGNS & signNode.
getValue(it.pos()))][0]);
3984 uniqueRegions.insert(
id);
3988 mData[n] =
Index32(count + uniqueRegions.size());
3999 template<
typename Po
intIndexLeafNode>
4004 MapPoints(
const std::vector<PointIndexLeafNode*>& pointIndexNodes,
4005 const std::vector<Int16LeafNodeType*>& signDataNodes,
4006 boost::scoped_array<Index32>& leafNodeCount)
4007 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
4008 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
4009 , mData(leafNodeCount.get())
4015 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
4020 Index32 pointOffset = mData[n];
4023 const Index pos = it.pos();
4026 pointOffset +=
Index32(sEdgeGroupTable[signs][0]);
4040 template<
typename TreeType,
typename PrimBuilder>
4051 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4055 bool invertSurfaceOrientation);
4059 void operator()(
const tbb::blocked_range<size_t>&)
const;
4067 bool const mInvertSurfaceOrientation;
4071 template<
typename TreeType,
typename PrimBuilder>
4073 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4077 bool invertSurfaceOrientation)
4078 : mSignFlagsLeafNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
4079 , mSignFlagsTree(&signFlagsTree)
4080 , mRefSignFlagsTree(nullptr)
4081 , mIndexTree(&idxTree)
4082 , mPolygonPoolList(&polygons)
4083 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4087 template<
typename InputTreeType,
typename PrimBuilder>
4092 Int16ValueAccessor signAcc(*mSignFlagsTree);
4096 const bool invertSurfaceOrientation = mInvertSurfaceOrientation;
4103 std::unique_ptr<Int16ValueAccessor> refSignAcc;
4104 if (mRefSignFlagsTree) refSignAcc.
reset(
new Int16ValueAccessor(*mRefSignFlagsTree));
4106 for (
size_t n = range.begin(); n != range.end(); ++n) {
4109 origin = node.origin();
4113 typename Int16LeafNodeType::ValueOnCIter iter = node.cbeginValueOn();
4114 for (; iter; ++iter) {
4115 if (iter.getValue() &
XEDGE) ++edgeCount;
4116 if (iter.getValue() &
YEDGE) ++edgeCount;
4117 if (iter.getValue() &
ZEDGE) ++edgeCount;
4120 if(edgeCount == 0)
continue;
4122 mesher.init(edgeCount, (*mPolygonPoolList)[n]);
4127 if (!signleafPt || !idxLeafPt)
continue;
4131 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
4135 for (iter = node.cbeginValueOn(); iter; ++iter) {
4136 ijk = iter.getCoord();
4138 Int16 flags = iter.getValue();
4140 if (!(flags & 0xE00))
continue;
4143 if (refSignLeafPt) {
4144 refFlags = refSignLeafPt->getValue(iter.pos());
4151 const uint8_t cell = uint8_t(
SIGNS & flags);
4153 if (sEdgeGroupTable[cell][0] > 1) {
4154 offsets[0] = (sEdgeGroupTable[cell][1] - 1);
4155 offsets[1] = (sEdgeGroupTable[cell][9] - 1);
4156 offsets[2] = (sEdgeGroupTable[cell][4] - 1);
4159 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
4161 flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher);
4164 flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher);
4177 template<
typename T>
4180 CopyArray(T * outputArray,
const T * inputArray,
size_t outputOffset = 0)
4181 : mOutputArray(outputArray), mInputArray(inputArray), mOutputOffset(outputOffset)
4185 void operator()(
const tbb::blocked_range<size_t>& inputArrayRange)
const 4187 const size_t offset = mOutputOffset;
4188 for (
size_t n = inputArrayRange.begin(), N = inputArrayRange.end(); n < N; ++n) {
4189 mOutputArray[offset + n] = mInputArray[n];
4194 T *
const mOutputArray;
4195 T
const *
const mInputArray;
4196 size_t const mOutputOffset;
4203 const std::vector<uint8_t>& pointFlags,
4204 boost::scoped_array<openvdb::Vec3s>& points,
4205 boost::scoped_array<unsigned>& numQuadsToDivide)
4206 : mPolygonPoolList(&polygons)
4207 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4208 , mPoints(points.get())
4209 , mNumQuadsToDivide(numQuadsToDivide.get())
4215 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4222 for (
size_t i = 0, I = polygons.
numQuads();
i < I; ++
i) {
4230 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4231 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4233 if (!edgePoly)
continue;
4235 const Vec3s& p0 = mPoints[quad[0]];
4236 const Vec3s& p1 = mPoints[quad[1]];
4237 const Vec3s& p2 = mPoints[quad[2]];
4238 const Vec3s& p3 = mPoints[quad[3]];
4247 mNumQuadsToDivide[n] = count;
4253 uint8_t
const *
const mPointFlags;
4254 Vec3s const *
const mPoints;
4255 unsigned *
const mNumQuadsToDivide;
4262 const boost::scoped_array<openvdb::Vec3s>& points,
4264 boost::scoped_array<openvdb::Vec3s>& centroids,
4265 boost::scoped_array<unsigned>& numQuadsToDivide,
4266 boost::scoped_array<unsigned>& centroidOffsets)
4267 : mPolygonPoolList(&polygons)
4268 , mPoints(points.get())
4269 , mCentroids(centroids.get())
4270 , mNumQuadsToDivide(numQuadsToDivide.get())
4271 , mCentroidOffsets(centroidOffsets.get())
4272 , mPointCount(pointCount)
4278 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4282 const size_t nonplanarCount = size_t(mNumQuadsToDivide[n]);
4284 if (nonplanarCount > 0) {
4290 size_t offset = mCentroidOffsets[n];
4292 size_t triangleIdx = 0;
4294 for (
size_t i = 0, I = polygons.
numQuads();
i < I; ++
i) {
4296 const char quadFlags = polygons.
quadFlags(
i);
4299 unsigned newPointIdx = unsigned(offset + mPointCount);
4303 mCentroids[offset] = (mPoints[quad[0]] + mPoints[quad[1]] +
4304 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25f;
4311 triangle[0] = quad[0];
4312 triangle[1] = newPointIdx;
4313 triangle[2] = quad[3];
4323 triangle[0] = quad[0];
4324 triangle[1] = quad[1];
4325 triangle[2] = newPointIdx;
4335 triangle[0] = quad[1];
4336 triangle[1] = quad[2];
4337 triangle[2] = newPointIdx;
4348 triangle[0] = quad[2];
4349 triangle[1] = quad[3];
4350 triangle[2] = newPointIdx;
4368 for (
size_t i = 0, I = polygons.
numQuads();
i < I; ++
i) {
4372 tmpPolygons.
quad(quadIdx) = quad;
4378 polygons.
copy(tmpPolygons);
4385 Vec3s const *
const mPoints;
4386 Vec3s *
const mCentroids;
4387 unsigned *
const mNumQuadsToDivide;
4388 unsigned *
const mCentroidOffsets;
4389 size_t const mPointCount;
4396 size_t polygonPoolListSize,
4398 size_t& pointListSize,
4399 std::vector<uint8_t>& pointFlags)
4401 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4403 boost::scoped_array<unsigned> numQuadsToDivide(
new unsigned[polygonPoolListSize]);
4405 tbb::parallel_for(polygonPoolListRange,
4408 boost::scoped_array<unsigned> centroidOffsets(
new unsigned[polygonPoolListSize]);
4410 size_t centroidCount = 0;
4414 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4415 centroidOffsets[n] = sum;
4416 sum += numQuadsToDivide[n];
4418 centroidCount = size_t(sum);
4421 boost::scoped_array<Vec3s> centroidList(
new Vec3s[centroidCount]);
4423 tbb::parallel_for(polygonPoolListRange,
4425 centroidList, numQuadsToDivide, centroidOffsets));
4427 if (centroidCount > 0) {
4429 const size_t newPointListSize = centroidCount + pointListSize;
4431 boost::scoped_array<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointListSize]);
4433 tbb::parallel_for(tbb::blocked_range<size_t>(0, pointListSize),
4436 tbb::parallel_for(tbb::blocked_range<size_t>(0, newPointListSize - pointListSize),
4439 pointListSize = newPointListSize;
4440 pointList.swap(newPointList);
4441 pointFlags.resize(pointListSize, 0);
4449 const std::vector<uint8_t>& pointFlags)
4450 : mPolygonPoolList(&polygons)
4451 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4457 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4461 for (
size_t i = 0, I = polygons.
numQuads();
i < I; ++
i) {
4469 const bool hasSeamLinePoint =
4470 mPointFlags[verts[0]] || mPointFlags[verts[1]] ||
4471 mPointFlags[verts[2]] || mPointFlags[verts[3]];
4473 if (!hasSeamLinePoint) {
4474 flags &= ~POLYFLAG_FRACTURE_SEAM;
4487 const bool hasSeamLinePoint =
4488 mPointFlags[verts[0]] || mPointFlags[verts[1]] || mPointFlags[verts[2]];
4490 if (!hasSeamLinePoint) {
4491 flags &= ~POLYFLAG_FRACTURE_SEAM;
4502 uint8_t
const *
const mPointFlags;
4508 std::vector<uint8_t>& pointFlags)
4510 tbb::parallel_for(tbb::blocked_range<size_t>(0, polygonPoolListSize),
4518 template<
typename InputTreeType>
4522 const PointList& pointList, boost::scoped_array<uint8_t>& pointMask,
4524 : mInputTree(&inputTree)
4525 , mPolygonPoolList(&polygons)
4526 , mPointList(&pointList)
4527 , mPointMask(pointMask.get())
4528 , mTransform(transform)
4529 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4535 using ValueType =
typename InputTreeType::LeafNodeType::ValueType;
4538 Vec3s centroid, normal;
4541 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<ValueType>();
4543 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4545 const PolygonPool& polygons = (*mPolygonPoolList)[n];
4551 const Vec3s& v0 = (*mPointList)[verts[0]];
4552 const Vec3s& v1 = (*mPointList)[verts[1]];
4553 const Vec3s& v2 = (*mPointList)[verts[2]];
4555 normal = (v2 - v0).cross((v1 - v0));
4558 centroid = (v0 + v1 + v2) * (1.0f / 3.0f);
4559 ijk = mTransform.worldToIndexCellCentered(centroid);
4564 if (invertGradientDir) {
4569 if (dir.dot(normal) < -0.5f) {
4574 mPointMask[verts[0]] = 1;
4575 mPointMask[verts[1]] = 1;
4576 mPointMask[verts[2]] = 1;
4585 InputTreeType
const *
const mInputTree;
4588 uint8_t *
const mPointMask;
4590 bool const mInvertSurfaceOrientation;
4594 template<
typename InputTree>
4597 bool invertSurfaceOrientation,
4598 const InputTree& inputTree,
4601 size_t polygonPoolListSize,
4603 const size_t pointListSize)
4605 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4607 boost::scoped_array<uint8_t> pointMask(
new uint8_t[pointListSize]);
4608 fillArray(pointMask.get(), uint8_t(0), pointListSize);
4610 tbb::parallel_for(polygonPoolListRange,
4612 inputTree, polygonPoolList, pointList, pointMask, transform, invertSurfaceOrientation));
4614 boost::scoped_array<uint8_t> pointUpdates(
new uint8_t[pointListSize]);
4615 fillArray(pointUpdates.get(), uint8_t(0), pointListSize);
4617 boost::scoped_array<Vec3s> newPoints(
new Vec3s[pointListSize]);
4618 fillArray(newPoints.get(),
Vec3s(0.0f, 0.0f, 0.0f), pointListSize);
4620 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4624 for (
size_t i = 0, I = polygons.
numQuads();
i < I; ++
i) {
4627 for (
int v = 0; v < 4; ++v) {
4629 const unsigned pointIdx = verts[v];
4631 if (pointMask[pointIdx] == 1) {
4633 newPoints[pointIdx] +=
4634 pointList[verts[0]] + pointList[verts[1]] +
4635 pointList[verts[2]] + pointList[verts[3]];
4637 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 4);
4645 for (
int v = 0; v < 3; ++v) {
4647 const unsigned pointIdx = verts[v];
4649 if (pointMask[pointIdx] == 1) {
4650 newPoints[pointIdx] +=
4651 pointList[verts[0]] + pointList[verts[1]] + pointList[verts[2]];
4653 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 3);
4659 for (
size_t n = 0, N = pointListSize; n < N; ++n) {
4660 if (pointUpdates[n] > 0) {
4661 const double weight = 1.0 / double(pointUpdates[n]);
4662 pointList[n] = newPoints[n] * float(weight);
4679 , mTriangles(nullptr)
4680 , mQuadFlags(nullptr)
4681 , mTriangleFlags(nullptr)
4688 : mNumQuads(numQuads)
4689 , mNumTriangles(numTriangles)
4692 , mQuadFlags(new char[mNumQuads])
4693 , mTriangleFlags(new char[mNumTriangles])
4704 for (
size_t i = 0;
i < mNumQuads; ++
i) {
4705 mQuads[
i] = rhs.mQuads[
i];
4706 mQuadFlags[
i] = rhs.mQuadFlags[
i];
4709 for (
size_t i = 0;
i < mNumTriangles; ++
i) {
4710 mTriangles[
i] = rhs.mTriangles[
i];
4711 mTriangleFlags[
i] = rhs.mTriangleFlags[
i];
4721 mQuadFlags.reset(
new char[mNumQuads]);
4729 mQuads.reset(
nullptr);
4730 mQuadFlags.reset(
nullptr);
4737 mNumTriangles =
size;
4739 mTriangleFlags.reset(
new char[mNumTriangles]);
4747 mTriangles.reset(
nullptr);
4748 mTriangleFlags.reset(
nullptr);
4755 if (!(n < mNumQuads))
return false;
4760 mQuads.reset(
nullptr);
4763 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
4764 boost::scoped_array<char> flags(
new char[n]);
4766 for (
size_t i = 0;
i < n; ++
i) {
4767 quads[
i] = mQuads[
i];
4768 flags[
i] = mQuadFlags[
i];
4772 mQuadFlags.swap(flags);
4784 if (!(n < mNumTriangles))
return false;
4789 mTriangles.reset(
nullptr);
4792 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
4793 boost::scoped_array<char> flags(
new char[n]);
4795 for (
size_t i = 0;
i < n; ++
i) {
4796 triangles[
i] = mTriangles[
i];
4797 flags[
i] = mTriangleFlags[
i];
4800 mTriangles.swap(triangles);
4801 mTriangleFlags.swap(flags);
4818 , mSeamPointListSize(0)
4819 , mPolygonPoolListSize(0)
4820 , mIsovalue(isovalue)
4821 , mPrimAdaptivity(adaptivity)
4822 , mSecAdaptivity(0.0)
4824 , mSurfaceMaskGrid(
GridBase::ConstPtr())
4825 , mAdaptivityGrid(
GridBase::ConstPtr())
4826 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
4829 , mInvertSurfaceMask(false)
4830 , mRelaxDisorientedTriangles(relaxDisorientedTriangles)
4831 , mQuantizedSeamPoints(nullptr)
4844 inline const size_t&
4847 return mPointListSize;
4865 inline const size_t&
4868 return mPolygonPoolListSize;
4876 mSecAdaptivity = secAdaptivity;
4881 mSeamPointListSize = 0;
4882 mQuantizedSeamPoints.reset(
nullptr);
4889 mSurfaceMaskGrid = mask;
4890 mInvertSurfaceMask = invertMask;
4897 mAdaptivityGrid = grid;
4904 mAdaptivityMaskTree = tree;
4908 inline std::vector<uint8_t>&
4915 inline const std::vector<uint8_t>&
4922 template<
typename InputGr
idType>
4928 using InputTreeType =
typename InputGridType::TreeType;
4929 using InputLeafNodeType =
typename InputTreeType::LeafNodeType;
4930 using InputValueType =
typename InputLeafNodeType::ValueType;
4934 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
4936 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
4937 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
4938 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
4939 using Index32TreeType =
typename InputTreeType::template ValueConverter<Index32>::Type;
4940 using Index32LeafNodeType =
typename Index32TreeType::LeafNodeType;
4945 mPolygonPoolListSize = 0;
4947 mPointFlags.clear();
4952 const InputValueType isovalue = InputValueType(mIsovalue);
4953 const float adaptivityThreshold = float(mPrimAdaptivity);
4954 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4960 const bool invertSurfaceOrientation = (!volume_to_mesh_internal::isBoolValue<InputValueType>()
4965 const InputTreeType& inputTree = inputGrid.tree();
4967 BoolTreeType intersectionTree(
false), adaptivityMask(
false);
4969 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeType::treeType()) {
4970 const BoolTreeType *refAdaptivityMask=
4971 static_cast<const BoolTreeType*
>(mAdaptivityMaskTree.get());
4972 adaptivityMask.topologyUnion(*refAdaptivityMask);
4975 Int16TreeType signFlagsTree(0);
4976 Index32TreeType pointIndexTree(boost::integer_traits<Index32>::const_max);
4982 intersectionTree, inputTree, isovalue);
4985 inputGrid, mSurfaceMaskGrid, mInvertSurfaceMask, isovalue);
4987 if (intersectionTree.empty())
return;
4990 signFlagsTree, pointIndexTree, intersectionTree, inputTree, isovalue);
4992 intersectionTree.clear();
4994 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
4995 pointIndexTree.getNodes(pointIndexLeafNodes);
4997 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
4998 signFlagsTree.getNodes(signFlagsLeafNodes);
5000 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
5005 Int16TreeType* refSignFlagsTree =
nullptr;
5006 Index32TreeType* refPointIndexTree =
nullptr;
5007 InputTreeType
const* refInputTree =
nullptr;
5009 if (mRefGrid && mRefGrid->type() == InputGridType::gridType()) {
5011 const InputGridType* refGrid =
static_cast<const InputGridType*
>(mRefGrid.get());
5012 refInputTree = &refGrid->tree();
5014 if (!mRefSignTree && !mRefIdxTree) {
5018 typename Int16TreeType::Ptr refSignFlagsTreePt(
new Int16TreeType(0));
5019 typename Index32TreeType::Ptr refPointIndexTreePt(
5020 new Index32TreeType(boost::integer_traits<Index32>::const_max));
5022 BoolTreeType refIntersectionTree(
false);
5025 refIntersectionTree, *refInputTree, isovalue);
5028 *refPointIndexTreePt, refIntersectionTree, *refInputTree, isovalue);
5030 mRefSignTree = refSignFlagsTreePt;
5031 mRefIdxTree = refPointIndexTreePt;
5034 if (mRefSignTree && mRefIdxTree) {
5038 refSignFlagsTree =
static_cast<Int16TreeType*
>(mRefSignTree.get());
5039 refPointIndexTree =
static_cast<Index32TreeType*
>(mRefIdxTree.get());
5043 if (refSignFlagsTree && refPointIndexTree) {
5049 if (mSeamPointListSize == 0) {
5053 std::vector<Int16LeafNodeType*> refSignFlagsLeafNodes;
5054 refSignFlagsTree->getNodes(refSignFlagsLeafNodes);
5056 boost::scoped_array<Index32> leafNodeOffsets(
5057 new Index32[refSignFlagsLeafNodes.size()]);
5059 tbb::parallel_for(tbb::blocked_range<size_t>(0, refSignFlagsLeafNodes.size()),
5061 refSignFlagsLeafNodes, leafNodeOffsets));
5065 for (
size_t n = 0, N = refSignFlagsLeafNodes.size(); n < N; ++n) {
5066 const Index32 tmp = leafNodeOffsets[n];
5067 leafNodeOffsets[n] = count;
5070 mSeamPointListSize = size_t(count);
5073 if (mSeamPointListSize != 0) {
5075 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
5077 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
5079 std::vector<Index32LeafNodeType*> refPointIndexLeafNodes;
5080 refPointIndexTree->getNodes(refPointIndexLeafNodes);
5082 tbb::parallel_for(tbb::blocked_range<size_t>(0, refPointIndexLeafNodes.size()),
5084 refPointIndexLeafNodes, refSignFlagsLeafNodes, leafNodeOffsets));
5088 if (mSeamPointListSize != 0) {
5090 tbb::parallel_for(auxiliaryLeafNodeRange,
5092 signFlagsLeafNodes, inputTree, *refPointIndexTree, *refSignFlagsTree,
5093 mQuantizedSeamPoints.get(), isovalue));
5098 const bool referenceMeshing = refSignFlagsTree && refPointIndexTree && refInputTree;
5103 boost::scoped_array<Index32> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
5107 inputGrid, pointIndexTree, pointIndexLeafNodes, signFlagsLeafNodes,
5108 isovalue, adaptivityThreshold, invertSurfaceOrientation);
5110 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridType::gridType()) {
5111 const FloatGridType* adaptivityGrid =
5112 static_cast<const FloatGridType*
>(mAdaptivityGrid.get());
5116 if (!adaptivityMask.empty()) {
5120 if (referenceMeshing) {
5124 tbb::parallel_for(auxiliaryLeafNodeRange, mergeOp);
5127 op(pointIndexLeafNodes, signFlagsLeafNodes, leafNodeOffsets);
5129 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5134 op(signFlagsLeafNodes, leafNodeOffsets);
5136 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5142 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
5143 const Index32 tmp = leafNodeOffsets[n];
5148 mPointListSize = size_t(pointCount);
5150 mPointFlags.clear();
5158 op(mPoints.get(), inputTree, pointIndexLeafNodes,
5159 signFlagsLeafNodes, leafNodeOffsets, transform, mIsovalue);
5161 if (referenceMeshing) {
5162 mPointFlags.resize(mPointListSize);
5163 op.setRefData(*refInputTree, *refPointIndexTree, *refSignFlagsTree,
5164 mQuantizedSeamPoints.get(), &mPointFlags.front());
5167 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5173 mPolygonPoolListSize = signFlagsLeafNodes.size();
5174 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
5181 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5182 mPolygons, invertSurfaceOrientation);
5184 if (referenceMeshing) {
5188 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5195 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5196 mPolygons, invertSurfaceOrientation);
5198 if (referenceMeshing) {
5202 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5206 signFlagsTree.clear();
5207 pointIndexTree.clear();
5210 if (adaptive && mRelaxDisorientedTriangles) {
5212 inputTree, transform, mPolygons, mPolygonPoolListSize, mPoints, mPointListSize);
5216 if (referenceMeshing) {
5218 mPolygons, mPolygonPoolListSize, mPoints, mPointListSize, mPointFlags);
5233 template<
typename Gr
idType>
5234 inline typename std::enable_if<std::is_scalar<typename GridType::ValueType>::value,
void>::type
5236 const GridType& grid,
5237 std::vector<Vec3s>& points,
5238 std::vector<Vec3I>& triangles,
5239 std::vector<Vec4I>& quads,
5244 VolumeToMesh mesher(isovalue, adaptivity, relaxDisorientedTriangles);
5253 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
5260 size_t numQuads = 0, numTriangles = 0;
5262 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5263 numTriangles += polygons.numTriangles();
5264 numQuads += polygons.numQuads();
5268 triangles.resize(numTriangles);
5270 quads.resize(numQuads);
5274 size_t qIdx = 0, tIdx = 0;
5276 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5278 for (
size_t i = 0, I = polygons.numQuads();
i < I; ++
i) {
5279 quads[qIdx++] = polygons.quad(
i);
5282 for (
size_t i = 0, I = polygons.numTriangles();
i < I; ++
i) {
5283 triangles[tIdx++] = polygons.triangle(
i);
5289 template<
typename Gr
idType>
5290 inline typename std::enable_if<!std::is_scalar<typename GridType::ValueType>::value,
void>::type
5293 std::vector<Vec3s>&,
5294 std::vector<Vec3I>&,
5295 std::vector<Vec4I>&,
5307 template<
typename Gr
idType>
5310 const GridType& grid,
5311 std::vector<Vec3s>& points,
5312 std::vector<Vec3I>& triangles,
5313 std::vector<Vec4I>& quads,
5316 bool relaxDisorientedTriangles)
5318 doVolumeToMesh(grid, points, triangles, quads, isovalue, adaptivity, relaxDisorientedTriangles);
5322 template<
typename Gr
idType>
5325 const GridType& grid,
5326 std::vector<Vec3s>& points,
5327 std::vector<Vec4I>& quads,
5330 std::vector<Vec3I> triangles;
5331 doVolumeToMesh(grid, points, triangles, quads, isovalue, 0.0,
true);
5338 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:508
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:115
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:108
SharedPtr< const TreeBase > ConstPtr
Definition: Tree.h:68
OPENVDB_API const Index32 INVALID_IDX
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:797
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:215
T & z()
Definition: Vec3.h:111
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
Mat3< double > Mat3d
Definition: Mat3.h:708
uint32_t Index32
Definition: Types.h:55
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:261
T * data
Definition: LeafBuffer.h:71
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
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:419
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
Vec3< int32_t > Vec3i
Definition: Vec3.h:675
Index32 Index
Definition: Types.h:57
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:317
Vec3< float > Vec3s
Definition: Vec3.h:677
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
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
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:275
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:61
Vec4< int32_t > Vec4i
Definition: Vec4.h:585
#define OPENVDB_VERSION_NAME
Definition: version.h:43
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:198
int16_t Int16
Definition: Types.h:58
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1059
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
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:376
Definition: Exceptions.h:39
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:107
const Coord & max() const
Definition: Coord.h:335
Vec3< double > Vec3d
Definition: Vec3.h:678
Gradient operators defined in index space of various orders.
Definition: Operators.h:122
Definition: Exceptions.h:92
Coord & reset(Int32 x, Int32 y, Int32 z)
Reset all three coordinates with the specified arguments.
Definition: Coord.h:93
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:104
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:147
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
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
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
const Coord & min() const
Definition: Coord.h:334
Base class for typed trees.
Definition: Tree.h:64
SharedPtr< TreeBase > Ptr
Definition: Tree.h:67
static constexpr size_t size
The size of a LeafBuffer when LeafBuffer::mOutOfCore is atomic.
Definition: LeafBuffer.h:85
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:263
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:198
static const Index DIM
Definition: LeafNode.h:74
Definition: LeafNode.h:233