8#ifndef OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED 
    9#define OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED 
   20#include <tbb/blocked_range.h> 
   21#include <tbb/parallel_for.h> 
   22#include <tbb/parallel_reduce.h> 
   60template<
typename Gr
idT, 
typename InterrupterT = util::NullInterrupter>
 
   64    std::vector<openvdb::Vec4s>& spheres,
 
   65    const Vec2i& sphereCount = 
Vec2i(1, 50),
 
   66    bool overlapping = 
false,
 
   67    float minRadius = 1.0,
 
   68    float maxRadius = std::numeric_limits<float>::max(),
 
   70    int instanceCount = 10000,
 
   71    InterrupterT* interrupter = 
nullptr);
 
   80template<
typename Gr
idT>
 
   81class ClosestSurfacePoint
 
   84    using Ptr = std::unique_ptr<ClosestSurfacePoint>;
 
   85    using TreeT = 
typename GridT::TreeType;
 
   86    using BoolTreeT = 
typename TreeT::template ValueConverter<bool>::Type;
 
   87    using Index32TreeT = 
typename TreeT::template ValueConverter<Index32>::Type;
 
   88    using Int16TreeT = 
typename TreeT::template ValueConverter<Int16>::Type;
 
  101    template<
typename InterrupterT = util::NullInterrupter>
 
  102    static Ptr create(
const GridT& grid, 
float isovalue = 0.0,
 
  103        InterrupterT* interrupter = 
nullptr);
 
  108    bool search(
const std::vector<Vec3R>& 
points, std::vector<float>& distances);
 
  121    using Index32LeafT = 
typename Index32TreeT::LeafNodeType;
 
  122    using IndexRange = std::pair<size_t, size_t>;
 
  124    std::vector<Vec4R> mLeafBoundingSpheres, mNodeBoundingSpheres;
 
  125    std::vector<IndexRange> mLeafRanges;
 
  126    std::vector<const Index32LeafT*> mLeafNodes;
 
  128    size_t mPointListSize = 0, mMaxNodeLeafs = 0;
 
  129    typename Index32TreeT::Ptr mIdxTreePt;
 
  130    typename Int16TreeT::Ptr mSignTreePt;
 
  133    template<
typename InterrupterT = util::NullInterrupter>
 
  134    bool initialize(
const GridT&, 
float isovalue, InterrupterT*);
 
  135    bool search(std::vector<Vec3R>&, std::vector<float>&, 
bool transformPoints);
 
 
  146namespace v2s_internal {
 
  150    PointAccessor(std::vector<Vec3R>& 
points)
 
  155    void add(
const Vec3R &pos)
 
  157        mPoints.push_back(pos);
 
  160    std::vector<Vec3R>& mPoints;
 
  164template<
typename Index32LeafT>
 
  169    LeafOp(std::vector<Vec4R>& leafBoundingSpheres,
 
  170        const std::vector<const Index32LeafT*>& leafNodes,
 
  171        const math::Transform& transform,
 
  172        const PointList& surfacePointList);
 
  174    void run(
bool threaded = 
true);
 
  177    void operator()(
const tbb::blocked_range<size_t>&) 
const;
 
  180    std::vector<Vec4R>& mLeafBoundingSpheres;
 
  181    const std::vector<const Index32LeafT*>& mLeafNodes;
 
  182    const math::Transform& mTransform;
 
  186template<
typename Index32LeafT>
 
  187LeafOp<Index32LeafT>::LeafOp(
 
  188    std::vector<Vec4R>& leafBoundingSpheres,
 
  189    const std::vector<const Index32LeafT*>& leafNodes,
 
  190    const math::Transform& transform,
 
  191    const PointList& surfacePointList)
 
  192    : mLeafBoundingSpheres(leafBoundingSpheres)
 
  193    , mLeafNodes(leafNodes)
 
  194    , mTransform(transform)
 
  195    , mSurfacePointList(surfacePointList)
 
  199template<
typename Index32LeafT>
 
  201LeafOp<Index32LeafT>::run(
bool threaded)
 
  204        tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafNodes.size()), *
this);
 
  206        (*this)(tbb::blocked_range<size_t>(0, mLeafNodes.size()));
 
  210template<
