9 #ifndef OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED 
   10 #define OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED 
   19 #include <tbb/blocked_range.h> 
   20 #include <tbb/parallel_reduce.h> 
   21 #include <type_traits>  
   38 template<
typename Gr
idType>
 
   39 typename GridType::Ptr
 
   49 template<
typename Gr
idType>
 
   50 typename GridType::Ptr
 
   51 clip(
const GridType& grid, 
const math::NonlinearFrustumMap& frustum, 
bool keepInterior = 
true);
 
   65 template<
typename Gr
idType, 
typename MaskTreeType>
 
   66 typename GridType::Ptr
 
   67 clip(
const GridType& grid, 
const Grid<MaskTreeType>& 
mask, 
bool keepInterior = 
true);
 
   74 namespace clip_internal {
 
   78 using MaskValueType = ValueMask;
 
   82 template<
typename TreeT>
 
   83 class MaskInteriorVoxels
 
   87     using LeafNodeT = 
typename TreeT::LeafNodeType;
 
   89     MaskInteriorVoxels(
const TreeT& tree): mAcc(tree) {}
 
   91     template<
typename LeafNodeType>
 
   92     void operator()(LeafNodeType& leaf, 
size_t )
 const 
   94         const auto* refLeaf = mAcc.probeConstLeaf(leaf.origin());
 
   96             for (
auto iter = leaf.beginValueOff(); iter; ++iter) {
 
   97                 const auto pos = iter.pos();
 
  104      tree::ValueAccessor<const TreeT> mAcc;
 
  111 template<
typename TreeT>
 
  116     using MaskLeafManagerT = tree::LeafManager<const MaskTreeT>;
 
  118     CopyLeafNodes(
const TreeT&, 
const MaskLeafManagerT&);
 
  122     typename TreeT::Ptr tree()
 const { 
return mNewTree; }
 
  125     void operator()(
const tbb::blocked_range<size_t>&);
 
  126     void join(
const CopyLeafNodes& rhs) { mNewTree->merge(*rhs.mNewTree); }
 
  129     const MaskTreeT* mClipMask;
 
  131     const MaskLeafManagerT* mLeafNodes;
 
  132     typename TreeT::Ptr mNewTree;
 
  136 template<
typename TreeT>
 
  137 CopyLeafNodes<TreeT>::CopyLeafNodes(
const TreeT& tree, 
const MaskLeafManagerT& leafNodes)
 
  139     , mLeafNodes(&leafNodes)
 
  140     , mNewTree(new TreeT(mTree->background()))
 
  145 template<
typename TreeT>
 
  146 CopyLeafNodes<TreeT>::CopyLeafNodes(CopyLeafNodes& rhs, 
tbb::split)
 
  148     , mLeafNodes(rhs.mLeafNodes)
 
  149     , mNewTree(new TreeT(mTree->background()))
 
  154 template<
typename TreeT>
 
  156 CopyLeafNodes<TreeT>::run(
bool threaded)
 
  158     if (threaded) tbb::parallel_reduce(mLeafNodes->getRange(), *
this);
 
  159     else (*
this)(mLeafNodes->getRange());
 
  163 template<
typename TreeT>
 
  165 CopyLeafNodes<TreeT>::operator()(
const tbb::blocked_range<size_t>& 
range)
 
  167     tree::ValueAccessor<TreeT> acc(*mNewTree);
 
  168     tree::ValueAccessor<const TreeT> refAcc(*mTree);
 
  170     for (
auto n = range.begin(); 
n != range.end(); ++
n) {
 
  171         const auto& maskLeaf = mLeafNodes->leaf(
n);
 
  172         const auto& ijk = maskLeaf.origin();
 
  173         const auto* refLeaf = refAcc.probeConstLeaf(ijk);
 
  175         auto* newLeaf = acc.touchLeaf(ijk);
 
  178             for (
auto it = maskLeaf.cbeginValueOn(); it; ++it) {
 
  179                 const auto pos = it.pos();
 
  180                 newLeaf->setValueOnly(pos, refLeaf->getValue(pos));
 
  181                 newLeaf->setActiveState(pos, refLeaf->isValueOn(pos));
 
  185             bool isActive = refAcc.probeValue(ijk, value);
 
  187             for (
auto it = maskLeaf.cbeginValueOn(); it; ++it) {
 
  188                 const auto pos = it.pos();
 
  189                 newLeaf->setValueOnly(pos, value);
 
  190                 newLeaf->setActiveState(pos, isActive);
 
  202     static const char* 
name() { 
return "bin"; }
 
  203     static int radius() { 
return 2; }
 
  204     static bool mipmap() { 
return false; }
 
  205     static bool consistent() { 
return true; }
 
  207     template<
class TreeT>
 
  208     static bool sample(
const TreeT& inTree,
 
  211         return inTree.probeValue(
Coord::floor(inCoord), result);
 
  220 template<
typename FromGr
idT, 
typename ToGr
idT>
 
  223     using FromGridCPtrT = 
typename FromGridT::ConstPtr;
 
  224     using ToGridPtrT = 
typename ToGridT::Ptr;
 
  225     ToGridPtrT operator()(
const FromGridCPtrT& grid) { 
return ToGridPtrT(
new ToGridT(*grid)); }
 
  230 template<
typename Gr
idT>
 
  231 struct ConvertGrid<GridT, GridT>
 
  233     using GridCPtrT = 
typename GridT::ConstPtr;
 
  234     GridCPtrT operator()(
const GridCPtrT& grid) { 
return grid; }
 
  244 template<
typename Gr
idT>
 
  246     typename GridT::template ValueConverter<MaskValueType>::Type::Ptr>
::type 
  247 convertToMaskGrid(
const GridT& grid)
 
  250     auto mask = MaskGridT::create(
false);
 
  251     mask->topologyUnion(grid);
 
  252     mask->setTransform(grid.constTransform().copy());
 
  258 template<
typename Gr
idT>
 
  260     typename GridT::ConstPtr>
::type 
  261 convertToMaskGrid(
const GridT& grid)
 
  271 template<
typename Gr
idType>
 
  272 typename GridType::Ptr
 
  275     const typename GridType::template ValueConverter<MaskValueType>::Type& clipMask,
 
  278     using TreeT = 
typename GridType::TreeType;
 
  279     using MaskTreeT = 
typename GridType::TreeType::template ValueConverter<MaskValueType>::Type;
 
  281     const auto gridClass = grid.getGridClass();
 
  282     const auto& tree = grid.tree();
 
  284     MaskTreeT gridMask(
false);
 
  285     gridMask.topologyUnion(tree);
 
  288         tree::LeafManager<MaskTreeT> leafNodes(gridMask);
 
  289         leafNodes.foreach(MaskInteriorVoxels<TreeT>(tree));
 
  291         tree::ValueAccessor<const TreeT> acc(tree);
 
  293         typename MaskTreeT::ValueAllIter iter(gridMask);
 
  294         iter.setMaxDepth(MaskTreeT::ValueAllIter::LEAF_DEPTH - 1);
 
  296         for ( ; iter; ++iter) {
 
  302         gridMask.topologyIntersection(clipMask.constTree());
 
  304         gridMask.topologyDifference(clipMask.constTree());
 
  307     auto outGrid = grid.copyWithNewTree();
 
  310         tree::LeafManager<const MaskTreeT> leafNodes(gridMask);
 
  311         CopyLeafNodes<TreeT> maskOp(tree, leafNodes);
 
  313         outGrid->setTree(maskOp.tree());
 
  317         tree::ValueAccessor<const TreeT> refAcc(tree);
 
  318         tree::ValueAccessor<const MaskTreeT> maskAcc(gridMask);
 
  320         typename TreeT::ValueAllIter it(
outGrid->tree());
 
  321         it.setMaxDepth(TreeT::ValueAllIter::LEAF_DEPTH - 1);
 
  323             Coord ijk = it.getCoord();
 
  325             if (maskAcc.isValueOn(ijk)) {
 
  327                 bool isActive = refAcc.probeValue(ijk, value);
 
  330                 if (!isActive) it.setValueOff();
 
  335     outGrid->setTransform(grid.transform().copy());
 
  350 template<
typename Gr
idType>
 
  351 typename GridType::Ptr
 
  354     using MaskValueT = clip_internal::MaskValueType;
 
  358     Vec3d idxMin, idxMax;
 
  363     MaskGridT clipMask(
false);
 
  364     clipMask.fill(region, 
true, 
true);
 
  366     return clip_internal::doClip(grid, clipMask, keepInterior);
 
  371 template<
typename SrcGr
idType, 
typename ClipTreeType>
 
  372 typename SrcGridType::Ptr
 
  375     using MaskValueT = clip_internal::MaskValueType;
 
  378     using ClipMaskGridType = 
typename ClipGridType::template ValueConverter<MaskValueT>::Type;
 
  381     auto maskGrid = clip_internal::convertToMaskGrid(clipGrid);
 
  384     if (srcGrid.constTransform() != maskGrid->constTransform()) {
 
  385         auto resampledMask = ClipMaskGridType::create(
false);
 
  386         resampledMask->setTransform(srcGrid.constTransform().copy());
 
  387         tools::resampleToMatch<clip_internal::BoolSampler>(*maskGrid, *resampledMask);
 
  389         maskGrid = resampledMask;
 
  393     auto clipMask = clip_internal::ConvertGrid<
 
  394         ClipMaskGridType, SrcMaskGridType>()(maskGrid);
 
  397     return clip_internal::doClip(srcGrid, *clipMask, keepInterior);
 
  402 template<
typename Gr
idType>
 
  403 typename GridType::Ptr
 
  407     using TreeT = 
typename GridType::TreeType;
 
  408     using LeafT = 
typename TreeT::LeafNodeType;
 
  410     const auto& gridXform = inGrid.transform();
 
  411     const auto frustumIndexBBox = frustumMap.
getBBox();
 
  414     auto frustumContainsCoord = [&](
const Coord& ijk) -> 
bool {
 
  415         auto xyz = gridXform.indexToWorld(ijk);
 
  417         return frustumIndexBBox.isInside(xyz);
 
  422     auto toFrustumIndexSpace = [&](
const CoordBBox& inBBox) -> 
BBoxd {
 
  423         const Coord bounds[2] = { inBBox.
min(), inBBox.max() };
 
  426         for (
int i = 0; i < 8; ++i) {
 
  427             ijk[0] = bounds[(i & 1) >> 0][0];
 
  428             ijk[1] = bounds[(i & 2) >> 1][1];
 
  429             ijk[2] = bounds[(i & 4) >> 2][2];
 
  430             auto xyz = gridXform.indexToWorld(ijk);
 
  438     auto outGrid = inGrid.copyWithNewTree();
 
  444     const auto& bg = 
outGrid->background();
 
  446     auto outAcc = 
outGrid->getAccessor();
 
  452     auto tileIter = inGrid.beginValueAll();
 
  453     tileIter.setMaxDepth(GridType::ValueAllIter::LEAF_DEPTH - 1);
 
  455     for ( ; tileIter; ++tileIter) {
 
  456         const bool tileActive = tileIter.isValueOn();
 
  457         const auto& tileValue = tileIter.getValue();
 
  463         tileIter.getBoundingBox(tileBBox);
 
  464         const auto tileFrustumBBox = toFrustumIndexSpace(tileBBox);
 
  467         enum class CopyTile { kNone, kPartial, 
kFull };
 
  468         auto copyTile = CopyTile::kNone;
 
  470             if (frustumIndexBBox.isInside(tileFrustumBBox)) {
 
  472             } 
else if (frustumIndexBBox.hasOverlap(tileFrustumBBox)) {
 
  473                 copyTile = CopyTile::kPartial;
 
  476             if (!frustumIndexBBox.hasOverlap(tileFrustumBBox)) {
 
  478             } 
else if (!frustumIndexBBox.isInside(tileFrustumBBox)) {
 
  479                 copyTile = CopyTile::kPartial;
 
  483             case CopyTile::kNone:
 
  487                 outAcc.addTile(tileIter.getLevel(), tileBBox.min(), tileValue, tileActive);
 
  489             case CopyTile::kPartial:
 
  491                 for (std::vector<CoordBBox> bboxVec = { tileBBox }; !bboxVec.empty(); ) {
 
  496                     if (bboxVec.back().volume() > 64 && bboxVec.back().is_divisible()) {
 
  498                         bboxVec.emplace_back(bboxVec.back(), 
tbb::split{});
 
  501                     auto subBBox = bboxVec.back();
 
  506                         if (!frustumIndexBBox.hasOverlap(toFrustumIndexSpace(subBBox))) 
continue;
 
  508                         if (frustumIndexBBox.isInside(toFrustumIndexSpace(subBBox))) 
continue;
 
  512                     for (
const auto& ijk: subBBox) {
 
  513                         if (frustumContainsCoord(ijk) == keepInterior) {
 
  515                                 outAcc.setValueOn(ijk, tileValue);
 
  517                                 outAcc.setValueOff(ijk, tileValue);
 
  530     for (
auto leafIter = inGrid.constTree().beginLeaf(); leafIter; ++leafIter) {
 
  531         const auto leafBBox = leafIter->getNodeBoundingBox();
 
  532         const auto leafFrustumBBox = toFrustumIndexSpace(leafBBox);
 
  534             if (frustumIndexBBox.hasOverlap(leafFrustumBBox)) {
 
  535                 outAcc.touchLeaf(leafBBox.min());
 
  538             if (!frustumIndexBBox.hasOverlap(leafFrustumBBox)
 
  539                 || !frustumIndexBBox.isInside(leafFrustumBBox))
 
  541                 outAcc.touchLeaf(leafBBox.min());
 
  549     outLeafNodes.foreach(
 
  550         [&](LeafT& leaf, 
size_t ) {
 
  551             auto inAcc = inGrid.getConstAccessor();
 
  553             for (
auto voxelIter = leaf.beginValueAll(); voxelIter; ++voxelIter) {
 
  554                 const auto ijk = voxelIter.getCoord();
 
  555                 if (frustumContainsCoord(ijk) == keepInterior) {
 
  556                     const bool active = inAcc.probeValue(ijk, val);
 
  557                     voxelIter.setValue(val);
 
  558                     voxelIter.setValueOn(active);
 
  573 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
  575 #ifdef OPENVDB_INSTANTIATE_CLIP 
  579 #define _FUNCTION(TreeT) \ 
  580     Grid<TreeT>::Ptr clip(const Grid<TreeT>&, const BBoxd&, bool) 
  584 #define _FUNCTION(TreeT) \ 
  585     Grid<TreeT>::Ptr clip(const Grid<TreeT>&, const math::NonlinearFrustumMap&, bool) 
  589 #define _FUNCTION(TreeT) \ 
  590     Grid<TreeT>::Ptr clip_internal::doClip(const Grid<TreeT>&, const MaskGrid&, bool) 
  594 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 
  601 #endif // OPENVDB_TOOLS_CLIP_HAS_BEEN_INCLUDED 
GridType
List of types that are currently supported by NanoVDB. 
 
IMATH_HOSTDEVICE constexpr int floor(T x) IMATH_NOEXCEPT
 
const BBoxd & getBBox() const 
Return the bounding box that defines the frustum in pre-image space. 
 
GLsizei const GLfloat * value
 
This map is composed of three steps. First it will take a box of size (Lx X Ly X Lz) defined by a mem...
 
#define OPENVDB_USE_VERSION_NAMESPACE
 
void expand(ElementType padding)
Pad this bounding box. 
 
**But if you need a result
 
bool isNegative(const Type &x)
Return true if x is less than zero. 
 
#define OPENVDB_ALL_TREE_INSTANTIATE(Function)
 
GLint GLint GLsizei GLint GLenum GLenum type
 
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance. 
 
const Vec3T & min() const 
Return a const reference to the minimum point of this bounding box. 
 
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
 
OPENVDB_API void calculateBounds(const Transform &t, const Vec3d &minWS, const Vec3d &maxWS, Vec3d &minIS, Vec3d &maxIS)
Calculate an axis-aligned bounding box in index space from an axis-aligned bounding box in world spac...
 
Defined various multi-threaded utility functions for trees. 
 
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
 
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
 
GLuint const GLchar * name
 
Container class that associates a tree with a transform and metadata. 
 
const Vec3T & max() const 
Return a const reference to the maximum point of this bounding box. 
 
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
 
Vec3d applyInverseMap(const Vec3d &in) const override
Return the pre-image of in under the map. 
 
math::BBox< Vec3d > BBoxd
 
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)
 
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
 
#define OPENVDB_VERSION_NAME
The version namespace name for this library version. 
 
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...