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 size_t mNumQuads, mNumTriangles;
152 boost::scoped_array<openvdb::Vec4I> mQuads;
153 boost::scoped_array<openvdb::Vec3I> mTriangles;
154 boost::scoped_array<char> mQuadFlags, mTriangleFlags;
175 VolumeToMesh(
double isovalue = 0,
double adaptivity = 0);
182 const size_t& pointListSize()
const;
185 const size_t& polygonPoolListSize()
const;
189 std::vector<unsigned char>& pointFlags();
190 const std::vector<unsigned char>& pointFlags()
const;
198 template<
typename Gr
idT>
199 void operator()(
const GridT&);
247 void partition(
unsigned partitions = 1,
unsigned activePart = 0);
254 size_t mPointListSize, mSeamPointListSize, mPolygonPoolListSize;
255 double mIsovalue, mPrimAdaptivity, mSecAdaptivity;
262 bool mInvertSurfaceMask;
263 unsigned mPartitions, mActivePart;
265 boost::scoped_array<uint32_t> mQuantizedSeamPoints;
267 std::vector<unsigned char> mPointFlags;
281 const std::vector<Vec3d>& points,
282 const std::vector<Vec3d>& normals)
288 if (points.empty())
return avgPos;
290 for (
size_t n = 0, N = points.size(); n < N; ++n) {
294 avgPos /= double(points.size());
298 double m00=0,m01=0,m02=0,
305 for (
size_t n = 0, N = points.size(); n < N; ++n) {
307 const Vec3d& n_ref = normals[n];
310 m00 += n_ref[0] * n_ref[0];
311 m11 += n_ref[1] * n_ref[1];
312 m22 += n_ref[2] * n_ref[2];
314 m01 += n_ref[0] * n_ref[1];
315 m02 += n_ref[0] * n_ref[2];
316 m12 += n_ref[1] * n_ref[2];
319 rhs += n_ref * n_ref.
dot(points[n] - avgPos);
344 Mat3d D = Mat3d::identity();
347 double tolerance =
std::max(std::abs(eigenValues[0]), std::abs(eigenValues[1]));
348 tolerance =
std::max(tolerance, std::abs(eigenValues[2]));
352 for (
int i = 0; i < 3; ++i ) {
353 if (std::abs(eigenValues[i]) < tolerance) {
357 D[i][i] = 1.0 / eigenValues[i];
363 Mat3d pseudoInv = eigenVectors * D * eigenVectors.
transpose();
364 return avgPos + pseudoInv * rhs;
385 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,
386 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,
387 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,
388 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,
389 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,
390 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,
391 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,
392 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};
397 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,
398 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,
399 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,
400 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,
401 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,
402 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,
403 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,
404 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};
411 {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},
412 {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},
413 {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},
414 {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},
415 {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},
416 {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},
417 {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},
418 {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},
419 {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},
420 {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},
421 {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},
422 {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},
423 {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},
424 {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},
425 {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},
426 {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},
427 {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},
428 {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},
429 {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},
430 {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},
431 {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},
432 {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},
433 {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},
434 {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},
435 {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},
436 {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},
437 {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},
438 {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},
439 {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},
440 {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},
441 {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},
442 {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},
443 {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},
444 {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},
445 {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},
446 {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},
447 {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},
448 {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},
449 {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},
450 {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},
451 {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},
452 {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},
453 {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},
454 {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},
455 {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},
456 {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},
457 {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},
458 {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},
459 {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},
460 {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},
461 {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},
462 {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},
463 {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},
464 {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},
465 {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},
466 {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},
467 {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},
468 {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},
469 {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},
470 {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},
471 {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},
472 {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},
473 {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},
474 {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},
475 {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},
476 {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},
477 {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},
478 {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},
479 {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},
480 {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},
481 {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},
482 {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},
483 {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},
484 {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},
485 {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},
486 {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},
487 {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},
488 {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},
489 {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},
490 {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},
491 {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},
492 {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},
493 {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},
494 {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},
495 {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},
496 {0,0,0,0,0,0,0,0,0,0,0,0,0}};
505 double epsilon = 0.001)
508 Vec3d normal = (p2-p0).cross(p1-p3);
510 const Vec3d centroid = (p0 + p1 + p2 + p3);
511 const double d = centroid.
dot(normal) * 0.25;
515 double absDist = std::abs(p0.dot(normal) - d);
516 if (absDist > epsilon)
return false;
518 absDist = std::abs(p1.dot(normal) - d);
519 if (absDist > epsilon)
return false;
521 absDist = std::abs(p2.dot(normal) - d);
522 if (absDist > epsilon)
return false;
524 absDist = std::abs(p3.dot(normal) - d);
525 if (absDist > epsilon)
return false;
545 assert(!(v.x() > 1.0) && !(v.y() > 1.0) && !(v.z() > 1.0));
546 assert(!(v.x() < 0.0) && !(v.y() < 0.0) && !(v.z() < 0.0));
561 v.y() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
563 v.x() = double(data & MASK_FIRST_10_BITS) * 0.0009775171;
575 template<
typename AccessorT>
577 evalCellSigns(
const AccessorT& accessor,
const Coord& ijk,
typename AccessorT::ValueType iso)
581 if (accessor.getValue(coord) < iso) signs |= 1u;
583 if (accessor.getValue(coord) < iso) signs |= 2u;
585 if (accessor.getValue(coord) < iso) signs |= 4u;
587 if (accessor.getValue(coord) < iso) signs |= 8u;
588 coord[1] += 1; coord[2] = ijk[2];
589 if (accessor.getValue(coord) < iso) signs |= 16u;
591 if (accessor.getValue(coord) < iso) signs |= 32u;
593 if (accessor.getValue(coord) < iso) signs |= 64u;
595 if (accessor.getValue(coord) < iso) signs |= 128u;
602 template<
typename LeafT>
606 unsigned char signs = 0;
609 if (leaf.getValue(offset) < iso) signs |= 1u;
612 if (leaf.getValue(offset + 1) < iso) signs |= 8u;
615 if (leaf.getValue(offset + LeafT::DIM) < iso) signs |= 16u;
618 if (leaf.getValue(offset + LeafT::DIM + 1) < iso) signs |= 128u;
621 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) ) < iso) signs |= 2u;
624 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1) < iso) signs |= 4u;
627 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM) < iso) signs |= 32u;
630 if (leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1) < iso) signs |= 64u;
638 template<
class AccessorT>
641 const AccessorT& acc, Coord ijk,
typename AccessorT::ValueType iso)
646 }
else if (face == 3) {
649 }
else if (face == 2) {
652 }
else if (face == 4) {
655 }
else if (face == 5) {
658 }
else if (face == 6) {
665 template<
class AccessorT>
668 typename AccessorT::ValueType isovalue,
const int dim)
674 p[0] = accessor.getValue(coord) < isovalue;
676 p[1] = accessor.getValue(coord) < isovalue;
678 p[2] = accessor.getValue(coord) < isovalue;
680 p[3] = accessor.getValue(coord) < isovalue;
681 coord[1] += dim; coord[2] = ijk[2];
682 p[4] = accessor.getValue(coord) < isovalue;
684 p[5] = accessor.getValue(coord) < isovalue;
686 p[6] = accessor.getValue(coord) < isovalue;
688 p[7] = accessor.getValue(coord) < isovalue;
692 if (p[0]) signs |= 1u;
693 if (p[1]) signs |= 2u;
694 if (p[2]) signs |= 4u;
695 if (p[3]) signs |= 8u;
696 if (p[4]) signs |= 16u;
697 if (p[5]) signs |= 32u;
698 if (p[6]) signs |= 64u;
699 if (p[7]) signs |= 128u;
705 int i = ijk[0], ip = ijk[0] + hDim, ipp = ijk[0] + dim;
706 int j = ijk[1], jp = ijk[1] + hDim, jpp = ijk[1] + dim;
707 int k = ijk[2], kp = ijk[2] + hDim, kpp = ijk[2] + dim;
710 coord.reset(ip, j, k);
711 m = accessor.getValue(coord) < isovalue;
712 if (p[0] != m && p[1] != m)
return true;
715 coord.reset(ipp, j, kp);
716 m = accessor.getValue(coord) < isovalue;
717 if (p[1] != m && p[2] != m)
return true;
720 coord.reset(ip, j, kpp);
721 m = accessor.getValue(coord) < isovalue;
722 if (p[2] != m && p[3] != m)
return true;
725 coord.reset(i, j, kp);
726 m = accessor.getValue(coord) < isovalue;
727 if (p[0] != m && p[3] != m)
return true;
730 coord.reset(ip, jpp, k);
731 m = accessor.getValue(coord) < isovalue;
732 if (p[4] != m && p[5] != m)
return true;
735 coord.reset(ipp, jpp, kp);
736 m = accessor.getValue(coord) < isovalue;
737 if (p[5] != m && p[6] != m)
return true;
740 coord.reset(ip, jpp, kpp);
741 m = accessor.getValue(coord) < isovalue;
742 if (p[6] != m && p[7] != m)
return true;
745 coord.reset(i, jpp, kp);
746 m = accessor.getValue(coord) < isovalue;
747 if (p[7] != m && p[4] != m)
return true;
750 coord.reset(i, jp, k);
751 m = accessor.getValue(coord) < isovalue;
752 if (p[0] != m && p[4] != m)
return true;
755 coord.reset(ipp, jp, k);
756 m = accessor.getValue(coord) < isovalue;
757 if (p[1] != m && p[5] != m)
return true;
760 coord.reset(ipp, jp, kpp);
761 m = accessor.getValue(coord) < isovalue;
762 if (p[2] != m && p[6] != m)
return true;
766 coord.reset(i, jp, kpp);
767 m = accessor.getValue(coord) < isovalue;
768 if (p[3] != m && p[7] != m)
return true;
774 coord.reset(ip, jp, k);
775 m = accessor.getValue(coord) < isovalue;
776 if (p[0] != m && p[1] != m && p[4] != m && p[5] != m)
return true;
779 coord.reset(ipp, jp, kp);
780 m = accessor.getValue(coord) < isovalue;
781 if (p[1] != m && p[2] != m && p[5] != m && p[6] != m)
return true;
784 coord.reset(ip, jp, kpp);
785 m = accessor.getValue(coord) < isovalue;
786 if (p[2] != m && p[3] != m && p[6] != m && p[7] != m)
return true;
789 coord.reset(i, jp, kp);
790 m = accessor.getValue(coord) < isovalue;
791 if (p[0] != m && p[3] != m && p[4] != m && p[7] != m)
return true;
794 coord.reset(ip, j, kp);
795 m = accessor.getValue(coord) < isovalue;
796 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m)
return true;
799 coord.reset(ip, jpp, kp);
800 m = accessor.getValue(coord) < isovalue;
801 if (p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
804 coord.reset(ip, jp, kp);
805 m = accessor.getValue(coord) < isovalue;
806 if (p[0] != m && p[1] != m && p[2] != m && p[3] != m &&
807 p[4] != m && p[5] != m && p[6] != m && p[7] != m)
return true;
816 template <
class LeafType>
818 mergeVoxels(LeafType& leaf,
const Coord& start,
int dim,
int regionId)
820 Coord ijk, end = start;
825 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
826 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
827 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
828 if(leaf.isValueOn(ijk)) leaf.setValue(ijk, regionId);
837 template <
class LeafType>
840 typename LeafType::ValueType::value_type adaptivity)
842 if (adaptivity < 1e-6)
return false;
844 typedef typename LeafType::ValueType VecT;
845 Coord ijk, end = start;
850 std::vector<VecT> norms;
851 for (ijk[0] = start[0]; ijk[0] < end[0]; ++ijk[0]) {
852 for (ijk[1] = start[1]; ijk[1] < end[1]; ++ijk[1]) {
853 for (ijk[2] = start[2]; ijk[2] < end[2]; ++ijk[2]) {
855 if(!leaf.isValueOn(ijk))
continue;
856 norms.push_back(leaf.getValue(ijk));
861 size_t N = norms.size();
862 for (
size_t ni = 0; ni < N; ++ni) {
863 VecT n_i = norms[ni];
864 for (
size_t nj = 0; nj < N; ++nj) {
865 VecT n_j = norms[nj];
866 if ((1.0 - n_i.dot(n_j)) > adaptivity)
return false;
876 template<
typename TreeT,
typename LeafManagerT>
880 typedef typename TreeT::ValueType
ValueT;
883 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
886 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
892 SignData(
const TreeT& distTree,
const LeafManagerT& leafs,
ValueT iso);
894 void run(
bool threaded =
true);
896 typename Int16TreeT::Ptr
signTree()
const {
return mSignTree; }
897 typename IntTreeT::Ptr
idxTree()
const {
return mIdxTree; }
902 void operator()(
const tbb::blocked_range<size_t>&);
905 mSignTree->merge(*rhs.mSignTree);
906 mIdxTree->merge(*rhs.mIdxTree);
911 const TreeT& mDistTree;
914 const LeafManagerT& mLeafs;
917 typename Int16TreeT::Ptr mSignTree;
918 Int16AccessorT mSignAcc;
920 typename IntTreeT::Ptr mIdxTree;
921 IntAccessorT mIdxAcc;
926 template<
typename TreeT,
typename LeafManagerT>
928 const LeafManagerT& leafs,
ValueT iso)
929 : mDistTree(distTree)
930 , mDistAcc(mDistTree)
934 , mSignAcc(*mSignTree)
941 template<
typename TreeT,
typename LeafManagerT>
943 : mDistTree(rhs.mDistTree)
944 , mDistAcc(mDistTree)
946 , mIsovalue(rhs.mIsovalue)
948 , mSignAcc(*mSignTree)
955 template<
typename TreeT,
typename LeafManagerT>
959 if (threaded) tbb::parallel_reduce(mLeafs.getRange(), *
this);
960 else (*
this)(mLeafs.getRange());
963 template<
typename TreeT,
typename LeafManagerT>
967 typedef typename Int16TreeT::LeafNodeType Int16LeafT;
968 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
969 unsigned char signs, face;
972 std::auto_ptr<Int16LeafT> signLeafPt(
new Int16LeafT(ijk, 0));
974 for (
size_t n = range.begin(); n != range.end(); ++n) {
976 bool collectedData =
false;
978 coord = mLeafs.leaf(n).origin();
980 if (!signLeafPt.get()) signLeafPt.reset(
new Int16LeafT(coord, 0));
981 else signLeafPt->setOrigin(coord);
983 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
985 coord.offset(TreeT::LeafNodeType::DIM - 1);
987 for (iter = mLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
989 ijk = iter.getCoord();
991 if (leafPt && ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
997 if (signs != 0 && signs != 0xFF) {
1000 if (
bool(signs & 0x1) != bool(signs & 0x2)) flags |=
XEDGE;
1001 if (
bool(signs & 0x1) != bool(signs & 0x10)) flags |=
YEDGE;
1002 if (
bool(signs & 0x1) != bool(signs & 0x8)) flags |=
ZEDGE;
1007 flags |=
Int16(signs);
1009 signLeafPt->setValue(ijk, flags);
1010 collectedData =
true;
1014 if (collectedData) {
1015 mIdxAcc.touchLeaf(coord)->topologyUnion(*signLeafPt);
1016 mSignAcc.addLeaf(signLeafPt.release());
1029 CountPoints(std::vector<size_t>& pointList) : mPointList(pointList) {}
1031 template <
typename LeafNodeType>
1036 typename LeafNodeType::ValueOnCIter iter = leaf.cbeginValueOn();
1037 for (; iter; ++iter) {
1041 mPointList[leafIndex] = points;
1045 std::vector<size_t>& mPointList;
1050 template<
typename Int16TreeT>
1056 MapPoints(std::vector<size_t>& pointList,
const Int16TreeT& signTree)
1057 : mPointList(pointList)
1058 , mSignAcc(signTree)
1062 template <
typename LeafNodeType>
1065 size_t ptnIdx = mPointList[leafIndex];
1066 typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn();
1068 const typename Int16TreeT::LeafNodeType *signLeafPt =
1071 for (; iter; ++iter) {
1072 iter.setValue(ptnIdx);
1073 unsigned signs =
SIGNS & signLeafPt->getValue(iter.pos());
1079 std::vector<size_t>& mPointList;
1085 template<
typename IntTreeT>
1098 template <
typename LeafNodeType>
1106 typename IntLeafT::ValueOnIter iter = tmpLeaf.beginValueOn();
1107 for (; iter; ++iter) {
1108 if(iter.getValue() == 0) {
1114 int onVoxelCount = int(tmpLeaf.onVoxelCount());
1115 while (onVoxelCount > 0) {
1117 iter = tmpLeaf.beginValueOn();
1118 int regionId = iter.getValue();
1119 for (; iter; ++iter) {
1120 if (iter.getValue() == regionId) {
1127 mRegions[leafIndex] = regions;
1132 std::vector<size_t>& mRegions;
1140 inline double evalRoot(
double v0,
double v1,
double iso) {
return (iso - v0) / (v1 - v0); }
1144 template<
typename LeafT>
1148 values[0] = double(leaf.getValue(offset));
1149 values[3] = double(leaf.getValue(offset + 1));
1150 values[4] = double(leaf.getValue(offset + LeafT::DIM));
1151 values[7] = double(leaf.getValue(offset + LeafT::DIM + 1));
1152 values[1] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM)));
1153 values[2] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + 1));
1154 values[5] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM));
1155 values[6] = double(leaf.getValue(offset + (LeafT::DIM * LeafT::DIM) + LeafT::DIM + 1));
1160 template<
typename AccessorT>
1165 values[0] = double(acc.getValue(coord));
1168 values[1] = double(acc.getValue(coord));
1171 values[2] = double(acc.getValue(coord));
1174 values[3] = double(acc.getValue(coord));
1176 coord[1] += 1; coord[2] = ijk[2];
1177 values[4] = double(acc.getValue(coord));
1180 values[5] = double(acc.getValue(coord));
1183 values[6] = double(acc.getValue(coord));
1186 values[7] = double(acc.getValue(coord));
1193 unsigned char edgeGroup,
double iso)
1195 Vec3d avg(0.0, 0.0, 0.0);
1199 avg[0] +=
evalRoot(values[0], values[1], iso);
1205 avg[2] +=
evalRoot(values[1], values[2], iso);
1210 avg[0] +=
evalRoot(values[3], values[2], iso);
1216 avg[2] +=
evalRoot(values[0], values[3], iso);
1221 avg[0] +=
evalRoot(values[4], values[5], iso);
1229 avg[2] +=
evalRoot(values[5], values[6], iso);
1234 avg[0] +=
evalRoot(values[7], values[6], iso);
1242 avg[2] +=
evalRoot(values[4], values[7], iso);
1247 avg[1] +=
evalRoot(values[0], values[4], iso);
1253 avg[1] +=
evalRoot(values[1], values[5], iso);
1259 avg[1] +=
evalRoot(values[2], values[6], iso);
1265 avg[1] +=
evalRoot(values[3], values[7], iso);
1271 double w = 1.0 / double(samples);
1285 unsigned char signsMask,
unsigned char edgeGroup,
double iso)
1287 avg =
Vec3d(0.0, 0.0, 0.0);
1292 avg[0] +=
evalRoot(values[0], values[1], iso);
1299 avg[2] +=
evalRoot(values[1], values[2], iso);
1305 avg[0] +=
evalRoot(values[3], values[2], iso);
1312 avg[2] +=
evalRoot(values[0], values[3], iso);
1318 avg[0] +=
evalRoot(values[4], values[5], iso);
1327 avg[2] +=
evalRoot(values[5], values[6], iso);
1333 avg[0] +=
evalRoot(values[7], values[6], iso);
1342 avg[2] +=
evalRoot(values[4], values[7], iso);
1348 avg[1] +=
evalRoot(values[0], values[4], iso);
1355 avg[1] +=
evalRoot(values[1], values[5], iso);
1362 avg[1] +=
evalRoot(values[2], values[6], iso);
1369 avg[1] +=
evalRoot(values[3], values[7], iso);
1375 double w = 1.0 / double(samples);
1389 unsigned char signs,
unsigned char edgeGroup,
double iso)
1391 std::vector<Vec3d> samples;
1394 std::vector<double> weights;
1397 Vec3d avg(0.0, 0.0, 0.0);
1400 avg[0] =
evalRoot(values[0], values[1], iso);
1404 samples.push_back(avg);
1405 weights.push_back((avg-p).lengthSqr());
1411 avg[2] =
evalRoot(values[1], values[2], iso);
1413 samples.push_back(avg);
1414 weights.push_back((avg-p).lengthSqr());
1418 avg[0] =
evalRoot(values[3], values[2], iso);
1422 samples.push_back(avg);
1423 weights.push_back((avg-p).lengthSqr());
1429 avg[2] =
evalRoot(values[0], values[3], iso);
1431 samples.push_back(avg);
1432 weights.push_back((avg-p).lengthSqr());
1436 avg[0] =
evalRoot(values[4], values[5], iso);
1440 samples.push_back(avg);
1441 weights.push_back((avg-p).lengthSqr());
1447 avg[2] =
evalRoot(values[5], values[6], iso);
1449 samples.push_back(avg);
1450 weights.push_back((avg-p).lengthSqr());
1454 avg[0] =
evalRoot(values[7], values[6], iso);
1458 samples.push_back(avg);
1459 weights.push_back((avg-p).lengthSqr());
1465 avg[2] =
evalRoot(values[4], values[7], iso);
1467 samples.push_back(avg);
1468 weights.push_back((avg-p).lengthSqr());
1473 avg[1] =
evalRoot(values[0], values[4], iso);
1476 samples.push_back(avg);
1477 weights.push_back((avg-p).lengthSqr());
1482 avg[1] =
evalRoot(values[1], values[5], iso);
1485 samples.push_back(avg);
1486 weights.push_back((avg-p).lengthSqr());
1491 avg[1] =
evalRoot(values[2], values[6], iso);
1494 samples.push_back(avg);
1495 weights.push_back((avg-p).lengthSqr());
1500 avg[1] =
evalRoot(values[3], values[7], iso);
1503 samples.push_back(avg);
1504 weights.push_back((avg-p).lengthSqr());
1511 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1512 minWeight =
std::min(minWeight, weights[i]);
1513 maxWeight =
std::max(maxWeight, weights[i]);
1516 const double offset = maxWeight + minWeight * 0.1;
1517 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1518 weights[i] = offset - weights[i];
1522 double weightSum = 0.0;
1523 for (
size_t i = 0, I = weights.size(); i < I; ++i) {
1524 weightSum += weights[i];
1531 if (samples.size() > 1) {
1532 for (
size_t i = 0, I = samples.size(); i < I; ++i) {
1533 avg += samples[i] * (weights[i] / weightSum);
1536 avg = samples.front();
1547 const std::vector<double>& values,
unsigned char signs,
double iso)
1559 matchEdgeGroup(
unsigned char groupId,
unsigned char lhsSigns,
unsigned char rhsSigns)
1562 for (
size_t i = 1; i <= 12; ++i) {
1578 const std::vector<double>& lhsValues,
const std::vector<double>& rhsValues,
1579 unsigned char lhsSigns,
unsigned char rhsSigns,
1580 double iso,
size_t pointIdx,
const boost::scoped_array<uint32_t>& seamPoints)
1582 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1588 const unsigned char e(
id);
1589 uint32_t& quantizedPoint = seamPoints[pointIdx + (
id - 1)];
1594 weightedPointMask.push_back(
true);
1596 points.push_back(
computePoint(rhsValues, rhsSigns, e, iso));
1597 weightedPointMask.push_back(
false);
1601 points.push_back(
computePoint(lhsValues, lhsSigns, n, iso));
1602 weightedPointMask.push_back(
false);
1608 template <
typename TreeT,
typename LeafManagerT>
1614 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1618 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1626 GenPoints(
const LeafManagerT& signLeafs,
const TreeT& distTree,
1630 void run(
bool threaded =
true);
1634 std::vector<unsigned char>* mSeamPointMaskPt = NULL);
1639 void operator()(
const tbb::blocked_range<size_t>&)
const;
1642 const LeafManagerT& mSignLeafs;
1648 std::vector<size_t>& mIndices;
1650 const double mIsovalue;
1654 const TreeT* mRefDistTreePt;
1657 std::vector<unsigned char>* mSeamPointMaskPt;
1661 template <
typename TreeT,
typename LeafManagerT>
1664 std::vector<size_t>& indices,
const math::Transform& xform,
double iso)
1665 : mSignLeafs(signLeafs)
1666 , mDistAcc(distTree)
1672 , mRefSignTreePt(NULL)
1673 , mRefDistTreePt(NULL)
1674 , mRefIdxTreePt(NULL)
1675 , mSeamPointsPt(NULL)
1676 , mSeamPointMaskPt(NULL)
1681 template <
typename TreeT,
typename LeafManagerT>
1685 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
1686 else (*
this)(mSignLeafs.getRange());
1690 template <
typename TreeT,
typename LeafManagerT>
1695 mRefSignTreePt = refSignTree;
1696 mRefDistTreePt = refDistTree;
1697 mRefIdxTreePt = refIdxTree;
1698 mSeamPointsPt = seamPoints;
1699 mSeamPointMaskPt = seamPointMask;
1703 template <
typename TreeT,
typename LeafManagerT>
1706 const tbb::blocked_range<size_t>& range)
const
1708 typename IntTreeT::LeafNodeType::ValueOnIter iter;
1709 unsigned char signs, refSigns;
1712 std::vector<Vec3d> points(4);
1713 std::vector<bool> weightedPointMask(4);
1714 std::vector<double> values(8), refValues(8);
1720 boost::scoped_ptr<Int16CAccessorT> refSignAcc;
1721 if (mRefSignTreePt) refSignAcc.reset(
new Int16CAccessorT(*mRefSignTreePt));
1723 boost::scoped_ptr<IntCAccessorT> refIdxAcc;
1724 if (mRefIdxTreePt) refIdxAcc.reset(
new IntCAccessorT(*mRefIdxTreePt));
1726 boost::scoped_ptr<AccessorT> refDistAcc;
1727 if (mRefDistTreePt) refDistAcc.reset(
new AccessorT(*mRefDistTreePt));
1730 for (
size_t n = range.begin(); n != range.end(); ++n) {
1732 coord = mSignLeafs.leaf(n).origin();
1734 const typename TreeT::LeafNodeType *leafPt = mDistAcc.probeConstLeaf(coord);
1735 typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeLeaf(coord);
1739 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
1740 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(coord);
1742 const typename IntTreeT::LeafNodeType *refIdxLeafPt = NULL;
1743 if (refIdxAcc) refIdxLeafPt = refIdxAcc->probeConstLeaf(coord);
1745 const typename TreeT::LeafNodeType *refDistLeafPt = NULL;
1746 if (refDistAcc) refDistLeafPt = refDistAcc->probeConstLeaf(coord);
1750 size_t ptnIdx = mIndices[n];
1751 coord.offset(TreeT::LeafNodeType::DIM - 1);
1755 for (iter = idxLeafPt->beginValueOn(); iter; ++iter) {
1757 if(iter.getValue() != 0)
continue;
1759 iter.setValue(ptnIdx);
1761 offset = iter.pos();
1762 ijk = iter.getCoord();
1764 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1766 const Int16& flags = mSignLeafs.leaf(n).getValue(offset);
1767 signs =
SIGNS & flags;
1770 if ((flags &
SEAM) && refSignLeafPt && refIdxLeafPt) {
1771 if (refSignLeafPt->isValueOn(offset)) {
1772 refSigns = (
SIGNS & refSignLeafPt->getValue(offset));
1782 weightedPointMask.clear();
1784 if (refSigns == 0) {
1791 computeCellPoints(points, weightedPointMask, values, refValues, signs, refSigns,
1792 mIsovalue, refIdxLeafPt->getValue(offset), *mSeamPointsPt);
1796 for (
size_t i = 0, I = points.size(); i < I; ++i) {
1799 points[i][0] += double(ijk[0]);
1800 points[i][1] += double(ijk[1]);
1801 points[i][2] += double(ijk[2]);
1804 points[i] = mTransform.indexToWorld(points[i]);
1806 mPoints[ptnIdx][0] = float(points[i][0]);
1807 mPoints[ptnIdx][1] = float(points[i][1]);
1808 mPoints[ptnIdx][2] = float(points[i][2]);
1810 if (mSeamPointMaskPt && !weightedPointMask.empty() && weightedPointMask[i]) {
1811 (*mSeamPointMaskPt)[ptnIdx] = 1;
1819 int onVoxelCount = int(idxLeafPt->onVoxelCount());
1820 while (onVoxelCount > 0) {
1822 iter = idxLeafPt->beginValueOn();
1823 int regionId = iter.getValue(), count = 0;
1825 Vec3d avg(0.0), point;
1827 for (; iter; ++iter) {
1828 if (iter.getValue() != regionId)
continue;
1830 iter.setValue(ptnIdx);
1834 ijk = iter.getCoord();
1835 offset = iter.pos();
1837 signs = (
SIGNS & mSignLeafs.leaf(n).getValue(offset));
1839 if (ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2]) {
1848 avg[0] += double(ijk[0]) + points[0][0];
1849 avg[1] += double(ijk[1]) + points[0][1];
1850 avg[2] += double(ijk[2]) + points[0][2];
1857 double w = 1.0 / double(count);
1863 avg = mTransform.indexToWorld(avg);
1865 mPoints[ptnIdx][0] = float(avg[0]);
1866 mPoints[ptnIdx][1] = float(avg[1]);
1867 mPoints[ptnIdx][2] = float(avg[2]);
1878 template<
typename TreeT>
1884 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
1887 typedef typename TreeT::template ValueConverter<Int16>::Type
Int16TreeT;
1897 template <
typename LeafNodeType>
1898 void operator()(LeafNodeType &signLeaf,
size_t leafIndex)
const;
1906 const double mIsovalue;
1910 template<
typename TreeT>
1913 : mDistAcc(distTree)
1914 , mRefSignAcc(refSignTree)
1915 , mRefIdxAcc(refIdxTree)
1922 template<
typename TreeT>
1923 template <
typename LeafNodeType>
1927 Coord coord = signLeaf.origin();
1928 const typename Int16TreeT::LeafNodeType *refSignLeafPt = mRefSignAcc.probeConstLeaf(coord);
1930 if (!refSignLeafPt)
return;
1932 const typename TreeT::LeafNodeType *distLeafPt = mDistAcc.probeConstLeaf(coord);
1933 const typename IntTreeT::LeafNodeType *refIdxLeafPt = mRefIdxAcc.probeConstLeaf(coord);
1935 std::vector<double> values(8);
1936 unsigned char lhsSigns, rhsSigns;
1941 coord.offset(TreeT::LeafNodeType::DIM - 1);
1943 typename LeafNodeType::ValueOnCIter iter = signLeaf.cbeginValueOn();
1944 for (; iter; ++iter) {
1946 offset = iter.pos();
1947 ijk = iter.getCoord();
1949 const bool inclusiveCell = ijk[0] < coord[0] && ijk[1] < coord[1] && ijk[2] < coord[2];
1951 if ((iter.getValue() &
SEAM) && refSignLeafPt->isValueOn(offset)) {
1953 lhsSigns =
SIGNS & iter.getValue();
1954 rhsSigns =
SIGNS & refSignLeafPt->getValue(offset);
1957 if (inclusiveCell) {
1964 for (
size_t n = 1, N =
sEdgeGroupTable[lhsSigns][0] + 1; n < N; ++n) {
1970 uint32_t& data = mPoints[refIdxLeafPt->getValue(offset) + (
id - 1)];
1976 if (smaples > 0) data =
packPoint(point);
1991 template <
typename TreeT,
typename LeafManagerT>
1998 typedef typename TreeT::template ValueConverter<int>::Type
IntTreeT;
2001 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2003 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2006 typedef typename TreeT::template ValueConverter<float>::Type
FloatTreeT;
2015 void run(
bool threaded =
true);
2027 void operator()(
const tbb::blocked_range<size_t>&)
const;
2031 const LeafManagerT& mSignLeafs;
2036 const TreeT& mDistTree;
2040 ValueT mIsovalue, mSurfaceAdaptivity, mInternalAdaptivity;
2049 template <
typename TreeT,
typename LeafManagerT>
2051 const LeafManagerT& signLeafs,
const Int16TreeT& signTree,
2053 : mSignLeafs(signLeafs)
2054 , mSignTree(signTree)
2055 , mSignAcc(mSignTree)
2056 , mDistTree(distTree)
2057 , mDistAcc(mDistTree)
2060 , mSurfaceAdaptivity(adaptivity)
2061 , mInternalAdaptivity(adaptivity)
2063 , mAdaptivityGrid(NULL)
2065 , mRefSignTree(NULL)
2070 template <
typename TreeT,
typename LeafManagerT>
2074 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2075 else (*
this)(mSignLeafs.getRange());
2079 template <
typename TreeT,
typename LeafManagerT>
2084 mTransform = &distGridXForm;
2085 mAdaptivityGrid = &adaptivityField;
2089 template <
typename TreeT,
typename LeafManagerT>
2096 template <
typename TreeT,
typename LeafManagerT>
2100 mRefSignTree = signTree;
2101 mInternalAdaptivity = adaptivity;
2105 template <
typename TreeT,
typename LeafManagerT>
2111 typedef typename TreeT::LeafNodeType LeafT;
2112 typedef typename IntTreeT::LeafNodeType IntLeafT;
2113 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2114 typedef typename LeafT::template ValueConverter<Vec3T>::Type Vec3LeafT;
2116 const int LeafDim = LeafT::DIM;
2120 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2123 boost::scoped_ptr<FloatTreeCAccessorT> adaptivityAcc;
2124 if (mAdaptivityGrid) {
2125 adaptivityAcc.reset(
new FloatTreeCAccessorT(mAdaptivityGrid->tree()));
2129 boost::scoped_ptr<Int16TreeCAccessorT> refAcc;
2131 refAcc.reset(
new Int16TreeCAccessorT(*mRefSignTree));
2135 boost::scoped_ptr<BoolTreeCAccessorT> maskAcc;
2137 maskAcc.reset(
new BoolTreeCAccessorT(*mMask));
2142 Vec3LeafT gradientBuffer;
2143 Coord ijk, nijk, coord, end;
2145 for (
size_t n = range.begin(); n != range.end(); ++n) {
2147 const Coord& origin = mSignLeafs.leaf(n).origin();
2149 ValueT adaptivity = mSurfaceAdaptivity;
2151 if (refAcc && refAcc->probeConstLeaf(origin) == NULL) {
2152 adaptivity = mInternalAdaptivity;
2155 IntLeafT& idxLeaf = *idxAcc.
probeLeaf(origin);
2157 end[0] = origin[0] + LeafDim;
2158 end[1] = origin[1] + LeafDim;
2159 end[2] = origin[2] + LeafDim;
2161 mask.setValuesOff();
2165 const BoolLeafT* maskLeaf = maskAcc->probeConstLeaf(origin);
2166 if (maskLeaf != NULL) {
2167 typename BoolLeafT::ValueOnCIter it;
2168 for (it = maskLeaf->cbeginValueOn(); it; ++it) {
2169 ijk = it.getCoord();
2170 coord[0] = ijk[0] - (ijk[0] % 2);
2171 coord[1] = ijk[1] - (ijk[1] % 2);
2172 coord[2] = ijk[2] - (ijk[2] % 2);
2173 mask.setActiveState(coord,
true);
2179 LeafT adaptivityLeaf(origin, adaptivity);
2181 if (mAdaptivityGrid) {
2182 for (
Index offset = 0; offset < LeafT::NUM_VALUES; ++offset) {
2183 ijk = adaptivityLeaf.offsetToGlobalCoord(offset);
2184 Vec3d xyz = mAdaptivityGrid->transform().worldToIndex(
2185 mTransform->indexToWorld(ijk));
2187 adaptivityLeaf.setValueOnly(offset, tmpA * adaptivity);
2192 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2193 ijk = iter.getCoord();
2194 coord[0] = ijk[0] - (ijk[0] % 2);
2195 coord[1] = ijk[1] - (ijk[1] % 2);
2196 coord[2] = ijk[2] - (ijk[2] % 2);
2197 if(mask.isValueOn(coord))
continue;
2201 int flags = int(iter.getValue());
2202 unsigned char signs =
SIGNS & flags;
2204 mask.setActiveState(coord,
true);
2208 for (
int i = 0; i < 26; ++i) {
2210 signs =
SIGNS & mSignAcc.getValue(nijk);
2212 mask.setActiveState(coord,
true);
2220 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2221 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2222 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2224 mask.setActiveState(ijk,
true);
2231 gradientBuffer.setValuesOff();
2232 for (iter = mSignLeafs.leaf(n).cbeginValueOn(); iter; ++iter) {
2234 ijk = iter.getCoord();
2235 coord[0] = ijk[0] - (ijk[0] % dim);
2236 coord[1] = ijk[1] - (ijk[1] % dim);
2237 coord[2] = ijk[2] - (ijk[2] % dim);
2238 if(mask.isValueOn(coord))
continue;
2242 ValueT length = norm.length();
2243 if (length >
ValueT(1.0e-7)) {
2244 norm *=
ValueT(1.0) / length;
2246 gradientBuffer.setValue(ijk, norm);
2249 int regionId = 1, next_dim = dim << 1;
2252 for (ijk[0] = 0; ijk[0] < LeafDim; ijk[0] += dim) {
2253 coord[0] = ijk[0] - (ijk[0] % next_dim);
2254 for (ijk[1] = 0; ijk[1] < LeafDim; ijk[1] += dim) {
2255 coord[1] = ijk[1] - (ijk[1] % next_dim);
2256 for (ijk[2] = 0; ijk[2] < LeafDim; ijk[2] += dim) {
2257 coord[2] = ijk[2] - (ijk[2] % next_dim);
2258 adaptivity = adaptivityLeaf.getValue(ijk);
2259 if (mask.isValueOn(ijk) || !
isMergable(gradientBuffer, ijk, dim, adaptivity)) {
2260 mask.setActiveState(coord,
true);
2270 for (dim = 4; dim < LeafDim; dim = dim << 1) {
2271 next_dim = dim << 1;
2272 coord[0] = ijk[0] - (ijk[0] % next_dim);
2273 for (ijk[0] = origin[0]; ijk[0] < end[0]; ijk[0] += dim) {
2274 coord[1] = ijk[1] - (ijk[1] % next_dim);
2275 for (ijk[1] = origin[1]; ijk[1] < end[1]; ijk[1] += dim) {
2276 coord[2] = ijk[2] - (ijk[2] % next_dim);
2277 for (ijk[2] = origin[2]; ijk[2] < end[2]; ijk[2] += dim) {
2278 adaptivity = adaptivityLeaf.getValue(ijk);
2279 if (mask.isValueOn(ijk) ||
isNonManifold(mDistAcc, ijk, mIsovalue, dim) ||
2280 !
isMergable(gradientBuffer, ijk, dim, adaptivity))
2282 mask.setActiveState(coord,
true);
2291 adaptivity = adaptivityLeaf.getValue(origin);
2292 if (!(mask.isValueOn(origin) ||
isNonManifold(mDistAcc, origin, mIsovalue, LeafDim))
2293 &&
isMergable(gradientBuffer, origin, LeafDim, adaptivity))
2295 mergeVoxels(idxLeaf, origin, LeafDim, regionId++);
2311 mPolygonPool = &quadPool;
2319 mPolygonPool->
quad(mIdx) = verts;
2343 : mQuadIdx(0), mTriangleIdx(0), mPolygonPool(NULL), mTmpPolygonPool() {}
2347 mPolygonPool = &polygonPool;
2358 if (verts[0] != verts[1] && verts[0] != verts[2] && verts[0] != verts[3]
2359 && verts[1] != verts[2] && verts[1] != verts[3] && verts[2] != verts[3]) {
2360 mTmpPolygonPool.
quadFlags(mQuadIdx) = flags;
2361 addQuad(verts, reverse);
2363 verts[0] == verts[3] &&
2364 verts[1] != verts[2] &&
2365 verts[1] != verts[0] &&
2366 verts[2] != verts[0]) {
2368 addTriangle(verts[0], verts[1], verts[2], reverse);
2370 verts[1] == verts[2] &&
2371 verts[0] != verts[3] &&
2372 verts[0] != verts[1] &&
2373 verts[3] != verts[1]) {
2375 addTriangle(verts[0], verts[1], verts[3], reverse);
2377 verts[0] == verts[1] &&
2378 verts[2] != verts[3] &&
2379 verts[2] != verts[0] &&
2380 verts[3] != verts[0]) {
2382 addTriangle(verts[0], verts[2], verts[3], reverse);
2384 verts[2] == verts[3] &&
2385 verts[0] != verts[1] &&
2386 verts[0] != verts[2] &&
2387 verts[1] != verts[2]) {
2389 addTriangle(verts[0], verts[1], verts[2], reverse);
2397 for (
size_t i = 0; i < mQuadIdx; ++i) {
2398 mPolygonPool->
quad(i) = mTmpPolygonPool.
quad(i);
2404 for (
size_t i = 0; i < mTriangleIdx; ++i) {
2413 void addQuad(
const Vec4I& verts,
bool reverse)
2416 mTmpPolygonPool.
quad(mQuadIdx) = verts;
2418 Vec4I& quad = mTmpPolygonPool.
quad(mQuadIdx);
2427 void addTriangle(
unsigned v0,
unsigned v1,
unsigned v2,
bool reverse)
2443 size_t mQuadIdx, mTriangleIdx;
2444 PolygonPool *mPolygonPool;
2445 PolygonPool mTmpPolygonPool;
2449 template<
typename SignAccT,
typename IdxAccT,
typename PrimBuilder>
2452 const SignAccT& signAcc,
const IdxAccT& idxAcc, PrimBuilder& mesher,
Index32 pointListSize)
2458 const bool isInside = flags &
INSIDE;
2459 const int v0 = idxAcc.getValue(ijk);
2465 if (flags &
XEDGE) {
2467 quad[0] = v0 + offsets[0];
2468 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
2469 quad[1] = idxAcc.getValue(coord);
2471 cell =
SIGNS & signAcc.getValue(coord);
2474 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2478 quad[2] = idxAcc.getValue(coord);
2480 cell =
SIGNS & signAcc.getValue(coord);
2483 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2487 quad[3] = idxAcc.getValue(coord);
2489 cell =
SIGNS & signAcc.getValue(coord);
2492 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2495 mesher.addPrim(quad, isInside, tag[
bool(refFlags & XEDGE)]);
2499 if (flags &
YEDGE) {
2501 quad[0] = v0 + offsets[1];
2502 coord[0] = ijk[0]; coord[1] = ijk[1]; coord[2] = ijk[2]-1;
2503 quad[1] = idxAcc.getValue(coord);
2505 cell =
SIGNS & signAcc.getValue(coord);
2508 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2512 quad[2] = idxAcc.getValue(coord);
2514 cell =
SIGNS & signAcc.getValue(coord);
2517 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2521 quad[3] = idxAcc.getValue(coord);
2523 cell =
SIGNS & signAcc.getValue(coord);
2526 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2529 mesher.addPrim(quad, isInside, tag[
bool(refFlags & YEDGE)]);
2533 if (flags &
ZEDGE) {
2535 quad[0] = v0 + offsets[2];
2536 coord[0] = ijk[0]; coord[1] = ijk[1]-1; coord[2] = ijk[2];
2537 quad[1] = idxAcc.getValue(coord);
2539 cell =
SIGNS & signAcc.getValue(coord);
2542 if (tmpIdx < pointListSize) quad[1] = tmpIdx;
2546 quad[2] = idxAcc.getValue(coord);
2548 cell =
SIGNS & signAcc.getValue(coord);
2551 if (tmpIdx < pointListSize) quad[2] = tmpIdx;
2555 quad[3] = idxAcc.getValue(coord);
2557 cell =
SIGNS & signAcc.getValue(coord);
2560 if (tmpIdx < pointListSize) quad[3] = tmpIdx;
2563 mesher.addPrim(quad, !isInside, tag[
bool(refFlags & ZEDGE)]);
2571 template<
typename LeafManagerT,
typename PrimBuilder>
2575 typedef typename LeafManagerT::TreeType::template ValueConverter<int>::Type
IntTreeT;
2576 typedef typename LeafManagerT::TreeType::template ValueConverter<Int16>::Type
Int16TreeT;
2587 void run(
bool threaded =
true);
2595 void operator()(
const tbb::blocked_range<size_t>&)
const;
2598 const LeafManagerT& mSignLeafs;
2608 template<
typename LeafManagerT,
typename PrimBuilder>
2612 : mSignLeafs(signLeafs)
2613 , mSignTree(signTree)
2615 , mPolygonPoolList(polygons)
2616 , mPointListSize(pointListSize)
2617 , mRefSignTree(NULL)
2621 template<
typename LeafManagerT,
typename PrimBuilder>
2625 if (threaded) tbb::parallel_for(mSignLeafs.getRange(), *
this);
2626 else (*
this)(mSignLeafs.getRange());
2629 template<
typename LeafManagerT,
typename PrimBuilder>
2632 const tbb::blocked_range<size_t>& range)
const
2634 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter iter;
2645 boost::scoped_ptr<Int16AccessorT> refSignAcc;
2646 if (mRefSignTree) refSignAcc.reset(
new Int16AccessorT(*mRefSignTree));
2649 for (
size_t n = range.begin(); n != range.end(); ++n) {
2651 origin = mSignLeafs.leaf(n).origin();
2655 iter = mSignLeafs.leaf(n).cbeginValueOn();
2656 for (; iter; ++iter) {
2657 if (iter.getValue() &
XEDGE) ++edgeCount;
2658 if (iter.getValue() &
YEDGE) ++edgeCount;
2659 if (iter.getValue() &
ZEDGE) ++edgeCount;
2662 if(edgeCount == 0)
continue;
2664 mesher.init(edgeCount, mPolygonPoolList[n]);
2666 const typename Int16TreeT::LeafNodeType *signleafPt = signAcc.
probeConstLeaf(origin);
2667 const typename IntTreeT::LeafNodeType *idxLeafPt = idxAcc.
probeConstLeaf(origin);
2669 if (!signleafPt || !idxLeafPt)
continue;
2672 const typename Int16TreeT::LeafNodeType *refSignLeafPt = NULL;
2673 if (refSignAcc) refSignLeafPt = refSignAcc->probeConstLeaf(origin);
2677 iter = mSignLeafs.leaf(n).cbeginValueOn();
2678 for (; iter; ++iter) {
2679 ijk = iter.getCoord();
2681 Int16 flags = iter.getValue();
2683 if (!(flags & 0xE00))
continue;
2686 if (refSignLeafPt) {
2687 refFlags = refSignLeafPt->getValue(iter.pos());
2694 const unsigned char cell = (
SIGNS & flags);
2702 if (ijk[0] > origin[0] && ijk[1] > origin[1] && ijk[2] > origin[2]) {
2703 constructPolygons(flags, refFlags, offsets, ijk, *signleafPt, *idxLeafPt, mesher, mPointListSize);
2705 constructPolygons(flags, refFlags, offsets, ijk, signAcc, idxAcc, mesher, mPointListSize);
2721 PartOp(
size_t leafCount,
size_t partitions,
size_t activePart)
2723 size_t leafSegments = leafCount / partitions;
2724 mStart = leafSegments * activePart;
2725 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2728 template <
typename LeafNodeType>
2731 if (leafIndex < mStart || leafIndex >= mEnd) leaf.setValuesOff();
2735 size_t mStart, mEnd;
2742 template<
typename SrcTreeT>
2747 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
2755 void run(
bool threaded =
true);
2763 void operator()(
const tbb::blocked_range<size_t>&);
2769 size_t mStart, mEnd;
2772 template<
typename SrcTreeT>
2774 : mLeafManager(leafs)
2780 size_t leafSegments = leafCount / partitions;
2781 mStart = leafSegments * activePart;
2782 mEnd = activePart >= (partitions - 1) ? leafCount : mStart + leafSegments;
2785 template<
typename SrcTreeT>
2787 : mLeafManager(rhs.mLeafManager)
2789 , mStart(rhs.mStart)
2795 template<
typename SrcTreeT>
2799 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2800 else (*
this)(mLeafManager.getRange());
2804 template<
typename SrcTreeT>
2811 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
2812 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
2814 for (
size_t n = range.begin(); n != range.end(); ++n) {
2815 if (n < mStart || n >= mEnd)
continue;
2816 BoolLeafT* leaf = acc.
touchLeaf(mLeafManager.leaf(n).origin());
2817 leaf->topologyUnion(mLeafManager.leaf(n));
2825 template<
typename TreeT,
typename LeafManagerT>
2829 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
2833 GenSeamMask(
const LeafManagerT& leafs,
const TreeT& tree);
2835 void run(
bool threaded =
true);
2842 void operator()(
const tbb::blocked_range<size_t>&);
2847 const LeafManagerT& mLeafManager;
2854 template<
typename TreeT,
typename LeafManagerT>
2856 : mLeafManager(leafs)
2863 template<
typename TreeT,
typename LeafManagerT>
2865 : mLeafManager(rhs.mLeafManager)
2872 template<
typename TreeT,
typename LeafManagerT>
2876 if (threaded) tbb::parallel_reduce(mLeafManager.getRange(), *
this);
2877 else (*
this)(mLeafManager.getRange());
2881 template<
typename TreeT,
typename LeafManagerT>
2889 typename LeafManagerT::TreeType::LeafNodeType::ValueOnCIter it;
2891 for (
size_t n = range.begin(); n != range.end(); ++n) {
2893 it = mLeafManager.leaf(n).cbeginValueOn();
2897 ijk = it.getCoord();
2902 unsigned char lhsSigns = it.getValue() &
SIGNS;
2903 if (rhsSigns != lhsSigns) {
2915 template<
typename TreeT>
2923 template <
typename LeafNodeType>
2926 const typename TreeT::LeafNodeType *maskLeaf =
2929 if (!maskLeaf)
return;
2931 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
2935 if (maskLeaf->isValueOn(it.pos())) {
2936 it.setValue(it.getValue() |
SEAM);
2947 template<
typename BoolTreeT>
2952 MaskEdges(
const BoolTreeT& valueMask) : mMaskAcc(valueMask) {}
2954 template <
typename LeafNodeType>
2957 typename LeafNodeType::ValueOnIter it = leaf.beginValueOn();
2959 const typename BoolTreeT::LeafNodeType * maskLeaf =
2964 if (!maskLeaf->isValueOn(it.pos())) {
2965 it.setValue(0x1FF & it.getValue());
2970 it.setValue(0x1FF & it.getValue());
2986 std::vector<unsigned char>& usedPointMask)
2987 : mPolygons(polygons)
2988 , mPolyListCount(polyListCount)
2989 , mUsedPointMask(usedPointMask)
2993 void run(
bool threaded =
true)
2996 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
2998 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3008 for (
size_t n = range.begin(); n != range.end(); ++n) {
3010 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3012 mUsedPointMask[quad[0]] = 1;
3013 mUsedPointMask[quad[1]] = 1;
3014 mUsedPointMask[quad[2]] = 1;
3015 mUsedPointMask[quad[3]] = 1;
3020 mUsedPointMask[triangle[0]] = 1;
3021 mUsedPointMask[triangle[1]] = 1;
3022 mUsedPointMask[triangle[2]] = 1;
3030 size_t mPolyListCount;
3031 std::vector<unsigned char>& mUsedPointMask;
3040 size_t polyListCount,
const std::vector<unsigned>& indexMap)
3041 : mPolygons(polygons)
3042 , mPolyListCount(polyListCount)
3043 , mIndexMap(indexMap)
3047 void run(
bool threaded =
true)
3050 tbb::parallel_for(tbb::blocked_range<size_t>(0, mPolyListCount), *
this);
3052 (*this)(tbb::blocked_range<size_t>(0, mPolyListCount));
3060 for (
size_t n = range.begin(); n != range.end(); ++n) {
3062 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
3064 quad[0] = mIndexMap[quad[0]];
3065 quad[1] = mIndexMap[quad[1]];
3066 quad[2] = mIndexMap[quad[2]];
3067 quad[3] = mIndexMap[quad[3]];
3072 triangle[0] = mIndexMap[triangle[0]];
3073 triangle[1] = mIndexMap[triangle[1]];
3074 triangle[2] = mIndexMap[triangle[2]];
3082 size_t mPolyListCount;
3083 const std::vector<unsigned>& mIndexMap;
3093 std::auto_ptr<openvdb::Vec3s>& newPointList,
3095 const std::vector<unsigned>& indexMap,
3096 const std::vector<unsigned char>& usedPointMask)
3097 : mNewPointList(newPointList)
3098 , mOldPointList(oldPointList)
3099 , mIndexMap(indexMap)
3100 , mUsedPointMask(usedPointMask)
3104 void run(
bool threaded =
true)
3107 tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexMap.size()), *
this);
3109 (*this)(tbb::blocked_range<size_t>(0, mIndexMap.size()));
3117 for (
size_t n = range.begin(); n != range.end(); ++n) {
3118 if (mUsedPointMask[n]) {
3119 const size_t index = mIndexMap[n];
3120 mNewPointList.get()[index] = mOldPointList[n];
3126 std::auto_ptr<openvdb::Vec3s>& mNewPointList;
3128 const std::vector<unsigned>& mIndexMap;
3129 const std::vector<unsigned char>& mUsedPointMask;
3136 template<
typename SrcTreeT>
3141 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3153 void run(
bool threaded =
true);
3162 void operator()(
const tbb::blocked_range<size_t>&);
3176 template<
typename SrcTreeT>
3180 , mLeafManager(srcLeafs)
3181 , mSrcXForm(srcXForm)
3182 , mInvertMask(invertMask)
3188 template<
typename SrcTreeT>
3191 , mLeafManager(rhs.mLeafManager)
3192 , mSrcXForm(rhs.mSrcXForm)
3193 , mInvertMask(rhs.mInvertMask)
3199 template<
typename SrcTreeT>
3204 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3206 (*this)(mLeafManager.getRange());
3211 template<
typename SrcTreeT>
3217 typedef typename BoolTreeT::LeafNodeType BoolLeafT;
3222 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3223 for (
size_t n = range.begin(); n != range.end(); ++n) {
3225 ijk = mLeafManager.leaf(n).origin();
3226 BoolLeafT* leaf =
new BoolLeafT(ijk,
false);
3227 bool addLeaf =
false;
3229 if (maskXForm == mSrcXForm) {
3231 const BoolLeafT* maskLeaf = maskAcc.probeConstLeaf(ijk);
3235 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3236 Index pos = iter.pos();
3237 if(maskLeaf->isValueOn(pos) != mInvertMask) {
3238 leaf->setValueOn(pos);
3243 }
else if (maskAcc.isValueOn(ijk) != mInvertMask) {
3244 leaf->topologyUnion(mLeafManager.leaf(n));
3249 for (iter = mLeafManager.leaf(n).cbeginValueOn(); iter; ++iter) {
3250 ijk = iter.getCoord();
3251 xyz = maskXForm.
worldToIndex(mSrcXForm.indexToWorld(ijk));
3253 leaf->setValueOn(iter.pos());
3259 if (addLeaf) acc.
addLeaf(leaf);
3268 template<
typename SrcTreeT>
3272 typedef typename SrcTreeT::template ValueConverter<int>::Type
IntTreeT;
3273 typedef typename SrcTreeT::template ValueConverter<bool>::Type
BoolTreeT;
3280 void run(
bool threaded =
true);
3287 void operator()(
const tbb::blocked_range<size_t>&);
3294 bool neighboringLeaf(
const Coord&,
const IntTreeAccessorT&)
const;
3300 CoordBBox mLeafBBox;
3304 template<
typename SrcTreeT>
3307 : mLeafManager(leafs)
3308 , mMaskTree(maskTree)
3312 mIdxTree.evalLeafBoundingBox(mLeafBBox);
3313 mLeafBBox.expand(IntTreeT::LeafNodeType::DIM);
3317 template<
typename SrcTreeT>
3319 : mLeafManager(rhs.mLeafManager)
3320 , mMaskTree(rhs.mMaskTree)
3321 , mIdxTree(rhs.mIdxTree)
3323 , mLeafBBox(rhs.mLeafBBox)
3328 template<
typename SrcTreeT>
3333 tbb::parallel_reduce(mLeafManager.getRange(), *
this);
3335 (*this)(mLeafManager.getRange());
3340 template<
typename SrcTreeT>
3344 if (acc.probeConstLeaf(ijk))
return true;
3346 const int dim = IntTreeT::LeafNodeType::DIM;
3349 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2])))
return true;
3350 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2])))
return true;
3351 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2])))
return true;
3352 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2])))
return true;
3353 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] + dim)))
return true;
3354 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1], ijk[2] - dim)))
return true;
3357 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] - dim)))
return true;
3358 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] - dim)))
return true;
3359 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1], ijk[2] + dim)))
return true;
3360 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1], ijk[2] + dim)))
return true;
3361 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2])))
return true;
3362 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2])))
return true;
3363 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2])))
return true;
3364 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2])))
return true;
3365 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] + dim)))
return true;
3366 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] - dim, ijk[2] - dim)))
return true;
3367 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] + dim)))
return true;
3368 if (acc.probeConstLeaf(Coord(ijk[0], ijk[1] + dim, ijk[2] - dim)))
return true;
3371 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3372 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3373 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] + dim)))
return true;
3374 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] - dim, ijk[2] - dim)))
return true;
3375 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3376 if (acc.probeConstLeaf(Coord(ijk[0] - dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3377 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] + dim)))
return true;
3378 if (acc.probeConstLeaf(Coord(ijk[0] + dim, ijk[1] + dim, ijk[2] - dim)))
return true;
3384 template<
typename SrcTreeT>
3393 typename SrcTreeT::LeafNodeType::ValueOnCIter iter;
3395 for (
size_t n = range.begin(); n != range.end(); ++n) {
3397 const typename SrcTreeT::LeafNodeType&
3398 leaf = mLeafManager.leaf(n);
3400 ijk = leaf.origin();
3402 if (!mLeafBBox.isInside(ijk) || !neighboringLeaf(ijk, idxAcc))
continue;
3404 const typename BoolTreeT::LeafNodeType*
3407 if (!maskLeaf || !leaf.hasSameTopology(maskLeaf)) {
3408 acc.
touchLeaf(ijk)->topologyUnion(leaf);
3417 template<
typename TreeT>
3421 typedef typename TreeT::template ValueConverter<bool>::Type
BoolTreeT;
3427 GenTileMask(
const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso);
3429 void run(
bool threaded =
true);
3436 void operator()(
const tbb::blocked_range<size_t>&);
3441 const std::vector<Vec4i>& mTiles;
3442 const TreeT& mDistTree;
3449 template<
typename TreeT>
3451 const std::vector<Vec4i>& tiles,
const TreeT& distTree,
ValueT iso)
3453 , mDistTree(distTree)
3460 template<
typename TreeT>
3462 : mTiles(rhs.mTiles)
3463 , mDistTree(rhs.mDistTree)
3464 , mIsovalue(rhs.mIsovalue)
3470 template<
typename TreeT>
3474 if (threaded) tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mTiles.size()), *
this);
3475 else (*
this)(tbb::blocked_range<size_t>(0, mTiles.size()));
3479 template<
typename TreeT>
3484 CoordBBox region, bbox;
3486 bool processRegion =
true;
3490 for (
size_t n = range.begin(); n != range.end(); ++n) {
3492 const Vec4i& tile = mTiles[n];
3494 bbox.min()[0] = tile[0];
3495 bbox.min()[1] = tile[1];
3496 bbox.min()[2] = tile[2];
3498 bbox.max() = bbox.min();
3499 bbox.max().offset(tile[3]);
3501 const bool thisInside = (distAcc.
getValue(bbox.min()) < mIsovalue);
3510 processRegion =
true;
3512 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3516 if (processRegion) {
3518 region.min()[0] = region.max()[0] = ijk[0];
3519 mTree.fill(region,
true);
3526 processRegion =
true;
3528 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3531 if (processRegion) {
3533 region.min()[0] = region.max()[0] = ijk[0];
3534 mTree.fill(region,
true);
3544 processRegion =
true;
3546 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3549 if (processRegion) {
3551 region.min()[1] = region.max()[1] = ijk[1];
3552 mTree.fill(region,
true);
3559 processRegion =
true;
3561 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3564 if (processRegion) {
3566 region.min()[1] = region.max()[1] = ijk[1];
3567 mTree.fill(region,
true);
3577 processRegion =
true;
3579 processRegion = thisInside != (distAcc.
getValue(nijk) < mIsovalue);
3582 if (processRegion) {
3584 region.min()[2] = region.max()[2] = ijk[2];
3585 mTree.fill(region,
true);
3591 processRegion =
true;
3593 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3596 if (processRegion) {
3598 region.min()[2] = region.max()[2] = ijk[2];
3599 mTree.fill(region,
true);
3607 processRegion =
true;
3609 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3612 if (processRegion) {
3614 region.min()[1] = region.max()[1] = ijk[1];
3615 region.min()[2] = region.max()[2] = ijk[2];
3616 mTree.fill(region,
true);
3624 processRegion =
true;
3626 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3629 if (processRegion) {
3631 region.min()[1] = region.max()[1] = ijk[1];
3632 region.min()[0] = region.max()[0] = ijk[0];
3633 mTree.fill(region,
true);
3640 processRegion =
true;
3642 processRegion = !distAcc.
probeValue(ijk, value) && thisInside != (value < mIsovalue);
3645 if (processRegion) {
3647 region.min()[2] = region.max()[2] = ijk[2];
3648 region.min()[0] = region.max()[0] = ijk[0];
3649 mTree.fill(region,
true);
3658 template<
class DistTreeT,
class SignTreeT,
class IdxTreeT>
3660 tileData(
const DistTreeT& distTree, SignTreeT& signTree, IdxTreeT& idxTree,
double iso)
3662 typename DistTreeT::ValueOnCIter tileIter(distTree);
3663 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3665 if (!tileIter)
return;
3667 size_t tileCount = 0;
3668 for ( ; tileIter; ++tileIter) {
3672 std::vector<Vec4i> tiles(tileCount);
3675 tileIter = distTree.cbeginValueOn();
3676 tileIter.setMaxDepth(DistTreeT::ValueOnCIter::LEAF_DEPTH - 1);
3679 for (; tileIter; ++tileIter) {
3680 Vec4i& tile = tiles[tileCount++];
3681 tileIter.getBoundingBox(bbox);
3682 tile[0] = bbox.min()[0];
3683 tile[1] = bbox.min()[1];
3684 tile[2] = bbox.min()[2];
3685 tile[3] = bbox.max()[0] - bbox.min()[0];
3688 typename DistTreeT::ValueType isovalue =
typename DistTreeT::ValueType(iso);
3693 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
3696 BoolLeafManagerT leafs(tileMask.
tree());
3702 signTree.merge(*op.signTree());
3703 idxTree.merge(*op.idxTree());
3715 : mPointsIn(pointsIn) , mPointsOut(pointsOut)
3721 for (
size_t n = range.begin(); n < range.end(); ++n) {
3722 mPointsOut[n] = mPointsIn[n];
3728 std::vector<Vec3s>& mPointsOut;
3733 template <
typename LeafManagerT>
3737 double interiorWidth = 0.0, exteriorWidth = 0.0;
3739 typename LeafManagerT::TreeType::LeafNodeType::ValueOffCIter it;
3740 bool foundInterior =
false, foundExterior =
false;
3741 for (
size_t n = 0, N = leafs.leafCount(); n < N; ++n) {
3743 for (it = leafs.leaf(n).cbeginValueOff(); it; ++it) {
3744 double value = double(it.getValue());
3746 interiorWidth = value;
3747 foundInterior =
true;
3748 }
else if (value > 0.0) {
3749 exteriorWidth = value;
3750 foundExterior =
true;
3753 if (foundInterior && foundExterior)
break;
3756 if (foundInterior && foundExterior)
break;
3761 double minDist =
std::min(std::abs(interiorWidth - iso), std::abs(exteriorWidth - iso));
3762 return !(minDist > (2.0 * voxelSize));
3779 , mTriangleFlags(NULL)
3786 : mNumQuads(numQuads)
3787 , mNumTriangles(numTriangles)
3788 , mQuads(new openvdb::
Vec4I[mNumQuads])
3789 , mTriangles(new openvdb::
Vec3I[mNumTriangles])
3790 , mQuadFlags(new char[mNumQuads])
3791 , mTriangleFlags(new char[mNumTriangles])
3802 for (
size_t i = 0; i < mNumQuads; ++i) {
3803 mQuads[i] = rhs.mQuads[i];
3804 mQuadFlags[i] = rhs.mQuadFlags[i];
3807 for (
size_t i = 0; i < mNumTriangles; ++i) {
3808 mTriangles[i] = rhs.mTriangles[i];
3809 mTriangleFlags[i] = rhs.mTriangleFlags[i];
3819 mQuadFlags.reset(
new char[mNumQuads]);
3828 mQuadFlags.reset(NULL);
3835 mNumTriangles = size;
3837 mTriangleFlags.reset(
new char[mNumTriangles]);
3845 mTriangles.reset(NULL);
3846 mTriangleFlags.reset(NULL);
3857 , mSeamPointListSize(0)
3858 , mPolygonPoolListSize(0)
3859 , mIsovalue(isovalue)
3860 , mPrimAdaptivity(adaptivity)
3861 , mSecAdaptivity(0.0)
3863 , mSurfaceMaskGrid(
GridBase::ConstPtr())
3864 , mAdaptivityGrid(
GridBase::ConstPtr())
3865 , mAdaptivityMaskTree(
TreeBase::ConstPtr())
3868 , mInvertSurfaceMask(false)
3871 , mQuantizedSeamPoints(NULL)
3884 inline const size_t&
3887 return mPointListSize;
3905 inline const size_t&
3908 return mPolygonPoolListSize;
3916 mSecAdaptivity = secAdaptivity;
3921 mSeamPointListSize = 0;
3922 mQuantizedSeamPoints.reset(NULL);
3929 mSurfaceMaskGrid = mask;
3930 mInvertSurfaceMask = invertMask;
3937 mAdaptivityGrid = grid;
3944 mAdaptivityMaskTree = tree;
3951 mPartitions =
std::max(partitions,
unsigned(1));
3952 mActivePart =
std::min(activePart, mPartitions-1);
3956 inline std::vector<unsigned char>&
3963 inline const std::vector<unsigned char>&
3970 template<
typename Gr
idT>
3974 typedef typename GridT::TreeType DistTreeT;
3976 typedef typename DistTreeT::ValueType DistValueT;
3978 typedef typename DistTreeT::template ValueConverter<bool>::Type BoolTreeT;
3982 typedef typename DistTreeT::template ValueConverter<Int16>::Type Int16TreeT;
3985 typedef typename DistTreeT::template ValueConverter<int>::Type IntTreeT;
3986 typedef typename DistTreeT::template ValueConverter<float>::Type FloatTreeT;
3990 const openvdb::math::Transform& transform = distGrid.
transform();
3991 const DistTreeT& distTree = distGrid.tree();
3992 const DistValueT isovalue = DistValueT(mIsovalue);
3994 typename Int16TreeT::Ptr signTreePt;
3995 typename IntTreeT::Ptr idxTreePt;
3996 typename BoolTreeT::Ptr pointMask;
3998 BoolTreeT valueMask(
false), seamMask(
false);
3999 const bool adaptive = mPrimAdaptivity > 1e-7 || mSecAdaptivity > 1e-7;
4000 bool maskEdges =
false;
4003 const BoolGridT * surfaceMask = NULL;
4004 if (mSurfaceMaskGrid && mSurfaceMaskGrid->type() == BoolGridT::gridType()) {
4005 surfaceMask =
static_cast<const BoolGridT*
>(mSurfaceMaskGrid.get());
4008 const FloatGridT * adaptivityField = NULL;
4009 if (mAdaptivityGrid && mAdaptivityGrid->type() == FloatGridT::gridType()) {
4010 adaptivityField =
static_cast<const FloatGridT*
>(mAdaptivityGrid.get());
4013 if (mAdaptivityMaskTree && mAdaptivityMaskTree->type() == BoolTreeT::treeType()) {
4014 const BoolTreeT *adaptivityMaskPt =
4015 static_cast<const BoolTreeT*
>(mAdaptivityMaskTree.get());
4016 seamMask.topologyUnion(*adaptivityMaskPt);
4021 DistLeafManagerT distLeafs(distTree);
4024 bool padActiveVoxels =
false;
4027 padActiveVoxels =
true;
4030 mIsovalue, transform.voxelSize()[0]);
4033 if (surfaceMask || mPartitions > 1) {
4041 *surfaceMask, distLeafs, transform, mInvertSurfaceMask);
4043 valueMask.merge(masking.
tree());
4046 if (mPartitions > 1) {
4049 valueMask.pruneInactive();
4056 valueMask.merge(partitioner.
tree());
4062 BoolLeafManagerT leafs(valueMask);
4065 signDataOp(distTree, leafs, isovalue);
4068 signTreePt = signDataOp.
signTree();
4069 idxTreePt = signDataOp.
idxTree();
4076 BoolLeafManagerT bleafs(boundary.
tree());
4079 signDataOp(distTree, bleafs, isovalue);
4082 signTreePt->merge(*signDataOp.signTree());
4083 idxTreePt->merge(*signDataOp.idxTree());
4089 if (padActiveVoxels) {
4091 BoolTreeT regionMask(
false);
4092 regionMask.topologyUnion(distTree);
4095 BoolLeafManagerT leafs(regionMask);
4098 signDataOp(distTree, leafs, isovalue);
4101 signTreePt = signDataOp.
signTree();
4102 idxTreePt = signDataOp.
idxTree();
4107 signDataOp(distTree, distLeafs, isovalue);
4110 signTreePt = signDataOp.
signTree();
4111 idxTreePt = signDataOp.
idxTree();
4124 Int16TreeT *refSignTreePt = NULL;
4125 IntTreeT *refIdxTreePt = NULL;
4126 const DistTreeT *refDistTreePt = NULL;
4128 if (mRefGrid && mRefGrid->type() == GridT::gridType()) {
4130 const GridT* refGrid =
static_cast<const GridT*
>(mRefGrid.get());
4131 refDistTreePt = &refGrid->tree();
4134 if (!mRefSignTree && !mRefIdxTree) {
4136 DistLeafManagerT refDistLeafs(*refDistTreePt);
4138 signDataOp(*refDistTreePt, refDistLeafs, isovalue);
4142 mRefSignTree = signDataOp.
signTree();
4143 mRefIdxTree = signDataOp.
idxTree();
4147 if (mRefSignTree && mRefIdxTree) {
4148 refSignTreePt =
static_cast<Int16TreeT*
>(mRefSignTree.get());
4149 refIdxTreePt =
static_cast<IntTreeT*
>(mRefIdxTree.get());
4155 Int16LeafManagerT signLeafs(*signTreePt);
4164 if (refSignTreePt) {
4171 seamMask.merge(seamOp.
mask());
4175 std::vector<size_t> regions(signLeafs.leafCount(), 0);
4176 if (regions.empty())
return;
4181 signLeafs, *signTreePt, distTree, *idxTreePt, isovalue, DistValueT(mPrimAdaptivity));
4183 if (adaptivityField) {
4187 if (refSignTreePt || mAdaptivityMaskTree) {
4191 if (refSignTreePt) {
4192 merge.
setRefData(refSignTreePt, DistValueT(mSecAdaptivity));
4207 for (
size_t n = 0, N = regions.size(); n < N; ++n) {
4209 regions[n] = mPointListSize;
4210 mPointListSize += tmp;
4217 mPointFlags.clear();
4220 if (refSignTreePt && refIdxTreePt) {
4222 if (mSeamPointListSize == 0) {
4224 std::vector<size_t> pointMap;
4227 Int16LeafManagerT refSignLeafs(*refSignTreePt);
4228 pointMap.resize(refSignLeafs.leafCount(), 0);
4233 for (
size_t n = 0, N = pointMap.size(); n < N; ++n) {
4235 pointMap[n] = mSeamPointListSize;
4236 mSeamPointListSize += tmp;
4240 if (!pointMap.empty() && mSeamPointListSize != 0) {
4242 mQuantizedSeamPoints.reset(
new uint32_t[mSeamPointListSize]);
4243 memset(mQuantizedSeamPoints.get(), 0,
sizeof(uint32_t) * mSeamPointListSize);
4247 IntLeafManagerT refIdxLeafs(*refIdxTreePt);
4252 if (mSeamPointListSize != 0) {
4254 distTree, *refSignTreePt, *refIdxTreePt, mQuantizedSeamPoints, mIsovalue));
4260 pointOp(signLeafs, distTree, *idxTreePt, mPoints, regions, transform, mIsovalue);
4263 if (mSeamPointListSize != 0) {
4264 mPointFlags.resize(mPointListSize);
4265 pointOp.
setRefData(refSignTreePt, refDistTreePt, refIdxTreePt,
4266 &mQuantizedSeamPoints, &mPointFlags);
4272 mPolygonPoolListSize = signLeafs.leafCount();
4273 mPolygons.reset(
new PolygonPool[mPolygonPoolListSize]);
4278 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4286 mesher(signLeafs, *signTreePt, *idxTreePt, mPolygons,
Index32(mPointListSize));
4295 if ((surfaceMask || mPartitions > 1) && mPointListSize > 0) {
4298 std::vector<unsigned char> usedPointMask(mPointListSize, 0);
4304 std::vector<unsigned> indexMap(mPointListSize);
4305 size_t usedPointCount = 0;
4306 for (
size_t p = 0; p < mPointListSize; ++p) {
4307 if (usedPointMask[p]) indexMap[p] = usedPointCount++;
4310 if (usedPointCount < mPointListSize) {
4313 std::auto_ptr<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[usedPointCount]);
4318 mPointListSize = usedPointCount;
4319 mPoints.reset(newPointList.release());
4330 if (refSignTreePt || refIdxTreePt || refDistTreePt) {
4331 std::vector<Vec3s> newPoints;
4333 for (
size_t n = 0; n < mPolygonPoolListSize; ++n) {
4337 std::vector<size_t> nonPlanarQuads;
4338 nonPlanarQuads.reserve(polygons.
numQuads());
4340 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4348 const bool edgePoly = mPointFlags[quad[0]] || mPointFlags[quad[1]]
4349 || mPointFlags[quad[2]] || mPointFlags[quad[3]];
4351 if (!edgePoly)
continue;
4353 const Vec3s& p0 = mPoints[quad[0]];
4354 const Vec3s& p1 = mPoints[quad[1]];
4355 const Vec3s& p2 = mPoints[quad[2]];
4356 const Vec3s& p3 = mPoints[quad[3]];
4359 nonPlanarQuads.push_back(i);
4365 if (!nonPlanarQuads.empty()) {
4372 size_t triangleIdx = 0;
4373 for (
size_t i = 0; i < nonPlanarQuads.size(); ++i) {
4375 size_t& quadIdx = nonPlanarQuads[i];
4378 char& quadFlags = polygons.
quadFlags(quadIdx);
4381 Vec3s centroid = (mPoints[quad[0]] + mPoints[quad[1]] +
4382 mPoints[quad[2]] + mPoints[quad[3]]) * 0.25;
4384 size_t pointIdx = newPoints.size() + mPointListSize;
4386 newPoints.push_back(centroid);
4392 triangle[0] = quad[0];
4393 triangle[1] = pointIdx;
4394 triangle[2] = quad[3];
4398 if (mPointFlags[triangle[0]] || mPointFlags[triangle[2]]) {
4408 triangle[0] = quad[0];
4409 triangle[1] = quad[1];
4410 triangle[2] = pointIdx;
4414 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4424 triangle[0] = quad[1];
4425 triangle[1] = quad[2];
4426 triangle[2] = pointIdx;
4430 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4441 triangle[0] = quad[2];
4442 triangle[1] = quad[3];
4443 triangle[2] = pointIdx;
4447 if (mPointFlags[triangle[0]] || mPointFlags[triangle[1]]) {
4466 for (
size_t i = 0; i < polygons.
numQuads(); ++i) {
4470 tmpPolygons.
quad(quadIdx) = quad;
4477 polygons.
copy(tmpPolygons);
4483 if (!newPoints.empty()) {
4485 size_t newPointCount = newPoints.size() + mPointListSize;
4487 std::auto_ptr<openvdb::Vec3s> newPointList(
new openvdb::Vec3s[newPointCount]);
4489 for (
size_t i = 0; i < mPointListSize; ++i) {
4490 newPointList.get()[i] = mPoints[i];
4493 for (
size_t i = mPointListSize; i < newPointCount; ++i) {
4494 newPointList.get()[i] = newPoints[i - mPointListSize];
4497 mPointListSize = newPointCount;
4498 mPoints.reset(newPointList.release());
4499 mPointFlags.resize(mPointListSize, 0);
4508 template<
typename Gr
idType>
4511 const GridType& grid,
4512 std::vector<Vec3s>& points,
4513 std::vector<Vec3I>& triangles,
4514 std::vector<Vec4I>& quads,
4527 tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), ptnCpy);
4534 size_t numQuads = 0, numTriangles = 0;
4536 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4537 numTriangles += polygons.numTriangles();
4538 numQuads += polygons.numQuads();
4542 triangles.resize(numTriangles);
4544 quads.resize(numQuads);
4548 size_t qIdx = 0, tIdx = 0;
4550 openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
4552 for (
size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
4553 quads[qIdx++] = polygons.quad(i);
4556 for (
size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
4557 triangles[tIdx++] = polygons.triangle(i);
4563 template<
typename Gr
idType>
4566 const GridType& grid,
4567 std::vector<Vec3s>& points,
4568 std::vector<Vec4I>& quads,
4571 std::vector<Vec3I> triangles(0);
4572 volumeToMesh(grid,points, triangles, quads, isovalue, 0.0);
4583 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
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 const Index32 INVALID_IDX
boost::shared_ptr< const TreeBase > ConstPtr
Definition: Tree.h:68
void foreach(const LeafOp &op, bool threaded=true)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:461
T & z()
Definition: Vec3.h:96
uint32_t Index32
Definition: Types.h:54
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
Mat3< double > Mat3d
Definition: Mat3.h:666
Vec3< float > Vec3s
Definition: Vec3.h:604
Gradient operators defined in index space of various orders.
Definition: Operators.h:122
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:210
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:321
Abstract base class for typed grids.
Definition: Grid.h:103
Vec4< int32_t > Vec4i
Definition: Vec4.h:521
#define OPENVDB_VERSION_NAME
Definition: version.h:45
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the voxel as well as its value.
Definition: ValueAccessor.h:220
int16_t Int16
Definition: Types.h:57
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
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:328
Coord nearestCoord(const Vec3d &voxelCoord)
Return voxelCoord rounded to the closest integer coordinates.
Definition: util/Util.h:55
Vec3< double > Vec3d
Definition: Vec3.h:605
boost::shared_ptr< TreeBase > Ptr
Definition: Tree.h:67
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:455
Index32 Index
Definition: Types.h:56
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
boost::shared_ptr< const GridBase > ConstPtr
Definition: Grid.h:107
int getValueDepth(const Coord &xyz) const
Definition: ValueAccessor.h:229
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:295
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
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
OPENVDB_API const Coord COORD_OFFSETS[26]
coordinate offset table for neighboring voxels
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
Base class for typed trees.
Definition: Tree.h:64