typename Index32LeafT>
 
  212LeafOp<Index32LeafT>::operator()(
const tbb::blocked_range<size_t>& range)
 const 
  214    typename Index32LeafT::ValueOnCIter iter;
 
  217    for (
size_t n = range.begin(); n != range.end(); ++n) {
 
  223        for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
 
  224            avg += mSurfacePointList[iter.getValue()];
 
  227        if (count > 1) avg *= float(1.0 / 
double(count));
 
  230        for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
 
  231            float tmpDist = (mSurfacePointList[iter.getValue()] - avg).lengthSqr();
 
  232            if (tmpDist > maxDist) maxDist = tmpDist;
 
  235        Vec4R& sphere = mLeafBoundingSpheres[n];
 
  239        sphere[3] = maxDist * 2.0; 
 
  247    using IndexRange = std::pair<size_t, size_t>;
 
  249    NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
 
  250        const std::vector<IndexRange>& leafRanges,
 
  251        const std::vector<Vec4R>& leafBoundingSpheres);
 
  253    inline void run(
bool threaded = 
true);
 
  255    inline void operator()(
const tbb::blocked_range<size_t>&) 
const;
 
  258    std::vector<Vec4R>& mNodeBoundingSpheres;
 
  259    const std::vector<IndexRange>& mLeafRanges;
 
  260    const std::vector<Vec4R>& mLeafBoundingSpheres;
 
  264NodeOp::NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
 
  265    const std::vector<IndexRange>& leafRanges,
 
  266    const std::vector<Vec4R>& leafBoundingSpheres)
 
  267    : mNodeBoundingSpheres(nodeBoundingSpheres)
 
  268    , mLeafRanges(leafRanges)
 
  269    , mLeafBoundingSpheres(leafBoundingSpheres)
 
  277        tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafRanges.size()), *
