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>
36template<
class Gr
idType,
class InterruptType = util::NullInterrupter>
71 bool cutterOverlap =
true);
77 void clear() { mFragments.clear(); }
83 bool wasInterrupted(
int percent = -1)
const {
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;
102namespace level_set_fracture_internal {
105template<
typename LeafNodeType>
106struct FindMinMaxVoxelValue {
108 using ValueType =
typename LeafNodeType::ValueType;
110 FindMinMaxVoxelValue(
const std::vector<const LeafNodeType*>& nodes)
111 : minValue(
std::numeric_limits<ValueType>::max())
112 , maxValue(-minValue)
113 , mNodes(nodes.empty() ? nullptr : &nodes.front())
117 FindMinMaxVoxelValue(FindMinMaxVoxelValue& rhs, tbb::split)
118 : minValue(std::numeric_limits<ValueType>::
max())
119 , maxValue(-minValue)
124 void operator()(
const tbb::blocked_range<size_t>& range) {
125 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
126 const ValueType* data = mNodes[n]->buffer().data();
127 for (Index i = 0; i < LeafNodeType::SIZE; ++i) {
128 minValue = std::min(minValue, data[i]);
129 maxValue = std::max(maxValue, data[i]);
134 void join(FindMinMaxVoxelValue& rhs) {
135 minValue = std::min(minValue, rhs.minValue);
136 maxValue = std::max(maxValue, rhs.maxValue);
139 ValueType minValue, maxValue;
141 LeafNodeType
const *
const *
const mNodes;
152template<
class Gr
idType,
class InterruptType>
154 : mInterrupter(interrupter)
160template<
class Gr
idType,
class InterruptType>
172 GridType cutterGrid(*
const_cast<GridType*
>(&cutter),
ShallowCopy());
174 const bool hasInstanceRotations =
175 points && rotations &&
points->size() == rotations->size();
178 for (
size_t p = 0, P =
points->size(); p < P; ++p) {
179 int percent = int((
float(p) /
float(P)) * 100.0);
180 if (wasInterrupted(percent))
break;
182 GridType instCutterGrid;
183 instCutterGrid.setTransform(originalCutterTransform->copy());
186 if (hasInstanceRotations) {
191 xform->postTranslate((*
points)[p]);
193 xform->postTranslate((*
points)[p]);
196 cutterGrid.setTransform(xform);
200 if (mInterrupter !=
nullptr) {
202 if (hasInstanceRotations) {
209 if (hasInstanceRotations) {
216 if (wasInterrupted(percent))
break;
218 if (cutterOverlap && !mFragments.empty())
process(mFragments, instCutterGrid);
219 process(grids, instCutterGrid);
224 if (cutterOverlap && !mFragments.empty())
process(mFragments, cutter);
229 segmentFragments(mFragments);
230 segmentFragments(grids);
235template<
class Gr
idType,
class InterruptType>
237LevelSetFracture<GridType, InterruptType>::isValidFragment(GridType& grid)
const
239 using LeafNodeType =
typename GridType::TreeType::LeafNodeType;
241 if (grid.tree().leafCount() < 9) {
243 std::vector<const LeafNodeType*> nodes;
244 grid.tree().getNodes(nodes);
248 for (
size_t n = 0, N = nodes.size(); n < N; ++n) {
249 activeVoxelCount += nodes[n]->onVoxelCount();
252 if (activeVoxelCount < 27)
return false;
254 level_set_fracture_internal::FindMinMaxVoxelValue<LeafNodeType>
op(nodes);
255 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, nodes.size()),
op);
257 if ((
op.minValue < 0) == (
op.maxValue < 0))
return false;
264template<
class Gr
idType,
class InterruptType>
266LevelSetFracture<GridType, InterruptType>::segmentFragments(GridPtrList& grids)
const
268 GridPtrList newFragments;
270 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
272 std::vector<typename GridType::Ptr> segments;
275 for (
size_t n = 0, N = segments.size(); n < N; ++n) {
276 newFragments.push_back(segments[n]);
280 grids.swap(newFragments);
284template<
class Gr
idType,
class InterruptType>
286LevelSetFracture<GridType, InterruptType>::process(
287 GridPtrList& grids,
const GridType& cutter)
289 using GridPtr =
typename GridType::Ptr;
290 GridPtrList newFragments;
292 for (GridPtrListIter it = grids.begin(); it != grids.end(); ++it) {
299 if (!isValidFragment(*fragment))
continue;
302 if (!isValidFragment(*residual))
continue;
304 newFragments.push_back(fragment);
306 grid->tree().clear();
307 grid->tree().merge(residual->tree());
310 if (!newFragments.empty()) {
311 mFragments.splice(mFragments.end(), newFragments);
321#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
323#ifdef OPENVDB_INSTANTIATE_LEVELSETFRACTURE
Functions to efficiently perform various compositing operations on grids.
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
Tag dispatch class that distinguishes shallow copy constructors from deep copy constructors.
Definition Types.h:680
@ Z_AXIS
Definition Math.h:904
@ X_AXIS
Definition Math.h:902
@ Y_AXIS
Definition Math.h:903
Vec3< float > Vec3s
Definition Vec3.h:664
@ XYZ_ROTATION
Definition Math.h:909
Definition AttributeArray.h:42
bool wasInterrupted(T *i, int percent=-1)
Definition NullInterrupter.h:49
uint64_t Index64
Definition Types.h:53
openvdb::GridBase::Ptr GridPtr
Definition Utils.h:35
Definition Exceptions.h:13
Base class for interrupters.
Definition NullInterrupter.h:26
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:158