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>
102 using Type =
typename TreeType::template ValueConverter<ValueType>::Type;
115 template<
typename DenseType,
typename MaskTreeType>
118 const MaskTreeType& mask,
119 const typename DenseType::ValueType& background,
120 bool threaded =
true);
143 template<
typename ValueT,
typename OpType>
160 template<DSCompositeOp,
typename TreeT>
164 const typename TreeT::ValueType beta,
165 const typename TreeT::ValueType strength,
166 bool threaded =
true);
172 template<
typename OpType,
typename DenseType>
176 using Index = openvdb::math::Coord::ValueType;
182 using MaskTree =
typename ResultTreeType::template ValueConverter<ValueMask>::Type;
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)) {
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);
374 if (leaf !=
nullptr)
delete 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>
412 using MaskTree =
typename ResultTreeType::template ValueConverter<ValueMask>::Type;
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);
533 if (leaf !=
nullptr)
delete 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>
570 const MaskTreeType& maskProxy,
571 const typename DenseType::ValueType& background,
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) {
592 leafarray[n] = leafiter.
getLeaf();
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>
649 using IntType = openvdb::math::Coord::ValueType;
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();
680 const RangeType range(start.x(), end.x(), 1,
681 start.y(), end.y(), 1);
684 tbb::parallel_for(range, *
this);
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));
727 for (
size_t offset = 0; offset < size; ++offset) {
728 dp[offset] = mOp(dp[offset]);
737 template<
typename ValueT,
typename Po
intwiseOpT>
741 const PointwiseOpT& functor,
bool parallel)
751 transformer.
apply(parallel);
755 template<
typename CompositeMethod,
typename _TreeT>
760 using ValueT =
typename TreeT::ValueType;
761 using LeafT =
typename TreeT::LeafNodeType;
762 using MaskTreeT =
typename TreeT::template ValueConverter<ValueMask>::Type;
765 using Index = openvdb::math::Coord::ValueType;
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;
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;
827 compositeFromTile(mDense, localBBox, sourceValue,
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));
858 compositeFromLeaf(mDense, localBBox, uniformSource, uniformAlpha,
862 compositeFromLeaf(mDense, localBBox, uniformSource, *alphaLeaf,
869 ULeaf uniformAlpha(mAlpha.getValue(org));
871 compositeFromLeaf(mDense, localBBox, *sourceLeaf, uniformAlpha,
875 compositeFromLeaf(mDense, localBBox, *sourceLeaf, *alphaLeaf,
882 template<
typename LeafT1,
typename LeafT2>
884 const LeafT1& source,
const LeafT2& alpha,
887 using IntType = openvdb::math::Coord::ValueType;
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);
956 tbb::parallel_for(range, *
this);
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]) {
989 const ValueT d_old = mDense.getValue(ijk);
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);
1030 struct Line {
ValueT mValues[LeafT::DIM]; };
1031 class UniformLeaf :
private Line
1034 using ValueT =
typename LeafT::ValueType;
1037 UniformLeaf(
const ValueT&
value) : BaseT(init(value)) {}
1039 static const BaseT init(
const ValueT& value) {
1042 tmp.mValues[i] =
value;
1047 bool isDense()
const {
return true; }
1048 bool isValueOn(openvdb::math::Coord&)
const {
return true; }
1050 const ValueT& getValue(
const openvdb::math::Coord&)
const {
return BaseT::mValues[0]; }
1055 const TreeT& mSource;
1056 const TreeT& mAlpha;
1066 template<
typename ValueT>
1069 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1071 const ValueT strength,
1074 {
return (u + strength * alpha * (beta * v - u)); }
1077 template<
typename ValueT>
1080 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1085 {
return (u + sbeta * alpha * v); }
1088 template<
typename ValueT>
1091 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1096 {
return (u - sbeta * alpha * v); }
1099 template<
typename ValueT>
1102 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1107 {
return ( ( 1 - s * alpha) * u + s * alpha *
std::min(u, beta * v) ); }
1110 template<
typename ValueT>
1113 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1118 {
return ( ( 1 - s * alpha ) * u + s * alpha *
std::min(u, beta * v) ); }
1121 template<
typename ValueT>
1124 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
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>
1164 const TreeT& source,
const TreeT& alpha,
1165 const typename TreeT::ValueType beta,
1166 const typename TreeT::ValueType strength,
1169 using ValueT =
typename TreeT::ValueType;
1171 using Method =
typename Translator::OpT;
1192 #endif //OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED Index32 leafCount() const override
Return the number of leaf nodes.
Definition: Tree.h:338
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Iterator over all leaf nodes in this tree.
Definition: Tree.h:1003
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:184
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:219
This file defines a simple dense grid and efficient converters to and from VDB grids.
Definition: Exceptions.h:65
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
tree::Tree4< ValueMask, 5, 4, 3 >::Type MaskTree
Definition: openvdb.h:27
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Index32 Index
Definition: Types.h:54
LeafNodeT * getLeaf() const
Return the leaf node to which the iterator is pointing.
Definition: TreeIterator.h:1229
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1017
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:338
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202