this);
 
  279        (*this)(tbb::blocked_range<size_t>(0, mLeafRanges.size()));
 
  284NodeOp::operator()(
const tbb::blocked_range<size_t>& range)
 const 
  288    for (
size_t n = range.begin(); n != range.end(); ++n) {
 
  294        int count = int(mLeafRanges[n].second) - int(mLeafRanges[n].first);
 
  296        for (
size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
 
  297            avg[0] += mLeafBoundingSpheres[i][0];
 
  298            avg[1] += mLeafBoundingSpheres[i][1];
 
  299            avg[2] += mLeafBoundingSpheres[i][2];
 
  302        if (count > 1) avg *= float(1.0 / 
double(count));
 
  305        double maxDist = 0.0;
 
  307        for (
size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
 
  308            pos[0] = mLeafBoundingSpheres[i][0];
 
  309            pos[1] = mLeafBoundingSpheres[i][1];
 
  310            pos[2] = mLeafBoundingSpheres[i][2];
 
  311            const auto radiusSqr = mLeafBoundingSpheres[i][3];
 
  313            double tmpDist = (pos - avg).lengthSqr() + radiusSqr;
 
  314            if (tmpDist > maxDist) maxDist = tmpDist;
 
  317        Vec4R& sphere = mNodeBoundingSpheres[n];
 
  322        sphere[3] = maxDist * 2.0; 
 
  330template<
typename Index32LeafT>
 
  331class ClosestPointDist
 
  334    using IndexRange = std::pair<size_t, size_t>;
 
  337        std::vector<Vec3R>& instancePoints,
 
  338        std::vector<float>& instanceDistances,
 
  339        const PointList& surfacePointList,
 
  340        const std::vector<const Index32LeafT*>& leafNodes,
 
  341        const std::vector<IndexRange>& leafRanges,
 
  342        const std::vector<Vec4R>& leafBoundingSpheres,
 
  343        const std::vector<Vec4R>& nodeBoundingSpheres,
 
  345        bool transformPoints = 
false);
 
  348    void run(
bool threaded = 
true);
 
  351    void operator()(
const tbb::blocked_range<size_t>&) 
const;
 
  355    void evalLeaf(
size_t index, 
const Index32LeafT& leaf) 
const;
 
  356    void evalNode(
size_t pointIndex, 
size_t nodeIndex) 
const;
 
  359    std::vector<Vec3R>& mInstancePoints;
 
  360    std::vector<float>& mInstanceDistances;
 
  364    const std::vector<const Index32LeafT*>& mLeafNodes;
 
  365    const std::vector<IndexRange>& mLeafRanges;
 
  366    const std::vector<Vec4R>& mLeafBoundingSpheres;
 
  367    const std::vector<Vec4R>& mNodeBoundingSpheres;
 
  369    std::vector<float> mLeafDistances, mNodeDistances;
 
  371    const bool mTransformPoints;
 
  372    size_t mClosestPointIndex;
 
  376template<
typename Index32LeafT>
 
  377ClosestPointDist<Index32LeafT>::ClosestPointDist(
 
  378    std::vector<Vec3R>& instancePoints,
 
  379    std::vector<float>& instanceDistances,
 
  381    const std::vector<const Index32LeafT*>& leafNodes,
 
  382    const std::vector<IndexRange>& leafRanges,
 
  383    const std::vector<Vec4R>& leafBoundingSpheres,
 
  384    const std::vector<Vec4R>& nodeBoundingSpheres,
 
  386    bool transformPoints)
 
  387    : mInstancePoints(instancePoints)
 
  388    , mInstanceDistances(instanceDistances)
 
  389    , mSurfacePointList(surfacePointList)
 
  390    , mLeafNodes(leafNodes)
 
  391    , mLeafRanges(leafRanges)
 
  392    , mLeafBoundingSpheres(leafBoundingSpheres)
 
  393    , mNodeBoundingSpheres(nodeBoundingSpheres)
 
  394    , mLeafDistances(maxNodeLeafs, 0.0)
 
  395    , mNodeDistances(leafRanges.size(), 0.0)
 
  396    , mTransformPoints(transformPoints)
 
  397    , mClosestPointIndex(0)
 
  402template<
typename Index32LeafT>
 
  404ClosestPointDist<Index32LeafT>::run(
bool threaded)
 
  407        tbb::parallel_for(tbb::blocked_range<size_t>(0, mInstancePoints.size()), *
this);
 
  409        (*this)(tbb::blocked_range<size_t>(0, mInstancePoints.size()));
 
  413template<
typename Index32LeafT>
 
  415ClosestPointDist<Index32LeafT>::evalLeaf(
size_t index, 
const Index32LeafT& leaf)
 const 
  417    typename Index32LeafT::ValueOnCIter iter;
 
  418    const Vec3s center = mInstancePoints[index];
 
  419    size_t& closestPointIndex = 
const_cast<size_t&
>(mClosestPointIndex);
 
  421    for (iter = leaf.cbeginValueOn(); iter; ++iter) {
 
  423        const Vec3s& point = mSurfacePointList[iter.getValue()];
 
  424        float tmpDist = (point - center).lengthSqr();
 
  426        if (tmpDist < mInstanceDistances[index]) {
 
  427            mInstanceDistances[index] = tmpDist;
 
  428            closestPointIndex = iter.getValue();
 
  434template<
typename Index32LeafT>
 
  436ClosestPointDist<Index32LeafT>::evalNode(
size_t pointIndex, 
size_t nodeIndex)
 const 
  438    if (nodeIndex >= mLeafRanges.size()) 
return;
 
  440    const Vec3R& pos = mInstancePoints[pointIndex];
 
  441    float minDist = mInstanceDistances[pointIndex];
 
  442    size_t minDistIdx = 0;
 
  444    bool updatedDist = 
false;
 
  446    for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
 
  447        i < mLeafRanges[nodeIndex].second; ++i, ++n)
 
  449        float& distToLeaf = 
const_cast<float&
>(mLeafDistances[n]);
 
  451        center[0] = mLeafBoundingSpheres[i][0];
 
  452        center[1] = mLeafBoundingSpheres[i][1];
 
  453        center[2] = mLeafBoundingSpheres[i][2];
 
  454        const auto radiusSqr = mLeafBoundingSpheres[i][3];
 
  456        distToLeaf = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
 
  458        if (distToLeaf < minDist) {
 
  459            minDist = distToLeaf;
 
  465    if (!updatedDist) 
return;
 
  467    evalLeaf(pointIndex, *mLeafNodes[minDistIdx]);
 
  469    for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
 
  470        i < mLeafRanges[nodeIndex].second; ++i, ++n)
 
  472        if (mLeafDistances[n] < mInstanceDistances[pointIndex] && i != minDistIdx) {
 
  473            evalLeaf(pointIndex, *mLeafNodes[i]);
 
  479template<
typename Index32LeafT>
 
  481ClosestPointDist<Index32LeafT>::operator()(
const tbb::blocked_range<size_t>& range)
 const 
  484    for (
size_t n = range.begin(); n != range.end(); ++n) {
 
  486        const Vec3R& pos = mInstancePoints[n];
 
  487        float minDist = mInstanceDistances[n];
 
  488        size_t minDistIdx = 0;
 
  490        for (
size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
 
  491            float& distToNode = 
const_cast<float&
>(mNodeDistances[i]);
 
  493            center[0] = mNodeBoundingSpheres[i][0];
 
  494            center[1] = mNodeBoundingSpheres[i][1];
 
  495            center[2] = mNodeBoundingSpheres[i][2];
 
  496            const auto radiusSqr = mNodeBoundingSpheres[i][3];
 
  498            distToNode = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
 
  500            if (distToNode < minDist) {
 
  501                minDist = distToNode;
 
  506        evalNode(n, minDistIdx);
 
  508        for (
size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
 
  509            if (mNodeDistances[i] < mInstanceDistances[n] && i != minDistIdx) {
 
  514        mInstanceDistances[n] = std::sqrt(mInstanceDistances[n]);
 
  516        if (mTransformPoints) mInstancePoints[n] = mSurfacePointList[mClosestPointIndex];
 
  526        const std::vector<Vec3R>& points,
 
  527        std::vector<float>& distances,
 
  528        std::vector<unsigned char>& mask,
 
  531    float radius()
 const { 
return mRadius; }
 
  532    int index()
 const { 
return mIndex; }
 
  534    inline void run(
bool threaded = 
true);
 
  537    UpdatePoints(UpdatePoints&, tbb::split);
 
  538    inline void operator()(
const tbb::blocked_range<size_t>& range);
 
  539    void join(
const UpdatePoints& rhs)
 
  541        if (rhs.mRadius > mRadius) {
 
  542            mRadius = rhs.mRadius;
 
  548    const Vec4s& mSphere;
 
  549    const std::vector<Vec3R>& mPoints;
 
  550    std::vector<float>& mDistances;
 
  551    std::vector<unsigned char>& mMask;
 
  552    const bool mOverlapping;
 
  558UpdatePoints::UpdatePoints(
 
  560    const std::vector<Vec3R>& points,
 
  561    std::vector<float>& distances,
 
  562    std::vector<unsigned char>& mask,
 
  566    , mDistances(distances)
 
  568    , mOverlapping(overlapping)
 
  575UpdatePoints::UpdatePoints(UpdatePoints& rhs, tbb::split)
 
  576    : mSphere(rhs.mSphere)
 
  577    , mPoints(rhs.mPoints)
 
  578    , mDistances(rhs.mDistances)
 
  580    , mOverlapping(rhs.mOverlapping)
 
  590        tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPoints.size()), *
this);
 
  592        (*this)(tbb::blocked_range<size_t>(0, mPoints.size()));
 
  597UpdatePoints::operator()(
const tbb::blocked_range<size_t>& range)
 
  600    for (
size_t n = range.begin(); n != range.end(); ++n) {
 
  601        if (mMask[n]) 
continue;
 
  603        pos.x() = float(mPoints[n].x()) - mSphere[0];
 
  604        pos.y() = float(mPoints[n].y()) - mSphere[1];
 
  605        pos.z() = float(mPoints[n].z()) - mSphere[2];
 
  607        float dist = pos.length();
 
  609        if (dist < mSphere[3]) {
 
  615            mDistances[n] = std::min(mDistances[n], (dist - mSphere[3]));
 
  618        if (mDistances[n] > mRadius) {
 
  619            mRadius = mDistances[n];
 
  633template<
typename Gr
idT, 
typename InterrupterT>
 
  637    std::vector<openvdb::Vec4s>& spheres,
 
  638    const Vec2i& sphereCount,
 
  644    InterrupterT* interrupter)
 
  648    if (grid.empty()) 
return;
 
  651        minSphereCount = sphereCount[0],
 
  652        maxSphereCount = sphereCount[1];
 
  653    if ((minSphereCount > maxSphereCount) || (maxSphereCount < 1)) {
 
  655            << minSphereCount << 
") exceeds maximum count (" << maxSphereCount << 
")");
 
  658    spheres.reserve(maxSphereCount);
 
  660    auto gridPtr = grid.copy(); 
 
  668        isovalue = std::min(isovalue,
 
  679    auto numVoxels = gridPtr->activeVoxelCount();
 
  680    if (numVoxels < 10000) {
 
  681        const auto scale = 1.0 / 
math::Cbrt(2.0 * 10000.0 / 
double(numVoxels));
 
  682        auto scaledXform = gridPtr->transform().copy();
 
  683        scaledXform->preScale(scale);
 
  688        const auto newNumVoxels = newGridPtr->activeVoxelCount();
 
  689        if (newNumVoxels > numVoxels) {
 
  691                << numVoxels << 
" voxel" << (numVoxels == 1 ? 
"" : 
"s")
 
  692                << 
" to " << newNumVoxels << 
" voxel" << (newNumVoxels == 1 ? 
"" : 
"s"));
 
  693            gridPtr = newGridPtr;
 
  694            numVoxels = newNumVoxels;
 
  698    const bool addNarrowBandPoints = (numVoxels < 10000);
 
  699    int instances = std::max(instanceCount, maxSphereCount);
 
  701    using TreeT = 
typename GridT::TreeType;
 
  702    using BoolTreeT = 
typename TreeT::template ValueConverter<bool>::Type;
 
  703    using Int16TreeT = 
typename TreeT::template ValueConverter<Int16>::Type;
 
  705    using RandGen = std::mersenne_twister_engine<uint32_t, 32, 351, 175, 19,
 
  706        0xccab8ee7, 11, 0xffffffff, 7, 0x31b6ab00, 15, 0xffe50000, 17, 1812433253>; 
 
  709    const TreeT& 
tree = gridPtr->tree();
 
  712    std::vector<Vec3R> instancePoints;
 
  722            interiorMaskPtr->
tree().topologyUnion(
tree);
 
  725        if (interrupter && interrupter->wasInterrupted()) 
return;
 
  730        if (!addNarrowBandPoints || (minSphereCount <= 0)) {
 
  734            auto& maskTree = interiorMaskPtr->
tree();
 
  738            if (maskTree.empty()) { interiorMaskPtr->
setTree(copyOfTree); }
 
  742        instancePoints.reserve(instances);
 
  743        v2s_internal::PointAccessor ptnAcc(instancePoints);
 
  745        const auto scatterCount = 
Index64(addNarrowBandPoints ? (instances / 2) : instances);
 
  748            ptnAcc, scatterCount, mtRand, 1.0, interrupter);
 
  749        scatter(*interiorMaskPtr);
 
  752    if (interrupter && interrupter->wasInterrupted()) 
return;
 
  758    if (instancePoints.size() < 
size_t(instances)) {
 
  759        const Int16TreeT& signTree = csp->signTree();
 
  760        for (
auto leafIt = signTree.cbeginLeaf(); leafIt; ++leafIt) {
 
  761            for (
auto it = leafIt->cbeginValueOn(); it; ++it) {
 
  762                const int flags = int(it.getValue());
 
  763                if (!(volume_to_mesh_internal::EDGES & flags)
 
  764                    && (volume_to_mesh_internal::INSIDE & flags))
 
  766                    instancePoints.push_back(transform.
indexToWorld(it.getCoord()));
 
  768                if (instancePoints.size() == 
size_t(instances)) 
break;
 
  770            if (instancePoints.size() == 
size_t(instances)) 
break;
 
  774    if (interrupter && interrupter->wasInterrupted()) 
return;
 
  778    std::vector<float> instanceRadius;
 
  779    if (!csp->search(instancePoints, instanceRadius)) 
return;
 
  781    float largestRadius = 0.0;
 
  782    int largestRadiusIdx = 0;
 
  783    for (
size_t n = 0, N = instancePoints.size(); n < N; ++n) {
 
  784        if (instanceRadius[n] > largestRadius) {
 
  785            largestRadius = instanceRadius[n];
 
  786            largestRadiusIdx = int(n);
 
  790    std::vector<unsigned char> instanceMask(instancePoints.size(), 0);
 
  792    minRadius = float(minRadius * transform.
voxelSize()[0]);
 
  793    maxRadius = float(maxRadius * transform.
voxelSize()[0]);
 
  795    for (
size_t s = 0, S = std::min(
size_t(maxSphereCount), instancePoints.size()); s < S; ++s) {
 
  797        if (interrupter && interrupter->wasInterrupted()) 
return;
 
  799        largestRadius = std::min(maxRadius, largestRadius);
 
  801        if ((
int(s) >= minSphereCount) && (largestRadius < minRadius)) 
break;
 
  804            float(instancePoints[largestRadiusIdx].x()),
 
  805            float(instancePoints[largestRadiusIdx].y()),
 
  806            float(instancePoints[largestRadiusIdx].z()),
 
  809        spheres.push_back(sphere);
 
  810        instanceMask[largestRadiusIdx] = 1;
 
  812        v2s_internal::UpdatePoints 
op(
 
  813            sphere, instancePoints, instanceRadius, instanceMask, overlapping);
 
  816        largestRadius = 
op.radius();
 
  817        largestRadiusIdx = 
op.index();
 
 
  825template<
typename Gr
idT>
 
  826template<
typename InterrupterT>
 
  827typename ClosestSurfacePoint<GridT>::Ptr
 
  830    auto csp = 
Ptr{
new ClosestSurfacePoint};
 
  831    if (!csp->initialize(grid, isovalue, interrupter)) csp.reset();
 
 
  836template<
typename Gr
idT>
 
  837template<
typename InterrupterT>
 
  839ClosestSurfacePoint<GridT>::initialize(
 
  840    const GridT& grid, 
float isovalue, InterrupterT* interrupter)
 
  843    using ValueT = 
typename GridT::ValueType;
 
  845    const TreeT& 
tree = grid.tree();
 
  850        BoolTreeT mask(
false);
 
  851        volume_to_mesh_internal::identifySurfaceIntersectingVoxels(mask, 
tree, ValueT(isovalue));
 
  853        mSignTreePt.reset(
new Int16TreeT(0));
 
  854        mIdxTreePt.reset(
new Index32TreeT(std::numeric_limits<Index32>::max()));
 
  857        volume_to_mesh_internal::computeAuxiliaryData(
 
  858            *mSignTreePt, *mIdxTreePt, mask, 
tree, ValueT(isovalue));
 
  860        if (interrupter && interrupter->wasInterrupted()) 
return false;
 
  864        using Int16LeafNodeType = 
typename Int16TreeT::LeafNodeType;
 
  865        using Index32LeafNodeType = 
typename Index32TreeT::LeafNodeType;
 
  867        std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
 
  868        mSignTreePt->getNodes(signFlagsLeafNodes);
 
  870        const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
 
  872        std::unique_ptr<Index32[]> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
 
  874        tbb::parallel_for(auxiliaryLeafNodeRange,
 
  875            volume_to_mesh_internal::LeafNodePointCount<Int16LeafNodeType::LOG2DIM>
 
  876                (signFlagsLeafNodes, leafNodeOffsets));
 
  880            for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
 
  881                const Index32 tmp = leafNodeOffsets[n];
 
  882                leafNodeOffsets[n] = pointCount;
 
  886            mPointListSize = size_t(pointCount);
 
  887            mSurfacePointList.reset(
new Vec3s[mPointListSize]);
 
  891        std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
 
  892        mIdxTreePt->getNodes(pointIndexLeafNodes);
 
  894        tbb::parallel_for(auxiliaryLeafNodeRange, volume_to_mesh_internal::ComputePoints<TreeT>(
 
  895            mSurfacePointList.get(), 
tree, pointIndexLeafNodes,
 
  896            signFlagsLeafNodes, leafNodeOffsets, transform, ValueT(isovalue)));
 
  899    if (interrupter && interrupter->wasInterrupted()) 
return false;
 
  901    Index32LeafManagerT idxLeafs(*mIdxTreePt);
 
  903    using Index32RootNodeT = 
typename Index32TreeT::RootNodeType;
 
  904    using Index32NodeChainT = 
typename Index32RootNodeT::NodeChainType;
 
  905    static_assert(Index32NodeChainT::Size > 1,
 
  906        "expected tree depth greater than one");
 
  907    using Index32InternalNodeT = 
typename Index32NodeChainT::template Get<1>;
 
  909    typename Index32TreeT::NodeCIter nIt = mIdxTreePt->cbeginNode();
 
  910    nIt.setMinDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
 
  911    nIt.setMaxDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
 
  913    std::vector<const Index32InternalNodeT*> internalNodes;
 
  915    const Index32InternalNodeT* node = 
nullptr;
 
  918        if (node) internalNodes.push_back(node);
 
  921    std::vector<IndexRange>().swap(mLeafRanges);
 
  922    mLeafRanges.resize(internalNodes.size());
 
  924    std::vector<const Index32LeafT*>().swap(mLeafNodes);
 
  925    mLeafNodes.reserve(idxLeafs.leafCount());
 
  927    typename Index32InternalNodeT::ChildOnCIter leafIt;
 
  929    for (
size_t n = 0, N = internalNodes.size(); n < N; ++n) {
 
  931        mLeafRanges[n].first = mLeafNodes.size();
 
  933        size_t leafCount = 0;
 
  934        for (leafIt = internalNodes[n]->cbeginChildOn(); leafIt; ++leafIt) {
 
  935            mLeafNodes.push_back(&(*leafIt));
 
  939        mMaxNodeLeafs = std::max(leafCount, mMaxNodeLeafs);
 
  941        mLeafRanges[n].second = mLeafNodes.size();
 
  944    std::vector<Vec4R>().swap(mLeafBoundingSpheres);
 
  945    mLeafBoundingSpheres.resize(mLeafNodes.size());
 
  947    v2s_internal::LeafOp<Index32LeafT> leafBS(
 
  948        mLeafBoundingSpheres, mLeafNodes, transform, mSurfacePointList);
 
  952    std::vector<Vec4R>().swap(mNodeBoundingSpheres);
 
  953    mNodeBoundingSpheres.resize(internalNodes.size());
 
  955    v2s_internal::NodeOp nodeBS(mNodeBoundingSpheres, mLeafRanges, mLeafBoundingSpheres);
 
  961template<
typename Gr
idT>
 
  963ClosestSurfacePoint<GridT>::search(std::vector<Vec3R>& 
points,
 
  964    std::vector<float>& distances, 
bool transformPoints)
 
  967    distances.resize(
points.size(), std::numeric_limits<float>::infinity());
 
  969    v2s_internal::ClosestPointDist<Index32LeafT> cpd(
points, distances, mSurfacePointList,
 
  970        mLeafNodes, mLeafRanges, mLeafBoundingSpheres, mNodeBoundingSpheres,
 
  971        mMaxNodeLeafs, transformPoints);
 
  979template<
typename Gr
idT>
 
  983    return search(
const_cast<std::vector<Vec3R>& 
>(
points), distances, 
false);
 
 
  987template<
typename Gr
idT>
 
  990    std::vector<float>& distances)
 
 
 1001#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
 1003#ifdef OPENVDB_INSTANTIATE_VOLUMETOSPHERES 
 1010#define _FUNCTION(TreeT) \ 
 1011    void fillWithSpheres(const Grid<TreeT>&, std::vector<openvdb::Vec4s>&, const Vec2i&, \ 
 1012        bool, float, float, float, int, util::NullInterrupter*) 
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Implementation of morphological dilation and erosion.
Extract polygonal surfaces from scalar volumes.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition Grid.h:1269
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition Grid.h:908
static Ptr create(const ValueType &background)
Return a new grid with the given background value.
Definition Grid.h:1352
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition Grid.h:1489
SharedPtr< Grid > Ptr
Definition Grid.h:573
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition logging.h:256
#define OPENVDB_LOG_DEBUG_RUNTIME(message)
Log a debugging message in both debug and optimized builds.
Definition logging.h:270
OPENVDB_AX_API void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
Vec2< int32_t > Vec2i
Definition Vec2.h:530
Vec4< float > Vec4s
Definition Vec4.h:561
Vec3< double > Vec3d
Definition Vec3.h:665
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition Math.h:261
Vec3< float > Vec3s
Definition Vec3.h:664
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition Math.h:769
Definition AttributeArray.h:42
Definition PointDataGrid.h:170
static const Real LEVEL_SET_HALF_WIDTH
Definition Types.h:461
@ GRID_FOG_VOLUME
Definition Types.h:456
@ GRID_LEVEL_SET
Definition Types.h:455
OPENVDB_IMPORT void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types....
uint32_t Index32
Definition Types.h:52
math::Vec3< Real > Vec3R
Definition Types.h:72
uint64_t Index64
Definition Types.h:53
math::Vec4< Real > Vec4R
Definition Types.h:87
SharedPtr< T > StaticPtrCast(const SharedPtr< U > &ptr)
Return a new shared pointer that points to the same object as the given pointer after a static_cast.
Definition Types.h:146
Definition Exceptions.h:13
static T value()
Definition Math.h:148
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:158
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition version.h.in:162