37 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 38 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED 45 #include <boost/scoped_array.hpp> 47 #include <tbb/blocked_range.h> 48 #include <tbb/parallel_for.h> 49 #include <tbb/parallel_reduce.h> 50 #include <tbb/task_scheduler_init.h> 56 #include <type_traits> 80 template<
typename Gr
idType>
84 std::vector<Vec3s>& points,
85 std::vector<Vec4I>& quads,
86 double isovalue = 0.0);
101 template<
typename Gr
idType>
104 const GridType& grid,
105 std::vector<Vec3s>& points,
106 std::vector<Vec3I>& triangles,
107 std::vector<Vec4I>& quads,
108 double isovalue = 0.0,
109 double adaptivity = 0.0,
126 inline PolygonPool(
const size_t numQuads,
const size_t numTriangles);
130 inline void resetQuads(
size_t size);
131 inline void clearQuads();
133 inline void resetTriangles(
size_t size);
134 inline void clearTriangles();
139 const size_t&
numQuads()
const {
return mNumQuads; }
154 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
163 inline bool trimQuads(
const size_t n,
bool reallocate =
false);
164 inline bool trimTrinagles(
const size_t n,
bool reallocate =
false);
170 size_t mNumQuads, mNumTriangles;
171 boost::scoped_array<openvdb::Vec4I> mQuads;
172 boost::scoped_array<openvdb::Vec3I> mTriangles;
173 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
211 const std::vector<uint8_t>&
pointFlags()
const {
return mPointFlags; }
220 template<
typename InputGr
idType>
221 void operator()(
const InputGridType&);
274 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
275 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
282 bool mInvertSurfaceMask, mRelaxDisorientedTriangles;
284 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
285 std::vector<uint8_t> mPointFlags;
299 const std::vector<Vec3d>& points,
300 const std::vector<Vec3d>& normals)
306 if (points.empty())
return avgPos;
308 for (
size_t n = 0, N = points.size(); n < N; ++n) {
312 avgPos /= double(points.size());
316 double m00=0,m01=0,m02=0,
323 for (
size_t n = 0, N = points.size(); n < N; ++n) {
325 const Vec3d& n_ref = normals[n];
328 m00 += n_ref[0] * n_ref[0];
329 m11 += n_ref[1] * n_ref[1];
330 m22 += n_ref[2] * n_ref[2];
332 m01 += n_ref[0] * n_ref[1];
333 m02 += n_ref[0] * n_ref[2];
334 m12 += n_ref[1] * n_ref[2];
337 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
362 Mat3d D = Mat3d::identity();
365 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
366 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
370 for (
int i = 0; i < 3; ++i ) {
371 if (std::abs(eigenValues[i]) < tolerance) {
375 D[i][i] = 1.0 / eigenValues[i];
382 return avgPos + pseudoInv * rhs;
396 namespace volume_to_mesh_internal {
398 template<
typename ValueType>
401 FillArray(ValueType* array,
const ValueType& v) : mArray(array), mValue(v) { }
403 void operator()(
const tbb::blocked_range<size_t>& range)
const {
404 const ValueType v = mValue;
405 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
415 template<
typename ValueType>
417 fillArray(ValueType* array,
const ValueType& val,
const size_t length)
419 const auto grainSize = std::max<size_t>(
420 length / tbb::task_scheduler_init::default_num_threads(), 1024);
421 const tbb::blocked_range<size_t> range(0, length, grainSize);
433 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,
434 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,
435 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,
436 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,
437 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,
438 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,
439 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,
440 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};
445 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,
446 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,
447 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,
448 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,
449 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,
450 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,
451 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,
452 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};
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {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},
497 {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},
498 {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},
499 {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},
500 {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},
501 {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},
502 {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},
503 {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},
504 {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},
505 {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},
506 {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},
507 {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},
508 {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},
509 {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},
510 {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},
511 {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},
512 {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},
513 {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},
514 {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},
515 {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},
516 {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},
517 {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},
518 {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},
519 {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},
520 {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},
521 {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},
522 {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},
523 {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},
524 {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},
525 {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},
526 {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},
527 {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},
528 {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},
529 {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},
530 {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},
531 {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},
532 {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},
533 {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},
534 {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},
535 {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},
536 {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},
537 {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},
538 {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},
539 {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},
540 {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},
541 {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},
542 {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},
543 {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},
544 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
553 double epsilon = 0.001)
556 Vec3d normal = (p2-p0).cross(p1-p3);
558 const Vec3d centroid = (p0 + p1 + p2 + p3);
559 const double d = centroid.
dot(normal) * 0.25;
563 double absDist = std::abs(p0.dot(normal) - d);
564 if (absDist > epsilon)
return false;
566 absDist = std::abs(p1.dot(normal) - d);
567 if (absDist > epsilon)
return false;
569 absDist = std::abs(p2.dot(normal) - d);
570 if (absDist > epsilon)
return false;
572 absDist = std::abs(p3.dot(normal) - d);
573 if (absDist > epsilon)
return false;
597 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
598 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
639 template<
typename AccessorT>
644 values[0] = accessor.getValue(ijk);
646 values[1] = accessor.getValue(ijk);
648 values[2] = accessor.getValue(ijk);
650 values[3] = accessor.getValue(ijk);
652 values[4] = accessor.getValue(ijk);
654 values[5] = accessor.getValue(ijk);
656 values[6] = accessor.getValue(ijk);
658 values[7] = accessor.getValue(ijk);
662 template<
typename LeafT>
667 values[0] = leaf.getValue(offset);
668 values[3] = leaf.getValue(offset + 1);
669 values[4] = leaf.getValue(offset + LeafT::DIM);
670 values[7] = leaf.getValue(offset + LeafT::DIM + 1);
671 values[1] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM));
672 values[2] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1);
673 values[5] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM);
674 values[6] = leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1);
678 template<
typename ValueType>
691 return uint8_t(signs);
697 template<
typename AccessorT>
703 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 1u;
705 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 2u;
707 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 4u;
709 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 8u;
710 coord[1] += 1; coord[2] = ijk[2];
711 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 16u;
713 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 32u;
715 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 64u;
717 if (
isInsideValue(accessor.getValue(coord), iso)) signs |= 128u;
718 return uint8_t(signs);
724 template<
typename LeafT>
734 if (
isInsideValue(leaf.getValue(offset + 1), iso)) signs |= 8u;
737 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM), iso)) signs |= 16u;
740 if (
isInsideValue(leaf.getValue(offset + LeafT::DIM + 1), iso)) signs |= 128u;
743 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ), iso)) signs |= 2u;
746 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1), iso)) signs |= 4u;
749 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM), iso)) signs |= 32u;
752 if (
isInsideValue(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1), iso)) signs |= 64u;
754 return uint8_t(signs);
760 template<
class AccessorT>
763 const AccessorT& acc,
Coord ijk,
typename AccessorT::ValueType iso)
796 template<
class AccessorT>
799 typename AccessorT::ValueType isovalue,
const int dim)
812 coord[1] += dim; coord[2] = ijk[2];
823 if (p[0]) signs |= 1u;
824 if (p[1]) signs |= 2u;
825 if (p[2]) signs |= 4u;
826 if (p[3]) signs |= 8u;
827 if (p[4]) signs |= 16u;
828 if (p[5]) signs |= 32u;
829 if (p[6]) signs |= 64u;
830 if (p[7]) signs |= 128u;
836 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
837 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
838 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
841 coord.
reset(ip, j, k);
843 if (p[0] != m && p[1] != m)
return true;
846 coord.reset(ipp, j, kp);
848 if (p[1] != m && p[2] != m)
return true;
851 coord.reset(ip, j, kpp);
853 if (p[2] != m && p[3] != m)
return true;
856 coord.reset(i, j, kp);
858 if (p[0] != m && p[3] != m)
return true;
861 coord.reset(ip, jpp, k);
863 if (p[4] != m && p[5] != m)
return true;
866 coord.reset(ipp, jpp, kp);
868 if (p[5] != m && p[6] != m)
return true;
871 coord.reset(ip, jpp, kpp);
873 if (p[6] != m && p[7] != m)
return true;
876 coord.reset(i, jpp, kp);
878 if (p[7] != m && p[4] != m)
return true;
881 coord.reset(i, jp, k);
883 if (p[0] != m && p[4] != m)
return true;
886 coord.reset(ipp, jp, k);
888 if (p[1] != m && p[5] != m)
return true;
891 coord.reset(ipp, jp, kpp);
893 if (p[2] != m && p[6] != m)
return true;
897 coord.reset(i, jp, kpp);
899 if (p[3] != m && p[7] != m)
return true;
905 coord.reset(ip, jp, k);
907 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
910 coord.reset(ipp, jp, kp);
912 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
915 coord.reset(ip, jp, kpp);
917 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
920 coord.reset(i, jp, kp);
922 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
925 coord.reset(ip, j, kp);
927 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
930 coord.reset(ip, jpp, kp);
932 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
935 coord.reset(ip, jp, kp);
937 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
938 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
947 template <
class LeafType>
951 Coord ijk, end = start;
956 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
957 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
958 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
959 leaf.setValueOnly(ijk, regionId);
968 template <
class LeafType>
971 typename LeafType::ValueType::value_type adaptivity)
973 if (adaptivity < 1e-6)
return false;
975 using VecT =
typename LeafType::ValueType;
976 Coord ijk, end = start;
981 std::vector<VecT> norms;
982 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
983 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
984 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
986 if(!leaf.isValueOn(ijk))
continue;
987 norms.push_back(leaf.getValue(ijk));
992 size_t N = norms.size();
993 for (
size_t ni = 0; ni < N; ++ni) {
994 VecT n_i = norms[ni];
995 for (
size_t nj = 0; nj < N; ++nj) {
996 VecT n_j = norms[nj];
997 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
1008 inline double evalZeroCrossing(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1012 template<
typename LeafT>
1016 values[0] = double(leaf.getValue(offset));
1017 values[3] = double(leaf.getValue(offset + 1));
1018 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1019 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1020 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1021 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1022 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1023 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1028 template<
typename AccessorT>
1033 values[0] = double(acc.getValue(coord));
1036 values[1] = double(acc.getValue(coord));
1039 values[2] = double(acc.getValue(coord));
1042 values[3] = double(acc.getValue(coord));
1044 coord[1] += 1; coord[2] = ijk[2];
1045 values[4] = double(acc.getValue(coord));
1048 values[5] = double(acc.getValue(coord));
1051 values[6] = double(acc.getValue(coord));
1054 values[7] = double(acc.getValue(coord));
1061 unsigned char edgeGroup,
double iso)
1063 Vec3d avg(0.0, 0.0, 0.0);
1139 double w = 1.0 / double(samples);
1153 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1155 avg =
Vec3d(0.0, 0.0, 0.0);
1243 double w = 1.0 / double(samples);
1257 unsigned char signs,
unsigned char edgeGroup,
double iso)
1259 std::vector<Vec3d> samples;
1262 std::vector<double> weights;
1265 Vec3d avg(0.0, 0.0, 0.0);
1272 samples.push_back(avg);
1273 weights.push_back((avg-p).lengthSqr());
1281 samples.push_back(avg);
1282 weights.push_back((avg-p).lengthSqr());
1290 samples.push_back(avg);
1291 weights.push_back((avg-p).lengthSqr());
1299 samples.push_back(avg);
1300 weights.push_back((avg-p).lengthSqr());
1308 samples.push_back(avg);
1309 weights.push_back((avg-p).lengthSqr());
1317 samples.push_back(avg);
1318 weights.push_back((avg-p).lengthSqr());
1326 samples.push_back(avg);
1327 weights.push_back((avg-p).lengthSqr());
1335 samples.push_back(avg);
1336 weights.push_back((avg-p).lengthSqr());
1344 samples.push_back(avg);
1345 weights.push_back((avg-p).lengthSqr());
1353 samples.push_back(avg);
1354 weights.push_back((avg-p).lengthSqr());
1362 samples.push_back(avg);
1363 weights.push_back((avg-p).lengthSqr());
1371 samples.push_back(avg);
1372 weights.push_back((avg-p).lengthSqr());
1379 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1380 minWeight =
std::min(minWeight, weights[i]);
1381 maxWeight =
std::max(maxWeight, weights[i]);
1384 const double offset = maxWeight + minWeight * 0.1;
1385 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1386 weights[i] = offset - weights[i];
1390 double weightSum = 0.0;
1391 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1392 weightSum += weights[i];
1399 if (samples.size() > 1) {
1400 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1401 avg += samples[i] * (weights[i] / weightSum);
1404 avg = samples.front();
1415 const std::vector<double>& values,
unsigned char signs,
double iso)
1418 points.push_back(
computePoint(values, signs, uint8_t(n), iso));
1427 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1430 for (
size_t i = 1; i <= 12; ++i) {
1446 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1447 unsigned char lhsSigns,
unsigned char rhsSigns,
1448 double iso,
size_t pointIdx,
const uint32_t * seamPointArray)
1450 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1456 const unsigned char e = uint8_t(
id);
1457 const uint32_t& quantizedPoint = seamPointArray[pointIdx + (
id - 1)];
1462 weightedPointMask.push_back(
true);
1464 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1465 weightedPointMask.push_back(
false);
1469 points.push_back(
computePoint(lhsValues, lhsSigns, uint8_t(n), iso));
1470 weightedPointMask.push_back(
false);
1476 template <
typename InputTreeType>
1482 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1489 const InputTreeType& inputTree,
1490 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1491 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1492 const boost::scoped_array<Index32>& leafNodeOffsets,
1496 void setRefData(
const InputTreeType& refInputTree,
1499 const uint32_t * quantizedSeamLinePoints,
1500 uint8_t * seamLinePointsFlags);
1502 void operator()(
const tbb::blocked_range<size_t>&)
const;
1505 Vec3s *
const mPoints;
1506 InputTreeType
const *
const mInputTree;
1509 Index32 const *
const mNodeOffsets;
1511 double const mIsovalue;
1513 InputTreeType
const * mRefInputTree;
1516 uint32_t
const * mQuantizedSeamLinePoints;
1517 uint8_t * mSeamLinePointsFlags;
1521 template <
typename InputTreeType>
1524 const InputTreeType& inputTree,
1525 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
1526 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
1527 const boost::scoped_array<Index32>& leafNodeOffsets,
1530 : mPoints(pointArray)
1531 , mInputTree(&inputTree)
1532 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
1533 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1534 , mNodeOffsets(leafNodeOffsets.get())
1537 , mRefInputTree(nullptr)
1538 , mRefPointIndexTree(nullptr)
1539 , mRefSignFlagsTree(nullptr)
1540 , mQuantizedSeamLinePoints(nullptr)
1541 , mSeamLinePointsFlags(nullptr)
1545 template <
typename InputTreeType>
1548 const InputTreeType& refInputTree,
1551 const uint32_t * quantizedSeamLinePoints,
1552 uint8_t * seamLinePointsFlags)
1554 mRefInputTree = &refInputTree;
1555 mRefPointIndexTree = &refPointIndexTree;
1556 mRefSignFlagsTree = &refSignFlagsTree;
1557 mQuantizedSeamLinePoints = quantizedSeamLinePoints;
1558 mSeamLinePointsFlags = seamLinePointsFlags;
1561 template <
typename InputTreeType>
1569 using IndexType =
typename Index32TreeType::ValueType;
1572 using IndexArrayMap = std::map<IndexType, IndexArray>;
1574 InputTreeAccessor inputAcc(*mInputTree);
1578 std::vector<Vec3d> points(4);
1579 std::vector<bool> weightedPointMask(4);
1580 std::vector<double> values(8), refValues(8);
1581 const double iso = mIsovalue;
1585 std::unique_ptr<InputTreeAccessor> refInputAcc;
1586 std::unique_ptr<Index32TreeAccessor> refPointIndexAcc;
1587 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
1589 const bool hasReferenceData = mRefInputTree && mRefPointIndexTree && mRefSignFlagsTree;
1591 if (hasReferenceData) {
1592 refInputAcc.reset(
new InputTreeAccessor(*mRefInputTree));
1593 refPointIndexAcc.reset(
new Index32TreeAccessor(*mRefPointIndexTree));
1594 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
1597 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1600 const Coord& origin = pointIndexNode.origin();
1610 if (hasReferenceData) {
1611 refInputNode = refInputAcc->probeConstLeaf(origin);
1612 refPointIndexNode = refPointIndexAcc->probeConstLeaf(origin);
1613 refSignFlagsNode = refSignFlagsAcc->probeConstLeaf(origin);
1616 IndexType pointOffset = IndexType(mNodeOffsets[n]);
1617 IndexArrayMap regions;
1619 for (
auto it = pointIndexNode.beginValueOn(); it; ++it) {
1620 const Index offset = it.pos();
1622 const IndexType
id = it.getValue();
1625 regions[id].push_back(offset);
1630 pointIndexNode.setValueOnly(offset, pointOffset);
1632 const Int16 flags = signFlagsNode.getValue(offset);
1633 uint8_t signs = uint8_t(
SIGNS & flags);
1634 uint8_t refSigns = 0;
1636 if ((flags &
SEAM) && refPointIndexNode && refSignFlagsNode) {
1637 if (refSignFlagsNode->isValueOn(offset)) {
1638 refSigns = uint8_t(
SIGNS & refSignFlagsNode->getValue(offset));
1642 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1644 const bool inclusiveCell = inputNode &&
1645 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1646 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1647 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1655 weightedPointMask.clear();
1657 if (refSigns == 0) {
1662 if (inclusiveCell && refInputNode) {
1667 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1668 iso, refPointIndexNode->getValue(offset), mQuantizedSeamLinePoints);
1671 xyz[0] = double(ijk[0]);
1672 xyz[1] = double(ijk[1]);
1673 xyz[2] = double(ijk[2]);
1675 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1677 Vec3d& point = points[i];
1680 if (!std::isfinite(point[0]) ||
1681 !std::isfinite(point[1]) ||
1682 !std::isfinite(point[2]))
1685 "VolumeToMesh encountered NaNs or infs in the input VDB!" 1686 " Hint: Check the input and consider using the \"Diagnostics\" tool " 1687 "to detect and resolve the NaNs.");
1691 point = mTransform.indexToWorld(point);
1693 Vec3s& pos = mPoints[pointOffset];
1694 pos[0] = float(point[0]);
1695 pos[1] = float(point[1]);
1696 pos[2] = float(point[2]);
1698 if (mSeamLinePointsFlags && !weightedPointMask.empty() && weightedPointMask[i]) {
1699 mSeamLinePointsFlags[pointOffset] = uint8_t(1);
1707 for (
typename IndexArrayMap::iterator it = regions.begin(); it != regions.end(); ++it) {
1709 Vec3d avg(0.0), point(0.0);
1713 for (
size_t i = 0, I = voxels.size(); i < I; ++i) {
1715 const Index offset = voxels[i];
1716 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1718 const bool inclusiveCell = inputNode &&
1719 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1720 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1721 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1725 pointIndexNode.setValueOnly(offset, pointOffset);
1727 uint8_t signs = uint8_t(
SIGNS & signFlagsNode.getValue(offset));
1735 avg[0] += double(ijk[0]) + points[0][0];
1736 avg[1] += double(ijk[1]) + points[0][1];
1737 avg[2] += double(ijk[2]) + points[0][2];
1743 double w = 1.0 / double(count);
1749 avg = mTransform.indexToWorld(avg);
1751 Vec3s& pos = mPoints[pointOffset];
1752 pos[0] = float(avg[0]);
1753 pos[1] = float(avg[1]);
1754 pos[2] = float(avg[2]);
1765 template <
typename InputTreeType>
1771 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
1778 const InputTreeType& inputTree,
1781 uint32_t * quantizedPoints,
1783 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1784 , mInputTree(&inputTree)
1785 , mRefPointIndexTree(&refPointIndexTree)
1786 , mRefSignFlagsTree(&refSignFlagsTree)
1787 , mQuantizedPoints(quantizedPoints)
1798 std::vector<double> values(8);
1799 const double iso = double(mIsovalue);
1803 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1806 const Coord& origin = signFlagsNode.origin();
1809 if (!refSignNode)
continue;
1813 if (!refPointIndexNode)
continue;
1817 for (
typename Int16LeafNodeType::ValueOnCIter it = signFlagsNode.cbeginValueOn();
1820 const Index offset = it.pos();
1822 ijk = Index32LeafNodeType::offsetToLocalCoord(offset);
1824 const bool inclusiveCell = inputNode &&
1825 ijk[0] < int(Index32LeafNodeType::DIM - 1) &&
1826 ijk[1] < int(Index32LeafNodeType::DIM - 1) &&
1827 ijk[2] < int(Index32LeafNodeType::DIM - 1);
1831 if ((it.getValue() &
SEAM) && refSignNode->isValueOn(offset)) {
1833 uint8_t lhsSigns = uint8_t(
SIGNS & it.getValue());
1834 uint8_t rhsSigns = uint8_t(
SIGNS & refSignNode->getValue(offset));
1837 if (inclusiveCell) {
1844 for (
unsigned i = 1, I =
sEdgeGroupTable[lhsSigns][0] + 1; i < I; ++i) {
1850 uint32_t& data = mQuantizedPoints[
1851 refPointIndexNode->getValue(offset) + (
id - 1)];
1856 pos, values, lhsSigns, rhsSigns, uint8_t(i), iso);
1874 InputTreeType
const *
const mInputTree;
1877 uint32_t *
const mQuantizedPoints;
1882 template <
typename TreeType>
1888 const TreeType& refSignFlagsTree)
1889 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1890 , mRefSignFlagsTree(&refSignFlagsTree)
1898 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1901 const Coord& origin = signFlagsNode.origin();
1904 if (!refSignNode)
continue;
1906 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
1907 const Index offset = it.pos();
1909 uint8_t rhsSigns = uint8_t(refSignNode->getValue(offset) &
SIGNS);
1913 const typename LeafNodeType::ValueType value = it.getValue();
1914 uint8_t lhsSigns = uint8_t(value &
SIGNS);
1916 if (rhsSigns != lhsSigns) {
1917 signFlagsNode.setValueOnly(offset, value |
SEAM);
1928 TreeType
const *
const mRefSignFlagsTree;
1932 template <
typename BoolTreeType,
typename SignDataType>
1941 const BoolTreeType& maskTree)
1942 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1943 , mMaskTree(&maskTree)
1951 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
1954 const Coord& origin = signFlagsNode.origin();
1957 if (!maskNode)
continue;
1959 using ValueOnCIter =
typename SignDataLeafNodeType::ValueOnCIter;
1961 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
1962 const Index offset = it.pos();
1964 if (maskNode->isValueOn(offset)) {
1965 signFlagsNode.setValueOnly(offset, it.getValue() |
SEAM);
1975 BoolTreeType
const *
const mMaskTree;
1979 template <
typename TreeType>
1983 using BoolTreeType =
typename TreeType::template ValueConverter<bool>::Type;
1986 const TreeType& signFlagsTree,
1988 : mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
1989 , mSignFlagsTree(&signFlagsTree)
1996 : mSignFlagsNodes(rhs.mSignFlagsNodes)
1997 , mSignFlagsTree(rhs.mSignFlagsTree)
2007 using ValueOnCIter =
typename LeafNodeType::ValueOnCIter;
2008 using ValueType =
typename LeafNodeType::ValueType;
2014 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2019 for (ValueOnCIter it = signFlagsNode.cbeginValueOn(); it; ++it) {
2021 const ValueType flags = it.getValue();
2023 if (!(flags &
SEAM) && (flags &
EDGES)) {
2025 ijk = it.getCoord();
2027 bool isSeamLineVoxel =
false;
2029 if (flags &
XEDGE) {
2033 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2035 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2039 if (!isSeamLineVoxel && flags &
YEDGE) {
2041 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2043 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2045 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2049 if (!isSeamLineVoxel && flags &
ZEDGE) {
2051 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2053 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2055 isSeamLineVoxel = isSeamLineVoxel || (signFlagsAcc.
getValue(ijk) &
SEAM);
2059 if (isSeamLineVoxel) {
2060 maskAcc.
setValue(it.getCoord(),
true);
2070 TreeType
const *
const mSignFlagsTree;
2076 template<
typename SignDataTreeType>
2080 using SignDataType =
typename SignDataTreeType::ValueType;
2081 using SignDataLeafNodeType =
typename SignDataTreeType::LeafNodeType;
2082 using BoolTreeType =
typename SignDataTreeType::template ValueConverter<bool>::Type;
2084 std::vector<SignDataLeafNodeType*> signFlagsLeafNodes;
2085 signFlagsTree.getNodes(signFlagsLeafNodes);
2087 const tbb::blocked_range<size_t> nodeRange(0, signFlagsLeafNodes.size());
2089 tbb::parallel_for(nodeRange,
2092 BoolTreeType seamLineMaskTree(
false);
2095 maskSeamLine(signFlagsLeafNodes, signFlagsTree, seamLineMaskTree);
2097 tbb::parallel_reduce(nodeRange, maskSeamLine);
2099 tbb::parallel_for(nodeRange,
2107 template <
typename InputGr
idType>
2114 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
2118 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
2124 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2129 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2130 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2133 bool invertSurfaceOrientation);
2137 mSpatialAdaptivityTree = &grid.
tree();
2138 mSpatialAdaptivityTransform = &grid.
transform();
2148 mRefSignFlagsTree = &signFlagsData;
2149 mInternalAdaptivity = internalAdaptivity;
2152 void operator()(
const tbb::blocked_range<size_t>&)
const;
2163 float mSurfaceAdaptivity, mInternalAdaptivity;
2164 bool mInvertSurfaceOrientation;
2173 template <
typename InputGr
idType>
2175 const InputGridType& inputGrid,
2177 const std::vector<Index32LeafNodeType*>& pointIndexLeafNodes,
2178 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
2181 bool invertSurfaceOrientation)
2182 : mInputTree(&inputGrid.tree())
2183 , mInputTransform(&inputGrid.transform())
2184 , mPointIndexTree(&pointIndexTree)
2185 , mPointIndexNodes(pointIndexLeafNodes.empty() ? nullptr : &pointIndexLeafNodes.front())
2186 , mSignFlagsNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
2188 , mSurfaceAdaptivity(adaptivity)
2189 , mInternalAdaptivity(adaptivity)
2190 , mInvertSurfaceOrientation(invertSurfaceOrientation)
2191 , mSpatialAdaptivityTree(nullptr)
2192 , mMaskTree(nullptr)
2193 , mRefSignFlagsTree(nullptr)
2194 , mSpatialAdaptivityTransform(nullptr)
2199 template <
typename InputGr
idType>
2204 using Vec3sLeafNodeType =
typename InputLeafNodeType::template ValueConverter<Vec3sType>::Type;
2212 std::unique_ptr<FloatTreeAccessor> spatialAdaptivityAcc;
2213 if (mSpatialAdaptivityTree && mSpatialAdaptivityTransform) {
2214 spatialAdaptivityAcc.reset(
new FloatTreeAccessor(*mSpatialAdaptivityTree));
2217 std::unique_ptr<BoolTreeAccessor> maskAcc;
2219 maskAcc.reset(
new BoolTreeAccessor(*mMaskTree));
2222 std::unique_ptr<Int16TreeAccessor> refSignFlagsAcc;
2223 if (mRefSignFlagsTree) {
2224 refSignFlagsAcc.reset(
new Int16TreeAccessor(*mRefSignFlagsTree));
2227 InputTreeAccessor inputAcc(*mInputTree);
2228 Index32TreeAccessor pointIndexAcc(*mPointIndexTree);
2232 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<InputValueType>();
2233 std::unique_ptr<Vec3sLeafNodeType> gradientNode;
2236 const int LeafDim = InputLeafNodeType::DIM;
2238 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2240 mask.setValuesOff();
2245 const Coord& origin = pointIndexNode.origin();
2247 end[0] = origin[0] + LeafDim;
2248 end[1] = origin[1] + LeafDim;
2249 end[2] = origin[2] + LeafDim;
2254 if (maskLeaf !=
nullptr) {
2255 for (
typename BoolLeafNodeType::ValueOnCIter it = maskLeaf->cbeginValueOn();
2258 mask.setActiveState(it.getCoord() & ~1u,
true);
2263 float adaptivity = (refSignFlagsAcc && !refSignFlagsAcc->probeConstLeaf(origin)) ?
2264 mInternalAdaptivity : mSurfaceAdaptivity;
2266 bool useGradients = adaptivity < 1.0f;
2271 if (spatialAdaptivityAcc) {
2272 useGradients =
false;
2273 for (
Index offset = 0; offset < FloatLeafNodeType::NUM_VALUES; ++offset) {
2274 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2275 ijk = mSpatialAdaptivityTransform->worldToIndexCellCentered(
2276 mInputTransform->indexToWorld(ijk));
2277 float weight = spatialAdaptivityAcc->getValue(ijk);
2278 float adaptivityValue = weight * adaptivity;
2279 if (adaptivityValue < 1.0f) useGradients =
true;
2280 adaptivityLeaf.setValueOnly(offset, adaptivityValue);
2285 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2286 const Int16 flags = it.getValue();
2287 const unsigned char signs = static_cast<unsigned char>(
SIGNS &
int(flags));
2291 mask.setActiveState(it.getCoord() & ~1u,
true);
2293 }
else if (flags &
EDGES) {
2295 bool maskRegion =
false;
2297 ijk = it.getCoord();
2298 if (!pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2300 if (!maskRegion && flags &
XEDGE) {
2302 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2304 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2306 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2310 if (!maskRegion && flags &
YEDGE) {
2312 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2314 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2316 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2320 if (!maskRegion && flags &
ZEDGE) {
2322 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2324 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2326 if (!maskRegion && !pointIndexAcc.isValueOn(ijk)) maskRegion =
true;
2331 mask.setActiveState(it.getCoord() & ~1u,
true);
2338 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2339 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2340 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2341 if (!mask.isValueOn(ijk) &&
isNonManifold(inputAcc, ijk, mIsovalue, dim)) {
2342 mask.setActiveState(ijk,
true);
2353 gradientNode->setValuesOff();
2355 gradientNode.
reset(
new Vec3sLeafNodeType());
2358 for (
auto it = signFlagsNode.cbeginValueOn(); it; ++it) {
2359 ijk = it.getCoord();
2360 if (!mask.isValueOn(ijk & ~1u)) {
2364 if (invertGradientDir) {
2368 gradientNode->setValueOn(it.pos(), dir);
2375 for ( ; dim <= LeafDim; dim = dim << 1) {
2376 const unsigned coordMask = ~((dim << 1) - 1);
2377 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2378 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2379 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2381 adaptivity = adaptivityLeaf.getValue(ijk);
2383 if (mask.isValueOn(ijk)
2385 || (useGradients && !
isMergable(*gradientNode, ijk, dim, adaptivity)))
2387 mask.setActiveState(ijk & coordMask,
true);
2389 mergeVoxels(pointIndexNode, ijk, dim, regionId++);
2409 mPolygonPool = &quadPool;
2414 template<
typename IndexType>
2418 mPolygonPool->
quad(mIdx) = verts;
2448 mPolygonPool = &polygonPool;
2456 template<
typename IndexType>
2459 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2460 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2461 mPolygonPool->
quadFlags(mQuadIdx) = flags;
2462 addQuad(verts, reverse);
2464 verts[0] == verts[3] &&
2465 verts[1] != verts[2] &&
2466 verts[1] != verts[0] &&
2467 verts[2] != verts[0]) {
2469 addTriangle(verts[0], verts[1], verts[2], reverse);
2471 verts[1] == verts[2] &&
2472 verts[0] != verts[3] &&
2473 verts[0] != verts[1] &&
2474 verts[3] != verts[1]) {
2476 addTriangle(verts[0], verts[1], verts[3], reverse);
2478 verts[0] == verts[1] &&
2479 verts[2] != verts[3] &&
2480 verts[2] != verts[0] &&
2481 verts[3] != verts[0]) {
2483 addTriangle(verts[0], verts[2], verts[3], reverse);
2485 verts[2] == verts[3] &&
2486 verts[0] != verts[1] &&
2487 verts[0] != verts[2] &&
2488 verts[1] != verts[2]) {
2490 addTriangle(verts[0], verts[1], verts[2], reverse);
2497 mPolygonPool->
trimQuads(mQuadIdx,
true);
2503 template<
typename IndexType>
2507 mPolygonPool->
quad(mQuadIdx) = verts;
2509 Vec4I& quad = mPolygonPool->
quad(mQuadIdx);
2518 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2534 size_t mQuadIdx, mTriangleIdx;
2535 PolygonPool *mPolygonPool;
2539 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2542 bool invertSurfaceOrientation,
2545 const Vec3i& offsets,
2547 const SignAccT& signAcc,
2548 const IdxAccT& idxAcc,
2549 PrimBuilder& mesher)
2551 using IndexType =
typename IdxAccT::ValueType;
2554 const bool isActive = idxAcc.probeValue(ijk, v0);
2561 bool isInside = flags &
INSIDE;
2563 isInside = invertSurfaceOrientation ? !isInside : isInside;
2568 if (flags &
XEDGE) {
2570 quad[0] = v0 + offsets[0];
2574 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2575 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2580 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2581 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2586 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2587 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2591 mesher.addPrim(quad, isInside, tag[
bool(refFlags &
XEDGE)]);
2598 if (flags &
YEDGE) {
2600 quad[0] = v0 + offsets[1];
2604 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2605 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2610 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2611 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2616 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2617 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2621 mesher.addPrim(quad, isInside, tag[
bool(refFlags &
YEDGE)]);
2628 if (flags &
ZEDGE) {
2630 quad[0] = v0 + offsets[2];
2634 bool activeValues = idxAcc.probeValue(coord, quad[1]);
2635 uint8_t cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2640 activeValues = activeValues && idxAcc.probeValue(coord, quad[2]);
2641 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2646 activeValues = activeValues && idxAcc.probeValue(coord, quad[3]);
2647 cell = uint8_t(
SIGNS & signAcc.getValue(coord));
2651 mesher.addPrim(quad, !isInside, tag[
bool(refFlags &
ZEDGE)]);
2660 template<
typename InputTreeType>
2664 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
2669 : mInputTree(&inputTree)
2673 , mTileArray(tileArray)
2678 : mInputTree(rhs.mInputTree)
2679 , mIsovalue(rhs.mIsovalue)
2682 , mTileArray(rhs.mTileArray)
2688 void operator()(
const tbb::blocked_range<size_t>&);
2691 InputTreeType
const *
const mInputTree;
2695 Vec4i const *
const mTileArray;
2699 template<
typename InputTreeType>
2708 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
2710 const Vec4i& tile = mTileArray[n];
2712 bbox.
min()[0] = tile[0];
2713 bbox.
min()[1] = tile[1];
2714 bbox.
min()[2] = tile[2];
2729 bool processRegion =
true;
2734 if (processRegion) {
2737 region.
min()[0] = region.
max()[0] = ijk[0];
2738 mMask->fill(region,
false);
2745 processRegion =
true;
2747 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2751 if (processRegion) {
2754 region.
min()[0] = region.
max()[0] = ijk[0];
2755 mMask->fill(region,
false);
2765 processRegion =
true;
2770 if (processRegion) {
2773 region.
min()[1] = region.
max()[1] = ijk[1];
2774 mMask->fill(region,
false);
2781 processRegion =
true;
2783 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2787 if (processRegion) {
2790 region.
min()[1] = region.
max()[1] = ijk[1];
2791 mMask->fill(region,
false);
2801 processRegion =
true;
2806 if (processRegion) {
2809 region.
min()[2] = region.
max()[2] = ijk[2];
2810 mMask->fill(region,
false);
2816 processRegion =
true;
2818 processRegion = (!inputTreeAcc.
probeValue(ijk, value)
2822 if (processRegion) {
2825 region.
min()[2] = region.
max()[2] = ijk[2];
2826 mMask->fill(region,
false);
2832 template<
typename InputTreeType>
2835 typename InputTreeType::template ValueConverter<bool>::Type& mask)
2837 typename InputTreeType::ValueOnCIter tileIter(inputTree);
2838 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2840 size_t tileCount = 0;
2841 for ( ; tileIter; ++tileIter) {
2845 if (tileCount > 0) {
2846 boost::scoped_array<Vec4i> tiles(
new Vec4i[tileCount]);
2851 tileIter = inputTree.cbeginValueOn();
2852 tileIter.setMaxDepth(InputTreeType::ValueOnCIter::LEAF_DEPTH - 1);
2854 for (; tileIter; ++tileIter) {
2855 Vec4i& tile = tiles[index++];
2856 tileIter.getBoundingBox(bbox);
2857 tile[0] = bbox.
min()[0];
2858 tile[1] = bbox.
min()[1];
2859 tile[2] = bbox.
min()[2];
2860 tile[3] = bbox.
max()[0] - bbox.
min()[0];
2864 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, tileCount), op);
2877 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
2883 for (
size_t n = range.begin(); n < range.end(); ++n) {
2884 mPointsOut[n] = mPointsIn[n];
2890 std::vector<Vec3s>& mPointsOut;
2902 template<
typename LeafNodeType>
2941 IndexVector mCore, mMinX, mMaxX, mMinY, mMaxY, mMinZ, mMaxZ,
2942 mInternalNeighborsX, mInternalNeighborsY, mInternalNeighborsZ;
2946 template<
typename LeafNodeType>
2952 mCore.reserve((LeafNodeType::DIM - 2) * (LeafNodeType::DIM - 2));
2954 for (
Index x = 1; x < (LeafNodeType::DIM - 1); ++x) {
2955 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2956 for (
Index y = 1; y < (LeafNodeType::DIM - 1); ++y) {
2957 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2958 for (
Index z = 1; z < (LeafNodeType::DIM - 1); ++z) {
2959 mCore.push_back(offsetXY + z);
2965 mInternalNeighborsX.clear();
2966 mInternalNeighborsX.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2968 for (
Index x = 0; x < (LeafNodeType::DIM - 1); ++x) {
2969 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2970 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2971 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2972 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2973 mInternalNeighborsX.push_back(offsetXY + z);
2979 mInternalNeighborsY.clear();
2980 mInternalNeighborsY.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2982 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2983 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2984 for (
Index y = 0; y < (LeafNodeType::DIM - 1); ++y) {
2985 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
2986 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
2987 mInternalNeighborsY.push_back(offsetXY + z);
2993 mInternalNeighborsZ.clear();
2994 mInternalNeighborsZ.reserve(LeafNodeType::SIZE - (LeafNodeType::DIM * LeafNodeType::DIM));
2996 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
2997 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
2998 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
2999 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3000 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3001 mInternalNeighborsZ.push_back(offsetXY + z);
3008 mMinX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3010 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3011 const Index offsetXY = (y << LeafNodeType::LOG2DIM);
3012 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3013 mMinX.push_back(offsetXY + z);
3020 mMaxX.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3022 const Index offsetX = (LeafNodeType::DIM - 1) << (2 * LeafNodeType::LOG2DIM);
3023 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3024 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3025 for (
Index z = 0; z < LeafNodeType::DIM; ++z) {
3026 mMaxX.push_back(offsetXY + z);
3033 mMinY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3035 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3036 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3037 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3038 mMinY.push_back(offsetX + z);
3045 mMaxY.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3047 const Index offsetY = (LeafNodeType::DIM - 1) << LeafNodeType::LOG2DIM;
3048 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3049 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3050 for (
Index z = 0; z < (LeafNodeType::DIM - 1); ++z) {
3051 mMaxY.push_back(offsetX + offsetY + z);
3058 mMinZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3060 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3061 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3062 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3063 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3064 mMinZ.push_back(offsetXY);
3071 mMaxZ.reserve(LeafNodeType::DIM * LeafNodeType::DIM);
3073 for (
Index x = 0; x < LeafNodeType::DIM; ++x) {
3074 const Index offsetX = x << (2 * LeafNodeType::LOG2DIM);
3075 for (
Index y = 0; y < LeafNodeType::DIM; ++y) {
3076 const Index offsetXY = offsetX + (y << LeafNodeType::LOG2DIM);
3077 mMaxZ.push_back(offsetXY + (LeafNodeType::DIM - 1));
3088 template<
typename AccessorT,
int _AXIS>
3098 acc.setActiveState(ijk);
3100 acc.setActiveState(ijk);
3102 acc.setActiveState(ijk);
3104 acc.setActiveState(ijk);
3105 }
else if (_AXIS == 1) {
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);
3120 acc.setActiveState(ijk);
3129 template<
typename VoxelEdgeAcc,
typename LeafNode>
3137 if (VoxelEdgeAcc::AXIS == 0) {
3138 nvo = LeafNode::DIM * LeafNode::DIM;
3140 }
else if (VoxelEdgeAcc::AXIS == 1) {
3141 nvo = LeafNode::DIM;
3145 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3146 const Index& pos = (*offsets)[n];
3147 bool isActive = leafnode.isValueOn(pos) || leafnode.isValueOn(pos + nvo);
3148 if (isActive && (
isInsideValue(leafnode.getValue(pos), iso) !=
3150 edgeAcc.set(leafnode.offsetToGlobalCoord(pos));
3159 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3164 const std::vector<Index>* lhsOffsets = &voxels.
maxX();
3165 const std::vector<Index>* rhsOffsets = &voxels.
minX();
3166 Coord ijk = lhsNode.origin();
3168 if (VoxelEdgeAcc::AXIS == 0) {
3169 ijk[0] += LeafNode::DIM;
3170 }
else if (VoxelEdgeAcc::AXIS == 1) {
3171 ijk[1] += LeafNode::DIM;
3172 lhsOffsets = &voxels.
maxY();
3173 rhsOffsets = &voxels.
minY();
3174 }
else if (VoxelEdgeAcc::AXIS == 2) {
3175 ijk[2] += LeafNode::DIM;
3176 lhsOffsets = &voxels.
maxZ();
3177 rhsOffsets = &voxels.
minZ();
3180 typename LeafNode::ValueType value;
3181 const LeafNode* rhsNodePt = acc.probeConstLeaf(ijk);
3184 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3185 const Index& pos = (*lhsOffsets)[n];
3186 bool isActive = lhsNode.isValueOn(pos) || rhsNodePt->isValueOn((*rhsOffsets)[n]);
3187 if (isActive && (
isInsideValue(lhsNode.getValue(pos), iso) !=
3188 isInsideValue(rhsNodePt->getValue((*rhsOffsets)[n]), iso))) {
3189 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3192 }
else if (!acc.probeValue(ijk, value)) {
3194 for (
size_t n = 0, N = lhsOffsets->size(); n < N; ++n) {
3195 const Index& pos = (*lhsOffsets)[n];
3196 if (lhsNode.isValueOn(pos) && (inside !=
isInsideValue(lhsNode.getValue(pos), iso))) {
3197 edgeAcc.set(lhsNode.offsetToGlobalCoord(pos));
3207 template<
typename LeafNode,
typename TreeAcc,
typename VoxelEdgeAcc>
3212 Coord ijk = leafnode.origin();
3213 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3214 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3215 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3217 typename LeafNode::ValueType value;
3218 if (!acc.probeConstLeaf(ijk) && !acc.probeValue(ijk, value)) {
3225 for (
size_t n = 0, N = offsets->size(); n < N; ++n) {
3227 const Index& pos = (*offsets)[n];
3228 if (leafnode.isValueOn(pos)
3231 ijk = leafnode.offsetToGlobalCoord(pos);
3232 if (VoxelEdgeAcc::AXIS == 0) --ijk[0];
3233 else if (VoxelEdgeAcc::AXIS == 1) --ijk[1];
3234 else if (VoxelEdgeAcc::AXIS == 2) --ijk[2];
3244 template<
typename InputTreeType>
3250 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3253 const InputTreeType& inputTree,
3254 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3259 void operator()(
const tbb::blocked_range<size_t>&);
3261 mIntersectionAccessor.
tree().merge(rhs.mIntersectionAccessor.
tree());
3278 template<
typename InputTreeType>
3280 const InputTreeType& inputTree,
3281 const std::vector<const InputLeafNodeType*>& inputLeafNodes,
3284 : mInputAccessor(inputTree)
3285 , mInputNodes(inputLeafNodes.empty() ? nullptr : &inputLeafNodes.front())
3286 , mIntersectionTree(false)
3287 , mIntersectionAccessor(intersectionTree)
3289 , mOffsets(&mOffsetData)
3296 template<
typename InputTreeType>
3299 : mInputAccessor(rhs.mInputAccessor.tree())
3300 , mInputNodes(rhs.mInputNodes)
3301 , mIntersectionTree(false)
3302 , mIntersectionAccessor(mIntersectionTree)
3304 , mOffsets(rhs.mOffsets)
3305 , mIsovalue(rhs.mIsovalue)
3310 template<
typename InputTreeType>
3318 for (
size_t n = range.begin(); n != range.end(); ++n) {
3349 template<
typename InputTreeType>
3352 typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3353 const InputTreeType& inputTree,
3354 typename InputTreeType::ValueType isovalue)
3356 using InputLeafNodeType =
typename InputTreeType::LeafNodeType;
3358 std::vector<const InputLeafNodeType*> inputLeafNodes;
3359 inputTree.getNodes(inputLeafNodes);
3362 inputTree, inputLeafNodes, intersectionTree, isovalue);
3364 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, inputLeafNodes.size()), op);
3373 template<
typename InputTreeType>
3379 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3383 const InputTreeType& inputTree,
3384 const std::vector<BoolLeafNodeType*>& nodes,
3389 void operator()(
const tbb::blocked_range<size_t>&);
3391 mIntersectionAccessor.
tree().merge(rhs.mIntersectionAccessor.
tree());
3405 template<
typename InputTreeType>
3407 const InputTreeType& inputTree,
3408 const std::vector<BoolLeafNodeType*>& nodes,
3411 : mInputAccessor(inputTree)
3412 , mNodes(nodes.empty() ? nullptr : &nodes.front())
3413 , mIntersectionTree(false)
3414 , mIntersectionAccessor(intersectionTree)
3420 template<
typename InputTreeType>
3423 : mInputAccessor(rhs.mInputAccessor.tree())
3424 , mNodes(rhs.mNodes)
3425 , mIntersectionTree(false)
3426 , mIntersectionAccessor(mIntersectionTree)
3427 , mIsovalue(rhs.mIsovalue)
3432 template<
typename InputTreeType>
3443 for (
size_t n = range.begin(); n != range.end(); ++n) {
3447 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3449 if (!it.getValue()) {
3451 ijk = it.getCoord();
3453 const bool inside =
isInsideValue(mInputAccessor.getValue(ijk), iso);
3472 template<
typename BoolTreeType>
3478 const std::vector<BoolLeafNodeType*>& maskNodes,
3479 BoolTreeType& borderTree)
3480 : mMaskTree(&maskTree)
3481 , mMaskNodes(maskNodes.empty() ? nullptr : &maskNodes.front())
3482 , mTmpBorderTree(false)
3483 , mBorderTree(&borderTree)
3488 : mMaskTree(rhs.mMaskTree)
3489 , mMaskNodes(rhs.mMaskNodes)
3490 , mTmpBorderTree(false)
3491 , mBorderTree(&mTmpBorderTree)
3503 for (
size_t n = range.begin(); n != range.end(); ++n) {
3507 for (
typename BoolLeafNodeType::ValueOnCIter it = node.cbeginValueOn(); it; ++it) {
3509 ijk = it.getCoord();
3511 const bool lhs = it.getValue();
3514 bool isEdgeVoxel =
false;
3517 isEdgeVoxel = (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3520 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3523 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3526 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3530 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3533 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3536 isEdgeVoxel = isEdgeVoxel || (maskAcc.
probeValue(ijk, rhs) && lhs != rhs);
3547 BoolTreeType
const *
const mMaskTree;
3550 BoolTreeType mTmpBorderTree;
3551 BoolTreeType *
const mBorderTree;
3555 template<
typename BoolTreeType>
3560 SyncMaskValues(
const std::vector<BoolLeafNodeType*>& nodes,
const BoolTreeType& mask)
3561 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3568 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3572 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3579 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3580 const Index pos = it.pos();
3581 if (maskNode->getValue(pos)) {
3582 node.setValueOnly(pos,
true);
3591 BoolTreeType
const *
const mMaskTree;
3598 template<
typename BoolTreeType>
3603 MaskSurface(
const std::vector<BoolLeafNodeType*>& nodes,
const BoolTreeType& mask,
3605 : mNodes(nodes.empty() ? nullptr : &nodes.front())
3607 , mInputTransform(inputTransform)
3608 , mMaskTransform(maskTransform)
3609 , mInvertMask(invert)
3615 using ValueOnIter =
typename BoolLeafNodeType::ValueOnIter;
3619 const bool matchingTransforms = mInputTransform == mMaskTransform;
3620 const bool maskState = mInvertMask;
3622 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3626 if (matchingTransforms) {
3632 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3633 const Index pos = it.pos();
3634 if (maskNode->isValueOn(pos) == maskState) {
3635 node.setValueOnly(pos,
true);
3641 if (maskTreeAcc.
isValueOn(node.origin()) == maskState) {
3642 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3643 node.setValueOnly(it.pos(),
true);
3653 for (ValueOnIter it = node.beginValueOn(); it; ++it) {
3658 if (maskTreeAcc.
isValueOn(ijk) == maskState) {
3659 node.setValueOnly(it.pos(),
true);
3669 BoolTreeType
const *
const mMaskTree;
3672 bool const mInvertMask;
3676 template<
typename InputGr
idType>
3679 typename InputGridType::TreeType::template ValueConverter<bool>::Type& intersectionTree,
3680 typename InputGridType::TreeType::template ValueConverter<bool>::Type& borderTree,
3681 const InputGridType& inputGrid,
3684 typename InputGridType::ValueType isovalue)
3686 using InputTreeType =
typename InputGridType::TreeType;
3687 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3688 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
3691 if (maskGrid && maskGrid->type() == BoolGridType::gridType()) {
3694 const InputTreeType& inputTree = inputGrid.tree();
3696 const BoolGridType * surfaceMask = static_cast<const BoolGridType*>(maskGrid.get());
3698 const BoolTreeType& maskTree = surfaceMask->tree();
3704 std::vector<BoolLeafNodeType*> intersectionLeafNodes;
3705 intersectionTree.getNodes(intersectionLeafNodes);
3707 tbb::parallel_for(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()),
3709 intersectionLeafNodes, maskTree, transform, maskTransform, invertMask));
3715 intersectionTree, intersectionLeafNodes, borderTree);
3716 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), borderOp);
3721 BoolTreeType tmpIntersectionTree(
false);
3724 inputTree, intersectionLeafNodes, tmpIntersectionTree, isovalue);
3726 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3728 std::vector<BoolLeafNodeType*> tmpIntersectionLeafNodes;
3729 tmpIntersectionTree.getNodes(tmpIntersectionLeafNodes);
3731 tbb::parallel_for(tbb::blocked_range<size_t>(0, tmpIntersectionLeafNodes.size()),
3734 intersectionTree.clear();
3735 intersectionTree.merge(tmpIntersectionTree);
3743 template<
typename InputTreeType>
3751 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
3756 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3762 void operator()(
const tbb::blocked_range<size_t>&);
3764 mSignFlagsAccessor.
tree().merge(rhs.mSignFlagsAccessor.
tree());
3765 mPointIndexAccessor.
tree().merge(rhs.mPointIndexAccessor.
tree());
3781 template<
typename InputTreeType>
3783 const InputTreeType& inputTree,
3784 const std::vector<const BoolLeafNodeType*>& intersectionLeafNodes,
3788 : mInputAccessor(inputTree)
3789 , mIntersectionNodes(&intersectionLeafNodes.front())
3791 , mSignFlagsAccessor(signFlagsTree)
3792 , mPointIndexTree(std::numeric_limits<
Index32>::
max())
3793 , mPointIndexAccessor(pointIndexTree)
3800 template<
typename InputTreeType>
3802 : mInputAccessor(rhs.mInputAccessor.tree())
3803 , mIntersectionNodes(rhs.mIntersectionNodes)
3805 , mSignFlagsAccessor(mSignFlagsTree)
3806 , mPointIndexTree(std::numeric_limits<
Index32>::
max())
3807 , mPointIndexAccessor(mPointIndexTree)
3808 , mIsovalue(rhs.mIsovalue)
3813 template<
typename InputTreeType>
3817 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
3821 typename std::unique_ptr<Int16LeafNodeType> signsNodePt(
new Int16LeafNodeType(ijk, 0));
3823 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3830 if (!signsNodePt.get()) signsNodePt.
reset(
new Int16LeafNodeType(origin, 0));
3831 else signsNodePt->setOrigin(origin);
3833 bool updatedNode =
false;
3837 const Index pos = it.pos();
3838 ijk = BoolLeafNodeType::offsetToLocalCoord(pos);
3841 ijk[0] <
int(BoolLeafNodeType::DIM - 1) &&
3842 ijk[1] <
int(BoolLeafNodeType::DIM - 1) &&
3843 ijk[2] <
int(BoolLeafNodeType::DIM - 1) ) {
3851 if (signFlags != 0 && signFlags != 0xFF) {
3853 const bool inside = signFlags & 0x1;
3855 int edgeFlags = inside ?
INSIDE : 0;
3857 if (!it.getValue()) {
3858 edgeFlags |= inside != ((signFlags & 0x02) != 0) ?
XEDGE : 0;
3859 edgeFlags |= inside != ((signFlags & 0x10) != 0) ?
YEDGE : 0;
3860 edgeFlags |= inside != ((signFlags & 0x08) != 0) ?
ZEDGE : 0;
3864 if (ambiguousCellFlags != 0) {
3866 origin + ijk, mIsovalue);
3869 edgeFlags |= int(signFlags);
3871 signsNodePt->setValueOn(pos,
Int16(edgeFlags));
3877 typename Index32TreeType::LeafNodeType* idxNode = mPointIndexAccessor.touchLeaf(origin);
3878 idxNode->topologyUnion(*signsNodePt);
3881 for (
auto it = idxNode->beginValueOn(); it; ++it) {
3882 idxNode->setValueOnly(it.pos(), 0);
3885 mSignFlagsAccessor.addLeaf(signsNodePt.release());
3891 template<
typename InputTreeType>
3894 typename InputTreeType::template ValueConverter<Int16>::Type& signFlagsTree,
3895 typename InputTreeType::template ValueConverter<Index32>::Type& pointIndexTree,
3896 const typename InputTreeType::template ValueConverter<bool>::Type& intersectionTree,
3897 const InputTreeType& inputTree,
3898 typename InputTreeType::ValueType isovalue)
3900 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
3901 using BoolLeafNodeType =
typename BoolTreeType::LeafNodeType;
3903 std::vector<const BoolLeafNodeType*> intersectionLeafNodes;
3904 intersectionTree.getNodes(intersectionLeafNodes);
3907 inputTree, intersectionLeafNodes, signFlagsTree, pointIndexTree, isovalue);
3909 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, intersectionLeafNodes.size()), op);
3916 template<Index32 LeafNodeLog2Dim>
3922 boost::scoped_array<Index32>& leafNodeCount)
3923 : mLeafNodes(leafNodes.empty() ? nullptr : &leafNodes.front())
3924 , mData(leafNodeCount.get())
3930 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3952 template<
typename Po
intIndexLeafNode>
3958 const std::vector<Int16LeafNodeType*>& signDataNodes,
3959 boost::scoped_array<Index32>& leafNodeCount)
3960 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
3961 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
3962 , mData(leafNodeCount.get())
3970 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
3977 std::set<IndexType> uniqueRegions;
3986 uniqueRegions.insert(
id);
3990 mData[n] =
Index32(count + uniqueRegions.size());
4001 template<
typename Po
intIndexLeafNode>
4006 MapPoints(
const std::vector<PointIndexLeafNode*>& pointIndexNodes,
4007 const std::vector<Int16LeafNodeType*>& signDataNodes,
4008 boost::scoped_array<Index32>& leafNodeCount)
4009 : mPointIndexNodes(pointIndexNodes.empty() ? nullptr : &pointIndexNodes.front())
4010 , mSignDataNodes(signDataNodes.empty() ? nullptr : &signDataNodes.front())
4011 , mData(leafNodeCount.get())
4017 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
4022 Index32 pointOffset = mData[n];
4025 const Index pos = it.pos();
4042 template<
typename TreeType,
typename PrimBuilder>
4053 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4057 bool invertSurfaceOrientation);
4061 void operator()(
const tbb::blocked_range<size_t>&)
const;
4069 bool const mInvertSurfaceOrientation;
4073 template<
typename TreeType,
typename PrimBuilder>
4075 const std::vector<Int16LeafNodeType*>& signFlagsLeafNodes,
4079 bool invertSurfaceOrientation)
4080 : mSignFlagsLeafNodes(signFlagsLeafNodes.empty() ? nullptr : &signFlagsLeafNodes.front())
4081 , mSignFlagsTree(&signFlagsTree)
4082 , mRefSignFlagsTree(nullptr)
4083 , mIndexTree(&idxTree)
4084 , mPolygonPoolList(&polygons)
4085 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4089 template<
typename InputTreeType,
typename PrimBuilder>
4094 Int16ValueAccessor signAcc(*mSignFlagsTree);
4098 const bool invertSurfaceOrientation = mInvertSurfaceOrientation;
4105 std::unique_ptr<Int16ValueAccessor> refSignAcc;
4106 if (mRefSignFlagsTree) refSignAcc.
reset(
new Int16ValueAccessor(*mRefSignFlagsTree));
4108 for (
size_t n = range.begin(); n != range.end(); ++n) {
4111 origin = node.origin();
4115 typename Int16LeafNodeType::ValueOnCIter iter = node.cbeginValueOn();
4116 for (; iter; ++iter) {
4117 if (iter.getValue() &
XEDGE) ++edgeCount;
4118 if (iter.getValue() &
YEDGE) ++edgeCount;
4119 if (iter.getValue() &
ZEDGE) ++edgeCount;
4122 if(edgeCount == 0)
continue;
4124 mesher.init(edgeCount, (*mPolygonPoolList)[n]);
4129 if (!signleafPt || !idxLeafPt)
continue;
4133 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
4137 for (iter = node.cbeginValueOn(); iter; ++iter) {
4138 ijk = iter.getCoord();
4140 Int16 flags = iter.getValue();
4142 if (!(flags & 0xE00))
continue;
4145 if (refSignLeafPt) {
4146 refFlags = refSignLeafPt->getValue(iter.pos());
4153 const uint8_t cell = uint8_t(
SIGNS & flags);
4161 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
4163 flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher);
4166 flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher);
4179 template<
typename T>
4182 CopyArray(T * outputArray,
const T * inputArray,
size_t outputOffset = 0)
4183 : mOutputArray(outputArray), mInputArray(inputArray), mOutputOffset(outputOffset)
4187 void operator()(
const tbb::blocked_range<size_t>& inputArrayRange)
const 4189 const size_t offset = mOutputOffset;
4190 for (
size_t n = inputArrayRange.begin(), N = inputArrayRange.end(); n < N; ++n) {
4191 mOutputArray[offset + n] = mInputArray[n];
4196 T *
const mOutputArray;
4197 T
const *
const mInputArray;
4198 size_t const mOutputOffset;
4205 const std::vector<uint8_t>& pointFlags,
4206 boost::scoped_array<openvdb::Vec3s>& points,
4207 boost::scoped_array<unsigned>& numQuadsToDivide)
4208 : mPolygonPoolList(&polygons)
4209 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4210 , mPoints(points.get())
4211 , mNumQuadsToDivide(numQuadsToDivide.get())
4217 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4224 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4232 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4233 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4235 if (!edgePoly)
continue;
4237 const Vec3s& p0 = mPoints[quad[0]];
4238 const Vec3s& p1 = mPoints[quad[1]];
4239 const Vec3s& p2 = mPoints[quad[2]];
4240 const Vec3s& p3 = mPoints[quad[3]];
4249 mNumQuadsToDivide[n] = count;
4255 uint8_t
const *
const mPointFlags;
4256 Vec3s const *
const mPoints;
4257 unsigned *
const mNumQuadsToDivide;
4264 const boost::scoped_array<openvdb::Vec3s>& points,
4266 boost::scoped_array<openvdb::Vec3s>& centroids,
4267 boost::scoped_array<unsigned>& numQuadsToDivide,
4268 boost::scoped_array<unsigned>& centroidOffsets)
4269 : mPolygonPoolList(&polygons)
4270 , mPoints(points.get())
4271 , mCentroids(centroids.get())
4272 , mNumQuadsToDivide(numQuadsToDivide.get())
4273 , mCentroidOffsets(centroidOffsets.get())
4280 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4284 const size_t nonplanarCount = size_t(mNumQuadsToDivide[n]);
4286 if (nonplanarCount > 0) {
4292 size_t offset = mCentroidOffsets[n];
4294 size_t triangleIdx = 0;
4296 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4298 const char quadFlags = polygons.
quadFlags(i);
4301 unsigned newPointIdx = unsigned(offset + mPointCount);
4305 mCentroids[offset] = (mPoints[quad[0]] + mPoints[quad[1]] +
4306 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25f;
4313 triangle[0] = quad[0];
4314 triangle[1] = newPointIdx;
4315 triangle[2] = quad[3];
4325 triangle[0] = quad[0];
4326 triangle[1] = quad[1];
4327 triangle[2] = newPointIdx;
4337 triangle[0] = quad[1];
4338 triangle[1] = quad[2];
4339 triangle[2] = newPointIdx;
4350 triangle[0] = quad[2];
4351 triangle[1] = quad[3];
4352 triangle[2] = newPointIdx;
4363 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4370 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4374 tmpPolygons.
quad(quadIdx) = quad;
4380 polygons.
copy(tmpPolygons);
4387 Vec3s const *
const mPoints;
4388 Vec3s *
const mCentroids;
4389 unsigned *
const mNumQuadsToDivide;
4390 unsigned *
const mCentroidOffsets;
4391 size_t const mPointCount;
4398 size_t polygonPoolListSize,
4400 size_t& pointListSize,
4401 std::vector<uint8_t>& pointFlags)
4403 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4405 boost::scoped_array<unsigned> numQuadsToDivide(
new unsigned[polygonPoolListSize]);
4407 tbb::parallel_for(polygonPoolListRange,
4410 boost::scoped_array<unsigned> centroidOffsets(
new unsigned[polygonPoolListSize]);
4412 size_t centroidCount = 0;
4416 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4417 centroidOffsets[n] = sum;
4418 sum += numQuadsToDivide[n];
4420 centroidCount = size_t(sum);
4423 boost::scoped_array<Vec3s> centroidList(
new Vec3s[centroidCount]);
4425 tbb::parallel_for(polygonPoolListRange,
4427 centroidList, numQuadsToDivide, centroidOffsets));
4429 if (centroidCount > 0) {
4431 const size_t newPointListSize = centroidCount + pointListSize;
4433 boost::scoped_array<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointListSize]);
4435 tbb::parallel_for(tbb::blocked_range<size_t>(0, pointListSize),
4438 tbb::parallel_for(tbb::blocked_range<size_t>(0, newPointListSize - pointListSize),
4441 pointListSize = newPointListSize;
4442 pointList.swap(newPointList);
4443 pointFlags.resize(pointListSize, 0);
4451 const std::vector<uint8_t>& pointFlags)
4452 : mPolygonPoolList(&polygons)
4453 , mPointFlags(pointFlags.empty() ? nullptr : &pointFlags.front())
4459 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4463 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4471 const bool hasSeamLinePoint =
4472 mPointFlags[verts[0]] || mPointFlags[verts[1]] ||
4473 mPointFlags[verts[2]] || mPointFlags[verts[3]];
4475 if (!hasSeamLinePoint) {
4481 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4489 const bool hasSeamLinePoint =
4490 mPointFlags[verts[0]] || mPointFlags[verts[1]] || mPointFlags[verts[2]];
4492 if (!hasSeamLinePoint) {
4504 uint8_t
const *
const mPointFlags;
4510 std::vector<uint8_t>& pointFlags)
4512 tbb::parallel_for(tbb::blocked_range<size_t>(0, polygonPoolListSize),
4520 template<
typename InputTreeType>
4524 const PointList& pointList, boost::scoped_array<uint8_t>& pointMask,
4526 : mInputTree(&inputTree)
4527 , mPolygonPoolList(&polygons)
4528 , mPointList(&pointList)
4529 , mPointMask(pointMask.get())
4530 , mTransform(transform)
4531 , mInvertSurfaceOrientation(invertSurfaceOrientation)
4537 using ValueType =
typename InputTreeType::LeafNodeType::ValueType;
4540 Vec3s centroid, normal;
4543 const bool invertGradientDir = mInvertSurfaceOrientation || isBoolValue<ValueType>();
4545 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
4547 const PolygonPool& polygons = (*mPolygonPoolList)[n];
4549 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4553 const Vec3s& v0 = (*mPointList)[verts[0]];
4554 const Vec3s& v1 = (*mPointList)[verts[1]];
4555 const Vec3s& v2 = (*mPointList)[verts[2]];
4557 normal = (v2 - v0).cross((v1 - v0));
4560 centroid = (v0 + v1 + v2) * (1.0f / 3.0f);
4566 if (invertGradientDir) {
4571 if (dir.dot(normal) < -0.5f) {
4576 mPointMask[verts[0]] = 1;
4577 mPointMask[verts[1]] = 1;
4578 mPointMask[verts[2]] = 1;
4587 InputTreeType
const *
const mInputTree;
4590 uint8_t *
const mPointMask;
4592 bool const mInvertSurfaceOrientation;
4596 template<
typename InputTree>
4599 bool invertSurfaceOrientation,
4600 const InputTree& inputTree,
4603 size_t polygonPoolListSize,
4605 const size_t pointListSize)
4607 const tbb::blocked_range<size_t> polygonPoolListRange(0, polygonPoolListSize);
4609 boost::scoped_array<uint8_t> pointMask(
new uint8_t[pointListSize]);
4610 fillArray(pointMask.get(), uint8_t(0), pointListSize);
4612 tbb::parallel_for(polygonPoolListRange,
4614 inputTree, polygonPoolList, pointList, pointMask, transform, invertSurfaceOrientation));
4616 boost::scoped_array<uint8_t> pointUpdates(
new uint8_t[pointListSize]);
4617 fillArray(pointUpdates.get(), uint8_t(0), pointListSize);
4619 boost::scoped_array<Vec3s> newPoints(
new Vec3s[pointListSize]);
4620 fillArray(newPoints.get(),
Vec3s(0.0f, 0.0f, 0.0f), pointListSize);
4622 for (
size_t n = 0, N = polygonPoolListSize; n < N; ++n) {
4626 for (
size_t i = 0, I = polygons.
numQuads(); i < I; ++i) {
4629 for (
int v = 0; v < 4; ++v) {
4631 const unsigned pointIdx = verts[v];
4633 if (pointMask[pointIdx] == 1) {
4635 newPoints[pointIdx] +=
4636 pointList[verts[0]] + pointList[verts[1]] +
4637 pointList[verts[2]] + pointList[verts[3]];
4639 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 4);
4644 for (
size_t i = 0, I = polygons.
numTriangles(); i < I; ++i) {
4647 for (
int v = 0; v < 3; ++v) {
4649 const unsigned pointIdx = verts[v];
4651 if (pointMask[pointIdx] == 1) {
4652 newPoints[pointIdx] +=
4653 pointList[verts[0]] + pointList[verts[1]] + pointList[verts[2]];
4655 pointUpdates[pointIdx] = uint8_t(pointUpdates[pointIdx] + 3);
4661 for (
size_t n = 0, N = pointListSize; n < N; ++n) {
4662 if (pointUpdates[n] > 0) {
4663 const double weight = 1.0 / double(pointUpdates[n]);
4664 pointList[n] = newPoints[n] * float(weight);
4681 , mTriangles(nullptr)
4682 , mQuadFlags(nullptr)
4683 , mTriangleFlags(nullptr)
4690 : mNumQuads(numQuads)
4691 , mNumTriangles(numTriangles)
4694 , mQuadFlags(new char[mNumQuads])
4695 , mTriangleFlags(new char[mNumTriangles])
4706 for (
size_t i = 0; i < mNumQuads; ++i) {
4707 mQuads[i] = rhs.mQuads[i];
4708 mQuadFlags[i] = rhs.mQuadFlags[i];
4711 for (
size_t i = 0; i < mNumTriangles; ++i) {
4712 mTriangles[i] = rhs.mTriangles[i];
4713 mTriangleFlags[i] = rhs.mTriangleFlags[i];
4723 mQuadFlags.reset(
new char[mNumQuads]);
4731 mQuads.reset(
nullptr);
4732 mQuadFlags.reset(
nullptr);
4739 mNumTriangles = size;
4741 mTriangleFlags.reset(
new char[mNumTriangles]);
4749 mTriangles.reset(
nullptr);
4750 mTriangleFlags.reset(
nullptr);
4757 if (!(n < mNumQuads))
return false;
4762 mQuads.reset(
nullptr);
4765 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
4766 boost::scoped_array<char> flags(
new char[n]);
4768 for (
size_t i = 0; i < n; ++i) {
4769 quads[i] = mQuads[i];
4770 flags[i] = mQuadFlags[i];
4774 mQuadFlags.swap(flags);
4786 if (!(n < mNumTriangles))
return false;
4791 mTriangles.reset(
nullptr);
4794 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
4795 boost::scoped_array<char> flags(
new char[n]);
4797 for (
size_t i = 0; i < n; ++i) {
4798 triangles[i] = mTriangles[i];
4799 flags[i] = mTriangleFlags[i];
4802 mTriangles.swap(triangles);
4803 mTriangleFlags.swap(flags);
4820 , mSeamPointListSize(0)
4821 , mPolygonPoolListSize(0)
4822 , mIsovalue(isovalue)
4823 , mPrimAdaptivity(adaptivity)
4824 , mSecAdaptivity(0.0)
4826 , mSurfaceMaskGrid(
GridBase::ConstPtr())
4827 , mAdaptivityGrid(
GridBase::ConstPtr())
4828 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
4831 , mInvertSurfaceMask(false)
4833 , mQuantizedSeamPoints(nullptr)
4843 mSecAdaptivity = secAdaptivity;
4848 mSeamPointListSize = 0;
4849 mQuantizedSeamPoints.reset(
nullptr);
4856 mSurfaceMaskGrid = mask;
4857 mInvertSurfaceMask = invertMask;
4864 mAdaptivityGrid = grid;
4871 mAdaptivityMaskTree = tree;
4875 template<
typename InputGr
idType>
4881 using InputTreeType =
typename InputGridType::TreeType;
4882 using InputLeafNodeType =
typename InputTreeType::LeafNodeType;
4883 using InputValueType =
typename InputLeafNodeType::ValueType;
4887 using FloatTreeType =
typename InputTreeType::template ValueConverter<float>::Type;
4889 using BoolTreeType =
typename InputTreeType::template ValueConverter<bool>::Type;
4890 using Int16TreeType =
typename InputTreeType::template ValueConverter<Int16>::Type;
4891 using Int16LeafNodeType =
typename Int16TreeType::LeafNodeType;
4892 using Index32TreeType =
typename InputTreeType::template ValueConverter<Index32>::Type;
4893 using Index32LeafNodeType =
typename Index32TreeType::LeafNodeType;
4898 mPolygonPoolListSize = 0;
4900 mPointFlags.clear();
4905 const InputValueType isovalue = InputValueType(mIsovalue);
4906 const float adaptivityThreshold = float(mPrimAdaptivity);
4907 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4913 const bool invertSurfaceOrientation = (!volume_to_mesh_internal::isBoolValue<InputValueType>()
4918 const InputTreeType& inputTree = inputGrid.tree();
4920 BoolTreeType intersectionTree(
false), adaptivityMask(
false);
4922 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeType::treeType()) {
4923 const BoolTreeType *refAdaptivityMask=
4924 static_cast<const BoolTreeType*>(mAdaptivityMaskTree.get());
4925 adaptivityMask.topologyUnion(*refAdaptivityMask);
4928 Int16TreeType signFlagsTree(0);
4935 intersectionTree, inputTree, isovalue);
4938 inputGrid, mSurfaceMaskGrid, mInvertSurfaceMask, isovalue);
4940 if (intersectionTree.empty())
return;
4943 signFlagsTree, pointIndexTree, intersectionTree, inputTree, isovalue);
4945 intersectionTree.clear();
4947 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
4948 pointIndexTree.getNodes(pointIndexLeafNodes);
4950 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
4951 signFlagsTree.getNodes(signFlagsLeafNodes);
4953 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
4958 Int16TreeType* refSignFlagsTree =
nullptr;
4959 Index32TreeType* refPointIndexTree =
nullptr;
4960 InputTreeType
const* refInputTree =
nullptr;
4962 if (mRefGrid && mRefGrid->type() == InputGridType::gridType()) {
4964 const InputGridType* refGrid = static_cast<const InputGridType*>(mRefGrid.get());
4965 refInputTree = &refGrid->tree();
4967 if (!mRefSignTree && !mRefIdxTree) {
4971 typename Int16TreeType::Ptr refSignFlagsTreePt(
new Int16TreeType(0));
4972 typename Index32TreeType::Ptr refPointIndexTreePt(
4975 BoolTreeType refIntersectionTree(
false);
4978 refIntersectionTree, *refInputTree, isovalue);
4981 *refPointIndexTreePt, refIntersectionTree, *refInputTree, isovalue);
4983 mRefSignTree = refSignFlagsTreePt;
4984 mRefIdxTree = refPointIndexTreePt;
4987 if (mRefSignTree && mRefIdxTree) {
4991 refSignFlagsTree = static_cast<Int16TreeType*>(mRefSignTree.get());
4992 refPointIndexTree = static_cast<Index32TreeType*>(mRefIdxTree.get());
4996 if (refSignFlagsTree && refPointIndexTree) {
5002 if (mSeamPointListSize == 0) {
5006 std::vector<Int16LeafNodeType*> refSignFlagsLeafNodes;
5007 refSignFlagsTree->getNodes(refSignFlagsLeafNodes);
5009 boost::scoped_array<Index32> leafNodeOffsets(
5010 new Index32[refSignFlagsLeafNodes.size()]);
5012 tbb::parallel_for(tbb::blocked_range<size_t>(0, refSignFlagsLeafNodes.size()),
5014 refSignFlagsLeafNodes, leafNodeOffsets));
5018 for (
size_t n = 0, N = refSignFlagsLeafNodes.size(); n < N; ++n) {
5019 const Index32 tmp = leafNodeOffsets[n];
5020 leafNodeOffsets[n] = count;
5023 mSeamPointListSize = size_t(count);
5026 if (mSeamPointListSize != 0) {
5028 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
5030 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
5032 std::vector<Index32LeafNodeType*> refPointIndexLeafNodes;
5033 refPointIndexTree->getNodes(refPointIndexLeafNodes);
5035 tbb::parallel_for(tbb::blocked_range<size_t>(0, refPointIndexLeafNodes.size()),
5037 refPointIndexLeafNodes, refSignFlagsLeafNodes, leafNodeOffsets));
5041 if (mSeamPointListSize != 0) {
5043 tbb::parallel_for(auxiliaryLeafNodeRange,
5045 signFlagsLeafNodes, inputTree, *refPointIndexTree, *refSignFlagsTree,
5046 mQuantizedSeamPoints.get(), isovalue));
5051 const bool referenceMeshing = refSignFlagsTree && refPointIndexTree && refInputTree;
5056 boost::scoped_array<Index32> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
5060 inputGrid, pointIndexTree, pointIndexLeafNodes, signFlagsLeafNodes,
5061 isovalue, adaptivityThreshold, invertSurfaceOrientation);
5063 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridType::gridType()) {
5064 const FloatGridType* adaptivityGrid =
5065 static_cast<const FloatGridType*>(mAdaptivityGrid.get());
5069 if (!adaptivityMask.empty()) {
5073 if (referenceMeshing) {
5077 tbb::parallel_for(auxiliaryLeafNodeRange, mergeOp);
5080 op(pointIndexLeafNodes, signFlagsLeafNodes, leafNodeOffsets);
5082 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5087 op(signFlagsLeafNodes, leafNodeOffsets);
5089 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5095 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
5096 const Index32 tmp = leafNodeOffsets[n];
5103 mPointFlags.clear();
5111 op(mPoints.get(), inputTree, pointIndexLeafNodes,
5112 signFlagsLeafNodes, leafNodeOffsets, transform, mIsovalue);
5114 if (referenceMeshing) {
5115 mPointFlags.resize(mPointListSize);
5116 op.setRefData(*refInputTree, *refPointIndexTree, *refSignFlagsTree,
5117 mQuantizedSeamPoints.get(), &mPointFlags.front());
5120 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5126 mPolygonPoolListSize = signFlagsLeafNodes.size();
5127 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
5134 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5135 mPolygons, invertSurfaceOrientation);
5137 if (referenceMeshing) {
5141 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5148 op(signFlagsLeafNodes, signFlagsTree, pointIndexTree,
5149 mPolygons, invertSurfaceOrientation);
5151 if (referenceMeshing) {
5155 tbb::parallel_for(auxiliaryLeafNodeRange, op);
5159 signFlagsTree.clear();
5160 pointIndexTree.clear();
5163 if (adaptive && mRelaxDisorientedTriangles) {
5165 inputTree, transform, mPolygons, mPolygonPoolListSize, mPoints, mPointListSize);
5169 if (referenceMeshing) {
5171 mPolygons, mPolygonPoolListSize, mPoints, mPointListSize, mPointFlags);
5186 template<
typename Gr
idType>
5187 inline typename std::enable_if<std::is_scalar<typename GridType::ValueType>::value,
void>::type
5189 const GridType& grid,
5190 std::vector<Vec3s>& points,
5191 std::vector<Vec3I>& triangles,
5192 std::vector<Vec4I>& quads,
5202 points.resize(mesher.pointListSize());
5206 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
5207 mesher.pointList().reset(
nullptr);
5213 size_t numQuads = 0, numTriangles = 0;
5214 for (
size_t n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) {
5215 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5216 numTriangles += polygons.numTriangles();
5217 numQuads += polygons.numQuads();
5221 triangles.resize(numTriangles);
5223 quads.resize(numQuads);
5227 size_t qIdx = 0, tIdx = 0;
5228 for (
size_t n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) {
5229 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
5231 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
5232 quads[qIdx++] = polygons.quad(i);
5235 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
5236 triangles[tIdx++] = polygons.triangle(i);
5242 template<
typename Gr
idType>
5243 inline typename std::enable_if<!std::is_scalar<typename GridType::ValueType>::value,
void>::type
5246 std::vector<Vec3s>&,
5247 std::vector<Vec3I>&,
5248 std::vector<Vec4I>&,
5253 OPENVDB_THROW(TypeError,
"volume to mesh conversion is supported only for scalar grids");
5260 template<
typename Gr
idType>
5263 const GridType& grid,
5264 std::vector<Vec3s>& points,
5265 std::vector<Vec3I>& triangles,
5266 std::vector<Vec4I>& quads,
5275 template<
typename Gr
idType>
5278 const GridType& grid,
5279 std::vector<Vec3s>& points,
5280 std::vector<Vec4I>& quads,
5283 std::vector<Vec3I> triangles;
5284 doVolumeToMesh(grid, points, triangles, quads, isovalue, 0.0,
true);
5291 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED Definition: LeafNode.h:236
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:216
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:377
Vec3< int32_t > Vec3i
Definition: Vec3.h:676
int16_t Int16
Definition: Types.h:62
Abstract base class for typed grids.
Definition: Grid.h:104
Index32 Index
Definition: Types.h:61
ValueOnCIter cbeginValueOn() const
Definition: LeafNode.h:320
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:785
static const Index SIZE
Definition: LeafNode.h:80
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition: ValueAccessor.h:264
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:267
Vec3< double > Vec3d
Definition: Vec3.h:679
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:201
std::vector< Index > IndexArray
Definition: PointMove.h:198
const Coord & max() const
Definition: Coord.h:338
Mat3< double > Mat3d
Definition: Mat3.h:843
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
Gradient operators defined in index space of various orders.
Definition: Operators.h:123
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1087
uint32_t Index32
Definition: Types.h:59
SharedPtr< TreeBase > Ptr
Definition: Tree.h:65
SharedPtr< const TreeBase > ConstPtr
Definition: Tree.h:66
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition: ValueAccessor.h:288
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:798
Vec4< int32_t > Vec4i
Definition: Vec4.h:584
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:110
T & z()
Definition: Vec3.h:112
const Coord & min() const
Definition: Coord.h:337
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:257
Definition: Exceptions.h:40
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:422
const Buffer & buffer() const
Definition: LeafNode.h:368
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition: LeafNode.h:64
Base class for typed trees.
Definition: Tree.h:62
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:502
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:115
TreeType & tree() const
Return a reference to the tree associated with this accessor.
Definition: ValueAccessor.h:148
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:276
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:108
Coord & reset(Int32 x, Int32 y, Int32 z)
Reset all three coordinates with the specified arguments.
Definition: Coord.h:96
const ValueType * data() const
Return a const pointer to the array of voxel values.
Definition: LeafBuffer.h:397
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:422
Definition: Exceptions.h:92
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
Vec3< float > Vec3s
Definition: Vec3.h:678
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:347
OPENVDB_API const Index32 INVALID_IDX
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118