OpenVDB: ParticlesToLevelSet.h Source File

OpenVDB 6.1.0

ParticlesToLevelSet.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30
88
89 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
90 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
91
92 #include <tbb/parallel_reduce.h>
93 #include <tbb/blocked_range.h>
94 #include <openvdb/Types.h>
95 #include <openvdb/Grid.h>
96 #include <openvdb/math/Math.h>
97 #include <openvdb/math/Transform.h>
98 #include <openvdb/tree/LeafManager.h>
99 #include <openvdb/util/logging.h>
100 #include <openvdb/util/NullInterrupter.h>
101 #include "Composite.h" // for csgUnion()
102 #include "PointPartitioner.h"
103 #include "Prune.h"
104 #include "SignedFloodFill.h"
105 #include <functional>
106 #include <iostream>
107 #include <type_traits>
108 #include <vector>
109
110
111 namespace openvdb {
112 OPENVDB_USE_VERSION_NAMESPACE
113 namespace OPENVDB_VERSION_NAME {
114 namespace tools {
115
120 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
121 inline void particlesToSdf(const ParticleListT&, GridT&, InterrupterT* = nullptr);
122
127 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
128 inline void particlesToSdf(const ParticleListT&, GridT&, Real radius, InterrupterT* = nullptr);
129
137 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
138 inline void particleTrailsToSdf(const ParticleListT&, GridT&, Real delta=1, InterrupterT* =nullptr);
139
144 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
145 inline void particlesToMask(const ParticleListT&, GridT&, InterrupterT* = nullptr);
146
151 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
152 inline void particlesToMask(const ParticleListT&, GridT&, Real radius, InterrupterT* = nullptr);
153
161 template<typename GridT, typename ParticleListT, typename InterrupterT = util::NullInterrupter>
162 inline void particleTrailsToMask(const ParticleListT&, GridT&,Real delta=1,InterrupterT* =nullptr);
163
164
166
167
168 namespace p2ls_internal {
169 // This is a simple type that combines a distance value and a particle
170 // attribute. It's required for attribute transfer which is performed
171 // in the ParticlesToLevelSet::Raster member class defined below.
173 template<typename VisibleT, typename BlindT> class BlindData;
174 }
175
176
177 template<typename SdfGridT,
178 typename AttributeT = void,
179 typename InterrupterT = util::NullInterrupter>
180 class ParticlesToLevelSet
181 {
182 public:
183 using DisableT = typename std::is_void<AttributeT>::type;
184 using InterrupterType = InterrupterT;
185
186 using SdfGridType = SdfGridT;
187 using SdfType = typename SdfGridT::ValueType;
188
189 using AttType = typename std::conditional<DisableT::value, size_t, AttributeT>::type;
190 using AttGridType = typename SdfGridT::template ValueConverter<AttType>::Type;
191
192 static const bool OutputIsMask = std::is_same<SdfType, bool>::value;
193
212 explicit ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupt = nullptr);
213
214 ~ParticlesToLevelSet() { delete mBlindGrid; }
215
224 void finalize(bool prune = false);
225
229 typename AttGridType::Ptr attributeGrid() { return mAttGrid; }
230
232 Real getVoxelSize() const { return mDx; }
233
235 Real getHalfWidth() const { return mHalfWidth; }
236
238 Real getRmin() const { return mRmin; }
240 void setRmin(Real Rmin) { mRmin = math::Max(Real(0),Rmin); }
241
243 Real getRmax() const { return mRmax; }
245 void setRmax(Real Rmax) { mRmax = math::Max(mRmin,Rmax); }
246
248 bool ignoredParticles() const { return mMinCount>0 || mMaxCount>0; }
251 size_t getMinCount() const { return mMinCount; }
254 size_t getMaxCount() const { return mMaxCount; }
255
257 int getGrainSize() const { return mGrainSize; }
260 void setGrainSize(int grainSize) { mGrainSize = grainSize; }
261
264 template<typename ParticleListT>
265 void rasterizeSpheres(const ParticleListT& pa);
266
273 template<typename ParticleListT>
274 void rasterizeSpheres(const ParticleListT& pa, Real radius);
275
291 template<typename ParticleListT>
292 void rasterizeTrails(const ParticleListT& pa, Real delta=1.0);
293
294 private:
295 using BlindType = p2ls_internal::BlindData<SdfType, AttType>;
296 using BlindGridType = typename SdfGridT::template ValueConverter<BlindType>::Type;
297
299 template<typename ParticleListT, typename GridT> struct Raster;
300
301 SdfGridType* mSdfGrid;
302 typename AttGridType::Ptr mAttGrid;
303 BlindGridType* mBlindGrid;
304 InterrupterT* mInterrupter;
305 Real mDx, mHalfWidth;
306 Real mRmin, mRmax; // ignore particles outside this range of radii in voxel
307 size_t mMinCount, mMaxCount; // counters for ignored particles
308 int mGrainSize;
309 }; // class ParticlesToLevelSet
310
311
312 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
313 inline ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
314 ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupter) :
315 mSdfGrid(&grid),
316 mBlindGrid(nullptr),
317 mInterrupter(interrupter),
318 mDx(grid.voxelSize()[0]),
319 mHalfWidth(grid.background()/mDx),
320 mRmin(1.5),// corresponds to the Nyquist grid sampling frequency
321 mRmax(100.0),// corresponds to a huge particle (probably too large!)
322 mMinCount(0),
323 mMaxCount(0),
324 mGrainSize(1)
325 {
326 if (!mSdfGrid->hasUniformVoxels()) {
327 OPENVDB_THROW(RuntimeError, "ParticlesToLevelSet only supports uniform voxels!");
328 }
329 if (!DisableT::value) {
330 mBlindGrid = new BlindGridType(BlindType(grid.background()));
331 mBlindGrid->setTransform(mSdfGrid->transform().copy());
332 }
333 }
334
335 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
336 template<typename ParticleListT>
337 inline void ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
338 rasterizeSpheres(const ParticleListT& pa)
339 {
340 if (DisableT::value) {
341 Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
342 r.rasterizeSpheres();
343 } else {
344 Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
345 r.rasterizeSpheres();
346 }
347 }
348
349 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
350 template<typename ParticleListT>
351 inline void ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
352 rasterizeSpheres(const ParticleListT& pa, Real radius)
353 {
354 if (DisableT::value) {
355 Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
356 r.rasterizeSpheres(radius/mDx);
357 } else {
358 Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
359 r.rasterizeSpheres(radius/mDx);
360 }
361 }
362
363 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
364 template<typename ParticleListT>
365 inline void ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
366 rasterizeTrails(const ParticleListT& pa, Real delta)
367 {
368 if (DisableT::value) {
369 Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
370 r.rasterizeTrails(delta);
371 } else {
372 Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
373 r.rasterizeTrails(delta);
374 }
375 }
376
377
378 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
379 inline void
380 ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::finalize(bool prune)
381 {
382 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
383
384 if (!mBlindGrid) {
385 if (prune) {
386 if (OutputIsMask) {
387 tools::prune(mSdfGrid->tree());
388 } else {
389 tools::pruneLevelSet(mSdfGrid->tree());
390 }
391 }
392 return;
393 }
394
395 if (prune) tools::prune(mBlindGrid->tree());
396
397 using AttTreeT = typename AttGridType::TreeType;
398 using AttLeafT = typename AttTreeT::LeafNodeType;
399 using BlindTreeT = typename BlindGridType::TreeType;
400 using BlindLeafIterT = typename BlindTreeT::LeafCIter;
401 using BlindLeafT = typename BlindTreeT::LeafNodeType;
402 using SdfTreeT = typename SdfGridType::TreeType;
403 using SdfLeafT = typename SdfTreeT::LeafNodeType;
404
405 // Use topology copy constructors since output grids have the same topology as mBlindDataGrid
406 const BlindTreeT& blindTree = mBlindGrid->tree();
407
408 // Create the output attribute grid.
409 typename AttTreeT::Ptr attTree(new AttTreeT(
410 blindTree, blindTree.background().blind(), openvdb::TopologyCopy()));
411 // Note this overwrites any existing attribute grids!
412 mAttGrid = typename AttGridType::Ptr(new AttGridType(attTree));
413 mAttGrid->setTransform(mBlindGrid->transform().copy());
414
415 typename SdfTreeT::Ptr sdfTree; // the output mask or level set tree
416
417 // Extract the attribute grid and the mask or level set grid from mBlindDataGrid.
418 if (OutputIsMask) {
419 sdfTree.reset(new SdfTreeT(blindTree,
420 /*off=*/SdfType(0), /*on=*/SdfType(1), TopologyCopy()));
421
422 // Copy leaf voxels in parallel.
423 tree::LeafManager<AttTreeT> leafNodes(*attTree);
424 leafNodes.foreach([&](AttLeafT& attLeaf, size_t /*leafIndex*/) {
425 if (const auto* blindLeaf = blindTree.probeConstLeaf(attLeaf.origin())) {
426 for (auto iter = attLeaf.beginValueOn(); iter; ++iter) {
427 const auto pos = iter.pos();
428 attLeaf.setValueOnly(pos, blindLeaf->getValue(pos).blind());
429 }
430 }
431 });
432 // Copy tiles serially.
433 const auto blindAcc = mBlindGrid->getConstAccessor();
434 auto iter = attTree->beginValueOn();
435 iter.setMaxDepth(AttTreeT::ValueOnIter::LEAF_DEPTH - 1);
436 for ( ; iter; ++iter) {
437 iter.modifyValue([&](AttType& v) { v = blindAcc.getValue(iter.getCoord()).blind(); });
438 }
439 } else {
440 // Here we exploit the fact that by design level sets have no active tiles.
441 // Only leaf voxels can be active.
442 sdfTree.reset(new SdfTreeT(blindTree, blindTree.background().visible(), TopologyCopy()));
443 for (BlindLeafIterT n = blindTree.cbeginLeaf(); n; ++n) {
444 const BlindLeafT& leaf = *n;
445 const openvdb::Coord xyz = leaf.origin();
446 // Get leafnodes that were allocated during topology construction!
447 SdfLeafT* sdfLeaf = sdfTree->probeLeaf(xyz);
448 AttLeafT* attLeaf = attTree->probeLeaf(xyz);
449 // Use linear offset (vs coordinate) access for better performance!
450 typename BlindLeafT::ValueOnCIter m=leaf.cbeginValueOn();
451 if (!m) {//no active values in leaf node so copy everything
452 for (openvdb::Index k = 0; k!=BlindLeafT::SIZE; ++k) {
453 const BlindType& v = leaf.getValue(k);
454 sdfLeaf->setValueOnly(k, v.visible());
455 attLeaf->setValueOnly(k, v.blind());
456 }
457 } else {//only copy active values (using flood fill for the inactive values)
458 for(; m; ++m) {
459 const openvdb::Index k = m.pos();
460 const BlindType& v = *m;
461 sdfLeaf->setValueOnly(k, v.visible());
462 attLeaf->setValueOnly(k, v.blind());
463 }
464 }
465 }
466 tools::signedFloodFill(*sdfTree);//required since we only transferred active voxels!
467 }
468
469 if (mSdfGrid->empty()) {
470 mSdfGrid->setTree(sdfTree);
471 } else {
472 if (OutputIsMask) {
473 mSdfGrid->tree().topologyUnion(*sdfTree);
474 tools::prune(mSdfGrid->tree());
475 } else {
476 tools::csgUnion(mSdfGrid->tree(), *sdfTree, /*prune=*/true);
477 }
478 }
479
480 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
481 }
482
483
485
486
487 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
488 template<typename ParticleListT, typename GridT>
489 struct ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::Raster
490 {
491 using DisableT = typename std::is_void<AttributeT>::type;
492 using ParticlesToLevelSetT = ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>;
493 using SdfT = typename ParticlesToLevelSetT::SdfType; // type of signed distance values
494 using AttT = typename ParticlesToLevelSetT::AttType; // type of particle attribute
495 using ValueT = typename GridT::ValueType;
496 using AccessorT = typename GridT::Accessor;
497 using TreeT = typename GridT::TreeType;
498 using LeafNodeT = typename TreeT::LeafNodeType;
499 using PointPartitionerT = PointPartitioner<Index32, LeafNodeT::LOG2DIM>;
500
501 static const bool
502 OutputIsMask = std::is_same<SdfT, bool>::value,
503 DoAttrXfer = !DisableT::value;
504
506 Raster(ParticlesToLevelSetT& parent, GridT* grid, const ParticleListT& particles)
507 : mParent(parent)
508 , mParticles(particles)
509 , mGrid(grid)
510 , mMap(*(mGrid->transform().baseMap()))
511 , mMinCount(0)
512 , mMaxCount(0)
513 , mIsCopy(false)
514 {
515 mPointPartitioner = new PointPartitionerT;
516 mPointPartitioner->construct(particles, mGrid->transform());
517 }
518
520 Raster(Raster& other, tbb::split)
521 : mParent(other.mParent)
522 , mParticles(other.mParticles)
523 , mGrid(new GridT(*other.mGrid, openvdb::ShallowCopy()))
524 , mMap(other.mMap)
525 , mMinCount(0)
526 , mMaxCount(0)
527 , mTask(other.mTask)
528 , mIsCopy(true)
529 , mPointPartitioner(other.mPointPartitioner)
530 {
531 mGrid->newTree();
532 }
533
534 virtual ~Raster()
535 {
536 // Copy-constructed Rasters own temporary grids that have to be deleted,
537 // while the original has ownership of the bucket array.
538 if (mIsCopy) {
539 delete mGrid;
540 } else {
541 delete mPointPartitioner;
542 }
543 }
544
545 void rasterizeSpheres()
546 {
547 mMinCount = mMaxCount = 0;
548 if (mParent.mInterrupter) {
549 mParent.mInterrupter->start("Rasterizing particles to level set using spheres");
550 }
551 mTask = std::bind(&Raster::rasterSpheres, std::placeholders::_1, std::placeholders::_2);
552 this->cook();
553 if (mParent.mInterrupter) mParent.mInterrupter->end();
554 }
555
556 void rasterizeSpheres(Real radius)
557 {
558 mMinCount = radius < mParent.mRmin ? mParticles.size() : 0;
559 mMaxCount = radius > mParent.mRmax ? mParticles.size() : 0;
560 if (mMinCount>0 || mMaxCount>0) {//skipping all particles!
561 mParent.mMinCount = mMinCount;
562 mParent.mMaxCount = mMaxCount;
563 } else {
564 if (mParent.mInterrupter) {
565 mParent.mInterrupter->start(
566 "Rasterizing particles to level set using const spheres");
567 }
568 mTask = std::bind(&Raster::rasterFixedSpheres,
569 std::placeholders::_1, std::placeholders::_2, radius);
570 this->cook();
571 if (mParent.mInterrupter) mParent.mInterrupter->end();
572 }
573 }
574
575 void rasterizeTrails(Real delta=1.0)
576 {
577 mMinCount = mMaxCount = 0;
578 if (mParent.mInterrupter) {
579 mParent.mInterrupter->start("Rasterizing particles to level set using trails");
580 }
581 mTask = std::bind(&Raster::rasterTrails,
582 std::placeholders::_1, std::placeholders::_2, delta);
583 this->cook();
584 if (mParent.mInterrupter) mParent.mInterrupter->end();
585 }
586
588 void operator()(const tbb::blocked_range<size_t>& r)
589 {
590 assert(mTask);
591 mTask(this, r);
592 mParent.mMinCount = mMinCount;
593 mParent.mMaxCount = mMaxCount;
594 }
595
597 void join(Raster& other)
598 {
599 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
600 if (OutputIsMask) {
601 if (DoAttrXfer) {
602 tools::compMax(*mGrid, *other.mGrid);
603 } else {
604 mGrid->topologyUnion(*other.mGrid);
605 }
606 } else {
607 tools::csgUnion(*mGrid, *other.mGrid, /*prune=*/true);
608 }
609 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
610 mMinCount += other.mMinCount;
611 mMaxCount += other.mMaxCount;
612 }
613
614 private:
616 Raster& operator=(const Raster&) { return *this; }
617
619 bool ignoreParticle(Real R)
620 {
621 if (R < mParent.mRmin) {// below the cutoff radius
622 ++mMinCount;
623 return true;
624 }
625 if (R > mParent.mRmax) {// above the cutoff radius
626 ++mMaxCount;
627 return true;
628 }
629 return false;
630 }
631
634 void rasterSpheres(const tbb::blocked_range<size_t>& r)
635 {
636 AccessorT acc = mGrid->getAccessor(); // local accessor
637 bool run = true;
638 const Real invDx = 1 / mParent.mDx;
639 AttT att;
640 Vec3R pos;
641 Real rad;
642
643 // Loop over buckets
644 for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
645 // Loop over particles in bucket n.
646 typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
647 for ( ; run && iter; ++iter) {
648 const Index32& id = *iter;
649 mParticles.getPosRad(id, pos, rad);
650 const Real R = invDx * rad;// in voxel units
651 if (this->ignoreParticle(R)) continue;
652 const Vec3R P = mMap.applyInverseMap(pos);
653 this->getAtt<DisableT>(id, att);
654 run = this->makeSphere(P, R, att, acc);
655 }//end loop over particles
656 }//end loop over buckets
657 }
658
662 void rasterFixedSpheres(const tbb::blocked_range<size_t>& r, Real R)
663 {
664 AccessorT acc = mGrid->getAccessor(); // local accessor
665 AttT att;
666 Vec3R pos;
667
668 // Loop over buckets
669 for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
670 // Loop over particles in bucket n.
671 for (auto iter = mPointPartitioner->indices(n); iter; ++iter) {
672 const Index32& id = *iter;
673 this->getAtt<DisableT>(id, att);
674 mParticles.getPos(id, pos);
675 const Vec3R P = mMap.applyInverseMap(pos);
676 this->makeSphere(P, R, att, acc);
677 }
678 }
679 }
680
684 void rasterTrails(const tbb::blocked_range<size_t>& r, Real delta)
685 {
686 AccessorT acc = mGrid->getAccessor(); // local accessor
687 bool run = true;
688 AttT att;
689 Vec3R pos, vel;
690 Real rad;
691 const Vec3R origin = mMap.applyInverseMap(Vec3R(0,0,0));
692 const Real Rmin = mParent.mRmin, invDx = 1 / mParent.mDx;
693
694 // Loop over buckets
695 for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
696 // Loop over particles in bucket n.
697 typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
698 for ( ; run && iter; ++iter) {
699 const Index32& id = *iter;
700 mParticles.getPosRadVel(id, pos, rad, vel);
701 const Real R0 = invDx * rad;
702 if (this->ignoreParticle(R0)) continue;
703 this->getAtt<DisableT>(id, att);
704 const Vec3R P0 = mMap.applyInverseMap(pos);
705 const Vec3R V = mMap.applyInverseMap(vel) - origin; // exclude translation
706 const Real speed = V.length(), invSpeed = 1.0 / speed;
707 const Vec3R Nrml = -V * invSpeed; // inverse normalized direction
708 Vec3R P = P0; // local position of instance
709 Real R = R0, d = 0; // local radius and length of trail
710 for (size_t m = 0; run && d <= speed ; ++m) {
711 run = this->makeSphere(P, R, att, acc);
712 P += 0.5 * delta * R * Nrml; // adaptive offset along inverse velocity direction
713 d = (P - P0).length(); // current length of trail
714 R = R0 - (R0 - Rmin) * d * invSpeed; // R = R0 -> mRmin(e.g. 1.5)
715 }//end loop over sphere instances
716 }//end loop over particles
717 }//end loop over buckets
718 }
719
720 void cook()
721 {
722 // parallelize over the point buckets
723 const Index32 bucketCount = Index32(mPointPartitioner->size());
724
725 if (mParent.mGrainSize>0) {
726 tbb::parallel_reduce(
727 tbb::blocked_range<size_t>(0, bucketCount, mParent.mGrainSize), *this);
728 } else {
729 (*this)(tbb::blocked_range<size_t>(0, bucketCount));
730 }
731 }
732
740 bool makeSphere(const Vec3R& P, Real R, const AttT& att, AccessorT& acc)
741 {
742 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
743 if (OutputIsMask) {
744 return makeSphereMask(P, R, att, acc);
745 } else {
746 return makeNarrowBandSphere(P, R, att, acc);
747 }
748 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
749 }
750
765 bool makeNarrowBandSphere(const Vec3R& P, Real R, const AttT& att, AccessorT& acc)
766 {
767 const Real
768 dx = mParent.mDx,
769 w = mParent.mHalfWidth,
770 max = R + w, // maximum distance in voxel units
771 max2 = math::Pow2(max), // square of maximum distance in voxel units
772 min2 = math::Pow2(math::Max(Real(0), R - w)); // square of minimum distance
773 // Bounding box of the sphere
774 const Coord
775 lo(math::Floor(P[0]-max),math::Floor(P[1]-max),math::Floor(P[2]-max)),
776 hi(math::Ceil( P[0]+max),math::Ceil( P[1]+max),math::Ceil( P[2]+max));
777 const ValueT inside = -mGrid->background();
778
779 ValueT v;
780 size_t count = 0;
781 for (Coord c = lo; c.x() <= hi.x(); ++c.x()) {
782 //only check interrupter every 32'th scan in x
783 if (!(count++ & ((1<<5)-1)) && util::wasInterrupted(mParent.mInterrupter)) {
784 tbb::task::self().cancel_group_execution();
785 return false;
786 }
787 const Real x2 = math::Pow2(c.x() - P[0]);
788 for (c.y() = lo.y(); c.y() <= hi.y(); ++c.y()) {
789 const Real x2y2 = x2 + math::Pow2(c.y() - P[1]);
790 for (c.z() = lo.z(); c.z() <= hi.z(); ++c.z()) {
791 const Real x2y2z2 = x2y2 + math::Pow2(c.z()-P[2]); // squared dist from c to P
792 #if defined __INTEL_COMPILER
793 _Pragma("warning (push)")
794 _Pragma("warning (disable:186)") // "pointless comparison of unsigned integer with zero"
795 #endif
796 if (x2y2z2 >= max2 || (!acc.probeValue(c, v) && (v < ValueT(0))))
797 continue;//outside narrow band of the particle or inside existing level set
798 #if defined __INTEL_COMPILER
799 _Pragma("warning (pop)")
800 #endif
801 if (x2y2z2 <= min2) {//inside narrow band of the particle.
802 acc.setValueOff(c, inside);
803 continue;
804 }
805 // convert signed distance from voxel units to world units
806 //const ValueT d=dx*(math::Sqrt(x2y2z2) - R);
807 const ValueT d = Merge(static_cast<SdfT>(dx*(math::Sqrt(x2y2z2)-R)), att);
808 if (d < v) acc.setValue(c, d);//CSG union
809 }//end loop over z
810 }//end loop over y
811 }//end loop over x
812 return true;
813 }
814
817 bool makeSphereMask(const Vec3R& p, Real r, const AttT& att, AccessorT& acc)
818 {
819 const Real
820 rSquared = r * r, // sphere radius squared, in voxel units
821 inW = r / math::Sqrt(6.0); // half the width in voxel units of an inscribed cube
822 const Coord
823 // Bounding box of the sphere
824 outLo(math::Floor(p[0] - r), math::Floor(p[1] - r), math::Floor(p[2] - r)),
825 outHi(math::Ceil(p[0] + r), math::Ceil(p[1] + r), math::Ceil(p[2] + r)),
826 // Bounds of the inscribed cube
827 inLo(math::Ceil(p[0] - inW), math::Ceil(p[1] - inW), math::Ceil(p[2] - inW)),
828 inHi(math::Floor(p[0] + inW), math::Floor(p[1] + inW), math::Floor(p[2] + inW));
829 // Bounding boxes of regions comprising out - in
831 const std::vector<CoordBBox> padding{
832 CoordBBox(outLo.x(), outLo.y(), outLo.z(), inLo.x()-1, outHi.y(), outHi.z()),
833 CoordBBox(inHi.x()+1, outLo.y(), outLo.z(), outHi.x(), outHi.y(), outHi.z()),
834 CoordBBox(outLo.x(), outLo.y(), outLo.z(), outHi.x(), inLo.y()-1, outHi.z()),
835 CoordBBox(outLo.x(), inHi.y()+1, outLo.z(), outHi.x(), outHi.y(), outHi.z()),
836 CoordBBox(outLo.x(), outLo.y(), outLo.z(), outHi.x(), outHi.y(), inLo.z()-1),
837 CoordBBox(outLo.x(), outLo.y(), inHi.z()+1, outHi.x(), outHi.y(), outHi.z()),
838 };
839 const ValueT onValue = Merge(SdfT(1), att);
840
841 // Sparsely fill the inscribed cube.
843 acc.tree().sparseFill(CoordBBox(inLo, inHi), onValue);
844
845 // Densely fill the remaining regions.
846 for (const auto& bbox: padding) {
847 if (util::wasInterrupted(mParent.mInterrupter)) {
848 tbb::task::self().cancel_group_execution();
849 return false;
850 }
851 const Coord &bmin = bbox.min(), &bmax = bbox.max();
852 Coord c;
853 Real cx, cy, cz;
854 for (c = bmin, cx = c.x(); c.x() <= bmax.x(); ++c.x(), cx += 1) {
855 const Real x2 = math::Pow2(cx - p[0]);
856 for (c.y() = bmin.y(), cy = c.y(); c.y() <= bmax.y(); ++c.y(), cy += 1) {
857 const Real x2y2 = x2 + math::Pow2(cy - p[1]);
858 for (c.z() = bmin.z(), cz = c.z(); c.z() <= bmax.z(); ++c.z(), cz += 1) {
859 const Real x2y2z2 = x2y2 + math::Pow2(cz - p[2]);
860 if (x2y2z2 < rSquared) {
861 acc.setValue(c, onValue);
862 }
863 }
864 }
865 }
866 }
867 return true;
868 }
869
870 using FuncType = typename std::function<void (Raster*, const tbb::blocked_range<size_t>&)>;
871
872 template<typename DisableType>
873 typename std::enable_if<DisableType::value>::type
874 getAtt(size_t, AttT&) const {}
875
876 template<typename DisableType>
877 typename std::enable_if<!DisableType::value>::type
878 getAtt(size_t n, AttT& a) const { mParticles.getAtt(n, a); }
879
880 template<typename T>
881 typename std::enable_if<std::is_same<T, ValueT>::value, ValueT>::type
882 Merge(T s, const AttT&) const { return s; }
883
884 template<typename T>
885 typename std::enable_if<!std::is_same<T, ValueT>::value, ValueT>::type
886 Merge(T s, const AttT& a) const { return ValueT(s,a); }
887
888 ParticlesToLevelSetT& mParent;
889 const ParticleListT& mParticles;//list of particles
890 GridT* mGrid;
891 const math::MapBase& mMap;
892 size_t mMinCount, mMaxCount;//counters for ignored particles!
893 FuncType mTask;
894 const bool mIsCopy;
895 PointPartitionerT* mPointPartitioner;
896 }; // struct ParticlesToLevelSet::Raster
897
898
900
901
902 namespace p2ls_internal {
903
904 // This is a simple type that combines a distance value and a particle
905 // attribute. It's required for attribute transfer which is defined in the
906 // Raster class above.
908 template<typename VisibleT, typename BlindT>
909 class BlindData
910 {
911 public:
912 using type = VisibleT;
913 using VisibleType = VisibleT;
914 using BlindType = BlindT;
915
916 BlindData() {}
917 explicit BlindData(VisibleT v) : mVisible(v), mBlind(zeroVal<BlindType>()) {}
918 BlindData(VisibleT v, BlindT b) : mVisible(v), mBlind(b) {}
919 BlindData(const BlindData&) = default;
920 BlindData& operator=(const BlindData&) = default;
921 const VisibleT& visible() const { return mVisible; }
922 const BlindT& blind() const { return mBlind; }
923 OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
924 bool operator==(const BlindData& rhs) const { return mVisible == rhs.mVisible; }
925 OPENVDB_NO_FP_EQUALITY_WARNING_END
926 bool operator< (const BlindData& rhs) const { return mVisible < rhs.mVisible; }
927 bool operator> (const BlindData& rhs) const { return mVisible > rhs.mVisible; }
928 BlindData operator+(const BlindData& rhs) const { return BlindData(mVisible + rhs.mVisible); }
929 BlindData operator-(const BlindData& rhs) const { return BlindData(mVisible - rhs.mVisible); }
930 BlindData operator-() const { return BlindData(-mVisible, mBlind); }
931
932 protected:
933 VisibleT mVisible;
934 BlindT mBlind;
935 };
936
938 // Required by several of the tree nodes
939 template<typename VisibleT, typename BlindT>
940 inline std::ostream& operator<<(std::ostream& ostr, const BlindData<VisibleT, BlindT>& rhs)
941 {
942 ostr << rhs.visible();
943 return ostr;
944 }
945
947 // Required by math::Abs
948 template<typename VisibleT, typename BlindT>
949 inline BlindData<VisibleT, BlindT> Abs(const BlindData<VisibleT, BlindT>& x)
950 {
951 return BlindData<VisibleT, BlindT>(math::Abs(x.visible()), x.blind());
952 }
953
955 // Required to support the (zeroVal<BlindData>() + val) idiom.
956 template<typename VisibleT, typename BlindT, typename T>
957 inline BlindData<VisibleT, BlindT>
958 operator+(const BlindData<VisibleT, BlindT>& x, const T& rhs)
959 {
960 return BlindData<VisibleT, BlindT>(x.visible() + static_cast<VisibleT>(rhs), x.blind());
961 }
962
963 } // namespace p2ls_internal
964
965
967
968
969 // The following are convenience functions for common use cases.
970
971 template<typename GridT, typename ParticleListT, typename InterrupterT>
972 inline void
973 particlesToSdf(const ParticleListT& plist, GridT& grid, InterrupterT* interrupt)
974 {
975 static_assert(std::is_floating_point<typename GridT::ValueType>::value,
976 "particlesToSdf requires an SDF grid with floating-point values");
977
978 if (grid.getGridClass() != GRID_LEVEL_SET) {
979 OPENVDB_LOG_WARN("particlesToSdf requires a level set grid;"
980 " try Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
981 }
982
983 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
984 p2ls.rasterizeSpheres(plist);
985 tools::pruneLevelSet(grid.tree());
986 }
987
988 template<typename GridT, typename ParticleListT, typename InterrupterT>
989 inline void
990 particlesToSdf(const ParticleListT& plist, GridT& grid, Real radius, InterrupterT* interrupt)
991 {
992 static_assert(std::is_floating_point<typename GridT::ValueType>::value,
993 "particlesToSdf requires an SDF grid with floating-point values");
994
995 if (grid.getGridClass() != GRID_LEVEL_SET) {
996 OPENVDB_LOG_WARN("particlesToSdf requires a level set grid;"
997 " try Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
998 }
999
1000 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
1001 p2ls.rasterizeSpheres(plist, radius);
1002 tools::pruneLevelSet(grid.tree());
1003 }
1004
1005 template<typename GridT, typename ParticleListT, typename InterrupterT>
1006 inline void
1007 particleTrailsToSdf(const ParticleListT& plist, GridT& grid, Real delta, InterrupterT* interrupt)
1008 {
1009 static_assert(std::is_floating_point<typename GridT::ValueType>::value,
1010 "particleTrailsToSdf requires an SDF grid with floating-point values");
1011
1012 if (grid.getGridClass() != GRID_LEVEL_SET) {
1013 OPENVDB_LOG_WARN("particlesToSdf requires a level set grid;"
1014 " try Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
1015 }
1016
1017 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
1018 p2ls.rasterizeTrails(plist, delta);
1019 tools::pruneLevelSet(grid.tree());
1020 }
1021
1022 template<typename GridT, typename ParticleListT, typename InterrupterT>
1023 inline void
1024 particlesToMask(const ParticleListT& plist, GridT& grid, InterrupterT* interrupt)
1025 {
1026 static_assert(std::is_same<bool, typename GridT::ValueType>::value,
1027 "particlesToMask requires a boolean-valued grid");
1028 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
1029 p2ls.rasterizeSpheres(plist);
1030 tools::prune(grid.tree());
1031 }
1032
1033 template<typename GridT, typename ParticleListT, typename InterrupterT>
1034 inline void
1035 particlesToMask(const ParticleListT& plist, GridT& grid, Real radius, InterrupterT* interrupt)
1036 {
1037 static_assert(std::is_same<bool, typename GridT::ValueType>::value,
1038 "particlesToMask requires a boolean-valued grid");
1039 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
1040 p2ls.rasterizeSpheres(plist, radius);
1041 tools::prune(grid.tree());
1042 }
1043
1044 template<typename GridT, typename ParticleListT, typename InterrupterT>
1045 inline void
1046 particleTrailsToMask(const ParticleListT& plist, GridT& grid, Real delta, InterrupterT* interrupt)
1047 {
1048 static_assert(std::is_same<bool, typename GridT::ValueType>::value,
1049 "particleTrailsToMask requires a boolean-valued grid");
1050 ParticlesToLevelSet<GridT> p2ls(grid, interrupt);
1051 p2ls.rasterizeTrails(plist, delta);
1052 tools::prune(grid.tree());
1053 }
1054
1055 } // namespace tools
1056 } // namespace OPENVDB_VERSION_NAME
1057 } // namespace openvdb
1058
1059 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
1060
1061 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1062 // All rights reserved. This software is distributed under the
1063 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v6_1::math::Abs
Coord Abs(const Coord &xyz)
Definition: Coord.h:536
openvdb::v6_1::tools::ParticlesToLevelSet::OutputIsMask
static const bool OutputIsMask
Definition: ParticlesToLevelSet.h:192
Types.h
openvdb::v6_1::tools::ParticlesToLevelSet::ignoredParticles
bool ignoredParticles() const
Return true if any particles were ignored due to their size.
Definition: ParticlesToLevelSet.h:248
NullInterrupter.h
openvdb::v6_1::tools::particleTrailsToSdf
void particleTrailsToSdf(const ParticleListT &, GridT &, Real delta=1, InterrupterT *=nullptr)
Populate a scalar, floating-point grid with CSG-unioned trails of level set spheres with decreasing r...
Definition: ParticlesToLevelSet.h:1007
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Composite.h
Functions to efficiently perform various compositing operations on grids.
openvdb::v6_1::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:416
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
openvdb::v6_1::math::operator<
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:207
openvdb::v6_1::tools::ParticlesToLevelSet::InterrupterType
InterrupterT InterrupterType
Definition: ParticlesToLevelSet.h:184
openvdb::v6_1::ShallowCopy
Tag dispatch class that distinguishes shallow copy constructors from deep copy constructors.
Definition: Types.h:747
openvdb::v6_1::tools::particlesToSdf
void particlesToSdf(const ParticleListT &, GridT &, Real radius, InterrupterT *=nullptr)
Populate a scalar, floating-point grid with fixed-size, CSG-unioned level set spheres described by th...
Definition: ParticlesToLevelSet.h:990
openvdb::v6_1::tools::particlesToMask
void particlesToMask(const ParticleListT &, GridT &, Real radius, InterrupterT *=nullptr)
Activate a boolean grid wherever it intersects the fixed-size spheres described by the given particle...
Definition: ParticlesToLevelSet.h:1035
openvdb::v6_1::tools::ParticlesToLevelSet::DisableT
typename std::is_void< AttributeT >::type DisableT
Definition: ParticlesToLevelSet.h:183
Transform.h
openvdb::v6_1::tools::ParticlesToLevelSet::SdfType
typename SdfGridT::ValueType SdfType
Definition: ParticlesToLevelSet.h:187
logging.h
openvdb::v6_1::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
PointPartitioner.h
Spatially partitions points using a parallel radix-based sorting algorithm.
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v6_1::tree::LeafManager
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
openvdb::v6_1::tools::ParticlesToLevelSet::AttGridType
typename SdfGridT::template ValueConverter< AttType >::Type AttGridType
Definition: ParticlesToLevelSet.h:190
openvdb::v6_1::tools::particleTrailsToMask
void particleTrailsToMask(const ParticleListT &, GridT &, Real delta=1, InterrupterT *=nullptr)
Activate a boolean grid wherever it intersects trails of spheres with decreasing radius,...
Definition: ParticlesToLevelSet.h:1046
openvdb::v6_1::math::operator-
Vec3< typename promote< T, Coord::ValueType >::type > operator-(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be subtracted from a Vec3.
Definition: Coord.h:572
openvdb::v6_1::tools::ParticlesToLevelSet::setRmax
void setRmax(Real Rmax)
Set the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:245
openvdb::v6_1::operator<<
std::ostream & operator<<(std::ostream &ostr, const Metadata &metadata)
Write a Metadata to an output stream.
Definition: Metadata.h:401
openvdb::v6_1::tools::ParticlesToLevelSet::setGrainSize
void setGrainSize(int grainSize)
Set the grain size used for threading.
Definition: ParticlesToLevelSet.h:260
openvdb::v6_1::tools::signedFloodFill
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:294
openvdb::v6_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
openvdb::v6_1::Vec3R
math::Vec3< Real > Vec3R
Definition: Types.h:79
openvdb::v6_1::tools::particlesToMask
void particlesToMask(const ParticleListT &, GridT &, InterrupterT *=nullptr)
Activate a boolean grid wherever it intersects the spheres described by the given particle positions ...
Definition: ParticlesToLevelSet.h:1024
openvdb::v6_1::tools::csgUnion
void csgUnion(GridOrTreeT &a, GridOrTreeT &b, bool prune=true)
Given two level set grids, replace the A grid with the union of A and B.
Definition: Composite.h:1154
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
openvdb::v6_1::math::operator+
Vec3< typename promote< T, typename Coord::ValueType >::type > operator+(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be added to or subtracted from a Vec3.
Definition: Coord.h:546
openvdb::v6_1::math::operator>
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:219
openvdb::v6_1::Index
Index32 Index
Definition: Types.h:61
OPENVDB_LOG_WARN
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition: logging.h:280
openvdb::v6_1::tools::ParticlesToLevelSet::AttType
typename std::conditional< DisableT::value, size_t, AttributeT >::type AttType
Definition: ParticlesToLevelSet.h:189
SignedFloodFill.h
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v6_1::tree::LeafManager::foreach
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:523
openvdb::v6_1::zeroVal
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:86
openvdb::v6_1::tools::ParticlesToLevelSet::setRmin
void setRmin(Real Rmin)
Set the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:240
openvdb::v6_1::Real
double Real
Definition: Types.h:67
openvdb
Definition: Exceptions.h:40
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:149
openvdb::v6_1::tools::ParticlesToLevelSet::~ParticlesToLevelSet
~ParticlesToLevelSet()
Definition: ParticlesToLevelSet.h:214
openvdb::v6_1::tools::ParticlesToLevelSet::SdfGridType
SdfGridT SdfGridType
Definition: ParticlesToLevelSet.h:186
OPENVDB_NO_FP_EQUALITY_WARNING_END
#define OPENVDB_NO_FP_EQUALITY_WARNING_END
Definition: Math.h:75
openvdb::v6_1::RuntimeError
Definition: Exceptions.h:90
openvdb::v6_1::tools::ParticlesToLevelSet::getRmax
Real getRmax() const
Return the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:243
openvdb::v6_1::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v6_1::tools::ParticlesToLevelSet::getRmin
Real getRmin() const
Return the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:238
openvdb::v6_1::math::Sqrt
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:715
openvdb::v6_1::tools::ParticlesToLevelSet::getVoxelSize
Real getVoxelSize() const
Return the size of a voxel in world units.
Definition: ParticlesToLevelSet.h:232
OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
#define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
Definition: Math.h:74
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:150
openvdb::v6_1::tools::ParticlesToLevelSet::rasterizeTrails
void rasterizeTrails(const ParticleListT &pa, Real delta=1.0)
Rasterize each particle as a trail comprising the CSG union of spheres of decreasing radius.
Definition: ParticlesToLevelSet.h:366
openvdb::v6_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:52
openvdb::v6_1::math::Ceil
int Ceil(float x)
Return the ceiling of x.
Definition: Math.h:810
openvdb::v6_1::math::Floor
int Floor(float x)
Return the floor of x.
Definition: Math.h:802
openvdb::v6_1::tools::ParticlesToLevelSet::getHalfWidth
Real getHalfWidth() const
Return the half-width of the narrow band in voxel units.
Definition: ParticlesToLevelSet.h:235
openvdb::v6_1::tools::ParticlesToLevelSet::getGrainSize
int getGrainSize() const
Return the grain size used for threading.
Definition: ParticlesToLevelSet.h:257
Grid.h
openvdb::v6_1::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
openvdb::v6_1::tools::ParticlesToLevelSet::finalize
void finalize(bool prune=false)
This method syncs up the level set and attribute grids and therefore needs to be called before any of...
Definition: ParticlesToLevelSet.h:380
openvdb::v6_1::math::Max
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:549
openvdb::v6_1::tools::ParticlesToLevelSet::getMaxCount
size_t getMaxCount() const
Return the number of particles that were ignored because they were larger than the maximum radius.
Definition: ParticlesToLevelSet.h:254
openvdb::v6_1::tools::ParticlesToLevelSet::getMinCount
size_t getMinCount() const
Return the number of particles that were ignored because they were smaller than the minimum radius.
Definition: ParticlesToLevelSet.h:251
openvdb::v6_1::tools::ParticlesToLevelSet
Definition: ParticlesToLevelSet.h:180
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
LeafManager.h
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
openvdb::v6_1::math::operator==
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:498
openvdb::v6_1::tools::particlesToSdf
void particlesToSdf(const ParticleListT &, GridT &, InterrupterT *=nullptr)
Populate a scalar, floating-point grid with CSG-unioned level set spheres described by the given part...
Definition: ParticlesToLevelSet.h:973
openvdb::v6_1::GRID_LEVEL_SET
Definition: Types.h:504
openvdb::v6_1::tools::ParticlesToLevelSet::attributeGrid
AttGridType::Ptr attributeGrid()
Return a pointer to the grid containing the optional user-defined attribute.
Definition: ParticlesToLevelSet.h:229
openvdb::v6_1::tools::PointPartitioner
Definition: PointPartitioner.h:106
openvdb::v6_1::tools::prune
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:361
openvdb::v6_1::tools::ParticlesToLevelSet::rasterizeSpheres
void rasterizeSpheres(const ParticleListT &pa)
Rasterize each particle as a sphere with the particle's position and radius.
Definition: ParticlesToLevelSet.h:338
openvdb::v6_1::tools::compMax
void compMax(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute max(a, b) per voxel (using sparse traversal). Store the result in the A ...
Definition: Composite.h:757
openvdb::v6_1::math::Pow2
Type Pow2(Type x)
Return x2.
Definition: Math.h:502
openvdb::v6_1::Index32
uint32_t Index32
Definition: Types.h:59