27 #ifndef OPENVDB_TOOLS_FASTSWEEPING_HAS_BEEN_INCLUDED    28 #define OPENVDB_TOOLS_FASTSWEEPING_HAS_BEEN_INCLUDED    41 #ifdef BENCHMARK_FAST_SWEEPING    45 #include <tbb/parallel_for.h>    46 #include <tbb/enumerable_thread_specific.h>    47 #include <tbb/task_group.h>    49 #include <type_traits>    53 #include <unordered_map>   101 template<
typename Gr
idT>
   104          typename GridT::ValueType isoValue,
   134 template<
typename Gr
idT>
   137          typename GridT::ValueType isoValue = 0,
   190 template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
   191 typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr
   194          const ExtValueT& background,
   195          typename FogGridT::ValueType isoValue,
   198          const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
   248 template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
   249 typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr
   252          const ExtValueT &background,
   253          typename SdfGridT::ValueType isoValue = 0,
   256          const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
   311 template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
   312 std::pair<typename FogGridT::Ptr, typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr>
   315                const ExtValueT &background,
   316                typename FogGridT::ValueType isoValue,
   319                const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
   374 template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
   375 std::pair<typename SdfGridT::Ptr, typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr>
   378                const ExtValueT &background,
   379                typename SdfGridT::ValueType isoValue = 0,
   382                const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr extGrid = 
nullptr);
   412 template<
typename Gr
idT>
   438 template<
typename Gr
idT, 
typename MaskTreeT>
   442         bool ignoreActiveTiles = 
false,
   457 template<
typename SdfGr
idT, 
typename ExtValueT = 
typename SdfGr
idT::ValueType>
   461                   "FastSweeping requires SdfGridT to have floating-point values");
   463     using SdfValueT = 
typename SdfGridT::ValueType;
   464     using SdfTreeT = 
typename SdfGridT::TreeType;
   469     using ExtGridT = 
typename SdfGridT::template ValueConverter<ExtValueT>::Type;
   470     using ExtTreeT = 
typename ExtGridT::TreeType;
   474     using SweepMaskTreeT = 
typename SdfTreeT::template ValueConverter<ValueMask>::Type;
   497     typename SdfGridT::Ptr 
sdfGrid() { 
return mSdfGrid; }
   505     typename ExtGridT::Ptr 
extGrid() { 
return mExtGrid; }
   535     bool initSdf(
const SdfGridT &sdfGrid, SdfValueT isoValue, 
bool isInputSdf);
   583     template <
