10 #ifndef OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED
26 #include <tbb/blocked_range.h>
27 #include <tbb/parallel_reduce.h>
36 template<
class Gr
idType,
class InterruptType = util::NullInterrupter>
69 void fracture(
GridPtrList& grids,
const GridType& cutter,
bool segment =
false,
71 bool cutterOverlap =
true);
77 void clear() { mFragments.clear(); }
84 return mInterrupter && mInterrupter->wasInterrupted(percent);
87 bool isValidFragment(GridType&)
const;
88 void segmentFragments(GridPtrList&)
const;
89 void process(GridPtrList&,
const GridType& cutter);
91 InterruptType* mInterrupter;
92 GridPtrList mFragments;
101 namespace level_set_fracture_internal {
104 template<
typename LeafNodeType>
111 , maxValue(-minValue)
112 , mNodes(nodes.empty() ? nullptr : &nodes.front())
118 , maxValue(-minValue)
124 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
125 const ValueType* data = mNodes[n]->buffer().data();
126 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
127 minValue =
std::min(minValue, data[i]);
128 maxValue =
std::max(maxValue, data[i]);
140 LeafNodeType
const *
const *
const mNodes;
150 template<
class Gr
idType,
class InterruptType>
152 : mInterrupter(interrupter)
158 template<
class Gr
idType,
class InterruptType>
161 bool segmentation,
const Vec3sList* points,
const QuatsList* rotations,
bool cutterOverlap)
166 if (points && points->size() != 0) {
170 GridType cutterGrid(*const_cast<GridType*>(&cutter),
ShallowCopy());
172 const bool hasInstanceRotations =
173 points && rotations && points->size() == rotations->size();
176 for (
size_t p = 0, P = points->size(); p < P; ++p) {
177 int percent = int((
float(p) /
float(P)) * 100.0);
180 GridType instCutterGrid;
181 instCutterGrid.setTransform(originalCutterTransform->copy());
184 if (hasInstanceRotations) {
189 xform->postTranslate((*points)[p]);
191 xform->postTranslate((*points)[p]);
194 cutterGrid.setTransform(xform);
198 if (mInterrupter !=
nullptr) {
200 if (hasInstanceRotations) {
201 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, *mInterrupter);
203 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, *mInterrupter);
207 if (hasInstanceRotations) {
208 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, interrupter);
210 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, interrupter);
216 if (cutterOverlap && !mFragments.empty()) process(mFragments, instCutterGrid);
217 process(grids, instCutterGrid);
222 if (cutterOverlap && !mFragments.empty()) process(mFragments, cutter);
223 process(grids, cutter);
227 segmentFragments(mFragments);
228 segmentFragments(grids);
233 template<
class Gr
idType,
class InterruptType>
237 using LeafNodeType =
typename GridType::TreeType::LeafNodeType;
239 if (grid.tree().leafCount() < 9) {
241 std::vector<const LeafNodeType*> nodes;
242 grid.tree().getNodes(nodes);
246 for (
size_t n = 0, N = nodes.size(); n < N; ++n) {
247 activeVoxelCount += nodes[n]->onVoxelCount();
250 if (activeVoxelCount < 27)
return false;
252 level_set_fracture_internal::FindMinMaxVoxelValue<LeafNodeType> op(nodes);
253 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
255 if ((op.minValue < 0) == (op.maxValue < 0))
return false;
262 template<
class Gr
idType,
class InterruptType>
264 LevelSetFracture<GridType, InterruptType>::segmentFragments(GridPtrList& grids)
const
266 GridPtrList newFragments;
268 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
270 std::vector<typename GridType::Ptr> segments;
273 for (
size_t n = 0, N = segments.size(); n < N; ++n) {
274 newFragments.push_back(segments[n]);
278 grids.swap(newFragments);
282 template<
class Gr
idType,
class InterruptType>
284 LevelSetFracture<GridType, InterruptType>::process(
285 GridPtrList& grids,
const GridType& cutter)
287 using GridPtr =
typename GridType::Ptr;
288 GridPtrList newFragments;
290 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
297 if (!isValidFragment(*fragment))
continue;
300 if (!isValidFragment(*residual))
continue;
302 newFragments.push_back(fragment);
304 grid->tree().clear();
305 grid->tree().merge(residual->tree());
308 if (!newFragments.empty()) {
309 mFragments.splice(mFragments.end(), newFragments);
317 #endif // OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED