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 {
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();
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;
152 template<
class Gr
idType,
class InterruptType>
154 : mInterrupter(interrupter)
160 template<
class Gr
idType,
class InterruptType>
168 if (points && points->size() != 0) {
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);
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) {
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.
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.