37 #ifndef OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED
38 #define OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED
53 #include <tbb/blocked_range.h>
54 #include <tbb/parallel_reduce.h>
63 template<
class Gr
idType,
class InterruptType = util::NullInterrupter>
96 void fracture(
GridPtrList& grids,
const GridType& cutter,
bool segment =
false,
98 bool cutterOverlap =
true);
104 void clear() { mFragments.clear(); }
111 return mInterrupter && mInterrupter->wasInterrupted(percent);
114 bool isValidFragment(GridType&)
const;
115 void segmentFragments(GridPtrList&)
const;
116 void process(GridPtrList&,
const GridType& cutter);
118 InterruptType* mInterrupter;
119 GridPtrList mFragments;
128 namespace level_set_fracture_internal {
131 template<
typename LeafNodeType>
138 , maxValue(-minValue)
139 , mNodes(nodes.empty() ? nullptr : &nodes.front())
145 , maxValue(-minValue)
151 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
152 const ValueType* data = mNodes[n]->buffer().data();
153 for (
Index i = 0; i < LeafNodeType::SIZE; ++i) {
154 minValue =
std::min(minValue, data[i]);
155 maxValue =
std::max(maxValue, data[i]);
167 LeafNodeType
const *
const *
const mNodes;
177 template<
class Gr
idType,
class InterruptType>
179 : mInterrupter(interrupter)
185 template<
class Gr
idType,
class InterruptType>
188 bool segmentation,
const Vec3sList* points,
const QuatsList* rotations,
bool cutterOverlap)
193 if (points && points->size() != 0) {
197 GridType cutterGrid(*
const_cast<GridType*
>(&cutter),
ShallowCopy());
199 const bool hasInstanceRotations =
200 points && rotations && points->size() == rotations->size();
203 for (
size_t p = 0, P = points->size(); p < P; ++p) {
204 int percent = int((
float(p) /
float(P)) * 100.0);
207 GridType instCutterGrid;
208 instCutterGrid.setTransform(originalCutterTransform->copy());
211 if (hasInstanceRotations) {
216 xform->postTranslate((*points)[p]);
218 xform->postTranslate((*points)[p]);
221 cutterGrid.setTransform(xform);
225 if (mInterrupter !=
nullptr) {
227 if (hasInstanceRotations) {
228 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, *mInterrupter);
230 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, *mInterrupter);
234 if (hasInstanceRotations) {
235 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, interrupter);
237 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, interrupter);
243 if (cutterOverlap && !mFragments.empty()) process(mFragments, instCutterGrid);
244 process(grids, instCutterGrid);
249 if (cutterOverlap && !mFragments.empty()) process(mFragments, cutter);
250 process(grids, cutter);
254 segmentFragments(mFragments);
255 segmentFragments(grids);
260 template<
class Gr
idType,
class InterruptType>
264 using LeafNodeType =
typename GridType::TreeType::LeafNodeType;
266 if (grid.tree().leafCount() < 9) {
268 std::vector<const LeafNodeType*> nodes;
269 grid.tree().getNodes(nodes);
273 for (
size_t n = 0, N = nodes.size(); n < N; ++n) {
274 activeVoxelCount += nodes[n]->onVoxelCount();
277 if (activeVoxelCount < 27)
return false;
279 level_set_fracture_internal::FindMinMaxVoxelValue<LeafNodeType> op(nodes);
280 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()), op);
282 if ((op.minValue < 0) == (op.maxValue < 0))
return false;
289 template<
class Gr
idType,
class InterruptType>
291 LevelSetFracture<GridType, InterruptType>::segmentFragments(GridPtrList& grids)
const
293 GridPtrList newFragments;
295 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
297 std::vector<typename GridType::Ptr> segments;
300 for (
size_t n = 0, N = segments.size(); n < N; ++n) {
301 newFragments.push_back(segments[n]);
305 grids.swap(newFragments);
309 template<
class Gr
idType,
class InterruptType>
311 LevelSetFracture<GridType, InterruptType>::process(
312 GridPtrList& grids,
const GridType& cutter)
314 using GridPtr =
typename GridType::Ptr;
315 GridPtrList newFragments;
317 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
324 if (!isValidFragment(*fragment))
continue;
327 if (!isValidFragment(*residual))
continue;
329 newFragments.push_back(fragment);
331 grid->tree().clear();
332 grid->tree().merge(residual->tree());
335 if (!newFragments.empty()) {
336 mFragments.splice(mFragments.end(), newFragments);
344 #endif // OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED