4 #ifndef OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
5 #define OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
7 #include <tbb/parallel_reduce.h>
8 #include <tbb/blocked_range3d.h>
9 #include <tbb/blocked_range2d.h>
10 #include <tbb/blocked_range.h>
89 template<
typename OpType,
typename DenseType>
90 typename OpType::ResultTreeType::Ptr
92 const typename OpType::ResultValueType& background,
93 bool threaded =
true);
98 template<
typename DenseType,
typename TreeType>
115 template<
typename DenseType,
typename MaskTreeType>
118 const MaskTreeType&
mask,
120 bool threaded =
true);
143 template<
typename ValueT,
typename OpType>
160 template<DSCompositeOp,
typename TreeT>
166 bool threaded =
true);
172 template<
typename OpType,
typename DenseType>
184 using Range3d = tbb::blocked_range3d<Index, Index, Index>;
187 const DenseType& mDense;
188 const OpType& mFunctor;
192 typename ResultTreeType::Ptr mMask;
193 openvdb::math::Coord mMin;
198 mDense(dense), mFunctor(functor),
199 mBackground(background),
207 const OpType& functor,
209 mDense(dense), mFunctor(functor),
210 mBackground(background),
216 if (!dense.bbox().isInside(mBBox)) {
217 OPENVDB_THROW(ValueError,
"Data extraction window out of bound");
222 mDense(other.mDense), mFunctor(other.mFunctor),
223 mBackground(other.mBackground), mBBox(other.mBBox),
224 mWidth(other.mWidth),
229 typename ResultTreeType::Ptr
extract(
bool threaded =
true)
236 openvdb::math::Coord padded_min = mBBox.min();
237 openvdb::math::Coord padded_max = mBBox.max();
240 padded_min &= ~(mWidth - 1);
241 padded_max &= ~(mWidth - 1);
243 padded_max[0] += mWidth - 1;
244 padded_max[1] += mWidth - 1;
245 padded_max[2] += mWidth - 1;
251 const Index xleafCount = ( padded_max.x() - padded_min.x() + 1 ) / mWidth;
252 const Index yleafCount = ( padded_max.y() - padded_min.y() + 1 ) / mWidth;
253 const Index zleafCount = ( padded_max.z() - padded_min.z() + 1 ) / mWidth;
257 Range3d leafRange(0, xleafCount, 1,
263 tbb::parallel_reduce(leafRange, *
this);
276 const Index imin = range.pages().begin();
277 const Index imax = range.pages().end();
279 const Index jmin = range.rows().begin();
280 const Index jmax = range.rows().end();
282 const Index kmin = range.cols().begin();
283 const Index kmax = range.cols().end();
289 for (
Index i = imin; i < imax; ++i) {
290 for (
Index j = jmin;
j < jmax; ++
j) {
291 for (
Index k = kmin; k < kmax; ++k) {
294 const openvdb::math::Coord origin =
295 mMin + openvdb::math::Coord(mWidth * i,
299 if (leaf ==
nullptr) {
302 leaf->setOrigin(origin);
303 leaf->fill(mBackground);
304 leaf->setValuesOff();
314 localBBox.intersect(mBBox);
318 if (localBBox.empty())
continue;
321 const openvdb::math::Coord
start = localBBox.getStart();
322 const openvdb::math::Coord
end = localBBox.getEnd();
329 openvdb::math::Coord ijk;
332 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
333 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
334 for (ijk[2] = start.z(),
335 offset = ResultLeafNodeType::coordToOffset(ijk),
336 dp = &mDense.getValue(ijk);
337 ijk[2] < end.z(); ++ijk[2], ++
offset, ++dp) {
339 mFunctor(*dp, offset, leaf);
346 openvdb::math::Coord ijk;
348 for (ijk[2] = start.z(); ijk[2] < end.z(); ++ijk[2]) {
349 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1]) {
350 for (ijk[0] = start.x(),
351 dp = &mDense.getValue(ijk);
352 ijk[0] < end.x(); ++ijk[0], ++dp) {
354 mFunctor(*dp, ijk, leaf);
363 if (!leaf->isEmpty()) {
364 mMask->addLeaf(leaf);
378 mMask->merge(*rhs.mMask);
383 template<
typename OpType,
typename DenseType>
384 typename OpType::ResultTreeType::Ptr
386 const typename OpType::ResultValueType& background,
395 return extractor.
extract(threaded);
402 template<
typename DenseType,
typename MaskTreeType>
414 using MaskLeafVec = std::vector<const typename MaskTree::LeafNodeType*>;
421 mDense(dense), mBackground(background), mBBox(dense.bbox()),
427 mDense(other.mDense), mBackground(other.mBackground), mBBox(other.mBBox),
428 mLeafVec(other.mLeafVec), mResult( new
ResultTreeType(mBackground))
431 typename ResultTreeType::Ptr
extract(
bool threaded =
true)
433 tbb::blocked_range<size_t>
range(0, mLeafVec.size());
436 tbb::parallel_reduce(
range, *
this);
453 for (
size_t idx = range.begin(); idx < range.end(); ++ idx) {
463 localBBox.intersect(mBBox);
467 if (localBBox.empty())
continue;
471 if (leaf ==
nullptr) {
474 leaf->setOrigin(maskLeaf->origin());
475 leaf->fill(mBackground);
476 leaf->setValuesOff();
482 const openvdb::math::Coord
start = localBBox.getStart();
483 const openvdb::math::Coord
end = localBBox.getEnd();
485 openvdb::math::Coord ijk;
488 && maskLeaf->isDense()) {
492 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
493 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
494 for (ijk[2] = start.z(),
495 offset = ResultLeafNodeType::coordToOffset(ijk),
496 src = &mDense.getValue(ijk);
497 ijk[2] < end.z(); ++ijk[2], ++
offset, ++
src) {
500 leaf->setValueOn(offset, *src);
509 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
510 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
511 for (ijk[2] = start.z(),
512 offset = ResultLeafNodeType::coordToOffset(ijk);
513 ijk[2] < end.z(); ++ijk[2], ++
offset) {
515 if (maskLeaf->isValueOn(offset)) {
517 leaf->setValueOn(offset, denseValue);
525 if (!leaf->isEmpty()) {
526 mResult->addLeaf(leaf);
537 mResult->merge(*rhs.mResult);
542 const DenseType& mDense;
547 typename ResultTreeType::Ptr mResult;
553 template<
typename _ResultTreeType,
typename DenseValueType>
559 template<
typename CoordOrIndex>
inline void
562 leaf->setValueOn(offset, a);
567 template<
typename DenseType,
typename MaskTreeType>
568 typename DSConverter<DenseType, MaskTreeType>::Type::Ptr
570 const MaskTreeType& maskProxy,
575 using DenseValueType =
typename LeafExtractor::DenseValueType;
576 using ResultTreeType =
typename LeafExtractor::ResultTreeType;
577 using MaskLeafVec =
typename LeafExtractor::MaskLeafVec;
579 using MaskLeafCIter =
typename LeafExtractor::MaskLeafCIter;
588 const size_t leafCount = maskTree.
leafCount();
589 MaskLeafVec leafarray(leafCount);
590 MaskLeafCIter leafiter = maskTree.
cbeginLeaf();
591 for (
size_t n = 0;
n != leafCount; ++
n, ++leafiter) {
598 LeafExtractor leafextractor(dense, background, leafarray);
599 typename ResultTreeType::Ptr resultTree = leafextractor.extract(threaded);
609 typename MaskTreeType::ValueOnCIter tileIter(maskProxy);
610 tileIter.setMaxDepth(MaskTreeType::ValueOnCIter::LEAF_DEPTH - 1);
614 if (!tileIter)
return resultTree;
616 ExtractionRule allrule;
622 for ( ; tileIter; ++tileIter) {
626 tileIter.getBoundingBox(bbox);
627 bbox.intersect(dense.bbox());
629 if (bbox.empty())
continue;
632 typename ResultTreeType::Ptr fromTileTree = copyData.
extract(threaded);
633 resultTree->merge(*fromTileTree);
643 template<
typename _ValueT,
typename OpType>
650 using RangeType = tbb::blocked_range2d<IntType, IntType>;
659 mDense(dense), mOp(functor), mBBox(dense.bbox())
663 mBBox.intersect(bbox);
667 mDense(other.mDense), mOp(other.mOp), mBBox(other.mBBox) {}
673 if (mBBox.empty())
return;
676 const openvdb::math::Coord
start = mBBox.getStart();
677 const openvdb::math::Coord
end = mBBox.getEnd();
681 start.y(), end.y(), 1);
695 const size_t zlength = size_t(mBBox.max().z() - mBBox.min().z() + 1);
697 const IntType imin = range.rows().begin();
698 const IntType imax = range.rows().end();
699 const IntType jmin = range.cols().begin();
700 const IntType jmax = range.cols().end();
703 openvdb::math::Coord xyz(imin, jmin, mBBox.min().z());
704 for (xyz[0] = imin; xyz[0] != imax; ++xyz[0]) {
705 for (xyz[1] = jmin; xyz[1] != jmax; ++xyz[1]) {
707 mOp.transform(mDense, xyz, zlength);
717 template<
typename ValueT,
typename Po
intWiseOp>
725 ValueT* dp =
const_cast<ValueT*
>(&dense.
getValue(ijk));
737 template<
typename ValueT,
typename Po
intwiseOpT>
741 const PointwiseOpT& functor,
bool parallel)
751 transformer.
apply(parallel);
755 template<
typename CompositeMethod,
typename _TreeT>
761 using LeafT =
typename TreeT::LeafNodeType;
766 using Range3d = tbb::blocked_range3d<Index, Index, Index>;
770 mDense(dense), mSource(source), mAlpha(alpha), mBeta(beta), mStrength(strength)
774 mDense(other.mDense), mSource(other.mSource), mAlpha(other.mAlpha),
775 mBeta(other.mBeta), mStrength(other.mStrength) {}
780 const ValueT beta = mBeta;
781 const ValueT strength = mStrength;
785 MaskTreeT maskTree(mSource,
false , openvdb::TopologyCopy());
786 maskTree.topologyUnion(mAlpha);
791 openvdb::tree::LeafManager<const MaskTreeT> maskLeafs(maskTree);
792 maskLeafs.foreach(*
this, threaded);
797 typename MaskTreeT::ValueOnCIter citer = maskTree.cbeginValueOn();
798 citer.setMaxDepth(MaskTreeT::ValueOnCIter::LEAF_DEPTH - 1);
805 for (; citer; ++citer) {
807 const openvdb::math::Coord org = citer.getCoord();
820 localBBox.intersect(mDense.
bbox());
824 if (localBBox.empty())
continue;
828 alphaValue, beta, strength, threaded);
836 using ULeaf = UniformLeaf;
838 localBBox.intersect(mDense.
bbox());
842 if (localBBox.empty())
return;
844 const openvdb::math::Coord org = maskLeaf.origin();
845 const LeafT* alphaLeaf = mAlpha.probeLeaf(org);
846 const LeafT* sourceLeaf = mSource.probeLeaf(org);
851 ULeaf uniformSource(mSource.getValue(org));
856 ULeaf uniformAlpha(mAlpha.getValue(org));
869 ULeaf uniformAlpha(mAlpha.getValue(org));
882 template<
typename LeafT1,
typename LeafT2>
889 const ValueT sbeta = strength * beta;
890 openvdb::math::Coord ijk = bbox.min();
893 if (alpha.isDense() ) {
896 const IntType
size = bbox.max().z() + 1 - bbox.min().z();
898 for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
899 for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
902 const ValueT*
a = &alpha.getValue(ijk);
903 const ValueT*
s = &source.getValue(ijk);
905 for (IntType idx = 0; idx <
size; ++idx) {
906 d[idx] = CompositeMethod::apply(d[idx], a[idx], s[idx],
907 strength, beta, sbeta);
915 for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
916 for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
917 for (ijk[2] = bbox.min().z(); ijk[2] < bbox.max().z() + 1; ++ijk[2]) {
919 if (alpha.isValueOn(ijk)) {
921 alpha.getValue(ijk), source.getValue(ijk), strength, beta, sbeta));
934 using TileTransformer = UniformTransformer;
935 TileTransformer functor(sourceValue, alphaValue, beta, strength);
948 Range3d range(bbox.min().x(), bbox.max().x(), LeafT::DIM,
949 bbox.min().y(), bbox.max().y(), LeafT::DIM,
950 bbox.min().z(), bbox.max().z(), LeafT::DIM);
971 const ValueT strength = mStrength;
972 const ValueT beta = mBeta;
973 const ValueT sbeta = strength * beta;
976 const Index imin = range.pages().begin();
977 const Index imax = range.pages().end();
979 const Index jmin = range.rows().begin();
980 const Index jmax = range.rows().end();
982 const Index kmin = range.cols().begin();
983 const Index kmax = range.cols().end();
986 for (ijk[0] = imin; ijk[0] < imax; ++ijk[0]) {
987 for (ijk[1] = jmin; ijk[1] < jmax; ++ijk[1]) {
988 for (ijk[2] = kmin; ijk[2] < kmax; ++ijk[2]) {
994 CompositeMethod::apply(d_old, alpha, src, strength, beta, sbeta));
1004 class UniformTransformer
1008 const ValueT& _strength) :
1009 mSource(source), mAlpha(alpha), mBeta(_beta),
1010 mStrength(_strength), mSBeta(_strength * _beta)
1015 return CompositeMethod::apply(input, mAlpha, mSource, mStrength, mBeta, mSBeta);
1031 class UniformLeaf :
private Line
1041 for (openvdb::Index i = 0; i < LeafT::DIM; ++i) {
1042 tmp.mValues[i] =
value;
1047 bool isDense()
const {
return true; }
1048 bool isValueOn(openvdb::math::Coord&)
const {
return true; }
1055 const TreeT& mSource;
1056 const TreeT& mAlpha;
1066 template<
typename ValueT>
1071 const ValueT strength,
1074 {
return (u + strength * alpha * (beta * v - u)); }
1077 template<
typename ValueT>
1085 {
return (u + sbeta * alpha * v); }
1088 template<
typename ValueT>
1096 {
return (u - sbeta * alpha * v); }
1099 template<
typename ValueT>
1107 {
return ( ( 1 - s * alpha) * u + s * alpha *
std::min(u, beta * v) ); }
1110 template<
typename ValueT>
1118 {
return ( ( 1 - s * alpha ) * u + s * alpha *
std::min(u, beta * v) ); }
1121 template<
typename ValueT>
1129 {
return ( ( 1 + alpha * (sbeta * v - s)) * u ); }
1135 template<DSCompositeOp OP,
typename ValueT>
1138 template<
typename ValueT>
1141 template<
typename ValueT>
1144 template<
typename ValueT>
1147 template<
typename ValueT>
1150 template<
typename ValueT>
1153 template<
typename ValueT>
1160 template<DSCompositeOp OpT,
typename TreeT>
1171 using Method =
typename Translator::OpT;
1192 #endif //OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
GLsizei const GLfloat * value
NanoTree< ValueMask > MaskTree
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
__hostdev__ float getValue(uint32_t i) const
This file defines a simple dense grid and efficient converters to and from VDB grids.
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Iterator over all leaf nodes in this tree.
Index32 leafCount() const override
Return the number of leaf nodes.
GLsizei GLsizei GLchar * source
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
GLfloat GLfloat GLfloat alpha
typename RootNodeType::LeafNodeType LeafNodeType
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
LeafNodeT * getLeaf() const
Return the leaf node to which the iterator is pointing.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
#define OPENVDB_THROW(exception, message)