31 #ifndef OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
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;
392 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,
393 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,
394 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,
395 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,
396 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,
397 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,
398 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,
399 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};
404 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,
405 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,
406 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,
407 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,
408 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,
409 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,
410 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,
411 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};
418 {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},
419 {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},
420 {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},
421 {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},
422 {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},
423 {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},
424 {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},
425 {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},
426 {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},
427 {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},
428 {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},
429 {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},
430 {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},
431 {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},
432 {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},
433 {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},
434 {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},
435 {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},
436 {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},
437 {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},
438 {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},
439 {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},
440 {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},
441 {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},
442 {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},
443 {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},
444 {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},
445 {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},
446 {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},
447 {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},
448 {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},
449 {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},
450 {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},
451 {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},
452 {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},
453 {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},
454 {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},
455 {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},
456 {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},
457 {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},
458 {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},
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {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},
497 {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},
498 {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},
499 {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},
500 {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},
501 {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},
502 {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},
503 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
512 double epsilon = 0.001)
515 Vec3d normal = (p2-p0).cross(p1-p3);
517 const Vec3d centroid = (p0 + p1 + p2 + p3);
518 const double d = centroid.
dot(normal) * 0.25;
522 double absDist = std::abs(p0.dot(normal) - d);
523 if (absDist > epsilon)
return false;
525 absDist = std::abs(p1.dot(normal) - d);
526 if (absDist > epsilon)
return false;
528 absDist = std::abs(p2.dot(normal) - d);
529 if (absDist > epsilon)
return false;
531 absDist = std::abs(p3.dot(normal) - d);
532 if (absDist > epsilon)
return false;
552 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
553 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
568 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
570 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
582 template<
typename AccessorT>
584 evalCellSigns(
const AccessorT& accessor,
const Coord& ijk,
typename AccessorT::ValueType iso)
588 if (accessor.getValue(coord) < iso) signs |= 1u;
590 if (accessor.getValue(coord) < iso) signs |= 2u;
592 if (accessor.getValue(coord) < iso) signs |= 4u;
594 if (accessor.getValue(coord) < iso) signs |= 8u;
595 coord[1] += 1; coord[2] = ijk[2];
596 if (accessor.getValue(coord) < iso) signs |= 16u;
598 if (accessor.getValue(coord) < iso) signs |= 32u;
600 if (accessor.getValue(coord) < iso) signs |= 64u;
602 if (accessor.getValue(coord) < iso) signs |= 128u;
609 template<
typename LeafT>
613 unsigned char signs = 0;
616 if (leaf.getValue(offset) < iso) signs |= 1u;
619 if (leaf.getValue(offset + 1) < iso) signs |= 8u;
622 if (leaf.getValue(offset + LeafT::DIM) < iso) signs |= 16u;
625 if (leaf.getValue(offset + LeafT::DIM + 1) < iso) signs |= 128u;
628 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ) < iso) signs |= 2u;
631 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1) < iso) signs |= 4u;
634 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM) < iso) signs |= 32u;
637 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1) < iso) signs |= 64u;
645 template<
class AccessorT>
648 const AccessorT& acc, Coord ijk,
typename AccessorT::ValueType iso)
653 }
else if (face == 3) {
656 }
else if (face == 2) {
659 }
else if (face == 4) {
662 }
else if (face == 5) {
665 }
else if (face == 6) {
672 template<
class AccessorT>
675 typename AccessorT::ValueType isovalue,
const int dim)
681 p[0] = accessor.getValue(coord) < isovalue;
683 p[1] = accessor.getValue(coord) < isovalue;
685 p[2] = accessor.getValue(coord) < isovalue;
687 p[3] = accessor.getValue(coord) < isovalue;
688 coord[1] += dim; coord[2] = ijk[2];
689 p[4] = accessor.getValue(coord) < isovalue;
691 p[5] = accessor.getValue(coord) < isovalue;
693 p[6] = accessor.getValue(coord) < isovalue;
695 p[7] = accessor.getValue(coord) < isovalue;
699 if (p[0]) signs |= 1u;
700 if (p[1]) signs |= 2u;
701 if (p[2]) signs |= 4u;
702 if (p[3]) signs |= 8u;
703 if (p[4]) signs |= 16u;
704 if (p[5]) signs |= 32u;
705 if (p[6]) signs |= 64u;
706 if (p[7]) signs |= 128u;
712 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
713 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
714 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
717 coord.reset(ip, j, k);
718 m = accessor.getValue(coord) < isovalue;
719 if (p[0] != m && p[1] != m)
return true;
722 coord.reset(ipp, j, kp);
723 m = accessor.getValue(coord) < isovalue;
724 if (p[1] != m && p[2] != m)
return true;
727 coord.reset(ip, j, kpp);
728 m = accessor.getValue(coord) < isovalue;
729 if (p[2] != m && p[3] != m)
return true;
732 coord.reset(i, j, kp);
733 m = accessor.getValue(coord) < isovalue;
734 if (p[0] != m && p[3] != m)
return true;
737 coord.reset(ip, jpp, k);
738 m = accessor.getValue(coord) < isovalue;
739 if (p[4] != m && p[5] != m)
return true;
742 coord.reset(ipp, jpp, kp);
743 m = accessor.getValue(coord) < isovalue;
744 if (p[5] != m && p[6] != m)
return true;
747 coord.reset(ip, jpp, kpp);
748 m = accessor.getValue(coord) < isovalue;
749 if (p[6] != m && p[7] != m)
return true;
752 coord.reset(i, jpp, kp);
753 m = accessor.getValue(coord) < isovalue;
754 if (p[7] != m && p[4] != m)
return true;
757 coord.reset(i, jp, k);
758 m = accessor.getValue(coord) < isovalue;
759 if (p[0] != m && p[4] != m)
return true;
762 coord.reset(ipp, jp, k);
763 m = accessor.getValue(coord) < isovalue;
764 if (p[1] != m && p[5] != m)
return true;
767 coord.reset(ipp, jp, kpp);
768 m = accessor.getValue(coord) < isovalue;
769 if (p[2] != m && p[6] != m)
return true;
773 coord.reset(i, jp, kpp);
774 m = accessor.getValue(coord) < isovalue;
775 if (p[3] != m && p[7] != m)
return true;
781 coord.reset(ip, jp, k);
782 m = accessor.getValue(coord) < isovalue;
783 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
786 coord.reset(ipp, jp, kp);
787 m = accessor.getValue(coord) < isovalue;
788 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
791 coord.reset(ip, jp, kpp);
792 m = accessor.getValue(coord) < isovalue;
793 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
796 coord.reset(i, jp, kp);
797 m = accessor.getValue(coord) < isovalue;
798 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
801 coord.reset(ip, j, kp);
802 m = accessor.getValue(coord) < isovalue;
803 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
806 coord.reset(ip, jpp, kp);
807 m = accessor.getValue(coord) < isovalue;
808 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
811 coord.reset(ip, jp, kp);
812 m = accessor.getValue(coord) < isovalue;
813 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
814 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
823 template <
class LeafType>
825 mergeVoxels(LeafType& leaf,
const Coord& start,
int dim,
int regionId)
827 Coord ijk, end = start;
832 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
833 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
834 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
835 if(leaf.isValueOn(ijk)) leaf.setValue(ijk, regionId);
844 template <
class LeafType>
847 typename LeafType::ValueType::value_type adaptivity)
849 if (adaptivity < 1e-6)
return false;
851 typedef typename LeafType::ValueType VecT;
852 Coord ijk, end = start;
857 std::vector<VecT> norms;
858 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
859 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
860 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
862 if(!leaf.isValueOn(ijk))
continue;
863 norms.push_back(leaf.getValue(ijk));
868 size_t N = norms.size();
869 for (
size_t ni = 0; ni < N; ++ni) {
870 VecT n_i = norms[ni];
871 for (
size_t nj = 0; nj < N; ++nj) {
872 VecT n_j = norms[nj];
873 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
883 template<
typename TreeT,
typename LeafManagerT>
887 typedef typename TreeT::ValueType
ValueT;
890 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
893 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
899 SignData(
const TreeT& distTree,
const LeafManagerT& leafs,
ValueT iso);
901 void run(
bool threaded =
true);
903 typename Int16TreeT::Ptr
signTree()
const {
return mSignTree; }
904 typename IntTreeT::Ptr
idxTree()
const {
return mIdxTree; }
909 void operator()(
const tbb::blocked_range<size_t>&);
912 mSignTree->merge(*rhs.mSignTree);
913 mIdxTree->merge(*rhs.mIdxTree);
918 const TreeT& mDistTree;
921 const LeafManagerT& mLeafs;
924 typename Int16TreeT::Ptr mSignTree;
925 Int16AccessorT mSignAcc;
927 typename IntTreeT::Ptr mIdxTree;
928 IntAccessorT mIdxAcc;
933 template<
typename TreeT,
typename LeafManagerT>
935 const LeafManagerT& leafs,
ValueT iso)
936 : mDistTree(distTree)
937 , mDistAcc(mDistTree)
941 , mSignAcc(*mSignTree)
948 template<
typename TreeT,
typename LeafManagerT>
950 : mDistTree(rhs.mDistTree)
951 , mDistAcc(mDistTree)
953 , mIsovalue(rhs.mIsovalue)
955 , mSignAcc(*mSignTree)
962 template<
typename TreeT,
typename LeafManagerT>
966 if (threaded) tbb::parallel_reduce(mLeafs.getRange(), *
this);
967 else (*
this)(mLeafs.getRange());
970 template<
typename TreeT,
typename LeafManagerT>
974 typedef typename Int16TreeT::LeafNodeType Int16LeafT;
975 typedef typename IntTreeT::LeafNodeType IntLeafT;
976 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
977 unsigned char signs, face;
980 std::auto_ptr<Int16LeafT> signLeafPt(
new Int16LeafT(ijk, 0));
982 for (
size_t n = range.begin(); n != range.end(); ++n) {
984 bool collectedData =
false;
986 coord = mLeafs.leaf(n).origin();
988 if (!signLeafPt.get()) signLeafPt.reset(
new Int16LeafT(coord, 0));
989 else signLeafPt->setOrigin(coord);
991 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
993 coord.offset(TreeT::LeafNodeType::DIM - 1);
995 for (iter = mLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
997 ijk = iter.getCoord();
999 if (leafPt && ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
1005 if (signs != 0 && signs != 0xFF) {
1008 if (
bool(signs & 0x1) != bool(signs & 0x2)) flags |=
XEDGE;
1009 if (
bool(signs & 0x1) != bool(signs & 0x10)) flags |=
YEDGE;
1010 if (
bool(signs & 0x1) != bool(signs & 0x8)) flags |=
ZEDGE;
1015 flags |=
Int16(signs);
1017 signLeafPt->setValue(ijk, flags);
1018 collectedData =
true;
1022 if (collectedData) {
1024 IntLeafT* idxLeaf = mIdxAcc.touchLeaf(coord);
1025 idxLeaf->topologyUnion(*signLeafPt);
1026 typename IntLeafT::ValueOnIter it = idxLeaf->beginValueOn();
1031 mSignAcc.addLeaf(signLeafPt.release());
1044 CountPoints(std::vector<size_t>& pointList) : mPointList(pointList) {}
1046 template <
typename LeafNodeType>
1051 typename LeafNodeType::ValueOnCIter iter = leaf.cbeginValueOn();
1052 for (; iter; ++iter) {
1056 mPointList[leafIndex] = points;
1060 std::vector<size_t>& mPointList;
1065 template<
typename Int16TreeT>
1071 MapPoints(std::vector<size_t>& pointList,
const Int16TreeT& signTree)
1072 : mPointList(pointList)
1073 , mSignAcc(signTree)
1077 template <
typename LeafNodeType>
1080 size_t ptnIdx = mPointList[leafIndex];
1081 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
1083 const typename Int16TreeT::LeafNodeType *signLeafPt =
1086 for (; iter; ++iter) {
1087 iter.setValue(ptnIdx);
1088 unsigned signs =
SIGNS & signLeafPt->getValue(iter.pos());
1094 std::vector<size_t>& mPointList;
1100 template<
typename IntTreeT>
1113 template <
typename LeafNodeType>
1121 typename IntLeafT::ValueOnIter iter = tmpLeaf.beginValueOn();
1122 for (; iter; ++iter) {
1123 if(iter.getValue() == 0) {
1129 int onVoxelCount = int(tmpLeaf.onVoxelCount());
1130 while (onVoxelCount > 0) {
1132 iter = tmpLeaf.beginValueOn();
1133 int regionId = iter.getValue();
1134 for (; iter; ++iter) {
1135 if (iter.getValue() == regionId) {
1142 mRegions[leafIndex] = regions;
1147 std::vector<size_t>& mRegions;
1155 inline double evalRoot(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1159 template<
typename LeafT>
1163 values[0] = double(leaf.getValue(offset));
1164 values[3] = double(leaf.getValue(offset + 1));
1165 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1166 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1167 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1168 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1169 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1170 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1175 template<
typename AccessorT>
1180 values[0] = double(acc.getValue(coord));
1183 values[1] = double(acc.getValue(coord));
1186 values[2] = double(acc.getValue(coord));
1189 values[3] = double(acc.getValue(coord));
1191 coord[1] += 1; coord[2] = ijk[2];
1192 values[4] = double(acc.getValue(coord));
1195 values[5] = double(acc.getValue(coord));
1198 values[6] = double(acc.getValue(coord));
1201 values[7] = double(acc.getValue(coord));
1208 unsigned char edgeGroup,
double iso)
1210 Vec3d avg(0.0, 0.0, 0.0);
1214 avg[0] +=
evalRoot(values[0], values[1], iso);
1220 avg[2] +=
evalRoot(values[1], values[2], iso);
1225 avg[0] +=
evalRoot(values[3], values[2], iso);
1231 avg[2] +=
evalRoot(values[0], values[3], iso);
1236 avg[0] +=
evalRoot(values[4], values[5], iso);
1244 avg[2] +=
evalRoot(values[5], values[6], iso);
1249 avg[0] +=
evalRoot(values[7], values[6], iso);
1257 avg[2] +=
evalRoot(values[4], values[7], iso);
1262 avg[1] +=
evalRoot(values[0], values[4], iso);
1268 avg[1] +=
evalRoot(values[1], values[5], iso);
1274 avg[1] +=
evalRoot(values[2], values[6], iso);
1280 avg[1] +=
evalRoot(values[3], values[7], iso);
1286 double w = 1.0 / double(samples);
1300 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1302 avg =
Vec3d(0.0, 0.0, 0.0);
1307 avg[0] +=
evalRoot(values[0], values[1], iso);
1314 avg[2] +=
evalRoot(values[1], values[2], iso);
1320 avg[0] +=
evalRoot(values[3], values[2], iso);
1327 avg[2] +=
evalRoot(values[0], values[3], iso);
1333 avg[0] +=
evalRoot(values[4], values[5], iso);
1342 avg[2] +=
evalRoot(values[5], values[6], iso);
1348 avg[0] +=
evalRoot(values[7], values[6], iso);
1357 avg[2] +=
evalRoot(values[4], values[7], iso);
1363 avg[1] +=
evalRoot(values[0], values[4], iso);
1370 avg[1] +=
evalRoot(values[1], values[5], iso);
1377 avg[1] +=
evalRoot(values[2], values[6], iso);
1384 avg[1] +=
evalRoot(values[3], values[7], iso);
1390 double w = 1.0 / double(samples);
1404 unsigned char signs,
unsigned char edgeGroup,
double iso)
1406 std::vector<Vec3d> samples;
1409 std::vector<double> weights;
1412 Vec3d avg(0.0, 0.0, 0.0);
1415 avg[0] =
evalRoot(values[0], values[1], iso);
1419 samples.push_back(avg);
1420 weights.push_back((avg-p).lengthSqr());
1426 avg[2] =
evalRoot(values[1], values[2], iso);
1428 samples.push_back(avg);
1429 weights.push_back((avg-p).lengthSqr());
1433 avg[0] =
evalRoot(values[3], values[2], iso);
1437 samples.push_back(avg);
1438 weights.push_back((avg-p).lengthSqr());
1444 avg[2] =
evalRoot(values[0], values[3], iso);
1446 samples.push_back(avg);
1447 weights.push_back((avg-p).lengthSqr());
1451 avg[0] =
evalRoot(values[4], values[5], iso);
1455 samples.push_back(avg);
1456 weights.push_back((avg-p).lengthSqr());
1462 avg[2] =
evalRoot(values[5], values[6], iso);
1464 samples.push_back(avg);
1465 weights.push_back((avg-p).lengthSqr());
1469 avg[0] =
evalRoot(values[7], values[6], iso);
1473 samples.push_back(avg);
1474 weights.push_back((avg-p).lengthSqr());
1480 avg[2] =
evalRoot(values[4], values[7], iso);
1482 samples.push_back(avg);
1483 weights.push_back((avg-p).lengthSqr());
1488 avg[1] =
evalRoot(values[0], values[4], iso);
1491 samples.push_back(avg);
1492 weights.push_back((avg-p).lengthSqr());
1497 avg[1] =
evalRoot(values[1], values[5], iso);
1500 samples.push_back(avg);
1501 weights.push_back((avg-p).lengthSqr());
1506 avg[1] =
evalRoot(values[2], values[6], iso);
1509 samples.push_back(avg);
1510 weights.push_back((avg-p).lengthSqr());
1515 avg[1] =
evalRoot(values[3], values[7], iso);
1518 samples.push_back(avg);
1519 weights.push_back((avg-p).lengthSqr());
1526 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1527 minWeight =
std::min(minWeight, weights[i]);
1528 maxWeight =
std::max(maxWeight, weights[i]);
1531 const double offset = maxWeight + minWeight * 0.1;
1532 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1533 weights[i] = offset - weights[i];
1537 double weightSum = 0.0;
1538 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1539 weightSum += weights[i];
1546 if (samples.size() > 1) {
1547 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1548 avg += samples[i] * (weights[i] / weightSum);
1551 avg = samples.front();
1562 const std::vector<double>& values,
unsigned char signs,
double iso)
1574 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1577 for (
size_t i = 1; i <= 12; ++i) {
1593 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1594 unsigned char lhsSigns,
unsigned char rhsSigns,
1595 double iso,
size_t pointIdx,
const boost::scoped_array<uint32_t>& seamPoints)
1597 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1603 const unsigned char e(
id);
1604 uint32_t& quantizedPoint = seamPoints[pointIdx + (
id - 1)];
1609 weightedPointMask.push_back(
true);
1611 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1612 weightedPointMask.push_back(
false);
1616 points.push_back(
computePoint(lhsValues, lhsSigns, n, iso));
1617 weightedPointMask.push_back(
false);
1623 template <
typename TreeT,
typename LeafManagerT>
1629 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1633 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1641 GenPoints(
const LeafManagerT& signLeafs,
const TreeT& distTree,
1645 void run(
bool threaded =
true);
1649 std::vector<unsigned char>* mSeamPointMaskPt = NULL);
1654 void operator()(
const tbb::blocked_range<size_t>&)
const;
1657 const LeafManagerT& mSignLeafs;
1663 std::vector<size_t>& mIndices;
1665 const double mIsovalue;
1669 const TreeT* mRefDistTreePt;
1672 std::vector<unsigned char>* mSeamPointMaskPt;
1676 template <
typename TreeT,
typename LeafManagerT>
1679 std::vector<size_t>& indices,
const math::Transform& xform,
double iso)
1680 : mSignLeafs(signLeafs)
1681 , mDistAcc(distTree)
1687 , mRefSignTreePt(NULL)
1688 , mRefDistTreePt(NULL)
1689 , mRefIdxTreePt(NULL)
1690 , mSeamPointsPt(NULL)
1691 , mSeamPointMaskPt(NULL)
1696 template <
typename TreeT,
typename LeafManagerT>
1700 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
1701 else (*
this)(mSignLeafs.getRange());
1705 template <
typename TreeT,
typename LeafManagerT>
1710 mRefSignTreePt = refSignTree;
1711 mRefDistTreePt = refDistTree;
1712 mRefIdxTreePt = refIdxTree;
1713 mSeamPointsPt = seamPoints;
1714 mSeamPointMaskPt = seamPointMask;
1718 template <
typename TreeT,
typename LeafManagerT>
1721 const tbb::blocked_range<size_t>& range)
const
1723 typename IntTreeT::LeafNodeType::ValueOnIter iter;
1724 unsigned char signs, refSigns;
1727 std::vector<Vec3d> points(4);
1728 std::vector<bool> weightedPointMask(4);
1729 std::vector<double> values(8), refValues(8);
1735 boost::scoped_ptr<Int16CAccessorT> refSignAcc;
1736 if (mRefSignTreePt) refSignAcc.reset(
new Int16CAccessorT(*mRefSignTreePt));
1738 boost::scoped_ptr<IntCAccessorT> refIdxAcc;
1739 if (mRefIdxTreePt) refIdxAcc.reset(
new IntCAccessorT(*mRefIdxTreePt));
1741 boost::scoped_ptr<AccessorT> refDistAcc;
1742 if (mRefDistTreePt) refDistAcc.reset(
new AccessorT(*mRefDistTreePt));
1745 for (
size_t n = range.begin(); n != range.end(); ++n) {
1747 coord = mSignLeafs.leaf(n).origin();
1749 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
1750 typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeLeaf(coord);
1754 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
1755 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(coord);
1757 const typename IntTreeT::LeafNodeType *refIdxLeafPt = NULL;
1758 if (refIdxAcc) refIdxLeafPt = refIdxAcc->probeConstLeaf(coord);
1760 const typename TreeT::LeafNodeType *refDistLeafPt = NULL;
1761 if (refDistAcc) refDistLeafPt = refDistAcc->probeConstLeaf(coord);
1765 size_t ptnIdx = mIndices[n];
1766 coord.offset(TreeT::LeafNodeType::DIM - 1);
1770 for (iter = idxLeafPt->beginValueOn(); iter; ++iter) {
1772 if(iter.getValue() != 0)
continue;
1774 iter.setValue(ptnIdx);
1776 offset = iter.pos();
1777 ijk = iter.getCoord();
1779 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1781 const Int16& flags = mSignLeafs.leaf(n).getValue(offset);
1782 signs =
SIGNS & flags;
1785 if ((flags &
SEAM) && refSignLeafPt && refIdxLeafPt) {
1786 if (refSignLeafPt->isValueOn(offset)) {
1787 refSigns = (
SIGNS & refSignLeafPt->getValue(offset));
1797 weightedPointMask.clear();
1799 if (refSigns == 0) {
1806 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1807 mIsovalue, refIdxLeafPt->getValue(offset), *mSeamPointsPt);
1811 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1814 points[i][0] += double(ijk[0]);
1815 points[i][1] += double(ijk[1]);
1816 points[i][2] += double(ijk[2]);
1819 points[i] = mTransform.indexToWorld(points[i]);
1821 mPoints[ptnIdx][0] = float(points[i][0]);
1822 mPoints[ptnIdx][1] = float(points[i][1]);
1823 mPoints[ptnIdx][2] = float(points[i][2]);
1825 if (mSeamPointMaskPt && !weightedPointMask.empty() && weightedPointMask[i]) {
1826 (*mSeamPointMaskPt)[ptnIdx] = 1;
1834 int onVoxelCount = int(idxLeafPt->onVoxelCount());
1835 while (onVoxelCount > 0) {
1837 iter = idxLeafPt->beginValueOn();
1838 int regionId = iter.getValue(), count = 0;
1840 Vec3d avg(0.0), point;
1842 for (; iter; ++iter) {
1843 if (iter.getValue() != regionId)
continue;
1845 iter.setValue(ptnIdx);
1849 ijk = iter.getCoord();
1850 offset = iter.pos();
1852 signs = (
SIGNS & mSignLeafs.leaf(n).getValue(offset));
1854 if (ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
1863 avg[0] += double(ijk[0]) + points[0][0];
1864 avg[1] += double(ijk[1]) + points[0][1];
1865 avg[2] += double(ijk[2]) + points[0][2];
1872 double w = 1.0 / double(count);
1878 avg = mTransform.indexToWorld(avg);
1880 mPoints[ptnIdx][0] = float(avg[0]);
1881 mPoints[ptnIdx][1] = float(avg[1]);
1882 mPoints[ptnIdx][2] = float(avg[2]);
1893 template<
typename TreeT>
1899 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1902 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1912 template <
typename LeafNodeType>
1913 void operator()(LeafNodeType &signLeaf,
size_t leafIndex)
const;
1921 const double mIsovalue;
1925 template<
typename TreeT>
1928 : mDistAcc(distTree)
1929 , mRefSignAcc(refSignTree)
1930 , mRefIdxAcc(refIdxTree)
1937 template<
typename TreeT>
1938 template <
typename LeafNodeType>
1942 Coord coord = signLeaf.origin();
1943 const typename Int16TreeT::LeafNodeType *refSignLeafPt = mRefSignAcc.probeConstLeaf(coord);
1945 if (!refSignLeafPt)
return;
1947 const typename TreeT::LeafNodeType *distLeafPt = mDistAcc.probeConstLeaf(coord);
1948 const typename IntTreeT::LeafNodeType *refIdxLeafPt = mRefIdxAcc.probeConstLeaf(coord);
1950 std::vector<double> values(8);
1951 unsigned char lhsSigns, rhsSigns;
1956 coord.offset(TreeT::LeafNodeType::DIM - 1);
1958 typename LeafNodeType::ValueOnCIter iter = signLeaf.cbeginValueOn();
1959 for (; iter; ++iter) {
1961 offset = iter.pos();
1962 ijk = iter.getCoord();
1964 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1966 if ((iter.getValue() &
SEAM) && refSignLeafPt->isValueOn(offset)) {
1968 lhsSigns =
SIGNS & iter.getValue();
1969 rhsSigns =
SIGNS & refSignLeafPt->getValue(offset);
1972 if (inclusiveCell) {
1979 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1985 uint32_t& data = mPoints[refIdxLeafPt->getValue(offset) + (
id - 1)];
1991 if (smaples > 0) data =
packPoint(point);
2006 template <
typename TreeT,
typename LeafManagerT>
2013 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
2016 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2018 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2021 typedef typename TreeT::template ValueConverter<float>::Type
FloatTreeT;
2030 void run(
bool threaded =
true);
2042 void operator()(
const tbb::blocked_range<size_t>&)
const;
2046 const LeafManagerT& mSignLeafs;
2051 const TreeT& mDistTree;
2055 ValueT mIsovalue, mSurfaceAdaptivity, mInternalAdaptivity;
2064 template <
typename TreeT,
typename LeafManagerT>
2066 const LeafManagerT& signLeafs,
const Int16TreeT& signTree,
2068 : mSignLeafs(signLeafs)
2069 , mSignTree(signTree)
2070 , mSignAcc(mSignTree)
2071 , mDistTree(distTree)
2072 , mDistAcc(mDistTree)
2075 , mSurfaceAdaptivity(adaptivity)
2076 , mInternalAdaptivity(adaptivity)
2078 , mAdaptivityGrid(NULL)
2080 , mRefSignTree(NULL)
2085 template <
typename TreeT,
typename LeafManagerT>
2089 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2090 else (*
this)(mSignLeafs.getRange());
2094 template <
typename TreeT,
typename LeafManagerT>
2099 mTransform = &distGridXForm;
2100 mAdaptivityGrid = &adaptivityField;
2104 template <
typename TreeT,
typename LeafManagerT>
2111 template <
typename TreeT,
typename LeafManagerT>
2115 mRefSignTree = signTree;
2116 mInternalAdaptivity = adaptivity;
2120 template <
typename TreeT,
typename LeafManagerT>
2126 typedef typename TreeT::LeafNodeType LeafT;
2127 typedef typename IntTreeT::LeafNodeType IntLeafT;
2128 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2129 typedef typename LeafT::template ValueConverter<Vec3T>::Type Vec3LeafT;
2131 const int LeafDim = LeafT::DIM;
2135 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2138 boost::scoped_ptr<FloatTreeCAccessorT> adaptivityAcc;
2139 if (mAdaptivityGrid) {
2140 adaptivityAcc.reset(
new FloatTreeCAccessorT(mAdaptivityGrid->tree()));
2144 boost::scoped_ptr<Int16TreeCAccessorT> refAcc;
2146 refAcc.reset(
new Int16TreeCAccessorT(*mRefSignTree));
2150 boost::scoped_ptr<BoolTreeCAccessorT> maskAcc;
2152 maskAcc.reset(
new BoolTreeCAccessorT(*
mMask));
2157 Vec3LeafT gradientBuffer;
2158 Coord ijk, nijk, coord, end;
2160 for (
size_t n = range.begin(); n != range.end(); ++n) {
2162 const Coord& origin = mSignLeafs.leaf(n).origin();
2164 ValueT adaptivity = mSurfaceAdaptivity;
2166 if (refAcc && refAcc->probeConstLeaf(origin) == NULL) {
2167 adaptivity = mInternalAdaptivity;
2170 IntLeafT& idxLeaf = *idxAcc.
probeLeaf(origin);
2172 end[0] = origin[0] + LeafDim;
2173 end[1] = origin[1] + LeafDim;
2174 end[2] = origin[2] + LeafDim;
2176 mask.setValuesOff();
2180 const BoolLeafT* maskLeaf = maskAcc->probeConstLeaf(origin);
2181 if (maskLeaf != NULL) {
2182 typename BoolLeafT::ValueOnCIter it;
2183 for (it = maskLeaf->cbeginValueOn(); it; ++it) {
2184 ijk = it.getCoord();
2185 coord[0] = ijk[0] - (ijk[0] % 2);
2186 coord[1] = ijk[1] - (ijk[1] % 2);
2187 coord[2] = ijk[2] - (ijk[2] % 2);
2188 mask.setActiveState(coord,
true);
2194 LeafT adaptivityLeaf(origin, adaptivity);
2196 if (mAdaptivityGrid) {
2197 for (
Index offset = 0; offset < LeafT::NUM_VALUES; ++offset) {
2198 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2199 Vec3d xyz = mAdaptivityGrid->transform().worldToIndex(
2200 mTransform->indexToWorld(ijk));
2202 adaptivityLeaf.setValueOnly(offset, tmpA * adaptivity);
2207 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2208 ijk = iter.getCoord();
2209 coord[0] = ijk[0] - (ijk[0] % 2);
2210 coord[1] = ijk[1] - (ijk[1] % 2);
2211 coord[2] = ijk[2] - (ijk[2] % 2);
2212 if(mask.isValueOn(coord))
continue;
2216 int flags = int(iter.getValue());
2217 unsigned char signs =
SIGNS & flags;
2219 mask.setActiveState(coord,
true);
2223 for (
int i = 0; i < 26; ++i) {
2225 signs =
SIGNS & mSignAcc.getValue(nijk);
2227 mask.setActiveState(coord,
true);
2235 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2236 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2237 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2239 mask.setActiveState(ijk,
true);
2246 gradientBuffer.setValuesOff();
2247 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2249 ijk = iter.getCoord();
2250 coord[0] = ijk[0] - (ijk[0] % dim);
2251 coord[1] = ijk[1] - (ijk[1] % dim);
2252 coord[2] = ijk[2] - (ijk[2] % dim);
2253 if(mask.isValueOn(coord))
continue;
2257 ValueT length = norm.length();
2258 if (length >
ValueT(1.0e-7)) {
2259 norm *=
ValueT(1.0) / length;
2261 gradientBuffer.setValue(ijk, norm);
2264 int regionId = 1, next_dim = dim << 1;
2267 for (ijk[0] = 0; ijk[0] < LeafDim; ijk[0] += dim) {
2268 coord[0] = ijk[0] - (ijk[0] % next_dim);
2269 for (ijk[1] = 0; ijk[1] < LeafDim; ijk[1] += dim) {
2270 coord[1] = ijk[1] - (ijk[1] % next_dim);
2271 for (ijk[2] = 0; ijk[2] < LeafDim; ijk[2] += dim) {
2272 coord[2] = ijk[2] - (ijk[2] % next_dim);
2273 adaptivity = adaptivityLeaf.getValue(ijk);
2274 if (mask.isValueOn(ijk) || !
isMergable(gradientBuffer, ijk, dim, adaptivity)) {
2275 mask.setActiveState(coord,
true);
2285 for (dim = 4; dim < LeafDim; dim = dim << 1) {
2286 next_dim = dim << 1;
2287 coord[0] = ijk[0] - (ijk[0] % next_dim);
2288 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2289 coord[1] = ijk[1] - (ijk[1] % next_dim);
2290 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2291 coord[2] = ijk[2] - (ijk[2] % next_dim);
2292 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2293 adaptivity = adaptivityLeaf.getValue(ijk);
2294 if (mask.isValueOn(ijk) ||
isNonManifold(mDistAcc, ijk, mIsovalue, dim) ||
2295 !
isMergable(gradientBuffer, ijk, dim, adaptivity))
2297 mask.setActiveState(coord,
true);
2306 adaptivity = adaptivityLeaf.getValue(origin);
2307 if (!(mask.isValueOn(origin) ||
isNonManifold(mDistAcc, origin, mIsovalue, LeafDim))
2308 &&
isMergable(gradientBuffer, origin, LeafDim, adaptivity))
2310 mergeVoxels(idxLeaf, origin, LeafDim, regionId++);
2326 mPolygonPool = &quadPool;
2334 mPolygonPool->
quad(mIdx) = verts;
2364 mPolygonPool = &polygonPool;
2374 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2375 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2376 mPolygonPool->
quadFlags(mQuadIdx) = flags;
2377 addQuad(verts, reverse);
2379 verts[0] == verts[3] &&
2380 verts[1] != verts[2] &&
2381 verts[1] != verts[0] &&
2382 verts[2] != verts[0]) {
2384 addTriangle(verts[0], verts[1], verts[2], reverse);
2386 verts[1] == verts[2] &&
2387 verts[0] != verts[3] &&
2388 verts[0] != verts[1] &&
2389 verts[3] != verts[1]) {
2391 addTriangle(verts[0], verts[1], verts[3], reverse);
2393 verts[0] == verts[1] &&
2394 verts[2] != verts[3] &&
2395 verts[2] != verts[0] &&
2396 verts[3] != verts[0]) {
2398 addTriangle(verts[0], verts[2], verts[3], reverse);
2400 verts[2] == verts[3] &&
2401 verts[0] != verts[1] &&
2402 verts[0] != verts[2] &&
2403 verts[1] != verts[2]) {
2405 addTriangle(verts[0], verts[1], verts[2], reverse);
2412 mPolygonPool->
trimQuads(mQuadIdx,
true);
2418 void addQuad(
const Vec4I& verts,
bool reverse)
2421 mPolygonPool->
quad(mQuadIdx) = verts;
2423 Vec4I& quad = mPolygonPool->
quad(mQuadIdx);
2432 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2448 size_t mQuadIdx, mTriangleIdx;
2449 PolygonPool *mPolygonPool;
2453 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2456 const SignAccT& signAcc,
const IdxAccT& idxAcc, PrimBuilder& mesher,
Index32 pointListSize)
2458 const Index32 v0 = idxAcc.getValue(ijk);
2465 const bool isInside = flags &
INSIDE;
2472 if (flags &
XEDGE) {
2474 quad[0] = v0 + offsets[0];
2478 coord[1] = ijk[1] - 1;
2481 quad[1] = idxAcc.getValue(coord);
2482 cell =
SIGNS & signAcc.getValue(coord);
2485 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2491 quad[2] = idxAcc.getValue(coord);
2492 cell =
SIGNS & signAcc.getValue(coord);
2495 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2501 quad[3] = idxAcc.getValue(coord);
2502 cell =
SIGNS & signAcc.getValue(coord);
2505 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2510 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2515 if (flags &
YEDGE) {
2517 quad[0] = v0 + offsets[1];
2522 coord[2] = ijk[2] - 1;
2524 quad[1] = idxAcc.getValue(coord);
2525 cell =
SIGNS & signAcc.getValue(coord);
2528 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2534 quad[2] = idxAcc.getValue(coord);
2535 cell =
SIGNS & signAcc.getValue(coord);
2538 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2544 quad[3] = idxAcc.getValue(coord);
2545 cell =
SIGNS & signAcc.getValue(coord);
2548 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2553 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2557 if (flags &
ZEDGE) {
2559 quad[0] = v0 + offsets[2];
2563 coord[1] = ijk[1] - 1;
2566 quad[1] = idxAcc.getValue(coord);
2567 cell =
SIGNS & signAcc.getValue(coord);
2570 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2576 quad[2] = idxAcc.getValue(coord);
2577 cell =
SIGNS & signAcc.getValue(coord);
2580 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2586 quad[3] = idxAcc.getValue(coord);
2587 cell =
SIGNS & signAcc.getValue(coord);
2590 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2595 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2604 template<
typename LeafManagerT,
typename PrimBuilder>
2608 typedef typename LeafManagerT::TreeType::template ValueConverter<int>::Type
IntTreeT;
2609 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2620 void run(
bool threaded =
true);
2628 void operator()(
const tbb::blocked_range<size_t>&)
const;
2631 const LeafManagerT& mSignLeafs;
2641 template<
typename LeafManagerT,
typename PrimBuilder>
2645 : mSignLeafs(signLeafs)
2646 , mSignTree(signTree)
2648 , mPolygonPoolList(polygons)
2649 , mPointListSize(pointListSize)
2650 , mRefSignTree(NULL)
2654 template<
typename LeafManagerT,
typename PrimBuilder>
2658 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2659 else (*
this)(mSignLeafs.getRange());
2662 template<
typename LeafManagerT,
typename PrimBuilder>
2665 const tbb::blocked_range<size_t>& range)
const
2667 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2678 boost::scoped_ptr<Int16AccessorT> refSignAcc;
2679 if (mRefSignTree) refSignAcc.reset(
new Int16AccessorT(*mRefSignTree));
2682 for (
size_t n = range.begin(); n != range.end(); ++n) {
2684 origin = mSignLeafs.leaf(n).origin();
2688 iter = mSignLeafs.leaf(n).cbeginValueOn();
2689 for (; iter; ++iter) {
2690 if (iter.getValue() &
XEDGE) ++edgeCount;
2691 if (iter.getValue() &
YEDGE) ++edgeCount;
2692 if (iter.getValue() &
ZEDGE) ++edgeCount;
2695 if(edgeCount == 0)
continue;
2697 mesher.init(edgeCount, mPolygonPoolList[n]);
2699 const typename Int16TreeT::LeafNodeType *signleafPt = signAcc.
probeConstLeaf(origin);
2700 const typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeConstLeaf(origin);
2702 if (!signleafPt || !idxLeafPt)
continue;
2705 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
2706 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
2710 iter = mSignLeafs.leaf(n).cbeginValueOn();
2711 for (; iter; ++iter) {
2712 ijk = iter.getCoord();
2714 Int16 flags = iter.getValue();
2716 if (!(flags & 0xE00))
continue;
2719 if (refSignLeafPt) {
2720 refFlags = refSignLeafPt->getValue(iter.pos());
2727 const unsigned char cell = (
SIGNS & flags);
2735 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
2736 constructPolygons(flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher, mPointListSize);
2738 constructPolygons(flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher, mPointListSize);
2754 PartOp(
size_t leafCount,
size_t partitions,
size_t activePart)
2756 size_t leafSegments = leafCount / partitions;
2757 mStart = leafSegments * activePart;
2758 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2761 template <
typename LeafNodeType>
2764 if (leafIndex < mStart || leafIndex >= mEnd) leaf.setValuesOff();
2768 size_t mStart, mEnd;
2775 template<
typename SrcTreeT>
2780 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
2788 void run(
bool threaded =
true);
2796 void operator()(
const tbb::blocked_range<size_t>&);
2802 size_t mStart, mEnd;
2805 template<
typename SrcTreeT>
2807 : mLeafManager(leafs)
2813 size_t leafSegments = leafCount / partitions;
2814 mStart = leafSegments * activePart;
2815 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2818 template<
typename SrcTreeT>
2820 : mLeafManager(rhs.mLeafManager)
2822 , mStart(rhs.mStart)
2828 template<
typename SrcTreeT>
2832 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2833 else (*
this)(mLeafManager.getRange());
2837 template<
typename SrcTreeT>
2844 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2845 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
2847 for (
size_t n = range.begin(); n != range.end(); ++n) {
2848 if (n < mStart || n >= mEnd)
continue;
2849 BoolLeafT* leaf = acc.
touchLeaf(mLeafManager.leaf(n).origin());
2850 leaf->topologyUnion(mLeafManager.leaf(n));
2858 template<
typename TreeT,
typename LeafManagerT>
2862 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2866 GenSeamMask(
const LeafManagerT& leafs,
const TreeT& tree);
2868 void run(
bool threaded =
true);
2875 void operator()(
const tbb::blocked_range<size_t>&);
2880 const LeafManagerT& mLeafManager;
2887 template<
typename TreeT,
typename LeafManagerT>
2889 : mLeafManager(leafs)
2896 template<
typename TreeT,
typename LeafManagerT>
2898 : mLeafManager(rhs.mLeafManager)
2905 template<
typename TreeT,
typename LeafManagerT>
2909 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2910 else (*
this)(mLeafManager.getRange());
2914 template<
typename TreeT,
typename LeafManagerT>
2922 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter it;
2924 for (
size_t n = range.begin(); n != range.end(); ++n) {
2926 it = mLeafManager.leaf(n).cbeginValueOn();
2930 ijk = it.getCoord();
2935 unsigned char lhsSigns = it.getValue() &
SIGNS;
2936 if (rhsSigns != lhsSigns) {
2948 template<
typename TreeT>
2956 template <
typename LeafNodeType>
2959 const typename TreeT::LeafNodeType *maskLeaf =
2962 if (!maskLeaf)
return;
2964 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
2968 if (maskLeaf->isValueOn(it.pos())) {
2969 it.setValue(it.getValue() |
SEAM);
2980 template<
typename BoolTreeT>
2985 MaskEdges(
const BoolTreeT& valueMask) : mMaskAcc(valueMask) {}
2987 template <
typename LeafNodeType>
2990 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
2992 const typename BoolTreeT::LeafNodeType * maskLeaf =
2997 if (!maskLeaf->isValueOn(it.pos())) {
2998 it.setValue(0x1FF & it.getValue());
3003 it.setValue(0x1FF & it.getValue());
3019 std::vector<unsigned char>& usedPointMask)
3020 : mPolygons(polygons)
3021 , mPolyListCount(polyListCount)
3022 , mUsedPointMask(usedPointMask)
3026 void run(
bool threaded =
true)
3029 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
3031 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3041 for (
size_t n = range.begin(); n != range.end(); ++n) {
3043 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3045 mUsedPointMask[quad[0]] = 1;
3046 mUsedPointMask[quad[1]] = 1;
3047 mUsedPointMask[quad[2]] = 1;
3048 mUsedPointMask[quad[3]] = 1;
3053 mUsedPointMask[triangle[0]] = 1;
3054 mUsedPointMask[triangle[1]] = 1;
3055 mUsedPointMask[triangle[2]] = 1;
3063 size_t mPolyListCount;
3064 std::vector<unsigned char>& mUsedPointMask;
3073 size_t polyListCount,
const std::vector<unsigned>& indexMap)
3074 : mPolygons(polygons)
3075 , mPolyListCount(polyListCount)
3076 , mIndexMap(indexMap)
3080 void run(
bool threaded =
true)
3083 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
3085 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3093 for (
size_t n = range.begin(); n != range.end(); ++n) {
3095 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3097 quad[0] = mIndexMap[quad[0]];
3098 quad[1] = mIndexMap[quad[1]];
3099 quad[2] = mIndexMap[quad[2]];
3100 quad[3] = mIndexMap[quad[3]];
3105 triangle[0] = mIndexMap[triangle[0]];
3106 triangle[1] = mIndexMap[triangle[1]];
3107 triangle[2] = mIndexMap[triangle[2]];
3115 size_t mPolyListCount;
3116 const std::vector<unsigned>& mIndexMap;
3126 std::auto_ptr<openvdb::Vec3s>& newPointList,
3128 const std::vector<unsigned>& indexMap,
3129 const std::vector<unsigned char>& usedPointMask)
3130 : mNewPointList(newPointList)
3131 , mOldPointList(oldPointList)
3132 , mIndexMap(indexMap)
3133 , mUsedPointMask(usedPointMask)
3137 void run(
bool threaded =
true)
3140 tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexMap.size()), *
this);
3142 (*this)(tbb::blocked_range<size_t>(0, mIndexMap.size()));
3150 for (
size_t n = range.begin(); n != range.end(); ++n) {
3151 if (mUsedPointMask[n]) {
3152 const size_t index = mIndexMap[n];
3153 mNewPointList.get()[index] = mOldPointList[n];
3159 std::auto_ptr<openvdb::Vec3s>& mNewPointList;
3161 const std::vector<unsigned>& mIndexMap;
3162 const std::vector<unsigned char>& mUsedPointMask;
3169 template<
typename SrcTreeT>
3174 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3186 void run(
bool threaded =
true);
3195 void operator()(
const tbb::blocked_range<size_t>&);
3209 template<
typename SrcTreeT>
3213 , mLeafManager(srcLeafs)
3214 , mSrcXForm(srcXForm)
3215 , mInvertMask(invertMask)
3221 template<
typename SrcTreeT>
3224 , mLeafManager(rhs.mLeafManager)
3225 , mSrcXForm(rhs.mSrcXForm)
3226 , mInvertMask(rhs.mInvertMask)
3232 template<
typename SrcTreeT>
3237 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3239 (*this)(mLeafManager.getRange());
3244 template<
typename SrcTreeT>
3250 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
3255 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3256 for (
size_t n = range.begin(); n != range.end(); ++n) {
3258 ijk = mLeafManager.leaf(n).origin();
3259 BoolLeafT* leaf =
new BoolLeafT(ijk,
false);
3260 bool addLeaf =
false;
3262 if (maskXForm == mSrcXForm) {
3264 const BoolLeafT* maskLeaf = maskAcc.probeConstLeaf(ijk);
3268 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3269 Index pos = iter.pos();
3270 if(maskLeaf->isValueOn(pos) != mInvertMask) {
3271 leaf->setValueOn(pos);
3276 }
else if (maskAcc.isValueOn(ijk) != mInvertMask) {
3277 leaf->topologyUnion(mLeafManager.leaf(n));
3282 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3283 ijk = iter.getCoord();
3284 xyz = maskXForm.
worldToIndex(mSrcXForm.indexToWorld(ijk));
3286 leaf->setValueOn(iter.pos());
3292 if (addLeaf) acc.
addLeaf(leaf);
3301 template<
typename SrcTreeT>
3305 typedef typename SrcTreeT::template ValueConverter<int>::Type
IntTreeT;
3306 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3313 void run(
bool threaded =
true);
3320 void operator()(
const tbb::blocked_range<size_t>&);
3327 bool neighboringLeaf(
const Coord&,
const IntTreeAccessorT&)
const;
3333 CoordBBox mLeafBBox;
3337 template<
typename SrcTreeT>
3340 : mLeafManager(leafs)
3341 , mMaskTree(maskTree)
3345 mIdxTree.evalLeafBoundingBox(mLeafBBox);
3346 mLeafBBox.expand(IntTreeT::LeafNodeType::DIM);
3350 template<
typename SrcTreeT>
3352 : mLeafManager(rhs.mLeafManager)
3353 , mMaskTree(rhs.mMaskTree)
3354 , mIdxTree(rhs.mIdxTree)
3356 , mLeafBBox(rhs.mLeafBBox)
3361 template<
typename SrcTreeT>
3366 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3368 (*this)(mLeafManager.getRange());
3373 template<
typename SrcTreeT>
3377 if (acc.probeConstLeaf(ijk))
return true;
3379 const int dim = IntTreeT::LeafNodeType::DIM;
3382 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2])))
return true;
3383 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2])))
return true;
3384 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2])))
return true;
3385 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2])))
return true;
3386 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] + dim)))
return true;
3387 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] - dim)))
return true;
3390 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] - dim)))
return true;
3391 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] - dim)))
return true;
3392 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] + dim)))
return true;
3393 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] + dim)))
return true;
3394 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2])))
return true;
3395 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2])))
return true;
3396 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2])))
return true;
3397 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2])))
return true;
3398 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] + dim)))
return true;
3399 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] - dim)))
return true;
3400 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] + dim)))
return true;
3401 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] - dim)))
return true;
3404 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3405 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3406 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3407 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3408 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3409 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3410 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3411 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3417 template<
typename SrcTreeT>
3426 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3428 for (
size_t n = range.begin(); n != range.end(); ++n) {
3430 const typename SrcTreeT::LeafNodeType&
3431 leaf = mLeafManager.leaf(n);
3433 ijk = leaf.origin();
3435 if (!mLeafBBox.isInside(ijk) || !neighboringLeaf(ijk, idxAcc))
continue;
3437 const typename BoolTreeT::LeafNodeType*
3440 if (!maskLeaf || !leaf.hasSameTopology(maskLeaf)) {
3441 acc.
touchLeaf(ijk)->topologyUnion(leaf);
3450 template<
typename TreeT>
3454 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
3460 GenTileMask(
const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso);
3462 void run(
bool threaded =
true);
3469 void operator()(
const tbb::blocked_range<size_t>&);
3474 const std::vector<Vec4i>& mTiles;
3475 const TreeT& mDistTree;
3482 template<
typename TreeT>
3484 const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso)
3486 , mDistTree(distTree)
3493 template<
typename TreeT>
3495 : mTiles(rhs.mTiles)
3496 , mDistTree(rhs.mDistTree)
3497 , mIsovalue(rhs.mIsovalue)
3503 template<
typename TreeT>
3507 if (threaded) tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mTiles.size()), *
this);
3508 else (*
this)(tbb::blocked_range<size_t>(0, mTiles.size()));
3512 template<
typename TreeT>
3517 CoordBBox region, bbox;
3519 bool processRegion =
true;
3523 for (
size_t n = range.begin(); n != range.end(); ++n) {
3525 const Vec4i& tile = mTiles[n];
3527 bbox.min()[0] = tile[0];
3528 bbox.min()[1] = tile[1];
3529 bbox.min()[2] = tile[2];
3531 bbox.max() = bbox.min();
3532 bbox.max().offset(tile[3]);
3534 const bool thisInside = (distAcc.
getValue(bbox.min()) < mIsovalue);
3543 processRegion =
true;
3545 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3549 if (processRegion) {
3551 region.min()[0] = region.max()[0] = ijk[0];
3552 mTree.fill(region,
true);
3559 processRegion =
true;
3561 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3564 if (processRegion) {
3566 region.min()[0] = region.max()[0] = ijk[0];
3567 mTree.fill(region,
true);
3577 processRegion =
true;
3579 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3582 if (processRegion) {
3584 region.min()[1] = region.max()[1] = ijk[1];
3585 mTree.fill(region,
true);
3592 processRegion =
true;
3594 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3597 if (processRegion) {
3599 region.min()[1] = region.max()[1] = ijk[1];
3600 mTree.fill(region,
true);
3610 processRegion =
true;
3612 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3615 if (processRegion) {
3617 region.min()[2] = region.max()[2] = ijk[2];
3618 mTree.fill(region,
true);
3624 processRegion =
true;
3626 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3629 if (processRegion) {
3631 region.min()[2] = region.max()[2] = ijk[2];
3632 mTree.fill(region,
true);
3640 processRegion =
true;
3642 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3645 if (processRegion) {
3647 region.min()[1] = region.max()[1] = ijk[1];
3648 region.min()[2] = region.max()[2] = ijk[2];
3649 mTree.fill(region,
true);
3657 processRegion =
true;
3659 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3662 if (processRegion) {
3664 region.min()[1] = region.max()[1] = ijk[1];
3665 region.min()[0] = region.max()[0] = ijk[0];
3666 mTree.fill(region,
true);
3673 processRegion =
true;
3675 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3678 if (processRegion) {
3680 region.min()[2] = region.max()[2] = ijk[2];
3681 region.min()[0] = region.max()[0] = ijk[0];
3682 mTree.fill(region,
true);
3691 template<
class DistTreeT,
class SignTreeT,
class IdxTreeT>
3693 tileData(
const DistTreeT& distTree, SignTreeT& signTree, IdxTreeT& idxTree,
double iso)
3695 typename DistTreeT::ValueOnCIter tileIter(distTree);
3696 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3698 if (!tileIter)
return;
3700 size_t tileCount = 0;
3701 for ( ; tileIter; ++tileIter) {
3705 std::vector<Vec4i> tiles(tileCount);
3708 tileIter = distTree.cbeginValueOn();
3709 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3712 for (; tileIter; ++tileIter) {
3713 Vec4i& tile = tiles[tileCount++];
3714 tileIter.getBoundingBox(bbox);
3715 tile[0] = bbox.min()[0];
3716 tile[1] = bbox.min()[1];
3717 tile[2] = bbox.min()[2];
3718 tile[3] = bbox.max()[0] - bbox.min()[0];
3721 typename DistTreeT::ValueType isovalue =
typename DistTreeT::ValueType(iso);
3726 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
3729 BoolLeafManagerT leafs(tileMask.
tree());
3735 signTree.merge(*op.signTree());
3736 idxTree.merge(*op.idxTree());
3748 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
3754 for (
size_t n = range.begin(); n < range.end(); ++n) {
3755 mPointsOut[n] = mPointsIn[n];
3761 std::vector<Vec3s>& mPointsOut;
3766 template <
typename LeafManagerT>
3770 double interiorWidth = 0.0, exteriorWidth = 0.0;
3772 typename LeafManagerT::TreeType::LeafNodeType::ValueOffCIter it;
3773 bool foundInterior =
false, foundExterior =
false;
3774 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
3776 for (it = leafs.leaf(n).cbeginValueOff(); it; ++it) {
3777 double value = double(it.getValue());
3779 interiorWidth = value;
3780 foundInterior =
true;
3781 }
else if (value > 0.0) {
3782 exteriorWidth = value;
3783 foundExterior =
true;
3786 if (foundInterior && foundExterior)
break;
3789 if (foundInterior && foundExterior)
break;
3794 double minDist =
std::min(std::abs(interiorWidth - iso), std::abs(exteriorWidth - iso));
3795 return !(minDist > (2.0 * voxelSize));
3812 , mTriangleFlags(NULL)
3819 : mNumQuads(numQuads)
3820 , mNumTriangles(numTriangles)
3821 , mQuads(new openvdb::
Vec4I[mNumQuads])
3822 , mTriangles(new openvdb::
Vec3I[mNumTriangles])
3823 , mQuadFlags(new char[mNumQuads])
3824 , mTriangleFlags(new char[mNumTriangles])
3835 for (
size_t i = 0; i < mNumQuads; ++i) {
3836 mQuads[i] = rhs.mQuads[i];
3837 mQuadFlags[i] = rhs.mQuadFlags[i];
3840 for (
size_t i = 0; i < mNumTriangles; ++i) {
3841 mTriangles[i] = rhs.mTriangles[i];
3842 mTriangleFlags[i] = rhs.mTriangleFlags[i];
3852 mQuadFlags.reset(
new char[mNumQuads]);
3861 mQuadFlags.reset(NULL);
3868 mNumTriangles = size;
3870 mTriangleFlags.reset(
new char[mNumTriangles]);
3878 mTriangles.reset(NULL);
3879 mTriangleFlags.reset(NULL);
3886 if (!(n < mNumQuads))
return false;
3894 boost::scoped_array<openvdb::Vec4I> quads(
new openvdb::Vec4I[n]);
3895 boost::scoped_array<char> flags(
new char[n]);
3897 for (
size_t i = 0; i < n; ++i) {
3898 quads[i] = mQuads[i];
3899 flags[i] = mQuadFlags[i];
3903 mQuadFlags.swap(flags);
3915 if (!(n < mNumTriangles))
return false;
3920 mTriangles.reset(NULL);
3923 boost::scoped_array<openvdb::Vec3I> triangles(
new openvdb::Vec3I[n]);
3924 boost::scoped_array<char> flags(
new char[n]);
3926 for (
size_t i = 0; i < n; ++i) {
3927 triangles[i] = mTriangles[i];
3928 flags[i] = mTriangleFlags[i];
3931 mTriangles.swap(triangles);
3932 mTriangleFlags.swap(flags);
3948 , mSeamPointListSize(0)
3949 , mPolygonPoolListSize(0)
3950 , mIsovalue(isovalue)
3951 , mPrimAdaptivity(adaptivity)
3952 , mSecAdaptivity(0.0)
3954 , mSurfaceMaskGrid(
GridBase::ConstPtr())
3955 , mAdaptivityGrid(
GridBase::ConstPtr())
3956 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
3959 , mInvertSurfaceMask(false)
3962 , mQuantizedSeamPoints(NULL)
3975 inline const size_t&
3978 return mPointListSize;
3996 inline const size_t&
3999 return mPolygonPoolListSize;
4007 mSecAdaptivity = secAdaptivity;
4012 mSeamPointListSize = 0;
4013 mQuantizedSeamPoints.reset(NULL);
4020 mSurfaceMaskGrid = mask;
4021 mInvertSurfaceMask = invertMask;
4028 mAdaptivityGrid = grid;
4035 mAdaptivityMaskTree = tree;
4042 mPartitions =
std::max(partitions,
unsigned(1));
4043 mActivePart =
std::min(activePart, mPartitions-1);
4047 inline std::vector<unsigned char>&
4054 inline const std::vector<unsigned char>&
4061 template<
typename Gr
idT>
4065 typedef typename GridT::TreeType DistTreeT;
4067 typedef typename DistTreeT::ValueType DistValueT;
4069 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
4073 typedef typename DistTreeT::template ValueConverter<Int16>::Type Int16TreeT;
4076 typedef typename DistTreeT::template ValueConverter<int>::Type IntTreeT;
4077 typedef typename DistTreeT::template ValueConverter<float>::Type FloatTreeT;
4081 const openvdb::math::Transform& transform = distGrid.
transform();
4082 const DistTreeT& distTree = distGrid.tree();
4083 const DistValueT isovalue = DistValueT(mIsovalue);
4085 typename Int16TreeT::Ptr signTreePt;
4086 typename IntTreeT::Ptr idxTreePt;
4087 typename BoolTreeT::Ptr pointMask;
4089 BoolTreeT valueMask(
false), seamMask(
false);
4090 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4091 bool maskEdges =
false;
4094 const BoolGridT * surfaceMask = NULL;
4095 if (mSurfaceMaskGrid && mSurfaceMaskGrid->type() == BoolGridT::gridType()) {
4096 surfaceMask =
static_cast<const BoolGridT*
>(mSurfaceMaskGrid.get());
4099 const FloatGridT * adaptivityField = NULL;
4100 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridT::gridType()) {
4101 adaptivityField =
static_cast<const FloatGridT*
>(mAdaptivityGrid.get());
4104 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeT::treeType()) {
4105 const BoolTreeT *adaptivityMaskPt =
4106 static_cast<const BoolTreeT*
>(mAdaptivityMaskTree.get());
4107 seamMask.topologyUnion(*adaptivityMaskPt);
4113 DistLeafManagerT distLeafs(distTree);
4116 bool padActiveVoxels =
false;
4120 padActiveVoxels =
true;
4123 mIsovalue, transform.voxelSize()[0]);
4127 if (!padActiveVoxels) {
4129 distTree.evalActiveVoxelDim(dim);
4131 if (maxDim < 1000) {
4132 padActiveVoxels =
true;
4137 if (surfaceMask || mPartitions > 1) {
4145 *surfaceMask, distLeafs, transform, mInvertSurfaceMask);
4147 valueMask.merge(masking.
tree());
4150 if (mPartitions > 1) {
4153 valueMask.pruneInactive();
4160 valueMask.merge(partitioner.
tree());
4165 BoolLeafManagerT leafs(valueMask);
4168 signDataOp(distTree, leafs, isovalue);
4171 signTreePt = signDataOp.
signTree();
4172 idxTreePt = signDataOp.
idxTree();
4179 BoolLeafManagerT bleafs(boundary.
tree());
4182 signDataOp(distTree, bleafs, isovalue);
4185 signTreePt->merge(*signDataOp.signTree());
4186 idxTreePt->merge(*signDataOp.idxTree());
4192 if (padActiveVoxels) {
4194 BoolTreeT regionMask(
false);
4195 regionMask.topologyUnion(distTree);
4198 BoolLeafManagerT leafs(regionMask);
4201 signDataOp(distTree, leafs, isovalue);
4204 signTreePt = signDataOp.
signTree();
4205 idxTreePt = signDataOp.
idxTree();
4209 signDataOp(distTree, distLeafs, isovalue);
4212 signTreePt = signDataOp.
signTree();
4213 idxTreePt = signDataOp.
idxTree();
4224 Int16TreeT *refSignTreePt = NULL;
4225 IntTreeT *refIdxTreePt = NULL;
4226 const DistTreeT *refDistTreePt = NULL;
4228 if (mRefGrid && mRefGrid->type() == GridT::gridType()) {
4230 const GridT* refGrid =
static_cast<const GridT*
>(mRefGrid.get());
4231 refDistTreePt = &refGrid->tree();
4234 if (!mRefSignTree && !mRefIdxTree) {
4236 DistLeafManagerT refDistLeafs(*refDistTreePt);
4238 signDataOp(*refDistTreePt, refDistLeafs, isovalue);
4242 mRefSignTree = signDataOp.
signTree();
4243 mRefIdxTree = signDataOp.
idxTree();
4247 if (mRefSignTree && mRefIdxTree) {
4248 refSignTreePt =
static_cast<Int16TreeT*
>(mRefSignTree.get());
4249 refIdxTreePt =
static_cast<IntTreeT*
>(mRefIdxTree.get());
4255 Int16LeafManagerT signLeafs(*signTreePt);
4264 if (refSignTreePt) {
4271 seamMask.merge(seamOp.
mask());
4275 std::vector<size_t> regions(signLeafs.leafCount(), 0);
4276 if (regions.empty())
return;
4281 signLeafs, *signTreePt, distTree, *idxTreePt, isovalue, DistValueT(mPrimAdaptivity));
4283 if (adaptivityField) {
4287 if (refSignTreePt || mAdaptivityMaskTree) {
4291 if (refSignTreePt) {
4292 merge.
setRefData(refSignTreePt, DistValueT(mSecAdaptivity));
4307 for (
size_t n = 0, N = regions.size(); n < N; ++n) {
4309 regions[n] = mPointListSize;
4310 mPointListSize += tmp;
4317 mPointFlags.clear();
4320 if (refSignTreePt && refIdxTreePt) {
4322 if (mSeamPointListSize == 0) {
4324 std::vector<size_t> pointMap;
4327 Int16LeafManagerT refSignLeafs(*refSignTreePt);
4328 pointMap.resize(refSignLeafs.leafCount(), 0);
4333 for (
size_t n = 0, N = pointMap.size(); n < N; ++n) {
4335 pointMap[n] = mSeamPointListSize;
4336 mSeamPointListSize += tmp;
4340 if (!pointMap.empty() && mSeamPointListSize != 0) {
4342 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
4343 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
4347 IntLeafManagerT refIdxLeafs(*refIdxTreePt);
4352 if (mSeamPointListSize != 0) {
4354 distTree, *refSignTreePt, *refIdxTreePt, mQuantizedSeamPoints, mIsovalue));
4360 pointOp(signLeafs, distTree, *idxTreePt, mPoints, regions, transform, mIsovalue);
4363 if (mSeamPointListSize != 0) {
4364 mPointFlags.resize(mPointListSize);
4365 pointOp.
setRefData(refSignTreePt, refDistTreePt, refIdxTreePt,
4366 &mQuantizedSeamPoints, &mPointFlags);
4372 mPolygonPoolListSize = signLeafs.leafCount();
4373 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
4379 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4387 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4395 if ((surfaceMask || mPartitions > 1) && mPointListSize > 0) {
4398 std::vector<unsigned char> usedPointMask(mPointListSize, 0);
4404 std::vector<unsigned> indexMap(mPointListSize);
4405 size_t usedPointCount = 0;
4406 for (
size_t p = 0; p < mPointListSize; ++p) {
4407 if (usedPointMask[p]) indexMap[p] = usedPointCount++;
4410 if (usedPointCount < mPointListSize) {
4413 std::auto_ptr<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[usedPointCount]);
4418 mPointListSize = usedPointCount;
4419 mPoints.reset(newPointList.release());
4430 if (refSignTreePt || refIdxTreePt || refDistTreePt) {
4431 std::vector<Vec3s> newPoints;
4433 for (
size_t n = 0; n < mPolygonPoolListSize; ++n) {
4437 std::vector<size_t> nonPlanarQuads;
4438 nonPlanarQuads.reserve(polygons.
numQuads());
4440 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4448 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4449 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4451 if (!edgePoly)
continue;
4453 const Vec3s& p0 = mPoints[quad[0]];
4454 const Vec3s& p1 = mPoints[quad[1]];
4455 const Vec3s& p2 = mPoints[quad[2]];
4456 const Vec3s& p3 = mPoints[quad[3]];
4459 nonPlanarQuads.push_back(i);
4465 if (!nonPlanarQuads.empty()) {
4472 size_t triangleIdx = 0;
4473 for (
size_t i = 0; i < nonPlanarQuads.size(); ++i) {
4475 size_t& quadIdx = nonPlanarQuads[i];
4478 char& quadFlags = polygons.
quadFlags(quadIdx);
4481 Vec3s centroid = (mPoints[quad[0]] + mPoints[quad[1]] +
4482 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25;
4484 size_t pointIdx = newPoints.size() + mPointListSize;
4486 newPoints.push_back(centroid);
4492 triangle[0] = quad[0];
4493 triangle[1] = pointIdx;
4494 triangle[2] = quad[3];
4498 if (mPointFlags[triangle[0]] || mPointFlags[triangle[2]]) {
4508 triangle[0] = quad[0];
4509 triangle[1] = quad[1];
4510 triangle[2] = pointIdx;
4514 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4524 triangle[0] = quad[1];
4525 triangle[1] = quad[2];
4526 triangle[2] = pointIdx;
4530 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4541 triangle[0] = quad[2];
4542 triangle[1] = quad[3];
4543 triangle[2] = pointIdx;
4547 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4566 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4570 tmpPolygons.
quad(quadIdx) = quad;
4577 polygons.
copy(tmpPolygons);
4583 if (!newPoints.empty()) {
4585 size_t newPointCount = newPoints.size() + mPointListSize;
4587 std::auto_ptr<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointCount]);
4589 for (
size_t i = 0; i < mPointListSize; ++i) {
4590 newPointList.get()[i] = mPoints[i];
4593 for (
size_t i = mPointListSize; i < newPointCount; ++i) {
4594 newPointList.get()[i] = newPoints[i - mPointListSize];
4597 mPointListSize = newPointCount;
4598 mPoints.reset(newPointList.release());
4599 mPointFlags.resize(mPointListSize, 0);
4608 template<
typename Gr
idType>
4611 const GridType& grid,
4612 std::vector<Vec3s>& points,
4613 std::vector<Vec3I>& triangles,
4614 std::vector<Vec4I>& quads,
4627 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
4634 size_t numQuads = 0, numTriangles = 0;
4636 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4637 numTriangles += polygons.numTriangles();
4638 numQuads += polygons.numQuads();
4642 triangles.resize(numTriangles);
4644 quads.resize(numQuads);
4648 size_t qIdx = 0, tIdx = 0;
4650 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4652 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
4653 quads[qIdx++] = polygons.quad(i);
4656 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
4657 triangles[tIdx++] = polygons.triangle(i);
4663 template<
typename Gr
idType>
4666 const GridType& grid,
4667 std::vector<Vec3s>& points,
4668 std::vector<Vec4I>& quads,
4671 std::vector<Vec3I> triangles(0);
4672 volumeToMesh(grid,points, triangles, quads, isovalue, 0.0);
4683 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:321
OPENVDB_API const Index32 INVALID_IDX
boost::shared_ptr< const TreeBase > ConstPtr
Definition: Tree.h:68
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
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
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
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:328
int16_t Int16
Definition: Types.h:57
Mat3< double > Mat3d
Definition: Mat3.h:666
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:455
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
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: util/Util.h:55
Index32 Index
Definition: Types.h:56
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
Vec3< float > Vec3s
Definition: Vec3.h:604
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
boost::shared_ptr< const GridBase > ConstPtr
Definition: Grid.h:107
Abstract base class for typed grids.
Definition: Grid.h:103
Base class for typed trees.
Definition: Tree.h:64
#define OPENVDB_VERSION_NAME
Definition: version.h:45
Vec4< int32_t > Vec4i
Definition: Vec4.h:521
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
const MaskGridType * mMask
Definition: GridOperators.h:386
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
uint32_t Index32
Definition: Types.h:54
T & z()
Definition: Vec3.h:96
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Vec3< double > Vec3d
Definition: Vec3.h:605
boost::shared_ptr< TreeBase > Ptr
Definition: Tree.h:67
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
Gradient operators defined in index space of various orders.
Definition: Operators.h:122
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
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
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
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
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:295