27#ifndef OPENVDB_TOOLS_FASTSWEEPING_HAS_BEEN_INCLUDED 
   28#define OPENVDB_TOOLS_FASTSWEEPING_HAS_BEEN_INCLUDED 
   44#ifdef BENCHMARK_FAST_SWEEPING 
   48#include <tbb/parallel_for.h> 
   49#include <tbb/enumerable_thread_specific.h> 
   50#include <tbb/task_group.h> 
   56#include <unordered_map> 
  104template<
typename Gr
idT>
 
  106fogToSdf(
const GridT &fogGrid,
 
  107         typename GridT::ValueType isoValue,
 
  137template<
typename Gr
idT>
 
  139sdfToSdf(
const GridT &sdfGrid,
 
  140         typename GridT::ValueType isoValue = 0,
 
  193template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
  194typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr
 
  195fogToExt(
const FogGridT &fogGrid,
 
  197         const ExtValueT& background,
 
  198         typename FogGridT::ValueType isoValue,
 
  200         FastSweepingDomain mode = FastSweepingDomain::SWEEP_ALL,
 
  201         const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
 
  251template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
  252typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr
 
  255         const ExtValueT &background,
 
  256         typename SdfGridT::ValueType isoValue = 0,
 
  259         const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
 
  314template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
  315std::pair<typename FogGridT::Ptr, typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr>
 
  318               const ExtValueT &background,
 
  319               typename FogGridT::ValueType isoValue,
 
  322               const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
 
  377template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
  378std::pair<typename SdfGridT::Ptr, typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr>
 
  381               const ExtValueT &background,
 
  382               typename SdfGridT::ValueType isoValue = 0,
 
  385               const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
 
  415template<
typename Gr
idT>
 
  441template<
typename Gr
idT, 
typename MaskTreeT>
 
  445        bool ignoreActiveTiles = 
false,
 
  460template<
typename SdfGr
idT, 
typename ExtValueT = 
typename SdfGr
idT::ValueType>
 
  463    static_assert(std::is_floating_point<typename SdfGridT::ValueType>::value,
 
  464                  "FastSweeping requires SdfGridT to have floating-point values");
 
  466    using SdfValueT = 
typename SdfGridT::ValueType;
 
  467    using SdfTreeT = 
typename SdfGridT::TreeType;
 
  472    using ExtGridT = 
typename SdfGridT::template ValueConverter<ExtValueT>::Type;
 
  473    using ExtTreeT = 
typename ExtGridT::TreeType;
 
  477    using SweepMaskTreeT = 
typename SdfTreeT::template ValueConverter<ValueMask>::Type;
 
  500    typename SdfGridT::Ptr 
sdfGrid() { 
return mSdfGrid; }
 
  508    typename ExtGridT::Ptr 
extGrid() { 
return mExtGrid; }
 
  586    template <
typename ExtOpT>
 
  589                 const ExtValueT &background,
 
  593                 const typename ExtGridT::ConstPtr 
extGrid = 
nullptr);
 
  639    template<
typename MaskTreeT>
 
  655               bool finalize = 
true);
 
  667    bool isValid()
 const { 
return mSweepingVoxelCount > 0 && mBoundaryVoxelCount > 0; }
 
  683    void computeSweepMaskLeafOrigins();
 
  693    struct PruneMinMaxFltKernel;
 
  694    struct SweepingKernel;
 
  700    typename SdfGridT::Ptr mSdfGrid;
 
  701    typename ExtGridT::Ptr mExtGrid;
 
  702    typename ExtGridT::Ptr mExtGridInput; 
 
  703    SweepMaskTreeT mSweepMask; 
 
  704    std::vector<Coord> mSweepMaskLeafOrigins; 
 
  705    size_t mSweepingVoxelCount, mBoundaryVoxelCount;
 
  713template <
typename SdfGr
idT, 
typename ExtValueT>
 
  714const Coord FastSweeping<SdfGridT, ExtValueT>::mOffset[6] = {{-1,0,0},{1,0,0},
 
 
  718template <
typename SdfGr
idT, 
typename ExtValueT>
 
  720    : mSdfGrid(nullptr), mExtGrid(nullptr), mSweepingVoxelCount(0), mBoundaryVoxelCount(0), mSweepDirection(
FastSweepingDomain::
SWEEP_ALL), mIsInputSdf(true)
 
 
  724template <
typename SdfGr
idT, 
typename ExtValueT>
 
  730    if (mExtGridInput) mExtGridInput.reset();
 
  731    mSweepingVoxelCount = mBoundaryVoxelCount = 0;
 
 
 
  736template <
typename SdfGr
idT, 
typename ExtValueT>
 
  737void FastSweeping<SdfGridT, ExtValueT>::computeSweepMaskLeafOrigins()
 
  742    mSweepMask.voxelizeActiveTiles();
 
  745    using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
 
  746    LeafManagerT leafManager(mSweepMask);
 
  748    mSweepMaskLeafOrigins.resize(leafManager.leafCount());
 
  749    std::atomic<size_t> sweepingVoxelCount{0};
 
  750    auto kernel = [&](
const LeafT& leaf, 
size_t leafIdx) {
 
  751        mSweepMaskLeafOrigins[leafIdx] = leaf.origin();
 
  752        sweepingVoxelCount += leaf.onVoxelCount();
 
  754    leafManager.foreach(kernel, 
true, 1024);
 
  756    mBoundaryVoxelCount = 0;
 
  757    mSweepingVoxelCount = sweepingVoxelCount;
 
  759        const size_t totalCount = mSdfGrid->constTree().activeVoxelCount();
 
  761        mBoundaryVoxelCount = totalCount - mSweepingVoxelCount;
 
  765template <
typename SdfGr
idT, 
typename ExtValueT>
 
  769    mSdfGrid = fogGrid.deepCopy();
 
  772    kernel.
run(isoValue);
 
 
  776template <
typename SdfGr
idT, 
typename ExtValueT>
 
  777template <
typename OpT>
 
  783        if (
extGrid->transform() != fogGrid.transform())
 
  784            OPENVDB_THROW(
RuntimeError, 
"FastSweeping::initExt extension grid input should have the same transform as Fog/SDF grid!");
 
  788    mSdfGrid = fogGrid.deepCopy();
 
  790    mSweepDirection = mode;
 
  793        mExtGridInput = 
extGrid->deepCopy();
 
  795    mExtGrid->topologyUnion( *mSdfGrid );
 
  796    InitExt<OpT> kernel(*
this);
 
  797    kernel.run(isoValue, 
op);
 
 
  802template <
typename SdfGr
idT, 
typename ExtValueT>
 
  807    mSweepDirection = mode;
 
  809    kernel.
run(dilate, nn);
 
 
  813template <
typename SdfGr
idT, 
typename ExtValueT>
 
  814template<
typename MaskTreeT>
 
  820    if (mSdfGrid->transform() != mask.
transform()) {
 
  825        using T = 
typename MaskTreeT::template ValueConverter<bool>::Type;
 
  827        tmp->
tree().voxelizeActiveTiles();
 
  828        MaskKernel<T> kernel(*
this);
 
  829        kernel.run(tmp->
tree());
 
  831        if (ignoreActiveTiles || !mask.
tree().hasActiveTiles()) {
 
  832            MaskKernel<MaskTreeT> kernel(*
this);
 
  833            kernel.run(mask.
tree());
 
  835            using T = 
typename MaskTreeT::template ValueConverter<ValueMask>::Type;
 
  837            tmp.voxelizeActiveTiles(
true);
 
  838            MaskKernel<T> kernel(*
this);
 
 
  845template <
typename SdfGr
idT, 
typename ExtValueT>
 
  853                                     " a non-null reference extension grid input.");
 
  862    std::deque<SweepingKernel> kernels;
 
  863    for (
int i = 0; i < 4; i++) kernels.emplace_back(*
this);
 
  866#ifdef BENCHMARK_FAST_SWEEPING 
  871        tbb::task_group tasks;
 
  872        tasks.run([&] { kernels[0].computeVoxelSlices([](
const Coord &a){ 
return a[0]+a[1]+a[2]; }); });
 
  873        tasks.run([&] { kernels[1].computeVoxelSlices([](
const Coord &a){ 
return a[0]+a[1]-a[2]; }); });
 
  874        tasks.run([&] { kernels[2].computeVoxelSlices([](
const Coord &a){ 
return a[0]-a[1]+a[2]; }); });
 
  875        tasks.run([&] { kernels[3].computeVoxelSlices([](
const Coord &a){ 
return a[0]-a[1]-a[2]; }); });
 
  878#ifdef BENCHMARK_FAST_SWEEPING 
  884    for (
int i = 0; i < nIter; ++i) {
 
  889#ifdef BENCHMARK_FAST_SWEEPING 
  893      auto e = kernel.
run(*mSdfGrid);
 
  900#ifdef BENCHMARK_FAST_SWEEPING 
  901      std::cerr << 
"Min = " << e.min() << 
" Max = " << e.max() << std::endl;
 
  902      timer.
restart(
"Changing asymmetric background value");
 
  906#ifdef BENCHMARK_FAST_SWEEPING 
 
 
  917template <
typename SdfGr
idT, 
typename ExtValueT>
 
  928        tbb::parallel_reduce(mgr.
leafRange(), *
this);
 
 
  934        for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
 
  935            for (
auto voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
 
  936                const SdfValueT v = *voxelIter;
 
  937                const bool vEqFltMin = v == -std::numeric_limits<SdfValueT>::max();
 
  938                const bool vEqFltMax = v == std::numeric_limits<SdfValueT>::max();
 
  939                if (v < 
mMin && !vEqFltMin) 
mMin = v;
 
  940                if (v > 
mMax && !vEqFltMax) 
mMax = v;
 
 
 
  961template <
typename SdfGr
idT, 
typename ExtValueT>
 
  966    void operator()(
typename SdfTreeT::RootNodeType& node, 
size_t = 1)
 const {
 
  967        for (
auto iter = node.beginValueAll(); iter; ++iter) {
 
  968            if (*iter == -std::numeric_limits<SdfValueT>::max()) {
 
  971            if (*iter == std::numeric_limits<SdfValueT>::max()) {
 
 
  978    template<
typename NodeT>
 
  981        for (
auto iter = node.beginValueAll(); iter; ++iter) {
 
  982            if (*iter == -std::numeric_limits<SdfValueT>::max()) {
 
  985            if (*iter == std::numeric_limits<SdfValueT>::max()) {
 
 
  992    void operator()(
typename SdfTreeT::LeafNodeType& leaf, 
size_t = 1)
 const 
  994        for (
auto iter = leaf.beginValueOn(); iter; ++iter) {
 
  995            if (*iter == -std::numeric_limits<SdfValueT>::max()) {
 
  998            if (*iter == std::numeric_limits<SdfValueT>::max()) {
 
 
 
 1009template <
typename SdfGr
idT, 
typename ExtValueT>
 
 1024#ifdef BENCHMARK_FAST_SWEEPING 
 1029#ifdef BENCHMARK_FAST_SWEEPING 
 1030        timer.
restart(
"Changing background value");
 
 1032        static const SdfValueT Unknown = std::numeric_limits<SdfValueT>::max();
 
 1035 #ifdef BENCHMARK_FAST_SWEEPING 
 1036        timer.
restart(
"Dilating and updating mgr (parallel)");
 
 1040        const int delta = 5;
 
 1046#ifdef BENCHMARK_FAST_SWEEPING 
 1047        timer.
restart(
"Initializing grid and sweep mask");
 
 1051        mParent->mSweepMask.topologyUnion(
mParent->mSdfGrid->constTree());
 
 1054        using LeafT = 
typename SdfGridT::TreeType::LeafNodeType;
 
 1058        LeafManagerT leafManager(
mParent->mSdfGrid->tree());
 
 1060        auto kernel = [&](LeafT& leaf, 
size_t ) {
 
 1061            static const SdfValueT Unknown = std::numeric_limits<SdfValueT>::max();
 
 1063            auto* maskLeaf = 
mParent->mSweepMask.probeLeaf(leaf.origin());
 
 1066            for (
auto voxelIter = leaf.beginValueOn(); voxelIter; ++voxelIter) {
 
 1067                const SdfValueT value = *voxelIter;
 
 1068                SdfValueT inputValue;
 
 1069                const Coord ijk = voxelIter.getCoord();
 
 1072                    maskLeaf->setValueOff(voxelIter.pos());
 
 1076                            voxelIter.setValue(value > 0 ? Unknown : -Unknown);
 
 1079                            if (value > 0) voxelIter.setValue(Unknown);
 
 1081                                maskLeaf->setValueOff(voxelIter.pos());
 
 1082                                bool isInputOn = sdfInputAcc.probeValue(ijk, inputValue);
 
 1083                                if ( !isInputOn ) voxelIter.setValueOff();
 
 1084                                else voxelIter.setValue(inputValue);
 
 1088                            if (value < 0) voxelIter.setValue(-Unknown);
 
 1090                                maskLeaf->setValueOff(voxelIter.pos());
 
 1091                                bool isInputOn = sdfInputAcc.probeValue(ijk, inputValue);
 
 1092                                if ( !isInputOn ) voxelIter.setValueOff();
 
 1093                                else voxelIter.setValue(inputValue);
 
 1101        leafManager.foreach( kernel );
 
 1104        mParent->computeSweepMaskLeafOrigins();
 
 1106#ifdef BENCHMARK_FAST_SWEEPING 
 
 
 1119template <
typename SdfGr
idT, 
typename ExtValueT>
 
 1133        const bool hasActiveTiles = 
tree.hasActiveTiles();
 
 1135        if (
mParent->mIsInputSdf && hasActiveTiles) {
 
 1139#ifdef BENCHMARK_FAST_SWEEPING 
 1143        mParent->mSweepMask.topologyUnion(
mParent->mSdfGrid->constTree());
 
 1147          tbb::parallel_for(mgr.
leafRange(32), *
this);
 
 1151#ifdef BENCHMARK_FAST_SWEEPING 
 1152        timer.
restart(
"Initialize tiles - new");
 
 1156        mgr.foreachBottomUp(*
this);
 
 1157        tree.root().setBackground(std::numeric_limits<SdfValueT>::max(), 
false);
 
 1158        if (hasActiveTiles) 
tree.voxelizeActiveTiles();
 
 1162        mParent->computeSweepMaskLeafOrigins();
 
 
 1167        SweepMaskAccT sweepMaskAcc(
mParent->mSweepMask);
 
 1169        const SdfValueT isoValue = 
mIsoValue, above = 
mAboveSign*std::numeric_limits<SdfValueT>::max();
 
 1171        for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
 
 1172            SdfValueT* sdf = leafIter.buffer(1).data();
 
 1173            for (
auto voxelIter = leafIter->beginValueAll(); voxelIter; ++voxelIter) {
 
 1174                const SdfValueT value = *voxelIter;
 
 1175                const bool isAbove = value > isoValue;
 
 1176                if (!voxelIter.isValueOn()) {
 
 1177                    sdf[voxelIter.pos()] = isAbove ? above : -above;
 
 1179                    const Coord ijk = voxelIter.getCoord();
 
 1180                    stencil.
moveTo(ijk, value);
 
 1183                        sdf[voxelIter.pos()] = isAbove ? above : -above;
 
 1187                        const SdfValueT delta = value - isoValue;
 
 1189                            sdf[voxelIter.pos()] = 0;
 
 1192                            for (
int i=0; i<6;) {
 
 1193                                SdfValueT d = std::numeric_limits<SdfValueT>::max(), d2;
 
 1195                                if (mask.test(i++)) {
 
 1199                                if (d < std::numeric_limits<SdfValueT>::max()) sum += 1/(d*d);
 
 
 1209    template<
typename RootOrInternalNodeT>
 
 1212        const SdfValueT isoValue = 
mIsoValue, above = 
mAboveSign*std::numeric_limits<SdfValueT>::max();
 
 1213        for (
auto it = node.cbeginValueAll(); it; ++it) {
 
 1214          SdfValueT& v = 
const_cast<SdfValueT&
>(*it);
 
 1215          v = v > isoValue ? above : -above;
 
 
 
 1228template <
typename SdfGr
idT, 
typename ExtValueT>
 
 1229template <
typename OpT>
 
 1233    using OpPoolT = tbb::enumerable_thread_specific<OpT>;
 
 1235      mOpPool(
nullptr), mSdfGrid(parent.mSdfGrid.get()),
 
 1236      mExtGrid(parent.mExtGrid.get()), mIsoValue(0), mAboveSign(0) {}
 
 1237    InitExt(
const InitExt&) = 
default;
 
 1238    InitExt& 
operator=(
const InitExt&) = 
delete;
 
 1239    void run(SdfValueT isoValue, 
const OpT &opPrototype)
 
 1241        static_assert(std::is_convertible<
decltype(opPrototype(
Vec3d(0))),ExtValueT>::value, 
"Invalid return type of functor");
 
 1246        mAboveSign  = mParent->mIsInputSdf ? SdfValueT(1) : SdfValueT(-1);
 
 1247        mIsoValue = isoValue;
 
 1248        auto &tree1 = mSdfGrid->tree();
 
 1249        auto &tree2 = mExtGrid->tree();
 
 1250        const bool hasActiveTiles = tree1.hasActiveTiles();
 
 1252        if (mParent->mIsInputSdf && hasActiveTiles) {
 
 1253          OPENVDB_THROW(RuntimeError, 
"FastSweeping: A SDF should not have active tiles!");
 
 1256#ifdef BENCHMARK_FAST_SWEEPING
 
 1260        mParent->mSweepMask.clear();
 
 1261        mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
 
 1265          OpPoolT opPool(opPrototype);
 
 1268          tree::LeafManager<SdfTreeT> mgr(tree1, 1);
 
 1269          tbb::parallel_for(mgr.leafRange(32), *this);
 
 1270          mgr.swapLeafBuffer(1);
 
 1273#ifdef BENCHMARK_FAST_SWEEPING
 
 1274        timer.
restart(
"Initialize tiles");
 
 1277          tree::NodeManager<SdfTreeT, SdfTreeT::RootNodeType::LEVEL-1> mgr(tree1);
 
 1278          mgr.foreachBottomUp(*this);
 
 1279          tree1.root().setBackground(std::numeric_limits<SdfValueT>::max(), false);
 
 1280          if (hasActiveTiles) {
 
 1281#ifdef BENCHMARK_FAST_SWEEPING
 
 1282            timer.restart(
"Voxelizing active tiles");
 
 1284            tree1.voxelizeActiveTiles();
 
 1285            tree2.voxelizeActiveTiles();
 
 1291        mParent->computeSweepMaskLeafOrigins();
 
 1293#ifdef BENCHMARK_FAST_SWEEPING 
 1299    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1300    void sumHelper(ExtT& sum2, ExtT ext, 
bool update, 
const SdfT& )
 const { 
if (update) sum2 = ext; }
 
 1303    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<!std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1304    void sumHelper(ExtT& sum2, ExtT ext, 
bool , 
const SdfT&  d2)
 const { sum2 += 
static_cast<ExtValueT
>(d2 * ext); }
 
 1306    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1307    ExtT extValHelper(ExtT extSum, 
const SdfT& )
 const { 
return extSum; }
 
 1309    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<!std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1310    ExtT extValHelper(ExtT extSum, 
const SdfT& sdfSum)
 const {
return ExtT((SdfT(1) / sdfSum) * extSum); }
 
 1312    void operator()(
const LeafRange& r)
 const 
 1314        ExtAccT acc(mExtGrid->tree());
 
 1315        SweepMaskAccT sweepMaskAcc(mParent->mSweepMask);
 
 1316        math::GradStencil<SdfGridT, false> stencil(*mSdfGrid);
 
 1317        const math::Transform& xform = mExtGrid->transform();
 
 1318        typename OpPoolT::reference 
op = mOpPool->local();
 
 1319        const SdfValueT isoValue = mIsoValue, above = mAboveSign*std::numeric_limits<SdfValueT>::max();
 
 1320        const SdfValueT h = mAboveSign*
static_cast<SdfValueT
>(mSdfGrid->voxelSize()[0]);
 
 1321        for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
 
 1322            SdfValueT *sdf = leafIter.buffer(1).data();
 
 1323            ExtValueT *ext = acc.probeLeaf(leafIter->origin())->buffer().data();
 
 1324            for (
auto voxelIter = leafIter->beginValueAll(); voxelIter; ++voxelIter) {
 
 1325                const SdfValueT value = *voxelIter;
 
 1326                const bool isAbove = value > isoValue;
 
 1327                if (!voxelIter.isValueOn()) {
 
 1328                    sdf[voxelIter.pos()] = isAbove ? above : -above;
 
 1330                    const Coord ijk = voxelIter.getCoord();
 
 1331                    stencil.moveTo(ijk, value);
 
 1332                    const auto mask = stencil.intersectionMask( isoValue );
 
 1334                        sdf[voxelIter.pos()] = isAbove ? above : -above;
 
 1338                        sweepMaskAcc.setValueOff(ijk);
 
 1339                        const SdfValueT delta = value - isoValue;
 
 1341                            sdf[voxelIter.pos()] = 0;
 
 1342                            ext[voxelIter.pos()] = ExtValueT(
op(xform.indexToWorld(ijk)));
 
 1350                            SdfValueT minD = std::numeric_limits<SdfValueT>::max();
 
 1351                            for (
int n=0, i=0; i<6;) {
 
 1352                                SdfValueT d = std::numeric_limits<SdfValueT>::max(), d2;
 
 1353                                if (mask.test(i++)) {
 
 1354                                    d = 
math::Abs(delta/(value-stencil.getValue(i)));
 
 1357                                if (mask.test(i++)) {
 
 1358                                    d2 = 
math::Abs(delta/(value-stencil.getValue(i)));
 
 1364                                if (d < std::numeric_limits<SdfValueT>::max()) {
 
 1367                                    const Vec3R xyz(
static_cast<SdfValueT
>(ijk[0])+d*
static_cast<SdfValueT
>(FastSweeping::mOffset[n][0]),
 
 1368                                                    static_cast<SdfValueT
>(ijk[1])+d*
static_cast<SdfValueT
>(FastSweeping::mOffset[n][1]),
 
 1369                                                    static_cast<SdfValueT
>(ijk[2])+d*
static_cast<SdfValueT
>(FastSweeping::mOffset[n][2]));
 
 1371                                    sumHelper(sum2, ExtValueT(
op(xform.indexToWorld(xyz))), d < minD, d2);
 
 1372                                    if (d < minD) minD = d;
 
 1375                            ext[voxelIter.pos()] = extValHelper(sum2, sum1);
 
 1376                            sdf[voxelIter.pos()] = isAbove ? h / 
math::Sqrt(sum1) : -h / math::
Sqrt(sum1);
 
 1384    template<
typename RootOrInternalNodeT>
 
 1385    void operator()(
const RootOrInternalNodeT& node)
 const 
 1387        const SdfValueT isoValue = mIsoValue, above = mAboveSign*std::numeric_limits<SdfValueT>::max();
 
 1388        for (
auto it = node.cbeginValueAll(); it; ++it) {
 
 1389          SdfValueT& v = 
const_cast<SdfValueT&
>(*it);
 
 1390          v = v > isoValue ? above : -above;
 
 1398    SdfValueT      mIsoValue;
 
 1399    SdfValueT      mAboveSign;
 
 1403template <
typename SdfGr
idT, 
typename ExtValueT>
 
 1404template <
typename MaskTreeT>
 
 1405struct FastSweeping<SdfGridT, ExtValueT>::MaskKernel
 
 1407    using LeafRange = 
typename tree::LeafManager<const MaskTreeT>::LeafRange;
 
 1408    MaskKernel(FastSweeping &parent) : mParent(&parent),
 
 1409      mSdfGrid(parent.mSdfGrid.get()) {}
 
 1410    MaskKernel(
const MaskKernel &parent) = 
default;
 
 1411    MaskKernel& operator=(
const MaskKernel&) = 
delete;
 
 1413    void run(
const MaskTreeT &mask)
 
 1415#ifdef BENCHMARK_FAST_SWEEPING 
 1416        util::CpuTimer timer;
 
 1418        auto &lsTree = mSdfGrid->tree();
 
 1420        static const SdfValueT 
Unknown = std::numeric_limits<SdfValueT>::max();
 
 1422#ifdef BENCHMARK_FAST_SWEEPING 
 1423        timer.restart(
"Changing background value");
 
 1427#ifdef BENCHMARK_FAST_SWEEPING 
 1428        timer.restart(
"Union with mask");
 
 1430        lsTree.topologyUnion(mask);
 
 1433        tree::LeafManager<const MaskTreeT> mgr(mask);
 
 1435#ifdef BENCHMARK_FAST_SWEEPING 
 1436        timer.restart(
"Initializing grid and sweep mask");
 
 1439        mParent->mSweepMask.clear();
 
 1440        mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
 
 1442        using LeafManagerT = tree::LeafManager<SweepMaskTreeT>;
 
 1443        using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
 
 1444        LeafManagerT leafManager(mParent->mSweepMask);
 
 1446        auto kernel = [&](LeafT& leaf, 
size_t ) {
 
 1447            static const SdfValueT 
Unknown = std::numeric_limits<SdfValueT>::max();
 
 1448            SdfAccT acc(mSdfGrid->tree());
 
 1451            SdfValueT *data = acc.probeLeaf(leaf.origin())->buffer().data();
 
 1452            for (
auto voxelIter = leaf.beginValueOn(); voxelIter; ++voxelIter) {
 
 1453                if (math::Abs( data[voxelIter.pos()] ) < Unknown ) {
 
 1455                    voxelIter.setValue(
false);
 
 1459        leafManager.foreach( kernel );
 
 1462        mParent->computeSweepMaskLeafOrigins();
 
 1464#ifdef BENCHMARK_FAST_SWEEPING 
 1470    FastSweeping *mParent;
 
 1475template <
typename SdfGr
idT, 
typename ExtValueT>
 
 1483    template<
typename HashOp>
 
 1486#ifdef BENCHMARK_FAST_SWEEPING 
 1491        const SweepMaskTreeT& maskTree = mParent->mSweepMask;
 
 1494        using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
 
 1495        LeafManagerT leafManager(maskTree);
 
 1502        constexpr int maskOffset = LeafT::DIM * 3;
 
 1503        constexpr int maskRange = maskOffset * 2;
 
 1506        std::vector<int8_t> leafSliceMasks(leafManager.leafCount()*maskRange);
 
 1507        auto kernel1 = [&](
const LeafT& leaf, 
size_t leafIdx) {
 
 1508            const size_t leafOffset = leafIdx * maskRange;
 
 1509            for (
auto voxelIter = leaf.cbeginValueOn(); voxelIter; ++voxelIter) {
 
 1510                const Coord ijk = LeafT::offsetToLocalCoord(voxelIter.pos());
 
 1511                leafSliceMasks[leafOffset + 
hash(ijk) + maskOffset] = uint8_t(1);
 
 1514        leafManager.foreach( kernel1 );
 
 1519        using ThreadLocalMap = std::unordered_map<int64_t, std::deque<size_t>>;
 
 1520        tbb::enumerable_thread_specific<ThreadLocalMap> pool;
 
 1521        auto kernel2 = [&](
const LeafT& leaf, 
size_t leafIdx) {
 
 1522            ThreadLocalMap& map = pool.local();
 
 1523            const Coord& origin = leaf.origin();
 
 1524            const int64_t leafKey = 
hash(origin);
 
 1525            const size_t leafOffset = leafIdx * maskRange;
 
 1526            for (
int sliceIdx = 0; sliceIdx < maskRange; sliceIdx++) {
 
 1527                if (leafSliceMasks[leafOffset + sliceIdx] == uint8_t(1)) {
 
 1528                    const int64_t voxelSliceKey = leafKey+sliceIdx-maskOffset;
 
 1529                    map[voxelSliceKey].emplace_back(leafIdx);
 
 1533        leafManager.foreach( kernel2 );
 
 1538        for (
auto poolIt = pool.begin(); poolIt != pool.end(); ++poolIt) {
 
 1539            const ThreadLocalMap& map = *poolIt;
 
 1540            for (
const auto& it : map) {
 
 1541                for (
const size_t leafIdx : it.second) {
 
 1542                    mVoxelSliceMap[it.first].emplace_back(leafIdx, NodeMaskPtrT());
 
 1548        mVoxelSliceKeys.reserve(mVoxelSliceMap.size());
 
 1549        for (
const auto& it : mVoxelSliceMap) {
 
 1550            mVoxelSliceKeys.push_back(it.first);
 
 1554        auto kernel3 = [&](tbb::blocked_range<size_t>& range) {
 
 1555            for (
size_t i = range.begin(); i < range.end(); i++) {
 
 1556                const int64_t key = mVoxelSliceKeys[i];
 
 1557                for (
auto& it : mVoxelSliceMap[key]) {
 
 1558                    it.second = std::make_unique<NodeMaskT>();
 
 1562        tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceKeys.size()), kernel3);
 
 1569        auto kernel4 = [&](tbb::blocked_range<size_t>& range) {
 
 1570            for (
size_t i = range.begin(); i < range.end(); i++) {
 
 1571                const int64_t voxelSliceKey = mVoxelSliceKeys[i];
 
 1572                LeafSliceArray& leafSliceArray = mVoxelSliceMap[voxelSliceKey];
 
 1573                for (LeafSlice& leafSlice : leafSliceArray) {
 
 1574                    const size_t leafIdx = leafSlice.first;
 
 1575                    NodeMaskPtrT& nodeMask = leafSlice.second;
 
 1576                    const LeafT& leaf = leafManager.leaf(leafIdx);
 
 1577                    const Coord& origin = leaf.origin();
 
 1578                    const int64_t leafKey = 
hash(origin);
 
 1579                    for (
auto voxelIter = leaf.cbeginValueOn(); voxelIter; ++voxelIter) {
 
 1580                        const Index voxelIdx = voxelIter.pos();
 
 1581                        const Coord ijk = LeafT::offsetToLocalCoord(voxelIdx);
 
 1582                        const int64_t key = leafKey + 
hash(ijk);
 
 1583                        if (key == voxelSliceKey) {
 
 1584                            nodeMask->setOn(voxelIdx);
 
 1590        tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceKeys.size()), kernel4);
 
 
 1597        inline static Coord ijk(
const Coord &p, 
int i) { 
return p + FastSweeping::mOffset[i]; }
 
 1602        inline operator bool()
 const { 
return v < SdfValueT(1000); }
 
 
 1606    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1607    ExtT 
twoNghbr(
const NN& d1, 
const NN& d2, 
const SdfT& , 
const ExtT& v1, 
const ExtT& v2)
 const { 
return d1.
v < d2.
v ? v1 : v2; }
 
 1610    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<!std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1611    ExtT 
twoNghbr(
const NN& d1, 
const NN& d2, 
const SdfT& w, 
const ExtT& v1, 
const ExtT& v2)
 const { 
return ExtT(w*(d1.
v*v1 + d2.
v*v2)); }
 
 1614    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1615    ExtT 
threeNghbr(
const NN& d1, 
const NN& d2, 
const NN& d3, 
const SdfT& , 
const ExtT& v1, 
const ExtT& v2, 
const ExtT& v3)
 const {
 
 
 1622    template<typename ExtT = ExtValueT, typename SdfT = SdfValueT, typename std::enable_if<!std::is_same<ExtT, int>::value, 
int>::type = 0>
 
 1623    ExtT 
threeNghbr(
const NN& d1, 
const NN& d2, 
const NN& d3, 
const SdfT& w, 
const ExtT& v1, 
const ExtT& v2, 
const ExtT& v3)
 const {
 
 1624        return ExtT(w*(d1.
v*v1 + d2.
v*v2 + d3.
v*v3));
 
 
 1629        typename ExtGridT::TreeType *tree2 = mParent->mExtGrid ? &mParent->mExtGrid->tree() : 
nullptr;
 
 1630        typename ExtGridT::TreeType *tree3 = mParent->mExtGridInput ? &mParent->mExtGridInput->tree() : 
nullptr;
 
 1632        const SdfValueT h = 
static_cast<SdfValueT
>(mParent->mSdfGrid->voxelSize()[0]);
 
 1633        const SdfValueT sqrt2h = 
math::Sqrt(SdfValueT(2))*h;
 
 1635        const bool isInputSdf = mParent->mIsInputSdf;
 
 1642        const std::vector<Coord>& leafNodeOrigins = mParent->mSweepMaskLeafOrigins;
 
 1644        int64_t voxelSliceIndex(0);
 
 1646        auto kernel = [&](
const tbb::blocked_range<size_t>& range) {
 
 1647            using LeafT = 
typename SdfGridT::TreeType::LeafNodeType;
 
 1649            SdfAccT acc1(mParent->mSdfGrid->tree());
 
 1650            auto acc2 = std::unique_ptr<ExtAccT>(tree2 ? 
new ExtAccT(*tree2) : 
nullptr);
 
 1651            auto acc3 = std::unique_ptr<ExtAccT>(tree3 ? 
new ExtAccT(*tree3) : 
nullptr);
 
 1652            SdfValueT absV, sign, update, D;
 
 1655            const LeafSliceArray& leafSliceArray = mVoxelSliceMap[voxelSliceIndex];
 
 1659            for (
size_t i = range.begin(); i < range.end(); ++i) {
 
 1664                const LeafSlice& leafSlice = leafSliceArray[i];
 
 1665                const size_t leafIdx = leafSlice.first;
 
 1666                const NodeMaskPtrT& nodeMask = leafSlice.second;
 
 1668                const Coord& origin = leafNodeOrigins[leafIdx];
 
 1671                for (
auto indexIter = nodeMask->beginOn(); indexIter; ++indexIter) {
 
 1674                    ijk = origin + LeafT::offsetToLocalCoord(indexIter.pos());
 
 1677                    d1 = std::min(
NN(acc1, ijk, 0), 
NN(acc1, ijk, 1));
 
 1678                    d2 = std::min(
NN(acc1, ijk, 2), 
NN(acc1, ijk, 3));
 
 1679                    d3 = std::min(
NN(acc1, ijk, 4), 
NN(acc1, ijk, 5));
 
 1681                    if (!(d1 || d2 || d3)) 
continue;
 
 1686                    SdfValueT &value = 
const_cast<SdfValueT&
>(acc1.
getValue(ijk));
 
 1689                    sign = value >= SdfValueT(0) ? SdfValueT(1) : SdfValueT(-1);
 
 1695                    if (d2 < d1) std::swap(d1, d2);
 
 1696                    if (d3 < d2) std::swap(d2, d3);
 
 1697                    if (d2 < d1) std::swap(d1, d2);
 
 1703                    if (update <= d2.
v) {
 
 1704                        if (update < absV) {
 
 1705                            value = sign * update;
 
 1708                                ExtValueT updateExt = acc2->getValue(d1(ijk));
 
 1710                                    if (
isInputSdf) updateExt = (value >= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
 
 1711                                    else updateExt = (value <= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
 
 1714                                    if (
isInputSdf) updateExt = (value <= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
 
 1715                                    else updateExt = (value >= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
 
 1717                                acc2->setValue(ijk, updateExt);
 
 1727                    if (d2.
v <= sqrt2h + d1.
v) {
 
 1729                        update = SdfValueT(0.5) * (d1.
v + d2.
v + std::sqrt(D));
 
 1730                        if (update > d2.
v && update <= d3.
v) {
 
 1731                            if (update < absV) {
 
 1732                                value = sign * update;
 
 1737                                    const SdfValueT w = SdfValueT(1)/(d1.
v+d2.
v);
 
 1738                                    const ExtValueT v1 = acc2->getValue(d1(ijk));
 
 1739                                    const ExtValueT v2 = acc2->getValue(d2(ijk));
 
 1740                                    const ExtValueT extVal = 
twoNghbr(d1, d2, w, v1, v2);
 
 1742                                    ExtValueT updateExt = extVal;
 
 1744                                        if (
isInputSdf) updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1745                                        else updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1748                                        if (
isInputSdf) updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1749                                        else updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1751                                    acc2->setValue(ijk, updateExt);
 
 1762                    const SdfValueT d123 = d1.
v + d2.
v + d3.
v;
 
 1763                    D = d123*d123 - SdfValueT(3)*(d1.
v*d1.
v + d2.
v*d2.
v + d3.
v*d3.
v - h * h);
 
 1764                    if (D >= SdfValueT(0)) {
 
 1765                        update = SdfValueT(1.0/3.0) * (d123 + std::sqrt(D));
 
 1767                        if (update < absV) {
 
 1768                            value = sign * update;
 
 1774                                const SdfValueT w = SdfValueT(1)/(d1.
v+d2.
v+d3.
v);
 
 1775                                const ExtValueT v1 = acc2->getValue(d1(ijk));
 
 1776                                const ExtValueT v2 = acc2->getValue(d2(ijk));
 
 1777                                const ExtValueT v3 = acc2->getValue(d3(ijk));
 
 1778                                const ExtValueT extVal = 
threeNghbr(d1, d2, d3, w, v1, v2, v3);
 
 1780                                ExtValueT updateExt = extVal;
 
 1782                                    if (
isInputSdf) updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1783                                    else updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1786                                    if (
isInputSdf) updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1787                                    else updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
 
 1789                                acc2->setValue(ijk, updateExt);
 
 1797#ifdef BENCHMARK_FAST_SWEEPING 
 1801        for (
size_t i = 0; i < mVoxelSliceKeys.size(); i++) {
 
 1802            voxelSliceIndex = mVoxelSliceKeys[i];
 
 1803            tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceMap[voxelSliceIndex].size()), kernel);
 
 1806#ifdef BENCHMARK_FAST_SWEEPING 
 1807        timer.
restart(
"Backward sweeps");
 
 1809        for (
size_t i = mVoxelSliceKeys.size(); i > 0; i--) {
 
 1810            voxelSliceIndex = mVoxelSliceKeys[i-1];
 
 1811            tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceMap[voxelSliceIndex].size()), kernel);
 
 1814#ifdef BENCHMARK_FAST_SWEEPING 
 
 1820    using NodeMaskT = 
typename SweepMaskTreeT::LeafNodeType::NodeMaskType;
 
 1821    using NodeMaskPtrT = std::unique_ptr<NodeMaskT>;
 
 1824    using LeafSlice = std::pair<size_t, NodeMaskPtrT>;
 
 1825    using LeafSliceArray = std::deque<LeafSlice>;
 
 1826    using VoxelSliceMap = std::map<int64_t, LeafSliceArray>;
 
 1830    VoxelSliceMap mVoxelSliceMap;
 
 1831    std::vector<int64_t> mVoxelSliceKeys;
 
 
 1836template<
typename Gr
idT>
 
 1839         typename GridT::ValueType isoValue,
 
 1843    if (fs.initSdf(fogGrid, isoValue, 
false)) fs.sweep(nIter);
 
 1844    return fs.sdfGrid();
 
 
 1847template<
typename Gr
idT>
 
 1850         typename GridT::ValueType isoValue,
 
 1854    if (fs.initSdf(sdfGrid, isoValue, 
true)) fs.sweep(nIter);
 
 1855    return fs.sdfGrid();
 
 
 1858template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
 1859typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr
 
 1862         const ExtValueT& background,
 
 1863         typename FogGridT::ValueType isoValue,
 
 1866         const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid)
 
 1869  if (fs.initExt(fogGrid, 
op, background, isoValue, 
false, mode, extGrid))
 
 1870      fs.sweep(nIter, 
true);
 
 1871  return fs.extGrid();
 
 
 1874template<
typename SdfGr
idT, 
typename OpT, 
typename ExtValueT>
 
 1875typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr
 
 1878         const ExtValueT &background,
 
 1879         typename SdfGridT::ValueType isoValue,
 
 1882         const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid)
 
 1885  if (fs.initExt(sdfGrid, 
op, background, isoValue, 
true, mode, extGrid))
 
 1886      fs.sweep(nIter, 
true);
 
 1887  return fs.extGrid();
 
 
 1890template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
 1891std::pair<typename FogGridT::Ptr, typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr>
 
 1894               const ExtValueT &background,
 
 1895               typename FogGridT::ValueType isoValue,
 
 1898               const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid)
 
 1901  if (fs.initExt(fogGrid, 
op, background, isoValue, 
false, mode, extGrid))
 
 1902      fs.sweep(nIter, 
true);
 
 1903  return std::make_pair(fs.sdfGrid(), fs.extGrid());
 
 
 1906template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
 
 1907std::pair<typename SdfGridT::Ptr, typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr>
 
 1910               const ExtValueT &background,
 
 1911               typename SdfGridT::ValueType isoValue,
 
 1914               const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid)
 
 1917  if (fs.initExt(sdfGrid, 
op, background, isoValue, 
true, mode, extGrid))
 
 1918      fs.sweep(nIter, 
true);
 
 1919  return std::make_pair(fs.sdfGrid(), fs.extGrid());
 
 
 1922template<
typename Gr
idT>
 
 1931    if (fs.initDilate(sdfGrid, dilation, nn,  mode)) fs.sweep(nIter);
 
 1932    return fs.sdfGrid();
 
 
 1935template<
typename Gr
idT, 
typename MaskTreeT>
 
 1939        bool ignoreActiveTiles,
 
 1943    if (fs.initMask(sdfGrid, mask, ignoreActiveTiles)) fs.sweep(nIter);
 
 1944    return fs.sdfGrid();
 
 
 1953#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
 1955#ifdef OPENVDB_INSTANTIATE_FASTSWEEPING 
 1959#define _FUNCTION(TreeT) \ 
 1960    Grid<TreeT>::Ptr fogToSdf(const Grid<TreeT>&, TreeT::ValueType, int) 
 1964#define _FUNCTION(TreeT) \ 
 1965    Grid<TreeT>::Ptr sdfToSdf(const Grid<TreeT>&, TreeT::ValueType, int) 
 1969#define _FUNCTION(TreeT) \ 
 1970    Grid<TreeT>::Ptr dilateSdf(const Grid<TreeT>&, int, NearestNeighbors, int, FastSweepingDomain) 
 
 
 
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
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.
Functions to efficiently compute histograms, extrema (min/max) and statistics (mean,...
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition Grid.h:411
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid.
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition Grid.h:908
SharedPtr< Grid > Ptr
Definition Grid.h:573
Definition Exceptions.h:63
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:683
const ValueType & getValue(unsigned int pos=0) const
Return the value from the stencil buffer with linear offset pos.
Definition Stencils.h:97
std::bitset< 6 > intersectionMask(const ValueType &isoValue=zeroVal< ValueType >()) const
Return true a bit-mask where the 6 bits indicates if the center of the stencil intersects the iso-con...
Definition Stencils.h:188
void moveTo(const Coord &ijk)
Initialize the stencil buffer with the values of voxel (i, j, k) and its neighbors.
Definition Stencils.h:47
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition Stencils.h:1232
Templated class to compute the minimum and maximum values.
Definition Stats.h:32
Definition LeafManager.h:103
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
bool swapLeafBuffer(size_t bufferIdx, bool serial=false)
Swap each leaf node's buffer with the nth corresponding auxiliary buffer, where n = bufferIdx.
Definition LeafManager.h:360
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition LeafManager.h:346
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays,...
Definition NodeManager.h:532
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Definition NodeManager.h:632
void setValueOff(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as inactive.
Definition ValueAccessor.h:607
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:455
Simple timer for basic profiling.
Definition CpuTimer.h:67
double stop() const
Returns and prints time in milliseconds since construction or start was called.
Definition CpuTimer.h:128
double restart()
Re-start timer.
Definition CpuTimer.h:150
__hostdev__ uint32_t hash(uint32_t x)
Definition common.h:14
@ Unknown
Definition NanoVDB.h:219
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.
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition Math.h:349
float Sqrt(float x)
Return the square root of a floating-point value.
Definition Math.h:761
size_t MinIndex(const Vec3T &v)
Return the index [0,1,2] of the smallest value in a 3D vector.
Definition Math.h:930
Vec3< double > Vec3d
Definition Vec3.h:665
Coord Abs(const Coord &xyz)
Definition Coord.h:518
Type Pow2(Type x)
Return x2.
Definition Math.h:548
Definition PointDataGrid.h:170
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
Index32 Index
Definition Types.h:54
@ GRID_LEVEL_SET
Definition Types.h:455
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::Vec3< Real > Vec3R
Definition Types.h:72
GridType::Ptr createGrid()
Create a new grid of type GridType with background value zero.
Definition Grid.h:1765
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#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_REAL_TREE_INSTANTIATE(Function)
Definition version.h.in:162