31 #ifndef OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED 32 #define OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED 34 #include <tbb/parallel_reduce.h> 35 #include <tbb/blocked_range3d.h> 36 #include <tbb/blocked_range2d.h> 37 #include <tbb/blocked_range.h> 114 template<
typename OpType,
typename DenseType>
115 typename OpType::ResultTreeType::Ptr
117 const typename OpType::ResultValueType& background,
118 bool threaded =
true);
123 template <
typename DenseType,
typename TreeType>
struct DSConverter {
126 typedef typename TreeType::template ValueConverter<ValueType>::Type
Type;
139 template<
typename DenseType,
typename MaskTreeType>
142 const MaskTreeType& mask,
143 const typename DenseType::ValueType& background,
144 bool threaded =
true);
167 template<
typename ValueT,
typename OpType>
184 template<DSCompositeOp,
typename TreeT>
188 const typename TreeT::ValueType beta,
189 const typename TreeT::ValueType strength,
190 bool threaded =
true);
196 template<
typename OpType,
typename DenseType>
202 typedef openvdb::math::Coord::ValueType
Index;
208 typedef typename ResultTreeType::template ValueConverter<ValueMask>::Type
MaskTree;
210 typedef tbb::blocked_range3d<Index, Index, Index>
Range3d;
215 const DenseType& mDense;
216 const OpType& mFunctor;
218 const openvdb::math::CoordBBox mBBox;
220 typename ResultTreeType::Ptr mMask;
221 openvdb::math::Coord mMin;
228 mDense(dense), mFunctor(functor),
229 mBackground(background),
237 const openvdb::math::CoordBBox& bbox,
238 const OpType& functor,
240 mDense(dense), mFunctor(functor),
241 mBackground(background),
247 if (!dense.bbox().isInside(mBBox)) {
254 mDense(other.mDense), mFunctor(other.mFunctor),
255 mBackground(other.mBackground), mBBox(other.mBBox),
256 mWidth(other.mWidth),
261 typename ResultTreeType::Ptr
extract(
bool threaded =
true) {
269 openvdb::math::Coord padded_min = mBBox.min();
270 openvdb::math::Coord padded_max = mBBox.max();
273 padded_min &= ~(mWidth - 1);
274 padded_max &= ~(mWidth - 1);
276 padded_max[0] += mWidth - 1;
277 padded_max[1] += mWidth - 1;
278 padded_max[2] += mWidth - 1;
284 const Index xleafCount = ( padded_max.x() - padded_min.x() + 1 ) / mWidth;
285 const Index yleafCount = ( padded_max.y() - padded_min.y() + 1 ) / mWidth;
286 const Index zleafCount = ( padded_max.z() - padded_min.z() + 1 ) / mWidth;
291 Range3d leafRange(0, xleafCount, 1,
298 tbb::parallel_reduce(leafRange, *
this);
312 const Index imin = range.pages().begin();
313 const Index imax = range.pages().end();
315 const Index jmin = range.rows().begin();
316 const Index jmax = range.rows().end();
318 const Index kmin = range.cols().begin();
319 const Index kmax = range.cols().end();
325 for (
Index i = imin; i < imax; ++i) {
326 for (
Index j = jmin; j < jmax; ++j) {
327 for (
Index k = kmin; k < kmax; ++k) {
330 const openvdb::math::Coord origin =
331 mMin + openvdb::math::Coord(mWidth * i,
338 leaf->setOrigin(origin);
339 leaf->fill(mBackground);
340 leaf->setValuesOff();
345 openvdb::math::CoordBBox localBBox = leaf->getNodeBoundingBox();
350 localBBox.intersect(mBBox);
354 if (localBBox.empty())
continue;
357 const openvdb::math::Coord start = localBBox.getStart();
358 const openvdb::math::Coord end = localBBox.getEnd();
365 openvdb::math::Coord ijk;
368 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
369 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
370 for (ijk[2] = start.z(),
371 offset = ResultLeafNodeType::coordToOffset(ijk),
372 dp = &mDense.getValue(ijk);
373 ijk[2] < end.z(); ++ijk[2], ++offset, ++dp) {
375 mFunctor(*dp, offset, leaf);
382 openvdb::math::Coord ijk;
384 for (ijk[2] = start.z(); ijk[2] < end.z(); ++ijk[2]) {
385 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1]) {
386 for (ijk[0] = start.x(),
387 dp = &mDense.getValue(ijk);
388 ijk[0] < end.x(); ++ijk[0], ++dp) {
390 mFunctor(*dp, ijk, leaf);
399 if (!leaf->isEmpty()) {
400 mMask->addLeaf(leaf);
410 if (leaf != NULL)
delete leaf;
414 mMask->merge(*rhs.mMask);
419 template<
typename OpType,
typename DenseType>
420 typename OpType::ResultTreeType::Ptr
422 const typename OpType::ResultValueType& background,
432 return extractor.
extract(threaded);
439 template <
typename DenseType,
typename MaskTreeType>
450 typedef typename ResultTreeType::template ValueConverter<ValueMask>::Type
MaskTree;
452 typedef std::vector<const typename MaskTree::LeafNodeType*>
MaskLeafVec;
459 mDense(dense), mBackground(background), mBBox(dense.bbox()),
467 mDense(other.mDense), mBackground(other.mBackground), mBBox(other.mBBox),
468 mLeafVec(other.mLeafVec), mResult( new
ResultTreeType(mBackground))
471 typename ResultTreeType::Ptr
extract(
bool threaded =
true) {
473 tbb::blocked_range<size_t> range(0, mLeafVec.size());
476 tbb::parallel_reduce(range, *
this);
495 for (
size_t idx = range.begin(); idx < range.end(); ++ idx) {
501 openvdb::math::CoordBBox localBBox = maskLeaf->getNodeBoundingBox();
505 localBBox.intersect(mBBox);
509 if (localBBox.empty())
continue;
516 leaf->setOrigin(maskLeaf->origin());
517 leaf->fill(mBackground);
518 leaf->setValuesOff();
525 const openvdb::math::Coord start = localBBox.getStart();
526 const openvdb::math::Coord end = localBBox.getEnd();
529 openvdb::math::Coord ijk;
532 && maskLeaf->isDense()) {
536 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
537 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
538 for (ijk[2] = start.z(),
539 offset = ResultLeafNodeType::coordToOffset(ijk),
540 src = &mDense.getValue(ijk);
541 ijk[2] < end.z(); ++ijk[2], ++offset, ++src) {
544 leaf->setValueOn(offset, *src);
553 for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
554 for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
555 for (ijk[2] = start.z(),
556 offset = ResultLeafNodeType::coordToOffset(ijk);
557 ijk[2] < end.z(); ++ijk[2], ++offset) {
559 if (maskLeaf->isValueOn(offset)) {
561 leaf->setValueOn(offset, denseValue);
569 if (!leaf->isEmpty()) {
570 mResult->addLeaf(leaf);
577 if (leaf != NULL)
delete leaf;
581 mResult->merge(*rhs.mResult);
586 const DenseType& mDense;
587 const ResultValueType mBackground;
588 const openvdb::math::CoordBBox& mBBox;
589 const MaskLeafVec& mLeafVec;
591 typename ResultTreeType::Ptr mResult;
597 template<
typename _ResultTreeType,
typename DenseValueType>
603 template<
typename CoordOrIndex>
inline void 606 leaf->setValueOn(offset, a);
611 template <
typename DenseType,
typename MaskTreeType>
612 typename DSConverter<DenseType, MaskTreeType>::Type::Ptr
614 const MaskTreeType& maskProxy,
615 const typename DenseType::ValueType& background,
619 typedef typename LeafExtractor::DenseValueType DenseValueType;
620 typedef typename LeafExtractor::ResultTreeType ResultTreeType;
621 typedef typename LeafExtractor::MaskLeafVec MaskLeafVec;
623 typedef typename LeafExtractor::MaskLeafCIter MaskLeafCIter;
632 const size_t leafCount = maskTree.
leafCount();
633 MaskLeafVec leafarray(leafCount);
634 MaskLeafCIter leafiter = maskTree.
cbeginLeaf();
635 for (
size_t n = 0; n != leafCount; ++n, ++leafiter) {
636 leafarray[n] = leafiter.
getLeaf();
642 LeafExtractor leafextractor(dense, background, leafarray);
643 typename ResultTreeType::Ptr resultTree = leafextractor.extract(threaded);
653 typename MaskTreeType::ValueOnCIter tileIter(maskProxy);
654 tileIter.setMaxDepth(MaskTreeType::ValueOnCIter::LEAF_DEPTH - 1);
658 if (!tileIter)
return resultTree;
660 ExtractionRule allrule;
666 for ( ; tileIter; ++tileIter) {
670 tileIter.getBoundingBox(bbox);
673 if (bbox.
empty())
continue;
676 typename ResultTreeType::Ptr fromTileTree = copyData.
extract(threaded);
677 resultTree->merge(*fromTileTree);
687 template <
typename _ValueT,
typename OpType>
694 typedef openvdb::math::Coord::ValueType
IntType;
695 typedef tbb::blocked_range2d<IntType, IntType>
RangeType;
702 openvdb::math::CoordBBox mBBox;
706 const openvdb::math::CoordBBox& bbox,
707 const OpType& functor):
708 mDense(dense), mOp(functor), mBBox(dense.bbox())
712 mBBox.intersect(bbox);
716 mDense(other.mDense), mOp(other.mOp), mBBox(other.mBBox) {}
722 if (mBBox.empty())
return;
725 const openvdb::math::Coord start = mBBox.getStart();
726 const openvdb::math::Coord end = mBBox.getEnd();
729 const RangeType range(start.x(), end.x(), 1,
730 start.y(), end.y(), 1);
733 tbb::parallel_for(range, *
this);
744 const size_t zlength = size_t(mBBox.max().z() - mBBox.min().z() + 1);
746 const IntType imin = range.rows().begin();
747 const IntType imax = range.rows().end();
748 const IntType jmin = range.cols().begin();
749 const IntType jmax = range.cols().end();
752 openvdb::math::Coord xyz(imin, jmin, mBBox.min().z());
753 for (xyz[0] = imin; xyz[0] != imax; ++xyz[0]) {
754 for (xyz[1] = jmin; xyz[1] != jmax; ++xyz[1]) {
756 mOp.transform(mDense, xyz, zlength);
766 template <
typename ValueT,
typename Po
intWiseOp>
774 ValueT* dp = const_cast<ValueT*>(&dense.
getValue(ijk));
776 for (
size_t offset = 0; offset < size; ++offset) {
777 dp[offset] = mOp(dp[offset]);
786 template <
typename ValueT,
typename Po
intwiseOpT>
790 const PointwiseOpT& functor,
bool parallel)
800 transformer.
apply(parallel);
804 template <
typename CompositeMethod,
typename _TreeT>
810 typedef typename TreeT::ValueType
ValueT;
811 typedef typename TreeT::LeafNodeType
LeafT;
812 typedef typename TreeT::template ValueConverter<ValueMask>::Type
MaskTreeT;
815 typedef openvdb::math::Coord::ValueType
Index;
816 typedef tbb::blocked_range3d<Index, Index, Index>
Range3d;
820 mDense(dense), mSource(source), mAlpha(alpha), mBeta(beta), mStrength(strength)
824 mDense(other.mDense), mSource(other.mSource), mAlpha(other.mAlpha),
825 mBeta(other.mBeta), mStrength(other.mStrength) {}
831 const ValueT beta = mBeta;
832 const ValueT strenght = mStrength;
837 maskTree.topologyUnion(mAlpha);
842 openvdb::tree::LeafManager<const MaskTreeT> maskLeafs(maskTree);
843 maskLeafs.foreach(*
this, threaded);
848 typename MaskTreeT::ValueOnCIter citer = maskTree.cbeginValueOn();
849 citer.setMaxDepth(MaskTreeT::ValueOnCIter::LEAF_DEPTH - 1);
856 for (; citer; ++citer) {
858 const openvdb::math::Coord org = citer.getCoord();
870 openvdb::math::CoordBBox localBBox = citer.getBoundingBox();
871 localBBox.intersect(mDense.bbox());
875 if (localBBox.empty())
continue;
878 compositeFromTile(mDense, localBBox, sourceValue,
879 alphaValue, beta, strenght, threaded);
888 typedef UniformLeaf ULeaf;
889 openvdb::math::CoordBBox localBBox = maskLeaf.getNodeBoundingBox();
890 localBBox.intersect(mDense.bbox());
894 if (localBBox.empty())
return;
896 const openvdb::math::Coord org = maskLeaf.origin();
897 const LeafT* alphaLeaf = mAlpha.probeLeaf(org);
898 const LeafT* sourceLeaf = mSource.probeLeaf(org);
903 ULeaf uniformSource(mSource.getValue(org));
908 ULeaf uniformAlpha(mAlpha.getValue(org));
910 compositeFromLeaf(mDense, localBBox, uniformSource, uniformAlpha,
914 compositeFromLeaf(mDense, localBBox, uniformSource, *alphaLeaf,
921 ULeaf uniformAlpha(mAlpha.getValue(org));
923 compositeFromLeaf(mDense, localBBox, *sourceLeaf, uniformAlpha,
927 compositeFromLeaf(mDense, localBBox, *sourceLeaf, *alphaLeaf,
934 template <
typename LeafT1,
typename LeafT2>
936 const LeafT1& source,
const LeafT2& alpha,
939 typedef openvdb::math::Coord::ValueType IntType;
941 const ValueT sbeta = strength * beta;
942 openvdb::math::Coord ijk = bbox.min();
945 if (alpha.isDense() ) {
948 const IntType size = bbox.max().z() + 1 - bbox.min().z();
950 for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
951 for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
954 const ValueT* a = &alpha.getValue(ijk);
955 const ValueT* s = &source.getValue(ijk);
957 for (IntType idx = 0; idx < size; ++idx) {
958 d[idx] = CompositeMethod::apply(d[idx], a[idx], s[idx],
959 strength, beta, sbeta);
967 for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
968 for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
969 for (ijk[2] = bbox.min().z(); ijk[2] < bbox.max().z() + 1; ++ijk[2]) {
971 if (alpha.isValueOn(ijk)) {
974 CompositeMethod::apply(dense.
getValue(ijk),
975 alpha.getValue(ijk), source.getValue(ijk),
976 strength, beta, sbeta)
991 typedef UniformTransformer TileTransformer;
992 TileTransformer functor(sourceValue, alphaValue, beta, strength);
1005 const openvdb::math::CoordBBox& bbox = mDense.bbox();
1007 Range3d range(bbox.min().x(), bbox.max().x(), LeafT::DIM,
1008 bbox.min().y(), bbox.max().y(), LeafT::DIM,
1009 bbox.min().z(), bbox.max().z(), LeafT::DIM);
1015 tbb::parallel_for(range, *
this);
1031 const ValueT strength = mStrength;
1032 const ValueT beta = mBeta;
1033 const ValueT sbeta = strength * beta;
1036 const Index imin = range.pages().begin();
1037 const Index imax = range.pages().end();
1039 const Index jmin = range.rows().begin();
1040 const Index jmax = range.rows().end();
1042 const Index kmin = range.cols().begin();
1043 const Index kmax = range.cols().end();
1046 for (ijk[0] = imin; ijk[0] < imax; ++ijk[0]) {
1047 for (ijk[1] = jmin; ijk[1] < jmax; ++ijk[1]) {
1048 for (ijk[2] = kmin; ijk[2] < kmax; ++ijk[2]) {
1049 const ValueT d_old = mDense.getValue(ijk);
1053 mDense.setValue(ijk, CompositeMethod::apply(d_old, alpha, src,
1054 strength, beta, sbeta));
1067 class UniformTransformer
1070 UniformTransformer(
const ValueT& source,
const ValueT& alpha,
const ValueT& _beta,
1071 const ValueT& _strength) :
1072 mSource(source), mAlpha(alpha), mBeta(_beta),
1073 mStrength(_strength), mSBeta(_strength * _beta)
1076 ValueT operator()(
const ValueT& input)
const 1078 return CompositeMethod::apply(input, mAlpha, mSource,
1079 mStrength, mBeta, mSBeta);
1083 const ValueT mSource;
const ValueT mAlpha;
const ValueT mBeta;
1084 const ValueT mStrength;
const ValueT mSBeta;
1091 struct Line { ValueT mValues[LeafT::DIM]; };
1092 class UniformLeaf :
private Line
1095 typedef typename LeafT::ValueType ValueT;
1098 UniformLeaf(
const ValueT& value) : BaseT(init(value)) {}
1100 static const BaseT init(
const ValueT& value) {
1103 tmp.mValues[i] = value;
1108 bool isDense()
const {
return true; }
1109 bool isValueOn(openvdb::math::Coord&)
const {
return true; }
1111 inline const ValueT& getValue(
const openvdb::math::Coord& )
const 1112 {
return BaseT::mValues[0];}
1117 const TreeT& mSource;
1118 const TreeT& mAlpha;
1127 template <
typename ValueT>
1131 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1133 const ValueT strength,
1136 {
return (u + strength * alpha * (beta * v - u)); }
1140 template <
typename ValueT>
1143 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1148 {
return (u + sbeta * alpha * v); }
1151 template <
typename ValueT>
1154 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1159 {
return (u - sbeta * alpha * v); }
1162 template <
typename ValueT>
1165 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1170 {
return ( ( 1 - s * alpha) * u + s * alpha *
std::min(u, beta * v) ); }
1174 template <
typename ValueT>
1177 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1182 {
return ( ( 1 - s * alpha ) * u + s * alpha *
std::min(u, beta * v) ); }
1185 template <
typename ValueT>
1188 static inline ValueT
apply(
const ValueT u,
const ValueT alpha,
1193 {
return ( ( 1 + alpha * (sbeta * v - s)) * u ); }
1198 template <DSCompositeOp OP,
typename ValueT>
1202 template <
typename ValueT>
1205 template <
typename ValueT>
1208 template <
typename ValueT>
1211 template <
typename ValueT>
1214 template <
typename ValueT>
1217 template <
typename ValueT>
1224 template <DSCompositeOp OpT,
typename TreeT>
1227 const TreeT& source,
const TreeT& alpha,
1228 const typename TreeT::ValueType beta,
1229 const typename TreeT::ValueType strength,
1232 typedef typename TreeT::ValueType ValueT;
1234 typedef typename Translator::OpT Method;
1255 #endif //OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
tree::Tree4< ValueMask, 5, 4, 3 >::Type MaskTree
Definition: openvdb.h:54
Index32 Index
Definition: Types.h:61
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels)
Definition: TreeIterator.h:1235
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Index32 leafCount() const override
Return the number of leaf nodes.
Definition: Tree.h:368
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
This file defines a simple dense grid and efficient converters to and from VDB grids.
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:308
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:257
Definition: Exceptions.h:40
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1181
Definition: Exceptions.h:92
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
LeafNodeT * getLeaf() const
Return the leaf node to which the iterator is pointing.
Definition: TreeIterator.h:1278
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:448
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition: Coord.h:372