typename ExtOpT>
   584     bool initExt(
const SdfGridT &sdfGrid,
   586                  const ExtValueT &background,
   590                  const typename ExtGridT::ConstPtr extGrid = 
nullptr);
   613     bool initDilate(
const SdfGridT &sdfGrid,
   636     template<
typename MaskTreeT>
   637     bool initMask(
const SdfGridT &sdfGrid, 
const Grid<MaskTreeT> &mask, 
bool ignoreActiveTiles = 
false);
   651     void sweep(
int nIter = 1,
   652                bool finalize = 
true);
   664     bool isValid()
 const { 
return mSweepingVoxelCount > 0 && mBoundaryVoxelCount > 0; }
   680     void computeSweepMaskLeafOrigins();
   693     static const Coord mOffset[6];
   696     typename SdfGridT::Ptr mSdfGrid;
   697     typename ExtGridT::Ptr mExtGrid;
   698     typename ExtGridT::Ptr mExtGridInput; 
   699     SweepMaskTreeT mSweepMask; 
   700     std::vector<Coord> mSweepMaskLeafOrigins; 
   701     size_t mSweepingVoxelCount, mBoundaryVoxelCount;
   709 template <
typename SdfGr
idT, 
typename ExtValueT>
   714 template <
typename SdfGr
idT, 
typename ExtValueT>
   716     : mSdfGrid(nullptr), mExtGrid(nullptr), mSweepingVoxelCount(0), mBoundaryVoxelCount(0), mSweepDirection(
FastSweepingDomain::
SWEEP_ALL), mIsInputSdf(true)
   720 template <
typename SdfGr
idT, 
typename ExtValueT>
   726     if (mExtGridInput) mExtGridInput.reset();
   727     mSweepingVoxelCount = mBoundaryVoxelCount = 0;
   732 template <
typename SdfGr
idT, 
typename ExtValueT>
   738     mSweepMask.voxelizeActiveTiles();
   741     using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
   742     LeafManagerT leafManager(mSweepMask);
   744     mSweepMaskLeafOrigins.resize(leafManager.leafCount());
   746     auto kernel = [&](
const LeafT& leaf, 
size_t leafIdx) {
   747         mSweepMaskLeafOrigins[leafIdx] = leaf.origin();
   750     leafManager.foreach(kernel, 
true, 1024);
   752     mBoundaryVoxelCount = 0;
   755         const size_t totalCount = mSdfGrid->constTree().activeVoxelCount();
   756         assert( totalCount >= mSweepingVoxelCount );
   757         mBoundaryVoxelCount = totalCount - mSweepingVoxelCount;
   761 template <
typename SdfGr
idT, 
typename ExtValueT>
   765     mSdfGrid = fogGrid.deepCopy();
   768     kernel.
run(isoValue);
   772 template <
typename SdfGr
idT, 
typename ExtValueT>
   773 template <
typename OpT>
   779         if (extGrid->transform() != fogGrid.transform())
   780             OPENVDB_THROW(
RuntimeError, 
"FastSweeping::initExt extension grid input should have the same transform as Fog/SDF grid!");
   784     mSdfGrid = fogGrid.deepCopy();
   785     mExtGrid = createGrid<ExtGridT>( background );
   786     mSweepDirection = mode;
   789         mExtGridInput = extGrid->deepCopy();
   791     mExtGrid->topologyUnion( *mSdfGrid );
   792     InitExt<OpT> kernel(*
this);
   793     kernel.run(isoValue, op);
   798 template <
typename SdfGr
idT, 
typename ExtValueT>
   802     mSdfGrid = sdfGrid.deepCopy();
   803     mSweepDirection = mode;
   805     kernel.
run(dilate, nn);
   809 template <
typename SdfGr
idT, 
typename ExtValueT>
   810 template<
typename MaskTreeT>
   814     mSdfGrid = sdfGrid.deepCopy();
   816     if (mSdfGrid->transform() != mask.
transform()) {
   821         using T = 
typename MaskTreeT::template ValueConverter<bool>::Type;
   823         tmp->
tree().voxelizeActiveTiles();
   824         MaskKernel<T> kernel(*
this);
   825         kernel.run(tmp->
tree());
   827         if (ignoreActiveTiles || !mask.
tree().hasActiveTiles()) {
   828             MaskKernel<MaskTreeT> kernel(*
this);
   829             kernel.run(mask.
tree());
   831             using T = 
typename MaskTreeT::template ValueConverter<ValueMask>::Type;
   833             tmp.voxelizeActiveTiles(
true);
   834             MaskKernel<T> kernel(*
this);
   841 template <
typename SdfGr
idT, 
typename ExtValueT>
   849                                      " a non-null reference extension grid input.");
   858     std::deque<SweepingKernel> kernels;
   859     for (
int i = 0; i < 4; i++) kernels.emplace_back(*
this);
   862 #ifdef BENCHMARK_FAST_SWEEPING   867         tbb::task_group tasks;
   868         tasks.run([&] { kernels[0].computeVoxelSlices([](
const Coord &a){ 
return a[0]+a[1]+a[2]; }); });
   869         tasks.run([&] { kernels[1].computeVoxelSlices([](
const Coord &a){ 
return a[0]+a[1]-a[2]; }); });
   870         tasks.run([&] { kernels[2].computeVoxelSlices([](
const Coord &a){ 
return a[0]-a[1]+a[2]; }); });
   871         tasks.run([&] { kernels[3].computeVoxelSlices([](
const Coord &a){ 
return a[0]-a[1]-a[2]; }); });
   874 #ifdef BENCHMARK_FAST_SWEEPING   880     for (
int i = 0; i < nIter; ++i) {
   885 #ifdef BENCHMARK_FAST_SWEEPING   889       auto e = kernel.
run(*mSdfGrid);
   891 #ifdef BENCHMARK_FAST_SWEEPING   892       std::cerr << 
"Min = " << e.min() << 
" Max = " << e.max() << std::endl;
   893       timer.
restart(
"Changing asymmetric background value");
   897 #ifdef BENCHMARK_FAST_SWEEPING   906 template <
typename SdfGr
idT, 
typename ExtValueT>
   917         tbb::parallel_reduce(mgr.leafRange(), *
this);
   923         for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
   924             for (
auto voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
   925                 const SdfValueT v = *voxelIter;
   926                 if (v < mMin) mMin = v;
   927                 if (v > mMax) mMax = v;
   934         if (other.
mMin < mMin) mMin = other.
mMin;
   935         if (other.
mMax > mMax) mMax = other.
mMax;
   944 template <
typename SdfGr
idT, 
typename ExtValueT>
   950           mBackground(parent.mSdfGrid->background())
   952         mSdfGridInput = mParent->mSdfGrid->deepCopy();
   959 #ifdef BENCHMARK_FAST_SWEEPING   964 #ifdef BENCHMARK_FAST_SWEEPING   965         timer.
restart(
"Changing background value");
   970  #ifdef BENCHMARK_FAST_SWEEPING   971         timer.
restart(
"Dilating and updating mgr (parallel)");
   981 #ifdef BENCHMARK_FAST_SWEEPING   982         timer.
restart(
"Initializing grid and sweep mask");
   985         mParent->mSweepMask.clear();
   986         mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
   989         using LeafT = 
typename SdfGridT::TreeType::LeafNodeType;
   993         LeafManagerT leafManager(mParent->mSdfGrid->tree());
   995         auto kernel = [&](LeafT& leaf, 
size_t ) {
   997             const SdfValueT background = mBackground;
   998             auto* maskLeaf = mParent->mSweepMask.probeLeaf(leaf.origin());
   999             SdfConstAccT sdfInputAcc(mSdfGridInput->tree());
  1001             for (
auto voxelIter = leaf.beginValueOn(); voxelIter; ++voxelIter) {
  1002                 const SdfValueT 
value = *voxelIter;
  1003                 SdfValueT inputValue;
  1004                 const Coord ijk = voxelIter.getCoord();
  1007                     maskLeaf->setValueOff(voxelIter.pos());
  1011                             voxelIter.setValue(value > 0 ? Unknown : -Unknown);
  1014                             if (value > 0) voxelIter.setValue(Unknown);
  1016                                 maskLeaf->setValueOff(voxelIter.pos());
  1017                                 bool isInputOn = sdfInputAcc.probeValue(ijk, inputValue);
  1018                                 if ( !isInputOn ) voxelIter.setValueOff();
  1019                                 else voxelIter.setValue(inputValue);
  1023                             if (value < 0) voxelIter.setValue(-Unknown);
  1025                                 maskLeaf->setValueOff(voxelIter.pos());
  1026                                 bool isInputOn = sdfInputAcc.probeValue(ijk, inputValue);
  1027                                 if ( !isInputOn ) voxelIter.setValueOff();
  1028                                 else voxelIter.setValue(inputValue);
  1036         leafManager.foreach( kernel );
  1039         mParent->computeSweepMaskLeafOrigins();
  1041 #ifdef BENCHMARK_FAST_SWEEPING  1054 template <
typename SdfGr
idT, 
typename ExtValueT>
  1059       mSdfGrid(parent.mSdfGrid.get()), mIsoValue(0), mAboveSign(0) {}
  1065         mIsoValue   = isoValue;
  1066         mAboveSign  = mParent->mIsInputSdf ? SdfValueT(1) : SdfValueT(-1);
  1067         SdfTreeT &tree = mSdfGrid->tree();
  1068         const bool hasActiveTiles = tree.hasActiveTiles();
  1070         if (mParent->mIsInputSdf && hasActiveTiles) {
  1074 #ifdef BENCHMARK_FAST_SWEEPING  1077         mParent->mSweepMask.clear();
  1078         mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
  1082           tbb::parallel_for(mgr.
leafRange(32), *
this);
  1086 #ifdef BENCHMARK_FAST_SWEEPING  1087         timer.
restart(
"Initialize tiles - new");
  1091         mgr.foreachBottomUp(*
this);
  1093         if (hasActiveTiles) tree.voxelizeActiveTiles();
  1097         mParent->computeSweepMaskLeafOrigins();
  1105         const SdfValueT h = mAboveSign*
static_cast<SdfValueT
>(mSdfGrid->voxelSize()[0]);
  1106         for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
  1107             SdfValueT* sdf = leafIter.buffer(1).data();
  1108             for (
auto voxelIter = leafIter->beginValueAll(); voxelIter; ++voxelIter) {
  1109                 const SdfValueT 
value = *voxelIter;
  1110                 const bool isAbove = value > isoValue;
  1111                 if (!voxelIter.isValueOn()) {
  1112                     sdf[voxelIter.pos()] = isAbove ? above : -above;
  1114                     const Coord ijk = voxelIter.getCoord();
  1115                     stencil.
moveTo(ijk, value);
  1118                         sdf[voxelIter.pos()] = isAbove ? above : -above;
  1122                         const SdfValueT delta = value - isoValue;
  1124                             sdf[voxelIter.pos()] = 0;
  1127                             for (
int i=0; i<6;) {
  1130                                 if (mask.test(i++)) {
  1134                                 if (d < std::numeric_limits<SdfValueT>::max()) sum += 1/(d*d);
  1144     template<
typename RootOrInternalNodeT>
  1148         for (
auto it = node.cbeginValueAll(); it; ++it) {
  1149           SdfValueT& v = 
const_cast<SdfValueT&
>(*it);
  1150           v = v > isoValue ? above : -above;
  1163 template <
typename SdfGr
idT, 
typename ExtValueT>
  1164 template <
typename OpT>
  1168     using OpPoolT = tbb::enumerable_thread_specific<OpT>;
  1170       mOpPool(
nullptr), mSdfGrid(parent.mSdfGrid.get()),
  1171       mExtGrid(parent.mExtGrid.get()), mIsoValue(0), mAboveSign(0) {}
  1172     InitExt(
const InitExt&) = 
default;
  1173     InitExt& 
operator=(
const InitExt&) = 
delete;
  1174     void run(SdfValueT isoValue, 
const OpT &opPrototype)
  1176         static_assert(std::is_convertible<decltype(opPrototype(Vec3d(0))),ExtValueT>::
value, 
"Invalid return type of functor");
  1181         mAboveSign  = mParent->mIsInputSdf ? SdfValueT(1) : SdfValueT(-1);
  1182         mIsoValue = isoValue;
  1183         auto &tree1 = mSdfGrid->tree();
  1184         auto &tree2 = mExtGrid->tree();
  1185         const bool hasActiveTiles = tree1.hasActiveTiles();
  1187         if (mParent->mIsInputSdf && hasActiveTiles) {
  1191 #ifdef BENCHMARK_FAST_SWEEPING  1195         mParent->mSweepMask.clear();
  1196         mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
  1200           OpPoolT opPool(opPrototype);
  1204           tbb::parallel_for(mgr.
leafRange(32), *
this);
  1208 #ifdef BENCHMARK_FAST_SWEEPING  1209         timer.
restart(
"Initialize tiles");
  1213           mgr.foreachBottomUp(*
this);
  1215           if (hasActiveTiles) {
  1216 #ifdef BENCHMARK_FAST_SWEEPING  1217             timer.
restart(
"Voxelizing active tiles");
  1219             tree1.voxelizeActiveTiles();
  1220             tree2.voxelizeActiveTiles();
  1226         mParent->computeSweepMaskLeafOrigins();
  1228 #ifdef BENCHMARK_FAST_SWEEPING  1235     void sumHelper(ExtT& sum2, ExtT ext, 
bool update, 
const SdfT& )
 const { 
if (update) sum2 = ext; }
  1239     void sumHelper(ExtT& sum2, ExtT ext, 
bool , 
const SdfT&  d2)
 const { sum2 += 
static_cast<ExtValueT
>(d2 * ext); }
  1242     ExtT extValHelper(ExtT extSum, 
const SdfT& )
 const { 
return extSum; }
  1245     ExtT extValHelper(ExtT extSum, 
const SdfT& sdfSum)
 const {
return ExtT((SdfT(1) / sdfSum) * extSum); }
  1247     void operator()(
const LeafRange& r)
 const  1249         ExtAccT acc(mExtGrid->tree());
  1253         typename OpPoolT::reference op = mOpPool->local();
  1255         const SdfValueT h = mAboveSign*
static_cast<SdfValueT
>(mSdfGrid->voxelSize()[0]);
  1256         for (
auto leafIter = r.begin(); leafIter; ++leafIter) {
  1257             SdfValueT *sdf = leafIter.buffer(1).data();
  1258             ExtValueT *ext = acc.probeLeaf(leafIter->origin())->buffer().data();
  1259             for (
auto voxelIter = leafIter->beginValueAll(); voxelIter; ++voxelIter) {
  1260                 const SdfValueT 
value = *voxelIter;
  1261                 const bool isAbove = value > isoValue;
  1262                 if (!voxelIter.isValueOn()) {
  1263                     sdf[voxelIter.pos()] = isAbove ? above : -above;
  1265                     const Coord ijk = voxelIter.getCoord();
  1266                     stencil.
moveTo(ijk, value);
  1269                         sdf[voxelIter.pos()] = isAbove ? above : -above;
  1273                         sweepMaskAcc.setValueOff(ijk);
  1274                         const SdfValueT delta = value - isoValue;
  1276                             sdf[voxelIter.pos()] = 0;
  1277                             ext[voxelIter.pos()] = ExtValueT(op(xform.
indexToWorld(ijk)));
  1280                             ExtValueT sum2 = zeroVal<ExtValueT>();
  1286                             for (
int n=0, i=0; i<6;) {
  1288                                 if (mask.test(i++)) {
  1292                                 if (mask.test(i++)) {
  1299                                 if (d < std::numeric_limits<SdfValueT>::max()) {
  1302                                     const Vec3R xyz(static_cast<SdfValueT>(ijk[0])+d*static_cast<SdfValueT>(FastSweeping::mOffset[n][0]),
  1303                                                     static_cast<SdfValueT>(ijk[1])+d*static_cast<SdfValueT>(FastSweeping::mOffset[n][1]),
  1304                                                     static_cast<SdfValueT>(ijk[2])+d*static_cast<SdfValueT>(FastSweeping::mOffset[n][2]));
  1306                                     sumHelper(sum2, ExtValueT(op(xform.
indexToWorld(xyz))), d < minD, d2);
  1307                                     if (d < minD) minD = d;
  1310                             ext[voxelIter.pos()] = extValHelper(sum2, sum1);
  1319     template<
typename RootOrInternalNodeT>
  1320     void operator()(
const RootOrInternalNodeT& node)
 const  1323         for (
auto it = node.cbeginValueAll(); it; ++it) {
  1324           SdfValueT& v = 
const_cast<SdfValueT&
>(*it);
  1325           v = v > isoValue ? above : -above;
  1333     SdfValueT      mIsoValue;
  1334     SdfValueT      mAboveSign;
  1338 template <
typename SdfGr
idT, 
typename ExtValueT>
  1339 template <
typename MaskTreeT>
  1344       mSdfGrid(parent.mSdfGrid.get()) {}
  1345     MaskKernel(
const MaskKernel &parent) = 
default;
  1346     MaskKernel& 
operator=(
const MaskKernel&) = 
delete;
  1348     void run(
const MaskTreeT &mask)
  1350 #ifdef BENCHMARK_FAST_SWEEPING  1353         auto &lsTree = mSdfGrid->tree();
  1357 #ifdef BENCHMARK_FAST_SWEEPING  1358         timer.
restart(
"Changing background value");
  1362 #ifdef BENCHMARK_FAST_SWEEPING  1363         timer.
restart(
"Union with mask");
  1365         lsTree.topologyUnion(mask);
  1370 #ifdef BENCHMARK_FAST_SWEEPING  1371         timer.
restart(
"Initializing grid and sweep mask");
  1374         mParent->mSweepMask.clear();
  1375         mParent->mSweepMask.topologyUnion(mParent->mSdfGrid->constTree());
  1378         using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
  1379         LeafManagerT leafManager(mParent->mSweepMask);
  1381         auto kernel = [&](LeafT& leaf, 
size_t ) {
  1383             SdfAccT acc(mSdfGrid->tree());
  1386             SdfValueT *data = acc.
probeLeaf(leaf.origin())->buffer().data();
  1387             for (
auto voxelIter = leaf.beginValueOn(); voxelIter; ++voxelIter) {
  1388                 if (
math::Abs( data[voxelIter.pos()] ) < Unknown ) {
  1390                     voxelIter.setValue(
false);
  1394         leafManager.foreach( kernel );
  1397         mParent->computeSweepMaskLeafOrigins();
  1399 #ifdef BENCHMARK_FAST_SWEEPING  1410 template <
typename SdfGr
idT, 
typename ExtValueT>
  1418     template<
typename HashOp>
  1421 #ifdef BENCHMARK_FAST_SWEEPING  1426         const SweepMaskTreeT& maskTree = mParent->mSweepMask;
  1429         using LeafT = 
typename SweepMaskTreeT::LeafNodeType;
  1430         LeafManagerT leafManager(maskTree);
  1437         constexpr 
int maskOffset = LeafT::DIM * 3;
  1438         constexpr 
int maskRange = maskOffset * 2;
  1441         std::vector<int8_t> leafSliceMasks(leafManager.leafCount()*maskRange);
  1442         auto kernel1 = [&](
const LeafT& leaf, 
size_t leafIdx) {
  1443             const size_t leafOffset = leafIdx * maskRange;
  1444             for (
auto voxelIter = leaf.cbeginValueOn(); voxelIter; ++voxelIter) {
  1445                 const Coord ijk = LeafT::offsetToLocalCoord(voxelIter.pos());
  1446                 leafSliceMasks[leafOffset + 
hash(ijk) + maskOffset] = uint8_t(1);
  1449         leafManager.foreach( kernel1 );
  1454         using ThreadLocalMap = std::unordered_map<int64_t, std::deque<size_t>>;
  1455         tbb::enumerable_thread_specific<ThreadLocalMap> pool;
  1456         auto kernel2 = [&](
const LeafT& leaf, 
size_t leafIdx) {
  1457             ThreadLocalMap& map = pool.local();
  1458             const Coord& origin = leaf.origin();
  1459             const int64_t leafKey = 
hash(origin);
  1460             const size_t leafOffset = leafIdx * maskRange;
  1461             for (
int sliceIdx = 0; sliceIdx < maskRange; sliceIdx++) {
  1462                 if (leafSliceMasks[leafOffset + sliceIdx] == uint8_t(1)) {
  1463                     const int64_t voxelSliceKey = leafKey+sliceIdx-maskOffset;
  1464                     map[voxelSliceKey].emplace_back(leafIdx);
  1468         leafManager.foreach( kernel2 );
  1473         for (
auto poolIt = pool.begin(); poolIt != pool.end(); ++poolIt) {
  1474             const ThreadLocalMap& map = *poolIt;
  1475             for (
const auto& it : map) {
  1476                 for (
const size_t leafIdx : it.second) {
  1477                     mVoxelSliceMap[it.first].emplace_back(leafIdx, NodeMaskPtrT());
  1483         mVoxelSliceKeys.reserve(mVoxelSliceMap.size());
  1484         for (
const auto& it : mVoxelSliceMap) {
  1485             mVoxelSliceKeys.push_back(it.first);
  1489         auto kernel3 = [&](tbb::blocked_range<size_t>& range) {
  1490             for (
size_t i = range.begin(); i < range.end(); i++) {
  1491                 const int64_t key = mVoxelSliceKeys[i];
  1492                 for (
auto& it : mVoxelSliceMap[key]) {
  1493                     it.second = std::make_unique<NodeMaskT>();
  1497         tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceKeys.size()), kernel3);
  1504         auto kernel4 = [&](tbb::blocked_range<size_t>& range) {
  1505             for (
size_t i = range.begin(); i < range.end(); i++) {
  1506                 const int64_t voxelSliceKey = mVoxelSliceKeys[i];
  1507                 LeafSliceArray& leafSliceArray = mVoxelSliceMap[voxelSliceKey];
  1508                 for (LeafSlice& leafSlice : leafSliceArray) {
  1509                     const size_t leafIdx = leafSlice.first;
  1510                     NodeMaskPtrT& nodeMask = leafSlice.second;
  1511                     const LeafT& leaf = leafManager.leaf(leafIdx);
  1512                     const Coord& origin = leaf.origin();
  1513                     const int64_t leafKey = 
hash(origin);
  1514                     for (
auto voxelIter = leaf.cbeginValueOn(); voxelIter; ++voxelIter) {
  1515                         const Index voxelIdx = voxelIter.pos();
  1516                         const Coord ijk = LeafT::offsetToLocalCoord(voxelIdx);
  1517                         const int64_t key = leafKey + 
hash(ijk);
  1518                         if (key == voxelSliceKey) {
  1519                             nodeMask->setOn(voxelIdx);
  1525         tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceKeys.size()), kernel4);
  1532         inline static Coord 
ijk(
const Coord &p, 
int i) { 
return p + FastSweeping::mOffset[i]; }
  1534         NN(
const SdfAccT &a, 
const Coord &p, 
int i) : v(math::
Abs(a.getValue(ijk(p,i)))), n(i) {}
  1535         inline Coord 
operator()(
const Coord &p)
 const { 
return ijk(p, n); }
  1537         inline operator bool()
 const { 
return v < SdfValueT(1000); }
  1542     ExtT 
twoNghbr(
const NN& d1, 
const NN& d2, 
const SdfT& , 
const ExtT& v1, 
const ExtT& v2)
 const { 
return d1.
v < d2.
v ? v1 : v2; }
  1546     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)); }
  1550     ExtT 
threeNghbr(
const NN& d1, 
const NN& d2, 
const NN& d3, 
const SdfT& , 
const ExtT& v1, 
const ExtT& v2, 
const ExtT& v3)
 const {
  1558     ExtT 
threeNghbr(
const NN& d1, 
const NN& d2, 
const NN& d3, 
const SdfT& w, 
const ExtT& v1, 
const ExtT& v2, 
const ExtT& v3)
 const {
  1559         return ExtT(w*(d1.
v*v1 + d2.
v*v2 + d3.
v*v3));
  1564         typename ExtGridT::TreeType *tree2 = mParent->mExtGrid ? &mParent->mExtGrid->tree() : 
nullptr;
  1565         typename ExtGridT::TreeType *tree3 = mParent->mExtGridInput ? &mParent->mExtGridInput->tree() : 
nullptr;
  1567         const SdfValueT h = 
static_cast<SdfValueT
>(mParent->mSdfGrid->voxelSize()[0]);
  1568         const SdfValueT sqrt2h = 
math::Sqrt(SdfValueT(2))*h;
  1570         const bool isInputSdf = mParent->mIsInputSdf;
  1577         const std::vector<Coord>& leafNodeOrigins = mParent->mSweepMaskLeafOrigins;
  1579         int64_t voxelSliceIndex(0);
  1581         auto kernel = [&](
const tbb::blocked_range<size_t>& range) {
  1582             using LeafT = 
typename SdfGridT::TreeType::LeafNodeType;
  1584             SdfAccT acc1(mParent->mSdfGrid->tree());
  1585             auto acc2 = std::unique_ptr<ExtAccT>(tree2 ? 
new ExtAccT(*tree2) : 
nullptr);
  1586             auto acc3 = std::unique_ptr<ExtAccT>(tree3 ? 
new ExtAccT(*tree3) : 
nullptr);
  1587             SdfValueT absV, sign, update, D;
  1590             const LeafSliceArray& leafSliceArray = mVoxelSliceMap[voxelSliceIndex];
  1594             for (
size_t i = range.begin(); i < range.end(); ++i) {
  1599                 const LeafSlice& leafSlice = leafSliceArray[i];
  1600                 const size_t leafIdx = leafSlice.first;
  1601                 const NodeMaskPtrT& nodeMask = leafSlice.second;
  1603                 const Coord& origin = leafNodeOrigins[leafIdx];
  1606                 for (
auto indexIter = nodeMask->beginOn(); indexIter; ++indexIter) {
  1609                     ijk = origin + LeafT::offsetToLocalCoord(indexIter.pos());
  1616                     if (!(d1 || d2 || d3)) 
continue;
  1621                     SdfValueT &
value = 
const_cast<SdfValueT&
>(acc1.getValue(ijk));
  1624                     sign = value >= SdfValueT(0) ? SdfValueT(1) : SdfValueT(-1);
  1630                     if (d2 < d1) std::swap(d1, d2);
  1631                     if (d3 < d2) std::swap(d2, d3);
  1632                     if (d2 < d1) std::swap(d1, d2);
  1638                     if (update <= d2.
v) {
  1639                         if (update < absV) {
  1640                             value = sign * update;
  1643                                 ExtValueT updateExt = acc2->getValue(d1(ijk));
  1645                                     if (isInputSdf) updateExt = (value >= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
  1646                                     else updateExt = (value <= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
  1649                                     if (isInputSdf) updateExt = (value <= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
  1650                                     else updateExt = (value >= SdfValueT(0)) ? acc2->getValue(d1(ijk)) : acc3->getValue(ijk);
  1652                                 acc2->setValue(ijk, updateExt);
  1662                     if (d2.
v <= sqrt2h + d1.v) {
  1663                         D = SdfValueT(2) * h * h - 
math::Pow2(d1.v - d2.
v);
  1664                         update = SdfValueT(0.5) * (d1.v + d2.
v + std::sqrt(D));
  1665                         if (update > d2.
v && update <= d3.
v) {
  1666                             if (update < absV) {
  1667                                 value = sign * update;
  1672                                     const SdfValueT w = SdfValueT(1)/(d1.v+d2.
v);
  1673                                     const ExtValueT v1 = acc2->getValue(d1(ijk));
  1674                                     const ExtValueT v2 = acc2->getValue(d2(ijk));
  1675                                     const ExtValueT extVal = twoNghbr(d1, d2, w, v1, v2);
  1677                                     ExtValueT updateExt = extVal;
  1679                                         if (isInputSdf) updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1680                                         else updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1683                                         if (isInputSdf) updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1684                                         else updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1686                                     acc2->setValue(ijk, updateExt);
  1697                     const SdfValueT d123 = d1.v + d2.
v + d3.
v;
  1698                     D = d123*d123 - SdfValueT(3)*(d1.v*d1.v + d2.
v*d2.
v + d3.
v*d3.
v - h * h);
  1699                     if (D >= SdfValueT(0)) {
  1700                         update = SdfValueT(1.0/3.0) * (d123 + std::sqrt(D));
  1702                         if (update < absV) {
  1703                             value = sign * update;
  1709                                 const SdfValueT w = SdfValueT(1)/(d1.v+d2.
v+d3.
v);
  1710                                 const ExtValueT v1 = acc2->getValue(d1(ijk));
  1711                                 const ExtValueT v2 = acc2->getValue(d2(ijk));
  1712                                 const ExtValueT v3 = acc2->getValue(d3(ijk));
  1713                                 const ExtValueT extVal = threeNghbr(d1, d2, d3, w, v1, v2, v3);
  1715                                 ExtValueT updateExt = extVal;
  1717                                     if (isInputSdf) updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1718                                     else updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1721                                     if (isInputSdf) updateExt = (value <= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1722                                     else updateExt = (value >= SdfValueT(0)) ? extVal : acc3->getValue(ijk);
  1724                                 acc2->setValue(ijk, updateExt);
  1732 #ifdef BENCHMARK_FAST_SWEEPING  1736         for (
size_t i = 0; i < mVoxelSliceKeys.size(); i++) {
  1737             voxelSliceIndex = mVoxelSliceKeys[i];
  1738             tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceMap[voxelSliceIndex].size()), kernel);
  1741 #ifdef BENCHMARK_FAST_SWEEPING  1742         timer.
restart(
"Backward sweeps");
  1744         for (
size_t i = mVoxelSliceKeys.size(); i > 0; i--) {
  1745             voxelSliceIndex = mVoxelSliceKeys[i-1];
  1746             tbb::parallel_for(tbb::blocked_range<size_t>(0, mVoxelSliceMap[voxelSliceIndex].size()), kernel);
  1749 #ifdef BENCHMARK_FAST_SWEEPING  1755     using NodeMaskT = 
typename SweepMaskTreeT::LeafNodeType::NodeMaskType;
  1756     using NodeMaskPtrT = std::unique_ptr<NodeMaskT>;
  1759     using LeafSlice = std::pair<size_t, NodeMaskPtrT>;
  1760     using LeafSliceArray = std::deque<LeafSlice>;
  1761     using VoxelSliceMap = std::map<int64_t, LeafSliceArray>;
  1765     VoxelSliceMap mVoxelSliceMap;
  1766     std::vector<int64_t> mVoxelSliceKeys;
  1771 template<
typename Gr
idT>
  1774          typename GridT::ValueType isoValue,
  1778     if (fs.
initSdf(fogGrid, isoValue, 
false)) fs.
sweep(nIter);
  1782 template<
typename Gr
idT>
  1785          typename GridT::ValueType isoValue,
  1789     if (fs.
initSdf(sdfGrid, isoValue, 
true)) fs.
sweep(nIter);
  1793 template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
  1794 typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr
  1797          const ExtValueT& background,
  1798          typename FogGridT::ValueType isoValue,
  1801          const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr 
extGrid)
  1804   if (fs.
initExt(fogGrid, op, background, isoValue, 
false, mode, extGrid))
  1805       fs.
sweep(nIter, 
true);
  1809 template<
typename SdfGr
idT, 
typename OpT, 
typename ExtValueT>
  1810 typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr
  1813          const ExtValueT &background,
  1814          typename SdfGridT::ValueType isoValue,
  1817          const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr 
extGrid)
  1820   if (fs.
initExt(sdfGrid, op, background, isoValue, 
true, mode, extGrid))
  1821       fs.
sweep(nIter, 
true);
  1825 template<
typename FogGr
idT, 
typename ExtOpT, 
typename ExtValueT>
  1826 std::pair<typename FogGridT::Ptr, typename FogGridT::template ValueConverter<ExtValueT>::Type::Ptr>
  1829                const ExtValueT &background,
  1830                typename FogGridT::ValueType isoValue,
  1833                const typename FogGridT::template ValueConverter<ExtValueT>::Type::ConstPtr 
extGrid)
  1836   if (fs.
initExt(fogGrid, op, background, isoValue, 
false, mode, extGrid))
  1837       fs.
sweep(nIter, 
true);
  1841 template<
typename SdfGr
idT, 
typename ExtOpT, 
typename ExtValueT>
  1842 std::pair<typename SdfGridT::Ptr, typename SdfGridT::template ValueConverter<ExtValueT>::Type::Ptr>
  1845                const ExtValueT &background,
  1846                typename SdfGridT::ValueType isoValue,
  1849                const typename SdfGridT::template ValueConverter<ExtValueT>::Type::ConstPtr 
extGrid)
  1852   if (fs.
initExt(sdfGrid, op, background, isoValue, 
true, mode, extGrid))
  1853       fs.
sweep(nIter, 
true);
  1857 template<
typename Gr
idT>
  1870 template<
typename Gr
idT, 
typename MaskTreeT>
  1874         bool ignoreActiveTiles,
  1878     if (fs.
initMask(sdfGrid, mask, ignoreActiveTiles)) fs.
sweep(nIter);
  1888 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION  1890 #ifdef OPENVDB_INSTANTIATE_FASTSWEEPING  1894 #define _FUNCTION(TreeT) \  1895     Grid<TreeT>::Ptr fogToSdf(const Grid<TreeT>&, TreeT::ValueType, int)  1899 #define _FUNCTION(TreeT) \  1900     Grid<TreeT>::Ptr sdfToSdf(const Grid<TreeT>&, TreeT::ValueType, int)  1904 #define _FUNCTION(TreeT) \  1905     Grid<TreeT>::Ptr dilateSdf(const Grid<TreeT>&, int, NearestNeighbors, int, FastSweepingDomain)  1909 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION  1916 #endif // OPENVDB_TOOLS_FASTSWEEPING_HAS_BEEN_INCLUDED 
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:379
SharedPtr< Grid > Ptr
Definition: Grid.h:579
LeafRange leafRange(size_t grainsize=1) const 
Return a TBB-compatible LeafRange. 
Definition: LeafManager.h:345
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Templated class to compute the minimum and maximum values. 
Definition: Stats.h:30
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
size_t MinIndex(const Vec3T &v)
Return the index [0,1,2] of the smallest value in a 3D vector. 
Definition: Math.h:938
Functions to efficiently compute histograms, extrema (min/max) and statistics (mean, variance, etc.) of grid values. 
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:350
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:359
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive. 
Definition: ValueAccessor.h:266
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors. 
Definition: Types.h:644
Definition: LeafManager.h:101
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids. 
Definition: Grid.h:917
float Sqrt(float x)
Return the square root of a floating-point value. 
Definition: Math.h:764
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays, one for each level of the tree. 
Definition: NodeManager.h:30
Implementation of morphological dilation and erosion. 
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
Definition: Exceptions.h:63
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Index32 Index
Definition: Types.h:54
__hostdev__ uint32_t hash(uint32_t x)
Definition: common.h:13
Container class that associates a tree with a transform and metadata. 
Definition: Grid.h:28
double restart()
Re-start timer. 
Definition: CpuTimer.h:150
GridClass getGridClass() const 
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid...
double stop() const 
Returns and prints time in milliseconds since construction or start was called. 
Definition: CpuTimer.h:128
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. 
Miscellaneous utility methods that operate primarily or exclusively on level set grids. 
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)      
Definition: version.h.in:147
Definition: Stencils.h:1231
Coord Abs(const Coord &xyz)
Definition: Coord.h:514
Type Pow2(Type x)
Return x2. 
Definition: Math.h:551
Simple timer for basic profiling. 
Definition: CpuTimer.h:66
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
const ValueType & getValue(unsigned int pos=0) const
Return the value from the stencil buffer with linear offset pos. 
Definition: Stencils.h:97
Definition: ValueAccessor.h:182
#define OPENVDB_VERSION_NAME
The version namespace name for this library version. 
Definition: version.h.in:116
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids. 
Definition: Grid.h:415
void moveTo(const Coord &ijk)
Initialize the stencil buffer with the values of voxel (i, j, k) and its neighbors. 
Definition: Stencils.h:47
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202