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>
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;
91 InterruptType* mInterrupter;
102 namespace level_set_fracture_internal {
105 template<
typename LeafNodeType>
106 struct FindMinMaxVoxelValue {
110 FindMinMaxVoxelValue(
const std::vector<const LeafNodeType*>& nodes)
112 , maxValue(-minValue)
113 , mNodes(nodes.empty() ? nullptr : &nodes.front())
117 FindMinMaxVoxelValue(FindMinMaxVoxelValue& rhs,
tbb::split)
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) {
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);
141 LeafNodeType
const *
const *
const mNodes;
152 template<
class Gr
idType,
class InterruptType>
154 : mInterrupter(interrupter)
160 template<
class Gr
idType,
class InterruptType>
168 if (points && points->size() != 0) {
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);
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) {
203 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, *mInterrupter);
205 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, *mInterrupter);
209 if (hasInstanceRotations) {
210 doResampleToMatch<BoxSampler>(cutterGrid, instCutterGrid, interrupter);
212 doResampleToMatch<PointSampler>(cutterGrid, instCutterGrid, interrupter);
218 if (cutterOverlap && !mFragments.empty()) process(mFragments, instCutterGrid);
219 process(grids, instCutterGrid);
224 if (cutterOverlap && !mFragments.empty()) process(mFragments, cutter);
225 process(grids, cutter);
229 segmentFragments(mFragments);
230 segmentFragments(grids);
235 template<
class Gr
idType,
class InterruptType>
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;
264 template<
class Gr
idType,
class InterruptType>
266 LevelSetFracture<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);
284 template<
class Gr
idType,
class InterruptType>
286 LevelSetFracture<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
330 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
337 #endif // OPENVDB_TOOLS_LEVELSETFRACTURE_HAS_BEEN_INCLUDED
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
GLdouble GLdouble GLint GLint const GLdouble * points
Functions to efficiently perform various compositing operations on grids.
Tag dispatch class that distinguishes shallow copy constructors from deep copy constructors.
GridType
List of types that are currently supported by NanoVDB.
GA_API const UT_StringHolder rot
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Base class for interrupters.
SYS_FORCE_INLINE const_iterator end() const
#define OPENVDB_INSTANTIATE_CLASS
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GA_API const UT_StringHolder N
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
bool wasInterrupted(T *i, int percent=-1)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.