31 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
34 #include <openvdb/Platform.h>
35 #include <openvdb/tree/ValueAccessor.h>
36 #include <openvdb/util/Util.h>
37 #include <openvdb/math/Operators.h>
38 #include <openvdb/tools/Morphology.h>
39 #include <openvdb/tree/LeafManager.h>
41 #include <boost/scoped_array.hpp>
42 #include <boost/scoped_ptr.hpp>
43 #include <tbb/blocked_range.h>
44 #include <tbb/parallel_for.h>
45 #include <tbb/parallel_reduce.h>
72 template<
typename Gr
idType>
76 std::vector<Vec3s>& points,
77 std::vector<Vec4I>& quads,
78 double isovalue = 0.0);
89 template<
typename Gr
idType>
93 std::vector<Vec3s>& points,
94 std::vector<Vec3I>& triangles,
95 std::vector<Vec4I>& quads,
96 double isovalue = 0.0,
97 double adaptivity = 0.0);
113 inline PolygonPool(
const size_t numQuads,
const size_t numTriangles);
118 inline void resetQuads(
size_t size);
119 inline void clearQuads();
121 inline void resetTriangles(
size_t size);
122 inline void clearTriangles();
127 const size_t&
numQuads()
const {
return mNumQuads; }
142 const char&
quadFlags(
size_t n)
const {
return mQuadFlags[n]; }
151 inline bool trimQuads(
const size_t n,
bool reallocate =
false);
152 inline bool trimTrinagles(
const size_t n,
bool reallocate =
false);
158 size_t mNumQuads, mNumTriangles;
159 boost::scoped_array<openvdb::Vec4I> mQuads;
160 boost::scoped_array<openvdb::Vec3I> mTriangles;
161 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
182 VolumeToMesh(
double isovalue = 0,
double adaptivity = 0);
189 const size_t& pointListSize()
const;
192 const size_t& polygonPoolListSize()
const;
196 std::vector<unsigned char>& pointFlags();
197 const std::vector<unsigned char>& pointFlags()
const;
205 template<
typename Gr
idT>
206 void operator()(
const GridT&);
254 void partition(
unsigned partitions = 1,
unsigned activePart = 0);
261 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
262 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
269 bool mInvertSurfaceMask;
270 unsigned mPartitions, mActivePart;
272 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
274 std::vector<unsigned char> mPointFlags;
288 const std::vector<Vec3d>& points,
289 const std::vector<Vec3d>& normals)
295 if (points.empty())
return avgPos;
297 for (
size_t n = 0, N = points.size(); n < N; ++n) {
301 avgPos /= double(points.size());
305 double m00=0,m01=0,m02=0,
312 for (
size_t n = 0, N = points.size(); n < N; ++n) {
314 const Vec3d& n_ref = normals[n];
317 m00 += n_ref[0] * n_ref[0];
318 m11 += n_ref[1] * n_ref[1];
319 m22 += n_ref[2] * n_ref[2];
321 m01 += n_ref[0] * n_ref[1];
322 m02 += n_ref[0] * n_ref[2];
323 m12 += n_ref[1] * n_ref[2];
326 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
351 Mat3d D = Mat3d::identity();
354 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
355 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
359 for (
int i = 0; i < 3; ++i ) {
360 if (std::abs(eigenValues[i]) < tolerance) {
364 D[i][i] = 1.0 / eigenValues[i];
370 Mat3d pseudoInv = eigenVectors * D * eigenVectors.
transpose();
371 return avgPos + pseudoInv * rhs;
387 #ifdef OPENVDB_HAS_CXX11
388 typedef std::unique_ptr<T>
type;
402 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,
403 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,
404 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,
405 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,
406 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,
407 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,
408 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,
409 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};
414 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,
415 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,
416 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,
417 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,
418 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,
419 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,
420 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,
421 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};
428 {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},
429 {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},
430 {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},
431 {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},
432 {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},
433 {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},
434 {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},
435 {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},
436 {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},
437 {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},
438 {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},
439 {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},
440 {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},
441 {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},
442 {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},
443 {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},
444 {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},
445 {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},
446 {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},
447 {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},
448 {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},
449 {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},
450 {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},
451 {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},
452 {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},
453 {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},
454 {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},
455 {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},
456 {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},
457 {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},
458 {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},
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {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},
497 {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},
498 {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},
499 {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},
500 {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},
501 {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},
502 {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},
503 {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},
504 {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},
505 {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},
506 {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},
507 {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},
508 {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},
509 {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},
510 {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},
511 {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},
512 {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},
513 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
522 double epsilon = 0.001)
525 Vec3d normal = (p2-p0).cross(p1-p3);
527 const Vec3d centroid = (p0 + p1 + p2 + p3);
528 const double d = centroid.
dot(normal) * 0.25;
532 double absDist = std::abs(p0.dot(normal) - d);
533 if (absDist > epsilon)
return false;
535 absDist = std::abs(p1.dot(normal) - d);
536 if (absDist > epsilon)
return false;
538 absDist = std::abs(p2.dot(normal) - d);
539 if (absDist > epsilon)
return false;
541 absDist = std::abs(p3.dot(normal) - d);
542 if (absDist > epsilon)
return false;
562 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
563 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
578 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
580 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
592 template<
typename AccessorT>
594 evalCellSigns(
const AccessorT& accessor,
const Coord& ijk,
typename AccessorT::ValueType iso)
598 if (accessor.getValue(coord) < iso) signs |= 1u;
600 if (accessor.getValue(coord) < iso) signs |= 2u;
602 if (accessor.getValue(coord) < iso) signs |= 4u;
604 if (accessor.getValue(coord) < iso) signs |= 8u;
605 coord[1] += 1; coord[2] = ijk[2];
606 if (accessor.getValue(coord) < iso) signs |= 16u;
608 if (accessor.getValue(coord) < iso) signs |= 32u;
610 if (accessor.getValue(coord) < iso) signs |= 64u;
612 if (accessor.getValue(coord) < iso) signs |= 128u;
619 template<
typename LeafT>
623 unsigned char signs = 0;
626 if (leaf.getValue(offset) < iso) signs |= 1u;
629 if (leaf.getValue(offset + 1) < iso) signs |= 8u;
632 if (leaf.getValue(offset + LeafT::DIM) < iso) signs |= 16u;
635 if (leaf.getValue(offset + LeafT::DIM + 1) < iso) signs |= 128u;
638 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ) < iso) signs |= 2u;
641 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1) < iso) signs |= 4u;
644 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM) < iso) signs |= 32u;
647 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1) < iso) signs |= 64u;
655 template<
class AccessorT>
658 const AccessorT& acc, Coord ijk,
typename AccessorT::ValueType iso)
663 }
else if (face == 3) {
666 }
else if (face == 2) {
669 }
else if (face == 4) {
672 }
else if (face == 5) {
675 }
else if (face == 6) {
682 template<
class AccessorT>
685 typename AccessorT::ValueType isovalue,
const int dim)
691 p[0] = accessor.getValue(coord) < isovalue;
693 p[1] = accessor.getValue(coord) < isovalue;
695 p[2] = accessor.getValue(coord) < isovalue;
697 p[3] = accessor.getValue(coord) < isovalue;
698 coord[1] += dim; coord[2] = ijk[2];
699 p[4] = accessor.getValue(coord) < isovalue;
701 p[5] = accessor.getValue(coord) < isovalue;
703 p[6] = accessor.getValue(coord) < isovalue;
705 p[7] = accessor.getValue(coord) < isovalue;
709 if (p[0]) signs |= 1u;
710 if (p[1]) signs |= 2u;
711 if (p[2]) signs |= 4u;
712 if (p[3]) signs |= 8u;
713 if (p[4]) signs |= 16u;
714 if (p[5]) signs |= 32u;
715 if (p[6]) signs |= 64u;
716 if (p[7]) signs |= 128u;
722 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
723 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
724 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
727 coord.reset(ip, j, k);
728 m = accessor.getValue(coord) < isovalue;
729 if (p[0] != m && p[1] != m)
return true;
732 coord.reset(ipp, j, kp);
733 m = accessor.getValue(coord) < isovalue;
734 if (p[1] != m && p[2] != m)
return true;
737 coord.reset(ip, j, kpp);
738 m = accessor.getValue(coord) < isovalue;
739 if (p[2] != m && p[3] != m)
return true;
742 coord.reset(i, j, kp);
743 m = accessor.getValue(coord) < isovalue;
744 if (p[0] != m && p[3] != m)
return true;
747 coord.reset(ip, jpp, k);
748 m = accessor.getValue(coord) < isovalue;
749 if (p[4] != m && p[5] != m)
return true;
752 coord.reset(ipp, jpp, kp);
753 m = accessor.getValue(coord) < isovalue;
754 if (p[5] != m && p[6] != m)
return true;
757 coord.reset(ip, jpp, kpp);
758 m = accessor.getValue(coord) < isovalue;
759 if (p[6] != m && p[7] != m)
return true;
762 coord.reset(i, jpp, kp);
763 m = accessor.getValue(coord) < isovalue;
764 if (p[7] != m && p[4] != m)
return true;
767 coord.reset(i, jp, k);
768 m = accessor.getValue(coord) < isovalue;
769 if (p[0] != m && p[4] != m)
return true;
772 coord.reset(ipp, jp, k);
773 m = accessor.getValue(coord) < isovalue;
774 if (p[1] != m && p[5] != m)
return true;
777 coord.reset(ipp, jp, kpp);
778 m = accessor.getValue(coord) < isovalue;
779 if (p[2] != m && p[6] != m)
return true;
783 coord.reset(i, jp, kpp);
784 m = accessor.getValue(coord) < isovalue;
785 if (p[3] != m && p[7] != m)
return true;
791 coord.reset(ip, jp, k);
792 m = accessor.getValue(coord) < isovalue;
793 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
796 coord.reset(ipp, jp, kp);
797 m = accessor.getValue(coord) < isovalue;
798 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
801 coord.reset(ip, jp, kpp);
802 m = accessor.getValue(coord) < isovalue;
803 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
806 coord.reset(i, jp, kp);
807 m = accessor.getValue(coord) < isovalue;
808 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
811 coord.reset(ip, j, kp);
812 m = accessor.getValue(coord) < isovalue;
813 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
816 coord.reset(ip, jpp, kp);
817 m = accessor.getValue(coord) < isovalue;
818 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
821 coord.reset(ip, jp, kp);
822 m = accessor.getValue(coord) < isovalue;
823 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
824 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
833 template <
class LeafType>
835 mergeVoxels(LeafType& leaf,
const Coord& start,
int dim,
int regionId)
837 Coord ijk, end = start;
842 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
843 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
844 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
845 if(leaf.isValueOn(ijk)) leaf.setValue(ijk, regionId);
854 template <
class LeafType>
857 typename LeafType::ValueType::value_type adaptivity)
859 if (adaptivity < 1e-6)
return false;
861 typedef typename LeafType::ValueType VecT;
862 Coord ijk, end = start;
867 std::vector<VecT> norms;
868 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
869 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
870 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
872 if(!leaf.isValueOn(ijk))
continue;
873 norms.push_back(leaf.getValue(ijk));
878 size_t N = norms.size();
879 for (
size_t ni = 0; ni < N; ++ni) {
880 VecT n_i = norms[ni];
881 for (
size_t nj = 0; nj < N; ++nj) {
882 VecT n_j = norms[nj];
883 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
893 template<
typename TreeT,
typename LeafManagerT>
897 typedef typename TreeT::ValueType
ValueT;
900 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
903 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
909 SignData(
const TreeT& distTree,
const LeafManagerT& leafs,
ValueT iso);
911 void run(
bool threaded =
true);
913 typename Int16TreeT::Ptr
signTree()
const {
return mSignTree; }
914 typename IntTreeT::Ptr
idxTree()
const {
return mIdxTree; }
919 void operator()(
const tbb::blocked_range<size_t>&);
922 mSignTree->merge(*rhs.mSignTree);
923 mIdxTree->merge(*rhs.mIdxTree);
928 const TreeT& mDistTree;
931 const LeafManagerT& mLeafs;
934 typename Int16TreeT::Ptr mSignTree;
935 Int16AccessorT mSignAcc;
937 typename IntTreeT::Ptr mIdxTree;
938 IntAccessorT mIdxAcc;
943 template<
typename TreeT,
typename LeafManagerT>
945 const LeafManagerT& leafs,
ValueT iso)
946 : mDistTree(distTree)
947 , mDistAcc(mDistTree)
951 , mSignAcc(*mSignTree)
958 template<
typename TreeT,
typename LeafManagerT>
960 : mDistTree(rhs.mDistTree)
961 , mDistAcc(mDistTree)
963 , mIsovalue(rhs.mIsovalue)
965 , mSignAcc(*mSignTree)
972 template<
typename TreeT,
typename LeafManagerT>
976 if (threaded) tbb::parallel_reduce(mLeafs.getRange(), *
this);
977 else (*
this)(mLeafs.getRange());
980 template<
typename TreeT,
typename LeafManagerT>
984 typedef typename Int16TreeT::LeafNodeType Int16LeafT;
985 typedef typename IntTreeT::LeafNodeType IntLeafT;
986 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
987 unsigned char signs, face;
992 for (
size_t n = range.begin(); n != range.end(); ++n) {
994 bool collectedData =
false;
996 coord = mLeafs.leaf(n).origin();
998 if (!signLeafPt.get()) signLeafPt.reset(
new Int16LeafT(coord, 0));
999 else signLeafPt->setOrigin(coord);
1001 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
1003 coord.offset(TreeT::LeafNodeType::DIM - 1);
1005 for (iter = mLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
1007 ijk = iter.getCoord();
1009 if (leafPt && ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
1015 if (signs != 0 && signs != 0xFF) {
1018 if (
bool(signs & 0x1) != bool(signs & 0x2)) flags |=
XEDGE;
1019 if (
bool(signs & 0x1) != bool(signs & 0x10)) flags |=
YEDGE;
1020 if (
bool(signs & 0x1) != bool(signs & 0x8)) flags |=
ZEDGE;
1025 flags |=
Int16(signs);
1027 signLeafPt->setValue(ijk, flags);
1028 collectedData =
true;
1032 if (collectedData) {
1034 IntLeafT* idxLeaf = mIdxAcc.touchLeaf(coord);
1035 idxLeaf->topologyUnion(*signLeafPt);
1036 typename IntLeafT::ValueOnIter it = idxLeaf->beginValueOn();
1041 mSignAcc.addLeaf(signLeafPt.release());
1054 CountPoints(std::vector<size_t>& pointList) : mPointList(pointList) {}
1056 template <
typename LeafNodeType>
1061 typename LeafNodeType::ValueOnCIter iter = leaf.cbeginValueOn();
1062 for (; iter; ++iter) {
1066 mPointList[leafIndex] = points;
1070 std::vector<size_t>& mPointList;
1075 template<
typename Int16TreeT>
1081 MapPoints(std::vector<size_t>& pointList,
const Int16TreeT& signTree)
1082 : mPointList(pointList)
1083 , mSignAcc(signTree)
1087 template <
typename LeafNodeType>
1090 size_t ptnIdx = mPointList[leafIndex];
1091 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
1093 const typename Int16TreeT::LeafNodeType *signLeafPt =
1096 for (; iter; ++iter) {
1097 iter.setValue(ptnIdx);
1098 unsigned signs =
SIGNS & signLeafPt->getValue(iter.pos());
1104 std::vector<size_t>& mPointList;
1110 template<
typename IntTreeT>
1123 template <
typename LeafNodeType>
1131 typename IntLeafT::ValueOnIter iter = tmpLeaf.beginValueOn();
1132 for (; iter; ++iter) {
1133 if(iter.getValue() == 0) {
1139 int onVoxelCount = int(tmpLeaf.onVoxelCount());
1140 while (onVoxelCount > 0) {
1142 iter = tmpLeaf.beginValueOn();
1143 int regionId = iter.getValue();
1144 for (; iter; ++iter) {
1145 if (iter.getValue() == regionId) {
1152 mRegions[leafIndex] = regions;
1157 std::vector<size_t>& mRegions;
1165 inline double evalRoot(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1169 template<
typename LeafT>
1173 values[0] = double(leaf.getValue(offset));
1174 values[3] = double(leaf.getValue(offset + 1));
1175 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1176 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1177 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1178 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1179 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1180 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1185 template<
typename AccessorT>
1190 values[0] = double(acc.getValue(coord));
1193 values[1] = double(acc.getValue(coord));
1196 values[2] = double(acc.getValue(coord));
1199 values[3] = double(acc.getValue(coord));
1201 coord[1] += 1; coord[2] = ijk[2];
1202 values[4] = double(acc.getValue(coord));
1205 values[5] = double(acc.getValue(coord));
1208 values[6] = double(acc.getValue(coord));
1211 values[7] = double(acc.getValue(coord));
1218 unsigned char edgeGroup,
double iso)
1220 Vec3d avg(0.0, 0.0, 0.0);
1224 avg[0] +=
evalRoot(values[0], values[1], iso);
1230 avg[2] +=
evalRoot(values[1], values[2], iso);
1235 avg[0] +=
evalRoot(values[3], values[2], iso);
1241 avg[2] +=
evalRoot(values[0], values[3], iso);
1246 avg[0] +=
evalRoot(values[4], values[5], iso);
1254 avg[2] +=
evalRoot(values[5], values[6], iso);
1259 avg[0] +=
evalRoot(values[7], values[6], iso);
1267 avg[2] +=
evalRoot(values[4], values[7], iso);
1272 avg[1] +=
evalRoot(values[0], values[4], iso);
1278 avg[1] +=
evalRoot(values[1], values[5], iso);
1284 avg[1] +=
evalRoot(values[2], values[6], iso);
1290 avg[1] +=
evalRoot(values[3], values[7], iso);
1296 double w = 1.0 / double(samples);
1310 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1312 avg =
Vec3d(0.0, 0.0, 0.0);
1317 avg[0] +=
evalRoot(values[0], values[1], iso);
1324 avg[2] +=
evalRoot(values[1], values[2], iso);
1330 avg[0] +=
evalRoot(values[3], values[2], iso);
1337 avg[2] +=
evalRoot(values[0], values[3], iso);
1343 avg[0] +=
evalRoot(values[4], values[5], iso);
1352 avg[2] +=
evalRoot(values[5], values[6], iso);
1358 avg[0] +=
evalRoot(values[7], values[6], iso);
1367 avg[2] +=
evalRoot(values[4], values[7], iso);
1373 avg[1] +=
evalRoot(values[0], values[4], iso);
1380 avg[1] +=
evalRoot(values[1], values[5], iso);
1387 avg[1] +=
evalRoot(values[2], values[6], iso);
1394 avg[1] +=
evalRoot(values[3], values[7], iso);
1400 double w = 1.0 / double(samples);
1414 unsigned char signs,
unsigned char edgeGroup,
double iso)
1416 std::vector<Vec3d> samples;
1419 std::vector<double> weights;
1422 Vec3d avg(0.0, 0.0, 0.0);
1425 avg[0] =
evalRoot(values[0], values[1], iso);
1429 samples.push_back(avg);
1430 weights.push_back((avg-p).lengthSqr());
1436 avg[2] =
evalRoot(values[1], values[2], iso);
1438 samples.push_back(avg);
1439 weights.push_back((avg-p).lengthSqr());
1443 avg[0] =
evalRoot(values[3], values[2], iso);
1447 samples.push_back(avg);
1448 weights.push_back((avg-p).lengthSqr());
1454 avg[2] =
evalRoot(values[0], values[3], iso);
1456 samples.push_back(avg);
1457 weights.push_back((avg-p).lengthSqr());
1461 avg[0] =
evalRoot(values[4], values[5], iso);
1465 samples.push_back(avg);
1466 weights.push_back((avg-p).lengthSqr());
1472 avg[2] =
evalRoot(values[5], values[6], iso);
1474 samples.push_back(avg);
1475 weights.push_back((avg-p).lengthSqr());
1479 avg[0] =
evalRoot(values[7], values[6], iso);
1483 samples.push_back(avg);
1484 weights.push_back((avg-p).lengthSqr());
1490 avg[2] =
evalRoot(values[4], values[7], iso);
1492 samples.push_back(avg);
1493 weights.push_back((avg-p).lengthSqr());
1498 avg[1] =
evalRoot(values[0], values[4], iso);
1501 samples.push_back(avg);
1502 weights.push_back((avg-p).lengthSqr());
1507 avg[1] =
evalRoot(values[1], values[5], iso);
1510 samples.push_back(avg);
1511 weights.push_back((avg-p).lengthSqr());
1516 avg[1] =
evalRoot(values[2], values[6], iso);
1519 samples.push_back(avg);
1520 weights.push_back((avg-p).lengthSqr());
1525 avg[1] =
evalRoot(values[3], values[7], iso);
1528 samples.push_back(avg);
1529 weights.push_back((avg-p).lengthSqr());
1536 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1537 minWeight =
std::min(minWeight, weights[i]);
1538 maxWeight =
std::max(maxWeight, weights[i]);
1541 const double offset = maxWeight + minWeight * 0.1;
1542 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1543 weights[i] = offset - weights[i];
1547 double weightSum = 0.0;
1548 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1549 weightSum += weights[i];
1556 if (samples.size() > 1) {
1557 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1558 avg += samples[i] * (weights[i] / weightSum);
1561 avg = samples.front();
1572 const std::vector<double>& values,
unsigned char signs,
double iso)
1584 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1587 for (
size_t i = 1; i <= 12; ++i) {
1603 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1604 unsigned char lhsSigns,
unsigned char rhsSigns,
1605 double iso,
size_t pointIdx,
const boost::scoped_array<uint32_t>& seamPoints)
1607 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1613 const unsigned char e(
id);
1614 uint32_t& quantizedPoint = seamPoints[pointIdx + (
id - 1)];
1619 weightedPointMask.push_back(
true);
1621 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1622 weightedPointMask.push_back(
false);
1626 points.push_back(
computePoint(lhsValues, lhsSigns, n, iso));
1627 weightedPointMask.push_back(
false);
1633 template <
typename TreeT,
typename LeafManagerT>
1639 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1643 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1651 GenPoints(
const LeafManagerT& signLeafs,
const TreeT& distTree,
1655 void run(
bool threaded =
true);
1659 std::vector<unsigned char>* mSeamPointMaskPt = NULL);
1664 void operator()(
const tbb::blocked_range<size_t>&)
const;
1667 const LeafManagerT& mSignLeafs;
1673 std::vector<size_t>& mIndices;
1675 const double mIsovalue;
1679 const TreeT* mRefDistTreePt;
1682 std::vector<unsigned char>* mSeamPointMaskPt;
1686 template <
typename TreeT,
typename LeafManagerT>
1689 std::vector<size_t>& indices,
const math::Transform& xform,
double iso)
1690 : mSignLeafs(signLeafs)
1691 , mDistAcc(distTree)
1697 , mRefSignTreePt(NULL)
1698 , mRefDistTreePt(NULL)
1699 , mRefIdxTreePt(NULL)
1700 , mSeamPointsPt(NULL)
1701 , mSeamPointMaskPt(NULL)
1706 template <
typename TreeT,
typename LeafManagerT>
1710 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
1711 else (*
this)(mSignLeafs.getRange());
1715 template <
typename TreeT,
typename LeafManagerT>
1720 mRefSignTreePt = refSignTree;
1721 mRefDistTreePt = refDistTree;
1722 mRefIdxTreePt = refIdxTree;
1723 mSeamPointsPt = seamPoints;
1724 mSeamPointMaskPt = seamPointMask;
1728 template <
typename TreeT,
typename LeafManagerT>
1731 const tbb::blocked_range<size_t>& range)
const
1733 typename IntTreeT::LeafNodeType::ValueOnIter iter;
1734 unsigned char signs, refSigns;
1737 std::vector<Vec3d> points(4);
1738 std::vector<bool> weightedPointMask(4);
1739 std::vector<double> values(8), refValues(8);
1745 boost::scoped_ptr<Int16CAccessorT> refSignAcc;
1746 if (mRefSignTreePt) refSignAcc.reset(
new Int16CAccessorT(*mRefSignTreePt));
1748 boost::scoped_ptr<IntCAccessorT> refIdxAcc;
1749 if (mRefIdxTreePt) refIdxAcc.reset(
new IntCAccessorT(*mRefIdxTreePt));
1751 boost::scoped_ptr<AccessorT> refDistAcc;
1752 if (mRefDistTreePt) refDistAcc.reset(
new AccessorT(*mRefDistTreePt));
1755 for (
size_t n = range.begin(); n != range.end(); ++n) {
1757 coord = mSignLeafs.leaf(n).origin();
1759 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
1760 typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeLeaf(coord);
1764 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
1765 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(coord);
1767 const typename IntTreeT::LeafNodeType *refIdxLeafPt = NULL;
1768 if (refIdxAcc) refIdxLeafPt = refIdxAcc->probeConstLeaf(coord);
1770 const typename TreeT::LeafNodeType *refDistLeafPt = NULL;
1771 if (refDistAcc) refDistLeafPt = refDistAcc->probeConstLeaf(coord);
1775 size_t ptnIdx = mIndices[n];
1776 coord.offset(TreeT::LeafNodeType::DIM - 1);
1780 for (iter = idxLeafPt->beginValueOn(); iter; ++iter) {
1782 if(iter.getValue() != 0)
continue;
1784 iter.setValue(ptnIdx);
1786 offset = iter.pos();
1787 ijk = iter.getCoord();
1789 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1791 const Int16& flags = mSignLeafs.leaf(n).getValue(offset);
1792 signs =
SIGNS & flags;
1795 if ((flags &
SEAM) && refSignLeafPt && refIdxLeafPt) {
1796 if (refSignLeafPt->isValueOn(offset)) {
1797 refSigns = (
SIGNS & refSignLeafPt->getValue(offset));
1807 weightedPointMask.clear();
1809 if (refSigns == 0) {
1816 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1817 mIsovalue, refIdxLeafPt->getValue(offset), *mSeamPointsPt);
1821 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1824 points[i][0] += double(ijk[0]);
1825 points[i][1] += double(ijk[1]);
1826 points[i][2] += double(ijk[2]);
1829 points[i] = mTransform.indexToWorld(points[i]);
1831 mPoints[ptnIdx][0] = float(points[i][0]);
1832 mPoints[ptnIdx][1] = float(points[i][1]);
1833 mPoints[ptnIdx][2] = float(points[i][2]);
1835 if (mSeamPointMaskPt && !weightedPointMask.empty() && weightedPointMask[i]) {
1836 (*mSeamPointMaskPt)[ptnIdx] = 1;
1844 int onVoxelCount = int(idxLeafPt->onVoxelCount());
1845 while (onVoxelCount > 0) {
1847 iter = idxLeafPt->beginValueOn();
1848 int regionId = iter.getValue(), count = 0;
1850 Vec3d avg(0.0), point;
1852 for (; iter; ++iter) {
1853 if (iter.getValue() != regionId)
continue;
1855 iter.setValue(ptnIdx);
1859 ijk = iter.getCoord();
1860 offset = iter.pos();
1862 signs = (
SIGNS & mSignLeafs.leaf(n).getValue(offset));
1864 if (ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
1873 avg[0] += double(ijk[0]) + points[0][0];
1874 avg[1] += double(ijk[1]) + points[0][1];
1875 avg[2] += double(ijk[2]) + points[0][2];
1882 double w = 1.0 / double(count);
1888 avg = mTransform.indexToWorld(avg);
1890 mPoints[ptnIdx][0] = float(avg[0]);
1891 mPoints[ptnIdx][1] = float(avg[1]);
1892 mPoints[ptnIdx][2] = float(avg[2]);
1903 template<
typename TreeT>
1909 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1912 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1922 template <
typename LeafNodeType>
1923 void operator()(LeafNodeType &signLeaf,
size_t leafIndex)
const;
1931 const double mIsovalue;
1935 template<
typename TreeT>
1938 : mDistAcc(distTree)
1939 , mRefSignAcc(refSignTree)
1940 , mRefIdxAcc(refIdxTree)
1947 template<
typename TreeT>
1948 template <
typename LeafNodeType>
1952 Coord coord = signLeaf.origin();
1953 const typename Int16TreeT::LeafNodeType *refSignLeafPt = mRefSignAcc.probeConstLeaf(coord);
1955 if (!refSignLeafPt)
return;
1957 const typename TreeT::LeafNodeType *distLeafPt = mDistAcc.probeConstLeaf(coord);
1958 const typename IntTreeT::LeafNodeType *refIdxLeafPt = mRefIdxAcc.probeConstLeaf(coord);
1960 std::vector<double> values(8);
1961 unsigned char lhsSigns, rhsSigns;
1966 coord.offset(TreeT::LeafNodeType::DIM - 1);
1968 typename LeafNodeType::ValueOnCIter iter = signLeaf.cbeginValueOn();
1969 for (; iter; ++iter) {
1971 offset = iter.pos();
1972 ijk = iter.getCoord();
1974 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1976 if ((iter.getValue() &
SEAM) && refSignLeafPt->isValueOn(offset)) {
1978 lhsSigns =
SIGNS & iter.getValue();
1979 rhsSigns =
SIGNS & refSignLeafPt->getValue(offset);
1982 if (inclusiveCell) {
1989 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1995 uint32_t& data = mPoints[refIdxLeafPt->getValue(offset) + (
id - 1)];
2001 if (smaples > 0) data =
packPoint(point);
2016 template <
typename TreeT,
typename LeafManagerT>
2023 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
2026 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2028 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2031 typedef typename TreeT::template ValueConverter<float>::Type
FloatTreeT;
2040 void run(
bool threaded =
true);
2052 void operator()(
const tbb::blocked_range<size_t>&)
const;
2056 const LeafManagerT& mSignLeafs;
2061 const TreeT& mDistTree;
2065 ValueT mIsovalue, mSurfaceAdaptivity, mInternalAdaptivity;
2074 template <
typename TreeT,
typename LeafManagerT>
2076 const LeafManagerT& signLeafs,
const Int16TreeT& signTree,
2078 : mSignLeafs(signLeafs)
2079 , mSignTree(signTree)
2080 , mSignAcc(mSignTree)
2081 , mDistTree(distTree)
2082 , mDistAcc(mDistTree)
2085 , mSurfaceAdaptivity(adaptivity)
2086 , mInternalAdaptivity(adaptivity)
2088 , mAdaptivityGrid(NULL)
2090 , mRefSignTree(NULL)
2095 template <
typename TreeT,
typename LeafManagerT>
2099 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2100 else (*
this)(mSignLeafs.getRange());
2104 template <
typename TreeT,
typename LeafManagerT>
2109 mTransform = &distGridXForm;
2110 mAdaptivityGrid = &adaptivityField;
2114 template <
typename TreeT,
typename LeafManagerT>
2121 template <
typename TreeT,
typename LeafManagerT>
2125 mRefSignTree = signTree;
2126 mInternalAdaptivity = adaptivity;
2130 template <
typename TreeT,
typename LeafManagerT>
2136 typedef typename TreeT::LeafNodeType LeafT;
2137 typedef typename IntTreeT::LeafNodeType IntLeafT;
2138 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2139 typedef typename LeafT::template ValueConverter<Vec3T>::Type Vec3LeafT;
2141 const int LeafDim = LeafT::DIM;
2145 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2148 boost::scoped_ptr<FloatTreeCAccessorT> adaptivityAcc;
2149 if (mAdaptivityGrid) {
2150 adaptivityAcc.reset(
new FloatTreeCAccessorT(mAdaptivityGrid->tree()));
2154 boost::scoped_ptr<Int16TreeCAccessorT> refAcc;
2156 refAcc.reset(
new Int16TreeCAccessorT(*mRefSignTree));
2160 boost::scoped_ptr<BoolTreeCAccessorT> maskAcc;
2162 maskAcc.reset(
new BoolTreeCAccessorT(*mMask));
2167 Vec3LeafT gradientBuffer;
2168 Coord ijk, nijk, coord, end;
2170 for (
size_t n = range.begin(); n != range.end(); ++n) {
2172 const Coord& origin = mSignLeafs.leaf(n).origin();
2174 ValueT adaptivity = mSurfaceAdaptivity;
2176 if (refAcc && refAcc->probeConstLeaf(origin) == NULL) {
2177 adaptivity = mInternalAdaptivity;
2180 IntLeafT& idxLeaf = *idxAcc.
probeLeaf(origin);
2182 end[0] = origin[0] + LeafDim;
2183 end[1] = origin[1] + LeafDim;
2184 end[2] = origin[2] + LeafDim;
2186 mask.setValuesOff();
2190 const BoolLeafT* maskLeaf = maskAcc->probeConstLeaf(origin);
2191 if (maskLeaf != NULL) {
2192 typename BoolLeafT::ValueOnCIter it;
2193 for (it = maskLeaf->cbeginValueOn(); it; ++it) {
2194 ijk = it.getCoord();
2195 coord[0] = ijk[0] - (ijk[0] % 2);
2196 coord[1] = ijk[1] - (ijk[1] % 2);
2197 coord[2] = ijk[2] - (ijk[2] % 2);
2198 mask.setActiveState(coord,
true);
2204 LeafT adaptivityLeaf(origin, adaptivity);
2206 if (mAdaptivityGrid) {
2207 for (
Index offset = 0; offset < LeafT::NUM_VALUES; ++offset) {
2208 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2209 Vec3d xyz = mAdaptivityGrid->transform().worldToIndex(
2210 mTransform->indexToWorld(ijk));
2212 adaptivityLeaf.setValueOnly(offset, tmpA * adaptivity);
2217 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2218 ijk = iter.getCoord();
2219 coord[0] = ijk[0] - (ijk[0] % 2);
2220 coord[1] = ijk[1] - (ijk[1] % 2);
2221 coord[2] = ijk[2] - (ijk[2] % 2);
2222 if(mask.isValueOn(coord))
continue;
2226 int flags = int(iter.getValue());
2227 unsigned char signs =
SIGNS & flags;
2229 mask.setActiveState(coord,
true);
2233 for (
int i = 0; i < 26; ++i) {
2235 signs =
SIGNS & mSignAcc.getValue(nijk);
2237 mask.setActiveState(coord,
true);
2245 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2246 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2247 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2249 mask.setActiveState(ijk,
true);
2256 gradientBuffer.setValuesOff();
2257 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2259 ijk = iter.getCoord();
2260 coord[0] = ijk[0] - (ijk[0] % dim);
2261 coord[1] = ijk[1] - (ijk[1] % dim);
2262 coord[2] = ijk[2] - (ijk[2] % dim);
2263 if(mask.isValueOn(coord))
continue;
2267 ValueT length = norm.length();
2268 if (length >
ValueT(1.0e-7)) {
2269 norm *=
ValueT(1.0) / length;
2271 gradientBuffer.setValue(ijk, norm);
2274 int regionId = 1, next_dim = dim << 1;
2277 for (ijk[0] = 0; ijk[0] < LeafDim; ijk[0] += dim) {
2278 coord[0] = ijk[0] - (ijk[0] % next_dim);
2279 for (ijk[1] = 0; ijk[1] < LeafDim; ijk[1] += dim) {
2280 coord[1] = ijk[1] - (ijk[1] % next_dim);
2281 for (ijk[2] = 0; ijk[2] < LeafDim; ijk[2] += dim) {
2282 coord[2] = ijk[2] - (ijk[2] % next_dim);
2283 adaptivity = adaptivityLeaf.getValue(ijk);
2284 if (mask.isValueOn(ijk) || !
isMergable(gradientBuffer, ijk, dim, adaptivity)) {
2285 mask.setActiveState(coord,
true);
2295 for (dim = 4; dim < LeafDim; dim = dim << 1) {
2296 next_dim = dim << 1;
2297 coord[0] = ijk[0] - (ijk[0] % next_dim);
2298 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2299 coord[1] = ijk[1] - (ijk[1] % next_dim);
2300 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2301 coord[2] = ijk[2] - (ijk[2] % next_dim);
2302 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2303 adaptivity = adaptivityLeaf.getValue(ijk);
2304 if (mask.isValueOn(ijk) ||
isNonManifold(mDistAcc, ijk, mIsovalue, dim) ||
2305 !
isMergable(gradientBuffer, ijk, dim, adaptivity))
2307 mask.setActiveState(coord,
true);
2316 adaptivity = adaptivityLeaf.getValue(origin);
2317 if (!(mask.isValueOn(origin) ||
isNonManifold(mDistAcc, origin, mIsovalue, LeafDim))
2318 &&
isMergable(gradientBuffer, origin, LeafDim, adaptivity))
2320 mergeVoxels(idxLeaf, origin, LeafDim, regionId++);
2336 mPolygonPool = &quadPool;
2344 mPolygonPool->
quad(mIdx) = verts;
2374 mPolygonPool = &polygonPool;
2384 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2385 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2386 mPolygonPool->
quadFlags(mQuadIdx) = flags;
2387 addQuad(verts, reverse);
2389 verts[0] == verts[3] &&
2390 verts[1] != verts[2] &&
2391 verts[1] != verts[0] &&
2392 verts[2] != verts[0]) {
2394 addTriangle(verts[0], verts[1], verts[2], reverse);
2396 verts[1] == verts[2] &&
2397 verts[0] != verts[3] &&
2398 verts[0] != verts[1] &&
2399 verts[3] != verts[1]) {
2401 addTriangle(verts[0], verts[1], verts[3], reverse);
2403 verts[0] == verts[1] &&
2404 verts[2] != verts[3] &&
2405 verts[2] != verts[0] &&
2406 verts[3] != verts[0]) {
2408 addTriangle(verts[0], verts[2], verts[3], reverse);
2410 verts[2] == verts[3] &&
2411 verts[0] != verts[1] &&
2412 verts[0] != verts[2] &&
2413 verts[1] != verts[2]) {
2415 addTriangle(verts[0], verts[1], verts[2], reverse);
2422 mPolygonPool->
trimQuads(mQuadIdx,
true);
2428 void addQuad(
const Vec4I& verts,
bool reverse)
2431 mPolygonPool->
quad(mQuadIdx) = verts;
2433 Vec4I& quad = mPolygonPool->
quad(mQuadIdx);
2442 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2458 size_t mQuadIdx, mTriangleIdx;
2459 PolygonPool *mPolygonPool;
2463 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2466 const SignAccT& signAcc,
const IdxAccT& idxAcc, PrimBuilder& mesher,
Index32 pointListSize)
2468 const Index32 v0 = idxAcc.getValue(ijk);
2475 const bool isInside = flags &
INSIDE;
2482 if (flags &
XEDGE) {
2484 quad[0] = v0 + offsets[0];
2488 coord[1] = ijk[1] - 1;
2491 quad[1] = idxAcc.getValue(coord);
2492 cell =
SIGNS & signAcc.getValue(coord);
2495 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2501 quad[2] = idxAcc.getValue(coord);
2502 cell =
SIGNS & signAcc.getValue(coord);
2505 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2511 quad[3] = idxAcc.getValue(coord);
2512 cell =
SIGNS & signAcc.getValue(coord);
2515 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2520 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2525 if (flags &
YEDGE) {
2527 quad[0] = v0 + offsets[1];
2532 coord[2] = ijk[2] - 1;
2534 quad[1] = idxAcc.getValue(coord);
2535 cell =
SIGNS & signAcc.getValue(coord);
2538 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2544 quad[2] = idxAcc.getValue(coord);
2545 cell =
SIGNS & signAcc.getValue(coord);
2548 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2554 quad[3] = idxAcc.getValue(coord);
2555 cell =
SIGNS & signAcc.getValue(coord);
2558 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2563 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2567 if (flags &
ZEDGE) {
2569 quad[0] = v0 + offsets[2];
2573 coord[1] = ijk[1] - 1;
2576 quad[1] = idxAcc.getValue(coord);
2577 cell =
SIGNS & signAcc.getValue(coord);
2580 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2586 quad[2] = idxAcc.getValue(coord);
2587 cell =
SIGNS & signAcc.getValue(coord);
2590 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2596 quad[3] = idxAcc.getValue(coord);
2597 cell =
SIGNS & signAcc.getValue(coord);
2600 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2605 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2614 template<
typename LeafManagerT,
typename PrimBuilder>
2618 typedef typename LeafManagerT::TreeType::template ValueConverter<int>::Type
IntTreeT;
2619 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2630 void run(
bool threaded =
true);
2638 void operator()(
const tbb::blocked_range<size_t>&)
const;
2641 const LeafManagerT& mSignLeafs;
2651 template<
typename LeafManagerT,
typename PrimBuilder>
2655 : mSignLeafs(signLeafs)
2656 , mSignTree(signTree)
2658 , mPolygonPoolList(polygons)
2659 , mPointListSize(pointListSize)
2660 , mRefSignTree(NULL)
2664 template<
typename LeafManagerT,
typename PrimBuilder>
2668 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2669 else (*
this)(mSignLeafs.getRange());
2672 template<
typename LeafManagerT,
typename PrimBuilder>
2675 const tbb::blocked_range<size_t>& range)
const
2677 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2688 boost::scoped_ptr<Int16AccessorT> refSignAcc;
2689 if (mRefSignTree) refSignAcc.reset(
new Int16AccessorT(*mRefSignTree));
2692 for (
size_t n = range.begin(); n != range.end(); ++n) {
2694 origin = mSignLeafs.leaf(n).origin();
2698 iter = mSignLeafs.leaf(n).cbeginValueOn();
2699 for (; iter; ++iter) {
2700 if (iter.getValue() &
XEDGE) ++edgeCount;
2701 if (iter.getValue() &
YEDGE) ++edgeCount;
2702 if (iter.getValue() &
ZEDGE) ++edgeCount;
2705 if(edgeCount == 0)
continue;
2707 mesher.init(edgeCount, mPolygonPoolList[n]);
2709 const typename Int16TreeT::LeafNodeType *signleafPt = signAcc.
probeConstLeaf(origin);
2710 const typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeConstLeaf(origin);
2712 if (!signleafPt || !idxLeafPt)
continue;
2715 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
2716 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
2720 iter = mSignLeafs.leaf(n).cbeginValueOn();
2721 for (; iter; ++iter) {
2722 ijk = iter.getCoord();
2724 Int16 flags = iter.getValue();
2726 if (!(flags & 0xE00))
continue;
2729 if (refSignLeafPt) {
2730 refFlags = refSignLeafPt->getValue(iter.pos());
2737 const unsigned char cell = (
SIGNS & flags);
2745 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
2746 constructPolygons(flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher, mPointListSize);
2748 constructPolygons(flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher, mPointListSize);
2764 PartOp(
size_t leafCount,
size_t partitions,
size_t activePart)
2766 size_t leafSegments = leafCount / partitions;
2767 mStart = leafSegments * activePart;
2768 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2771 template <
typename LeafNodeType>
2774 if (leafIndex < mStart || leafIndex >= mEnd) leaf.setValuesOff();
2778 size_t mStart, mEnd;
2785 template<
typename SrcTreeT>
2790 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
2798 void run(
bool threaded =
true);
2806 void operator()(
const tbb::blocked_range<size_t>&);
2812 size_t mStart, mEnd;
2815 template<
typename SrcTreeT>
2817 : mLeafManager(leafs)
2823 size_t leafSegments = leafCount / partitions;
2824 mStart = leafSegments * activePart;
2825 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2828 template<
typename SrcTreeT>
2830 : mLeafManager(rhs.mLeafManager)
2832 , mStart(rhs.mStart)
2838 template<
typename SrcTreeT>
2842 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2843 else (*
this)(mLeafManager.getRange());
2847 template<
typename SrcTreeT>
2854 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2855 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
2857 for (
size_t n = range.begin(); n != range.end(); ++n) {
2858 if (n < mStart || n >= mEnd)
continue;
2859 BoolLeafT* leaf = acc.
touchLeaf(mLeafManager.leaf(n).origin());
2860 leaf->topologyUnion(mLeafManager.leaf(n));
2868 template<
typename TreeT,
typename LeafManagerT>
2872 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2876 GenSeamMask(
const LeafManagerT& leafs,
const TreeT& tree);
2878 void run(
bool threaded =
true);
2885 void operator()(
const tbb::blocked_range<size_t>&);
2890 const LeafManagerT& mLeafManager;
2897 template<
typename TreeT,
typename LeafManagerT>
2899 : mLeafManager(leafs)
2906 template<
typename TreeT,
typename LeafManagerT>
2908 : mLeafManager(rhs.mLeafManager)
2915 template<
typename TreeT,
typename LeafManagerT>
2919 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2920 else (*
this)(mLeafManager.getRange());
2924 template<
typename TreeT,
typename LeafManagerT>
2932 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter it;
2934 for (
size_t n = range.begin(); n != range.end(); ++n) {
2936 it = mLeafManager.leaf(n).cbeginValueOn();
2940 ijk = it.getCoord();
2945 unsigned char lhsSigns = it.getValue() &
SIGNS;
2946 if (rhsSigns != lhsSigns) {
2958 template<
typename TreeT>
2966 template <
typename LeafNodeType>
2969 const typename TreeT::LeafNodeType *maskLeaf =
2972 if (!maskLeaf)
return;
2974 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
2978 if (maskLeaf->isValueOn(it.pos())) {
2979 it.setValue(it.getValue() |
SEAM);
2990 template<
typename BoolTreeT>
2995 MaskEdges(
const BoolTreeT& valueMask) : mMaskAcc(valueMask) {}
2997 template <
typename LeafNodeType>
3000 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
3002 const typename BoolTreeT::LeafNodeType * maskLeaf =
3007 if (!maskLeaf->isValueOn(it.pos())) {
3008 it.setValue(0x1FF & it.getValue());
3013 it.setValue(0x1FF & it.getValue());
3029 std::vector<unsigned char>& usedPointMask)
3030 : mPolygons(polygons)
3031 , mPolyListCount(polyListCount)
3032 , mUsedPointMask(usedPointMask)
3036 void run(
bool threaded =
true)
3039 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
3041 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3051 for (
size_t n = range.begin(); n != range.end(); ++n) {
3053 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3055 mUsedPointMask[quad[0]] = 1;
3056 mUsedPointMask[quad[1]] = 1;
3057 mUsedPointMask[quad[2]] = 1;
3058 mUsedPointMask[quad[3]] = 1;
3063 mUsedPointMask[triangle[0]] = 1;
3064 mUsedPointMask[triangle[1]] = 1;
3065 mUsedPointMask[triangle[2]] = 1;
3073 size_t mPolyListCount;
3074 std::vector<unsigned char>& mUsedPointMask;
3083 size_t polyListCount,
const std::vector<unsigned>& indexMap)
3084 : mPolygons(polygons)
3085 , mPolyListCount(polyListCount)
3086 , mIndexMap(indexMap)
3090 void run(
bool threaded =
true)
3093 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
3095 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3103 for (
size_t n = range.begin(); n != range.end(); ++n) {
3105 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3107 quad[0] = mIndexMap[quad[0]];
3108 quad[1] = mIndexMap[quad[1]];
3109 quad[2] = mIndexMap[quad[2]];
3110 quad[3] = mIndexMap[quad[3]];
3115 triangle[0] = mIndexMap[triangle[0]];
3116 triangle[1] = mIndexMap[triangle[1]];
3117 triangle[2] = mIndexMap[triangle[2]];
3125 size_t mPolyListCount;
3126 const std::vector<unsigned>& mIndexMap;
3138 const std::vector<unsigned>& indexMap,
3139 const std::vector<unsigned char>& usedPointMask)
3140 : mNewPointList(newPointList)
3141 , mOldPointList(oldPointList)
3142 , mIndexMap(indexMap)
3143 , mUsedPointMask(usedPointMask)
3147 void run(
bool threaded =
true)
3150 tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexMap.size()), *
this);
3152 (*this)(tbb::blocked_range<size_t>(0, mIndexMap.size()));
3160 for (
size_t n = range.begin(); n != range.end(); ++n) {
3161 if (mUsedPointMask[n]) {
3162 const size_t index = mIndexMap[n];
3163 mNewPointList.get()[index] = mOldPointList[n];
3171 const std::vector<unsigned>& mIndexMap;
3172 const std::vector<unsigned char>& mUsedPointMask;
3179 template<
typename SrcTreeT>
3184 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3196 void run(
bool threaded =
true);
3205 void operator()(
const tbb::blocked_range<size_t>&);
3219 template<
typename SrcTreeT>
3223 , mLeafManager(srcLeafs)
3224 , mSrcXForm(srcXForm)
3225 , mInvertMask(invertMask)
3231 template<
typename SrcTreeT>
3234 , mLeafManager(rhs.mLeafManager)
3235 , mSrcXForm(rhs.mSrcXForm)
3236 , mInvertMask(rhs.mInvertMask)
3242 template<
typename SrcTreeT>
3247 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3249 (*this)(mLeafManager.getRange());
3254 template<
typename SrcTreeT>
3260 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
3265 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3266 for (
size_t n = range.begin(); n != range.end(); ++n) {
3268 ijk = mLeafManager.leaf(n).origin();
3269 BoolLeafT* leaf =
new BoolLeafT(ijk,
false);
3270 bool addLeaf =
false;
3272 if (maskXForm == mSrcXForm) {
3274 const BoolLeafT* maskLeaf = maskAcc.probeConstLeaf(ijk);
3278 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3279 Index pos = iter.pos();
3280 if(maskLeaf->isValueOn(pos) != mInvertMask) {
3281 leaf->setValueOn(pos);
3286 }
else if (maskAcc.isValueOn(ijk) != mInvertMask) {
3287 leaf->topologyUnion(mLeafManager.leaf(n));
3292 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3293 ijk = iter.getCoord();
3294 xyz = maskXForm.
worldToIndex(mSrcXForm.indexToWorld(ijk));
3296 leaf->setValueOn(iter.pos());
3302 if (addLeaf) acc.
addLeaf(leaf);
3311 template<
typename SrcTreeT>
3315 typedef typename SrcTreeT::template ValueConverter<int>::Type
IntTreeT;
3316 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3323 void run(
bool threaded =
true);
3330 void operator()(
const tbb::blocked_range<size_t>&);
3337 bool neighboringLeaf(
const Coord&,
const IntTreeAccessorT&)
const;
3343 CoordBBox mLeafBBox;
3347 template<
typename SrcTreeT>
3350 : mLeafManager(leafs)
3351 , mMaskTree(maskTree)
3355 mIdxTree.evalLeafBoundingBox(mLeafBBox);
3356 mLeafBBox.expand(IntTreeT::LeafNodeType::DIM);
3360 template<
typename SrcTreeT>
3362 : mLeafManager(rhs.mLeafManager)
3363 , mMaskTree(rhs.mMaskTree)
3364 , mIdxTree(rhs.mIdxTree)
3366 , mLeafBBox(rhs.mLeafBBox)
3371 template<
typename SrcTreeT>
3376 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3378 (*this)(mLeafManager.getRange());
3383 template<
typename SrcTreeT>
3387 if (acc.probeConstLeaf(ijk))
return true;
3389 const int dim = IntTreeT::LeafNodeType::DIM;
3392 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2])))
return true;
3393 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2])))
return true;
3394 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2])))
return true;
3395 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2])))
return true;
3396 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] + dim)))
return true;
3397 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] - dim)))
return true;
3400 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] - dim)))
return true;
3401 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] - dim)))
return true;
3402 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] + dim)))
return true;
3403 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] + dim)))
return true;
3404 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2])))
return true;
3405 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2])))
return true;
3406 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2])))
return true;
3407 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2])))
return true;
3408 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] + dim)))
return true;
3409 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] - dim)))
return true;
3410 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] + dim)))
return true;
3411 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] - dim)))
return true;
3414 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3415 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3416 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3417 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3418 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3419 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3420 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3421 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3427 template<
typename SrcTreeT>
3436 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3438 for (
size_t n = range.begin(); n != range.end(); ++n) {
3440 const typename SrcTreeT::LeafNodeType&
3441 leaf = mLeafManager.leaf(n);
3443 ijk = leaf.origin();
3445 if (!mLeafBBox.isInside(ijk) || !neighboringLeaf(ijk, idxAcc))
continue;
3447 const typename BoolTreeT::LeafNodeType*
3450 if (!maskLeaf || !leaf.hasSameTopology(maskLeaf)) {
3451 acc.
touchLeaf(ijk)->topologyUnion(leaf);
3460 template<
typename TreeT>
3464 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
3470 GenTileMask(
const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso);
3472 void run(
bool threaded =
true);
3479 void operator()(
const tbb::blocked_range<size_t>&);
3484 const std::vector<Vec4i>& mTiles;
3485 const TreeT& mDistTree;
3492 template<
typename TreeT>
3494 const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso)
3496 , mDistTree(distTree)
3503 template<
typename TreeT>
3505 : mTiles(rhs.mTiles)
3506 , mDistTree(rhs.mDistTree)
3507 , mIsovalue(rhs.mIsovalue)
3513 template<
typename TreeT>
3517 if (threaded) tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mTiles.size()), *
this);
3518 else (*
this)(tbb::blocked_range<size_t>(0, mTiles.size()));
3522 template<
typename TreeT>
3527 CoordBBox region, bbox;
3529 bool processRegion =
true;
3533 for (
size_t n = range.begin(); n != range.end(); ++n) {
3535 const Vec4i& tile = mTiles[n];
3537 bbox.min()[0] = tile[0];
3538 bbox.min()[1] = tile[1];
3539 bbox.min()[2] = tile[2];
3541 bbox.max() = bbox.min();
3542 bbox.max().offset(tile[3]);
3544 const bool thisInside = (distAcc.
getValue(bbox.min()) < mIsovalue);
3553 processRegion =
true;
3555 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3559 if (processRegion) {
3561 region.min()[0] = region.max()[0] = ijk[0];
3562 mTree.fill(region,
true);
3569 processRegion =
true;
3571 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3574 if (processRegion) {
3576 region.min()[0] = region.max()[0] = ijk[0];
3577 mTree.fill(region,
true);
3587 processRegion =
true;
3589 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3592 if (processRegion) {
3594 region.min()[1] = region.max()[1] = ijk[1];
3595 mTree.fill(region,
true);
3602 processRegion =
true;
3604 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3607 if (processRegion) {
3609 region.min()[1] = region.max()[1] = ijk[1];
3610 mTree.fill(region,
true);
3620 processRegion =
true;
3622 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3625 if (processRegion) {
3627 region.min()[2] = region.max()[2] = ijk[2];
3628 mTree.fill(region,
true);
3634 processRegion =
true;
3636 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3639 if (processRegion) {
3641 region.min()[2] = region.max()[2] = ijk[2];
3642 mTree.fill(region,
true);
3650 processRegion =
true;
3652 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3655 if (processRegion) {
3657 region.min()[1] = region.max()[1] = ijk[1];
3658 region.min()[2] = region.max()[2] = ijk[2];
3659 mTree.fill(region,
true);
3667 processRegion =
true;
3669 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3672 if (processRegion) {
3674 region.min()[1] = region.max()[1] = ijk[1];
3675 region.min()[0] = region.max()[0] = ijk[0];
3676 mTree.fill(region,
true);
3683 processRegion =
true;
3685 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3688 if (processRegion) {
3690 region.min()[2] = region.max()[2] = ijk[2];
3691 region.min()[0] = region.max()[0] = ijk[0];
3692 mTree.fill(region,
true);
3701 template<
class DistTreeT,
class SignTreeT,
class IdxTreeT>
3703 tileData(
const DistTreeT& distTree, SignTreeT& signTree, IdxTreeT& idxTree,
double iso)
3705 typename DistTreeT::ValueOnCIter tileIter(distTree);
3706 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3708 if (!tileIter)
return;
3710 size_t tileCount = 0;
3711 for ( ; tileIter; ++tileIter) {
3715 std::vector<Vec4i> tiles(tileCount);
3718 tileIter = distTree.cbeginValueOn();
3719 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3722 for (; tileIter; ++tileIter) {
3723 Vec4i& tile = tiles[tileCount++];
3724 tileIter.getBoundingBox(bbox);
3725 tile[0] = bbox.min()[0];
3726 tile[1] = bbox.min()[1];
3727 tile[2] = bbox.min()[2];
3728 tile[3] = bbox.max()[0] - bbox.min()[0];
3731 typename DistTreeT::ValueType isovalue =
typename DistTreeT::ValueType(iso);
3736 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
3739 BoolLeafManagerT leafs(tileMask.
tree());
3745 signTree.merge(*op.signTree());
3746 idxTree.merge(*op.idxTree());
3758 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
3764 for (
size_t n = range.begin(); n < range.end(); ++n) {
3765 mPointsOut[n] = mPointsIn[n];
3771 std::vector<Vec3s>& mPointsOut;
3776 template <
typename LeafManagerT>
3780 double interiorWidth = 0.0, exteriorWidth = 0.0;
3782 typename LeafManagerT::TreeType::LeafNodeType::ValueOffCIter it;
3783 bool foundInterior =
false, foundExterior =
false;
3784 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
3786 for (it = leafs.leaf(n).cbeginValueOff(); it; ++it) {
3787 double value = double(it.getValue());
3789 interiorWidth = value;
3790 foundInterior =
true;
3791 }
else if (value > 0.0) {
3792 exteriorWidth = value;
3793 foundExterior =
true;
3796 if (foundInterior && foundExterior)
break;
3799 if (foundInterior && foundExterior)
break;
3804 double minDist =
std::min(std::abs(interiorWidth - iso), std::abs(exteriorWidth - iso));
3805 return !(minDist > (2.0 * voxelSize));
3822 , mTriangleFlags(NULL)
3829 : mNumQuads(numQuads)
3830 , mNumTriangles(numTriangles)
3831 , mQuads(new openvdb::
Vec4I[mNumQuads])
3832 , mTriangles(new openvdb::
Vec3I[mNumTriangles])
3833 , mQuadFlags(new char[mNumQuads])
3834 , mTriangleFlags(new char[mNumTriangles])
3845 for (
size_t i = 0; i < mNumQuads; ++i) {
3846 mQuads[i] = rhs.mQuads[i];
3847 mQuadFlags[i] = rhs.mQuadFlags[i];
3850 for (
size_t i = 0; i < mNumTriangles; ++i) {
3851 mTriangles[i] = rhs.mTriangles[i];
3852 mTriangleFlags[i] = rhs.mTriangleFlags[i];
3862 mQuadFlags.reset(
new char[mNumQuads]);
3871 mQuadFlags.reset(NULL);
3878 mNumTriangles = size;
3880 mTriangleFlags.reset(
new char[mNumTriangles]);
3888 mTriangles.reset(NULL);
3889 mTriangleFlags.reset(NULL);
3896 if (!(n < mNumQuads))
return false;
3904 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
3905 boost::scoped_array<char> flags(
new char[n]);
3907 for (
size_t i = 0; i < n; ++i) {
3908 quads[i] = mQuads[i];
3909 flags[i] = mQuadFlags[i];
3913 mQuadFlags.swap(flags);
3925 if (!(n < mNumTriangles))
return false;
3930 mTriangles.reset(NULL);
3933 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
3934 boost::scoped_array<char> flags(
new char[n]);
3936 for (
size_t i = 0; i < n; ++i) {
3937 triangles[i] = mTriangles[i];
3938 flags[i] = mTriangleFlags[i];
3941 mTriangles.swap(triangles);
3942 mTriangleFlags.swap(flags);
3958 , mSeamPointListSize(0)
3959 , mPolygonPoolListSize(0)
3960 , mIsovalue(isovalue)
3961 , mPrimAdaptivity(adaptivity)
3962 , mSecAdaptivity(0.0)
3964 , mSurfaceMaskGrid(
GridBase::ConstPtr())
3965 , mAdaptivityGrid(
GridBase::ConstPtr())
3966 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
3969 , mInvertSurfaceMask(false)
3972 , mQuantizedSeamPoints(NULL)
3985 inline const size_t&
3988 return mPointListSize;
4006 inline const size_t&
4009 return mPolygonPoolListSize;
4017 mSecAdaptivity = secAdaptivity;
4022 mSeamPointListSize = 0;
4023 mQuantizedSeamPoints.reset(NULL);
4030 mSurfaceMaskGrid = mask;
4031 mInvertSurfaceMask = invertMask;
4038 mAdaptivityGrid = grid;
4045 mAdaptivityMaskTree = tree;
4052 mPartitions =
std::max(partitions,
unsigned(1));
4053 mActivePart =
std::min(activePart, mPartitions-1);
4057 inline std::vector<unsigned char>&
4064 inline const std::vector<unsigned char>&
4071 template<
typename Gr
idT>
4075 typedef typename GridT::TreeType DistTreeT;
4077 typedef typename DistTreeT::ValueType DistValueT;
4079 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
4083 typedef typename DistTreeT::template ValueConverter<Int16>::Type Int16TreeT;
4086 typedef typename DistTreeT::template ValueConverter<int>::Type IntTreeT;
4087 typedef typename DistTreeT::template ValueConverter<float>::Type FloatTreeT;
4091 const openvdb::math::Transform& transform = distGrid.
transform();
4092 const DistTreeT& distTree = distGrid.tree();
4093 const DistValueT isovalue = DistValueT(mIsovalue);
4095 typename Int16TreeT::Ptr signTreePt;
4096 typename IntTreeT::Ptr idxTreePt;
4097 typename BoolTreeT::Ptr pointMask;
4099 BoolTreeT valueMask(
false), seamMask(
false);
4100 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4101 bool maskEdges =
false;
4104 const BoolGridT * surfaceMask = NULL;
4105 if (mSurfaceMaskGrid && mSurfaceMaskGrid->type() == BoolGridT::gridType()) {
4106 surfaceMask =
static_cast<const BoolGridT*
>(mSurfaceMaskGrid.get());
4109 const FloatGridT * adaptivityField = NULL;
4110 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridT::gridType()) {
4111 adaptivityField =
static_cast<const FloatGridT*
>(mAdaptivityGrid.get());
4114 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeT::treeType()) {
4115 const BoolTreeT *adaptivityMaskPt =
4116 static_cast<const BoolTreeT*
>(mAdaptivityMaskTree.get());
4117 seamMask.topologyUnion(*adaptivityMaskPt);
4123 DistLeafManagerT distLeafs(distTree);
4126 bool padActiveVoxels =
false;
4130 padActiveVoxels =
true;
4133 mIsovalue, transform.voxelSize()[0]);
4137 if (!padActiveVoxels) {
4139 distTree.evalActiveVoxelDim(dim);
4141 if (maxDim < 1000) {
4142 padActiveVoxels =
true;
4147 if (surfaceMask || mPartitions > 1) {
4155 *surfaceMask, distLeafs, transform, mInvertSurfaceMask);
4157 valueMask.merge(masking.
tree());
4160 if (mPartitions > 1) {
4163 valueMask.pruneInactive();
4170 valueMask.merge(partitioner.
tree());
4175 BoolLeafManagerT leafs(valueMask);
4178 signDataOp(distTree, leafs, isovalue);
4181 signTreePt = signDataOp.
signTree();
4182 idxTreePt = signDataOp.
idxTree();
4189 BoolLeafManagerT bleafs(boundary.
tree());
4192 signDataOp(distTree, bleafs, isovalue);
4195 signTreePt->merge(*signDataOp.signTree());
4196 idxTreePt->merge(*signDataOp.idxTree());
4202 if (padActiveVoxels) {
4204 BoolTreeT regionMask(
false);
4205 regionMask.topologyUnion(distTree);
4208 BoolLeafManagerT leafs(regionMask);
4211 signDataOp(distTree, leafs, isovalue);
4214 signTreePt = signDataOp.
signTree();
4215 idxTreePt = signDataOp.
idxTree();
4219 signDataOp(distTree, distLeafs, isovalue);
4222 signTreePt = signDataOp.
signTree();
4223 idxTreePt = signDataOp.
idxTree();
4234 Int16TreeT *refSignTreePt = NULL;
4235 IntTreeT *refIdxTreePt = NULL;
4236 const DistTreeT *refDistTreePt = NULL;
4238 if (mRefGrid && mRefGrid->type() == GridT::gridType()) {
4240 const GridT* refGrid =
static_cast<const GridT*
>(mRefGrid.get());
4241 refDistTreePt = &refGrid->tree();
4244 if (!mRefSignTree && !mRefIdxTree) {
4246 DistLeafManagerT refDistLeafs(*refDistTreePt);
4248 signDataOp(*refDistTreePt, refDistLeafs, isovalue);
4252 mRefSignTree = signDataOp.
signTree();
4253 mRefIdxTree = signDataOp.
idxTree();
4257 if (mRefSignTree && mRefIdxTree) {
4258 refSignTreePt =
static_cast<Int16TreeT*
>(mRefSignTree.get());
4259 refIdxTreePt =
static_cast<IntTreeT*
>(mRefIdxTree.get());
4265 Int16LeafManagerT signLeafs(*signTreePt);
4274 if (refSignTreePt) {
4281 seamMask.merge(seamOp.
mask());
4285 std::vector<size_t> regions(signLeafs.leafCount(), 0);
4286 if (regions.empty())
return;
4291 signLeafs, *signTreePt, distTree, *idxTreePt, isovalue, DistValueT(mPrimAdaptivity));
4293 if (adaptivityField) {
4297 if (refSignTreePt || mAdaptivityMaskTree) {
4301 if (refSignTreePt) {
4302 merge.
setRefData(refSignTreePt, DistValueT(mSecAdaptivity));
4317 for (
size_t n = 0, N = regions.size(); n < N; ++n) {
4319 regions[n] = mPointListSize;
4320 mPointListSize += tmp;
4327 mPointFlags.clear();
4330 if (refSignTreePt && refIdxTreePt) {
4332 if (mSeamPointListSize == 0) {
4334 std::vector<size_t> pointMap;
4337 Int16LeafManagerT refSignLeafs(*refSignTreePt);
4338 pointMap.resize(refSignLeafs.leafCount(), 0);
4343 for (
size_t n = 0, N = pointMap.size(); n < N; ++n) {
4345 pointMap[n] = mSeamPointListSize;
4346 mSeamPointListSize += tmp;
4350 if (!pointMap.empty() && mSeamPointListSize != 0) {
4352 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
4353 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
4357 IntLeafManagerT refIdxLeafs(*refIdxTreePt);
4362 if (mSeamPointListSize != 0) {
4364 distTree, *refSignTreePt, *refIdxTreePt, mQuantizedSeamPoints, mIsovalue));
4370 pointOp(signLeafs, distTree, *idxTreePt, mPoints, regions, transform, mIsovalue);
4373 if (mSeamPointListSize != 0) {
4374 mPointFlags.resize(mPointListSize);
4375 pointOp.
setRefData(refSignTreePt, refDistTreePt, refIdxTreePt,
4376 &mQuantizedSeamPoints, &mPointFlags);
4382 mPolygonPoolListSize = signLeafs.leafCount();
4383 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
4389 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4397 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4405 if ((surfaceMask || mPartitions > 1) && mPointListSize > 0) {
4408 std::vector<unsigned char> usedPointMask(mPointListSize, 0);
4414 std::vector<unsigned> indexMap(mPointListSize);
4415 size_t usedPointCount = 0;
4416 for (
size_t p = 0; p < mPointListSize; ++p) {
4417 if (usedPointMask[p]) indexMap[p] = usedPointCount++;
4420 if (usedPointCount < mPointListSize) {
4429 mPointListSize = usedPointCount;
4430 mPoints.reset(newPointList.release());
4441 if (refSignTreePt || refIdxTreePt || refDistTreePt) {
4442 std::vector<Vec3s> newPoints;
4444 for (
size_t n = 0; n < mPolygonPoolListSize; ++n) {
4448 std::vector<size_t> nonPlanarQuads;
4449 nonPlanarQuads.reserve(polygons.
numQuads());
4451 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4459 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4460 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4462 if (!edgePoly)
continue;
4464 const Vec3s& p0 = mPoints[quad[0]];
4465 const Vec3s& p1 = mPoints[quad[1]];
4466 const Vec3s& p2 = mPoints[quad[2]];
4467 const Vec3s& p3 = mPoints[quad[3]];
4470 nonPlanarQuads.push_back(i);
4476 if (!nonPlanarQuads.empty()) {
4483 size_t triangleIdx = 0;
4484 for (
size_t i = 0; i < nonPlanarQuads.size(); ++i) {
4486 size_t& quadIdx = nonPlanarQuads[i];
4489 char& quadFlags = polygons.
quadFlags(quadIdx);
4492 Vec3s centroid = (mPoints[quad[0]] + mPoints[quad[1]] +
4493 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25;
4495 size_t pointIdx = newPoints.size() + mPointListSize;
4497 newPoints.push_back(centroid);
4503 triangle[0] = quad[0];
4504 triangle[1] = pointIdx;
4505 triangle[2] = quad[3];
4509 if (mPointFlags[triangle[0]] || mPointFlags[triangle[2]]) {
4519 triangle[0] = quad[0];
4520 triangle[1] = quad[1];
4521 triangle[2] = pointIdx;
4525 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4535 triangle[0] = quad[1];
4536 triangle[1] = quad[2];
4537 triangle[2] = pointIdx;
4541 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4552 triangle[0] = quad[2];
4553 triangle[1] = quad[3];
4554 triangle[2] = pointIdx;
4558 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4577 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4581 tmpPolygons.
quad(quadIdx) = quad;
4588 polygons.
copy(tmpPolygons);
4594 if (!newPoints.empty()) {
4596 size_t newPointCount = newPoints.size() + mPointListSize;
4601 for (
size_t i = 0; i < mPointListSize; ++i) {
4602 newPointList.get()[i] = mPoints[i];
4605 for (
size_t i = mPointListSize; i < newPointCount; ++i) {
4606 newPointList.get()[i] = newPoints[i - mPointListSize];
4609 mPointListSize = newPointCount;
4610 mPoints.reset(newPointList.release());
4611 mPointFlags.resize(mPointListSize, 0);
4620 template<
typename Gr
idType>
4623 const GridType& grid,
4624 std::vector<Vec3s>& points,
4625 std::vector<Vec3I>& triangles,
4626 std::vector<Vec4I>& quads,
4639 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
4646 size_t numQuads = 0, numTriangles = 0;
4648 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4649 numTriangles += polygons.numTriangles();
4650 numQuads += polygons.numQuads();
4654 triangles.resize(numTriangles);
4656 quads.resize(numQuads);
4660 size_t qIdx = 0, tIdx = 0;
4662 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4664 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
4665 quads[qIdx++] = polygons.quad(i);
4668 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
4669 triangles[tIdx++] = polygons.triangle(i);
4675 template<
typename Gr
idType>
4678 const GridType& grid,
4679 std::vector<Vec3s>& points,
4680 std::vector<Vec4I>& quads,
4683 std::vector<Vec3I> triangles(0);
4684 volumeToMesh(grid,points, triangles, quads, isovalue, 0.0);
4695 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
int16_t Int16
Definition: Types.h:58
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:328
boost::shared_ptr< const TreeBase > ConstPtr
Definition: Tree.h:68
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:321
T & z()
Definition: Vec3.h:96
Index32 Index
Definition: Types.h:57
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:378
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:344
OPENVDB_API const Index32 INVALID_IDX
Mat3< double > Mat3d
Definition: Mat3.h:666
Vec4< int32_t > Vec4i
Definition: Vec4.h:543
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:455
Abstract base class for typed grids.
Definition: Grid.h:103
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
#define OPENVDB_VERSION_NAME
Definition: version.h:45
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
boost::shared_ptr< const GridBase > ConstPtr
Definition: Grid.h:107
Gradient operators defined in index space of various orders.
Definition: Operators.h:122
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: util/Util.h:55
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:383
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:295
Base class for typed trees.
Definition: Tree.h:64
boost::shared_ptr< TreeBase > Ptr
Definition: Tree.h:67
uint32_t Index32
Definition: Types.h:55
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:463
Vec3< double > Vec3d
Definition: Vec3.h:625
Vec3< float > Vec3s
Definition: Vec3.h:624
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:757
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:229
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
void setValueOn(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:246
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:347