9 #ifndef OPENVDB_POINTS_RASTERIZE_SDF_IMPL_HAS_BEEN_INCLUDED 10 #define OPENVDB_POINTS_RASTERIZE_SDF_IMPL_HAS_BEEN_INCLUDED 19 namespace rasterize_sdf_internal
23 template <
typename ValueT>
26 static constexpr
bool Fixed =
true;
27 using ValueType = ValueT;
29 FixedRadius(
const ValueT ris) : mR(ris) {}
30 inline void reset(
const PointDataTree::LeafNodeType&)
const {}
31 inline const FixedRadius& eval(
const Index)
const {
return *
this; }
32 inline ValueT
get()
const {
return mR; }
41 template <
typename ValueT>
42 struct FixedBandRadius :
public FixedRadius<ValueT>
44 static constexpr
bool Fixed =
true;
45 using ValueType = ValueT;
47 FixedBandRadius(
const ValueT ris,
const float hb)
48 : FixedRadius<ValueT>(ris)
49 , mMinSearchIS(math::
Max(ValueT(0.0), ris - ValueT(hb)))
50 , mMaxSearchIS(ris + ValueT(hb))
51 , mMinSearchSqIS(mMinSearchIS*mMinSearchIS)
52 , mMaxSearchSqIS(mMaxSearchIS*mMaxSearchIS)
55 inline void reset(
const PointDataTree::LeafNodeType&)
const {}
57 inline const FixedBandRadius eval(
const Index,
const ValueT
scale)
const 59 if (scale == 1.0)
return *
this;
60 return FixedBandRadius(this->
get() * scale, this->halfband());
63 inline const FixedBandRadius& eval(
const Index)
const {
return *
this; }
64 inline float halfband()
const {
return mHalfBand; }
66 inline ValueT
min()
const {
return mMinSearchIS; }
67 inline ValueT minSq()
const {
return mMinSearchSqIS; }
68 inline ValueT
max()
const {
return mMaxSearchIS; }
69 inline ValueT maxSq()
const {
return mMaxSearchSqIS; }
71 const ValueT mMinSearchIS, mMaxSearchIS;
72 const ValueT mMinSearchSqIS, mMaxSearchSqIS;
75 const float mHalfBand;
81 struct FixedBandRadius<
Vec3f> :
public FixedRadius<Vec3f>
83 static constexpr
bool Fixed =
true;
84 using ValueType =
Vec3f;
85 FixedBandRadius(
const Vec3f ris,
const float hb)
86 : FixedRadius<
Vec3f>(ris)
88 inline void reset(
const PointDataTree::LeafNodeType&)
const {}
89 inline const FixedBandRadius& eval(
const Index)
const {
return *
this; }
90 inline float halfband()
const {
return mHalfBand; }
92 const float mHalfBand;
96 template <
typename ValueT,
typename ScaleT = ValueT,
typename CodecT = UnknownCodec>
99 static constexpr
bool Fixed =
false;
100 using ValueType = ValueT;
102 using RadiusHandleT = AttributeHandle<ValueT, CodecT>;
103 VaryingRadius(
const size_t ridx,
const ScaleT scale = ScaleT(1.0))
104 : mRIdx(ridx), mRHandle(), mScale(scale) {}
105 VaryingRadius(
const VaryingRadius& other)
106 : mRIdx(other.mRIdx), mRHandle(), mScale(other.mScale) {}
108 inline size_t size()
const {
return mRHandle->size(); }
110 inline void reset(
const PointDataTree::LeafNodeType& leaf)
112 mRHandle.reset(
new RadiusHandleT(leaf.constAttributeArray(mRIdx)));
116 inline auto eval(
const Index
id,
const ScaleT scale = ScaleT(1.0))
const 119 auto x = mRHandle->get(
id) * mScale *
scale;
120 return FixedRadius<decltype(x)>(x);
125 typename RadiusHandleT::UniquePtr mRHandle;
130 template <
typename ValueT,
typename ScaleT = ValueT,
typename CodecT = UnknownCodec>
131 struct VaryingBandRadius :
public VaryingRadius<ValueT, ScaleT, CodecT>
133 static constexpr
bool Fixed =
false;
134 using ValueType = ValueT;
136 using BaseT = VaryingRadius<ValueT, ScaleT, CodecT>;
137 VaryingBandRadius(
const size_t ridx,
const float halfband,
138 const ScaleT scale = ScaleT(1.0))
139 : BaseT(ridx, scale), mHalfBand(halfband) {}
141 inline float halfband()
const {
return mHalfBand; }
142 inline auto eval(
const Index
id,
const ScaleT scale = ScaleT(1.0))
const 144 auto r = this->BaseT::eval(
id, scale).get();
145 return FixedBandRadius<decltype(r)>(r, mHalfBand);
149 const float mHalfBand;
154 template <
typename SdfT,
155 typename PositionCodecT,
159 struct SignedDistanceFieldTransfer :
160 public TransformTransfer,
161 public FilteredTransfer<FilterT>,
162 public InterruptableTransfer,
163 public std::conditional<CPG,
164 VolumeTransfer<typename SdfT::TreeType, Int64Tree>,
165 VolumeTransfer<typename SdfT::TreeType>>::type
167 using TreeT =
typename SdfT::TreeType;
168 using ValueT =
typename TreeT::ValueType;
169 static_assert(std::is_floating_point<ValueT>::value,
170 "Spherical transfer only supports floating point values.");
171 static_assert(!std::is_reference<RadiusType>::value && !std::is_pointer<RadiusType>::value,
172 "Templated radius type must not be a reference or pointer");
174 using VolumeTransferT =
typename std::conditional<CPG,
175 VolumeTransfer<TreeT, Int64Tree>,
176 VolumeTransfer<TreeT>>::type;
177 using FilteredTransferT = FilteredTransfer<FilterT>;
178 using PositionHandleT = AttributeHandle<Vec3f, PositionCodecT>;
181 inline Vec3i range(
const Coord&,
size_t)
const {
return mMaxKernelWidth; }
183 inline void initialize(
const Coord& origin,
const size_t idx,
const CoordBBox& bounds)
189 inline bool startPointLeaf(
const PointDataTree::LeafNodeType& leaf)
191 FilteredTransferT::startPointLeaf(leaf);
192 mPosition = std::make_unique<PositionHandleT>(leaf.constAttributeArray(mPIdx));
195 if (CPG) mPLeafMask = (
Index64(mIds->find(&leaf)->second) << 32);
201 template <
bool EnableT = CPG>
202 SignedDistanceFieldTransfer(
const size_t pidx,
204 const RadiusType& rt,
205 const math::Transform& source,
206 const FilterT& filter,
207 util::NullInterrupter* interrupt,
210 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids,
211 typename std::enable_if<EnableT>::type* = 0)
212 : TransformTransfer(source, surface.transform())
213 , FilteredTransferT(filter)
214 , InterruptableTransfer(interrupt)
215 , VolumeTransferT(&(surface.tree()), cpg)
218 , mMaxKernelWidth(width)
220 , mBackground(surface.background())
221 , mDx(surface.voxelSize()[0])
228 template <
bool EnableT = CPG>
229 SignedDistanceFieldTransfer(
const size_t pidx,
231 const RadiusType& rt,
232 const math::Transform& source,
233 const FilterT& filter,
234 util::NullInterrupter* interrupt,
237 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>*,
238 typename std::enable_if<!EnableT>::type* = 0)
239 : TransformTransfer(source, surface.transform())
240 , FilteredTransferT(filter)
241 , InterruptableTransfer(interrupt)
242 , VolumeTransferT(surface.tree())
245 , mMaxKernelWidth(width)
247 , mBackground(surface.background())
248 , mDx(surface.voxelSize()[0])
252 SignedDistanceFieldTransfer(
const SignedDistanceFieldTransfer& other)
253 : TransformTransfer(other)
254 , FilteredTransferT(other)
255 , InterruptableTransfer(other)
256 , VolumeTransferT(other)
259 , mMaxKernelWidth(other.mMaxKernelWidth)
260 , mRadius(other.mRadius)
261 , mBackground(other.mBackground)
268 typename PositionHandleT::UniquePtr mPosition;
269 const Vec3i mMaxKernelWidth;
271 const ValueT mBackground;
273 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* mIds;
279 template <
typename SdfT,
280 typename PositionCodecT,
284 struct SphericalTransfer :
285 public SignedDistanceFieldTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>
287 using BaseT = SignedDistanceFieldTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>;
288 using typename BaseT::TreeT;
289 using typename BaseT::ValueT;
290 static const Index DIM = TreeT::LeafNodeType::DIM;
291 static const Index LOG2DIM = TreeT::LeafNodeType::LOG2DIM;
293 using RealT = double;
297 SphericalTransfer(
const size_t pidx,
299 const RadiusType& rt,
300 const math::Transform& source,
301 const FilterT& filter,
302 util::NullInterrupter* interrupt,
305 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids =
nullptr)
306 : SphericalTransfer(pidx,
Vec3i(width), rt, source, filter, interrupt, surface, cpg, ids) {}
312 inline void rasterizePoint(
const Coord& ijk,
314 const CoordBBox& bounds)
316 if (!BaseT::filter(
id))
return;
319 #if defined(__GNUC__) && !defined(__clang__) 320 #pragma GCC diagnostic push 321 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 323 Vec3d P = ijk.asVec3d() +
Vec3d(this->mPosition->get(
id));
324 #if defined(__GNUC__) && !defined(__clang__) 325 #pragma GCC diagnostic pop 327 P = this->transformSourceToTarget(P);
328 this->rasterizePoint(P,
id, bounds, this->mRadius.eval(
id));
333 inline bool endPointLeaf(
const PointDataTree::LeafNodeType&)
336 return !(this->
template mask<0>()->isOff());
339 inline bool finalize(
const Coord&,
const size_t)
344 auto& mask = *(this->
template mask<0>());
345 auto*
const data = this->
template buffer<0>();
346 for (
auto iter = mask.beginOn(); iter; ++iter) {
347 if (data[iter.pos()] == this->mBackground) mask.setOff(iter.pos());
350 if (CPG) *(this->
template mask<CPG ? 1 : 0>()) = mask;
359 SphericalTransfer(
const size_t pidx,
361 const RadiusType& rt,
362 const math::Transform& source,
363 const FilterT& filter,
364 util::NullInterrupter* interrupt,
367 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids =
nullptr)
368 : BaseT(pidx, width, rt, source, filter, interrupt, surface, cpg, ids) {}
377 inline void rasterizePoint(
const Vec3d& P,
379 const CoordBBox& bounds,
380 const FixedBandRadius<ElemT>& r)
382 const RealT
max = r.max();
383 CoordBBox intersectBox(Coord::round(P - max), Coord::round(P + max));
384 intersectBox.intersect(bounds);
385 if (intersectBox.empty())
return;
387 auto*
const data = this->
template buffer<0>();
388 auto*
const cpg = CPG ? this->
template buffer<CPG ? 1 : 0>() :
nullptr;
389 auto& mask = *(this->
template mask<0>());
399 const RealT min2 = r.minSq() == 0.0 ? -1.0 : r.minSq();
400 const RealT max2 = r.maxSq();
402 const Coord& a(intersectBox.min());
403 const Coord& b(intersectBox.max());
404 for (Coord c = a; c.x() <= b.x(); ++c.x()) {
405 const RealT x2 =
static_cast<RealT
>(
math::Pow2(c.x() - P[0]));
406 const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM);
407 for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
408 const RealT x2y2 =
static_cast<RealT
>(x2 +
math::Pow2(c.y() - P[1]));
409 const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM);
410 for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
411 const Index offset = ij + (c.z() & (DIM-1u));
412 if (!mask.isOn(offset))
continue;
414 const RealT x2y2z2 =
static_cast<RealT
>(x2y2 +
math::Pow2(c.z() - P[2]));
415 if (x2y2z2 >= max2)
continue;
416 if (x2y2z2 <= min2) {
417 data[offset] = -(this->mBackground);
422 const ValueT d = ValueT(this->mDx * (
math::Sqrt(x2y2z2) - r.get()));
423 ValueT& v = data[offset];
427 if (CPG) cpg[offset] =
Int64(this->mPLeafMask |
Index64(
id));
448 template <
typename SdfT,
449 typename PositionCodecT,
453 struct AveragePositionTransfer :
454 public SignedDistanceFieldTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>
456 using BaseT = SignedDistanceFieldTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>;
457 using typename BaseT::TreeT;
458 using typename BaseT::ValueT;
460 using VolumeTransferT =
typename std::conditional<CPG,
461 VolumeTransfer<typename SdfT::TreeType, Int64Tree>,
462 VolumeTransfer<typename SdfT::TreeType>>::type;
464 static const Index DIM = TreeT::LeafNodeType::DIM;
465 static const Index LOG2DIM = TreeT::LeafNodeType::LOG2DIM;
466 static const Index NUM_VALUES = TreeT::LeafNodeType::NUM_VALUES;
468 using RealT = double;
472 template <
typename S>
inline void addP(
const math::Vec3<S>& v) { P += v; }
473 template <
typename S>
inline void addR(
const S r) { R += r; }
474 template <
typename S>
inline void multR(
const S w) { R *= w; }
475 template <
typename S>
inline void multP(
const S w) { P *= w; }
476 inline RealT length()
const {
return P.length() - R; }
477 math::Vec3<RealT> P = math::Vec3<RealT>(0.0);
481 AveragePositionTransfer(
const size_t pidx,
483 const RadiusType& rt,
485 const math::Transform& source,
486 const FilterT& filter,
487 util::NullInterrupter* interrupt,
490 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids =
nullptr)
491 : AveragePositionTransfer(pidx,
Vec3i(width), rt, search, source, filter, interrupt, surface, cpg, ids) {}
493 AveragePositionTransfer(
const AveragePositionTransfer& other)
495 , mMaxSearchIS(other.mMaxSearchIS)
496 , mMaxSearchSqIS(other.mMaxSearchSqIS)
500 inline void initialize(
const Coord& origin,
const size_t idx,
const CoordBBox& bounds)
504 mWeights.assign(NUM_VALUES, PosRadPair());
516 auto*
const data = this->
template buffer<0>();
517 const auto& mask = *(this->
template mask<0>());
518 for (
auto iter = mask.beginOn(); iter; ++iter) {
519 data[iter.pos()] = ValueT(0);
523 inline void rasterizePoint(
const Coord& ijk,
525 const CoordBBox& bounds)
527 if (!BaseT::filter(
id))
return;
529 #if defined(__GNUC__) && !defined(__clang__) 530 #pragma GCC diagnostic push 531 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 533 const Vec3d PWS = this->sourceTransform().indexToWorld(ijk.asVec3d() +
Vec3d(this->mPosition->get(
id)));
534 #if defined(__GNUC__) && !defined(__clang__) 535 #pragma GCC diagnostic pop 537 const Vec3d P = this->targetTransform().worldToIndex(PWS);
539 CoordBBox intersectBox(Coord::round(P - mMaxSearchIS), Coord::round(P + mMaxSearchIS));
540 intersectBox.intersect(bounds);
541 if (intersectBox.empty())
return;
543 auto*
const data = this->
template buffer<0>();
544 auto*
const cpg = CPG ? this->
template buffer<CPG ? 1 : 0>() :
nullptr;
545 const auto& mask = *(this->
template mask<0>());
548 const auto& r = this->mRadius.eval(
id);
549 const RealT rad = r.get();
550 const RealT invsq = 1.0 / mMaxSearchSqIS;
552 const Coord& a(intersectBox.min());
553 const Coord& b(intersectBox.max());
554 for (Coord c = a; c.x() <= b.x(); ++c.x()) {
555 const RealT x2 =
static_cast<RealT
>(
math::Pow2(c.x() - P[0]));
556 const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM);
557 for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
558 const RealT x2y2 =
static_cast<RealT
>(x2 +
math::Pow2(c.y() - P[1]));
559 const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM);
560 for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
561 RealT x2y2z2 =
static_cast<RealT
>(x2y2 +
math::Pow2(c.z() - P[2]));
562 if (x2y2z2 >= mMaxSearchSqIS)
continue;
563 const Index offset = ij + (c.z() & (DIM-1u));
564 if (!mask.isOn(offset))
continue;
575 const float dist =
static_cast<float>(
math::Sqrt(x2y2z2) - r.get());
576 auto& d = mDist[offset];
593 data[offset] += x2y2z2;
595 auto& wt = mWeights[offset];
596 wt.addP(PWS * x2y2z2);
597 wt.addR(rad * x2y2z2);
603 inline bool endPointLeaf(
const PointDataTree::LeafNodeType&) {
return true; }
605 inline bool finalize(
const Coord& origin,
const size_t)
607 auto& mask = *(this->
template mask<0>());
608 auto*
const data = this->
template buffer<0>();
610 for (
auto iter = mask.beginOn(); iter; ++iter) {
611 const Index idx = iter.pos();
617 w = this->mBackground;
620 const Coord ijk = origin + TreeT::LeafNodeType::offsetToLocalCoord(idx);
621 const Vec3d ws = this->targetTransform().indexToWorld(ijk);
622 const RealT wi = RealT(1.0) / RealT(w);
623 auto& wt = mWeights[idx];
625 wt.multR(wi * this->mDx);
627 w =
static_cast<typename SdfT::ValueType
>(wt.length());
629 if (std::fabs(w) >= this->mBackground) {
630 w = std::copysign(this->mBackground, w);
637 if (CPG) *(this->
template mask<CPG ? 1 : 0>()) = mask;
646 AveragePositionTransfer(
const size_t pidx,
648 const RadiusType& rt,
650 const math::Transform& source,
651 const FilterT& filter,
652 util::NullInterrupter* interrupt,
655 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids =
nullptr)
656 : BaseT(pidx, width, rt, source, filter, interrupt, surface, cpg, ids)
657 , mMaxSearchIS(search)
658 , mMaxSearchSqIS(search*search)
663 const RealT mMaxSearchIS, mMaxSearchSqIS;
664 std::vector<PosRadPair> mWeights;
665 std::vector<float> mDist;
669 template <
typename MaskTreeT = MaskTree>
673 inline void join(SurfaceMaskOp& other)
675 if (mMask->leafCount() > other.mMask->leafCount()) {
676 mMask->topologyUnion(*other.mMask);
680 other.mMask->topologyUnion(*mMask);
681 mMask.reset(other.mMask.release());
684 if (mMaskOff->leafCount() > other.mMaskOff->leafCount()) {
685 mMaskOff->topologyUnion(*other.mMaskOff);
686 other.mMaskOff.reset();
689 other.mMaskOff->topologyUnion(*mMaskOff);
690 mMaskOff.reset(other.mMaskOff.release());
694 std::unique_ptr<MaskTreeT> mask() {
return std::move(mMask); }
695 std::unique_ptr<MaskTreeT> maskoff() {
return std::move(mMaskOff); }
698 SurfaceMaskOp(
const math::Transform& points,
699 const math::Transform& surface,
702 const CoordBBox*
const maxClipBounds =
nullptr,
703 util::NullInterrupter* interrupter =
nullptr)
704 : mMask(new MaskTreeT)
705 , mMaskOff(new MaskTreeT)
706 , mPointsTransform(points)
707 , mSurfaceTransform(surface)
708 , mMaxClipBounds(maxClipBounds ? this->toSurfaceBounds(*maxClipBounds) : CoordBBox::inf())
709 , mInterrupter(interrupter) {}
711 SurfaceMaskOp(
const SurfaceMaskOp& other)
712 : mMask(new MaskTreeT)
713 , mMaskOff(new MaskTreeT)
714 , mPointsTransform(other.mPointsTransform)
715 , mSurfaceTransform(other.mSurfaceTransform)
716 , mMaxClipBounds(other.mMaxClipBounds)
717 , mInterrupter(other.mInterrupter) {}
725 template <
typename LeafT>
726 inline bool activate(
const LeafT& leaf,
const int32_t dist)
728 CoordBBox bounds = this->toSurfaceBounds(this->getActiveBoundingBox(leaf));
729 if (bounds.empty())
return false;
736 template <
typename LeafT>
739 CoordBBox bounds = this->toSurfaceBounds(this->getActiveBoundingBox(leaf));
740 if (bounds.empty())
return false;
742 bounds.min() -= Coord(dist);
743 bounds.max() += Coord(dist);
748 template <
typename LeafT>
749 inline void deactivate(
const LeafT& leaf,
const int32_t dist)
754 CoordBBox bounds = this->toSurfaceBounds(leaf.getNodeBoundingBox());
760 inline void activate(CoordBBox& bounds)
762 bounds.intersect(mMaxClipBounds);
763 mMask->sparseFill(bounds,
true,
true);
766 inline void deactivate(
const CoordBBox& bounds)
768 mMaskOff->sparseFill(bounds,
true,
true);
771 inline bool interrupted()
774 thread::cancelGroupExecution();
782 template <
typename LeafT>
783 inline CoordBBox getActiveBoundingBox(
const LeafT& leaf)
const 786 const auto& mask = leaf.getValueMask();
789 bounds = leaf.getNodeBoundingBox();
792 for (
auto iter = mask.beginOn(); iter; ++iter) {
793 bounds.expand(leaf.offsetToLocalCoord(iter.pos()));
795 if (bounds.empty())
return bounds;
796 bounds.translate(leaf.origin());
805 inline CoordBBox toSurfaceBounds(
const CoordBBox& bounds)
const 807 if (bounds.empty())
return bounds;
812 const BBoxd wsbounds(
813 bounds.min().asVec3d() - 0.5,
814 bounds.max().asVec3d() + 0.5);
815 return mSurfaceTransform.worldToIndexCellCentered(
816 mPointsTransform.indexToWorld(wsbounds));
820 std::unique_ptr<MaskTreeT> mMask;
821 std::unique_ptr<MaskTreeT> mMaskOff;
822 const math::Transform& mPointsTransform;
823 const math::Transform& mSurfaceTransform;
824 const CoordBBox mMaxClipBounds;
825 util::NullInterrupter* mInterrupter;
829 template <
typename MaskTreeT>
830 struct FixedSurfaceMaskOp
831 :
public SurfaceMaskOp<MaskTreeT>
833 using BaseT = SurfaceMaskOp<MaskTreeT>;
835 tree::LeafManager<const points::PointDataTree>;
837 FixedSurfaceMaskOp(
const math::Transform& points,
838 const math::Transform& surface,
839 const double minBandRadius,
840 const double maxBandRadius,
841 const CoordBBox*
const maxClipBounds,
842 util::NullInterrupter* interrupter =
nullptr)
843 : BaseT(points, surface, maxClipBounds, interrupter)
850 const Real halfside = ((2.0 * minBandRadius) / std::sqrt(3.0)) / 2.0;
853 const int32_t
min =
static_cast<int32_t
>(
std::max(0.0, halfside));
861 const int32_t nodes = min / MaskTreeT::LeafNodeType::DIM;
864 mMin = (nodes-1) * MaskTreeT::LeafNodeType::DIM;
865 mMax =
static_cast<int32_t
>(
math::Round(maxBandRadius));
868 FixedSurfaceMaskOp(
const FixedSurfaceMaskOp& other,
tbb::split)
869 : BaseT(other), mMin(other.mMin), mMax(other.mMax) {}
871 void operator()(
const typename LeafManagerT::LeafRange& range)
873 if (this->interrupted())
return;
874 for (
auto leaf = range.begin(); leaf; ++leaf) {
877 if (mMin < 0)
return;
878 for (
auto leaf = range.begin(); leaf; ++leaf) {
888 template <
typename RadiusTreeT,
typename MaskTreeT>
889 struct VariableSurfaceMaskOp
890 :
public SurfaceMaskOp<MaskTreeT>
892 using BaseT = SurfaceMaskOp<MaskTreeT>;
894 tree::LeafManager<const points::PointDataTree>;
896 VariableSurfaceMaskOp(
const math::Transform& pointsTransform,
897 const math::Transform& surfaceTransform,
898 const RadiusTreeT*
const min,
899 const RadiusTreeT& max,
903 const CoordBBox*
const maxClipBounds,
904 util::NullInterrupter* interrupter =
nullptr)
905 : BaseT(pointsTransform, surfaceTransform, maxClipBounds, interrupter)
906 , mMin(min), mMax(max), mMinScale(minScale), mMaxScale(maxScale)
907 , mHalfband(halfband) {}
909 VariableSurfaceMaskOp(
const VariableSurfaceMaskOp&) =
default;
910 VariableSurfaceMaskOp(
const VariableSurfaceMaskOp& other,
tbb::split)
911 : VariableSurfaceMaskOp(other) {}
913 void operator()(
const typename LeafManagerT::LeafRange& range)
915 if (this->interrupted())
return;
916 const tree::ValueAccessor<const RadiusTreeT> maxacc(mMax);
917 for (
auto leafIter = range.begin(); leafIter; ++leafIter) {
918 const int32_t max = this->maxDist(maxacc.getValue(leafIter->origin()));
923 const tree::ValueAccessor<const RadiusTreeT> minacc(*mMin);
924 for (
auto leafIter = range.begin(); leafIter; ++leafIter) {
925 const int32_t
min = this->minDist(minacc.getValue(leafIter->origin()));
926 if (min < 0)
continue;
932 inline int32_t maxDist(
const typename RadiusTreeT::ValueType& maxRadiusWs)
const 935 const Real maxBandRadius = (
Real(maxRadiusWs) * mMaxScale) + mHalfband;
936 return static_cast<int32_t
>(
math::Round(maxBandRadius));
939 inline int32_t minDist(
const typename RadiusTreeT::ValueType& minRadiusWs)
const 942 Real minBandRadius =
math::Max(0.0, (
Real(minRadiusWs) * mMinScale) - mHalfband);
947 const Real halfside = ((2.0 * minBandRadius) / std::sqrt(3.0)) / 2.0;
950 const int32_t
min =
static_cast<int32_t
>(
std::max(0.0, halfside));
957 const int32_t nodes = min / MaskTreeT::LeafNodeType::DIM;
960 return (nodes-1) * MaskTreeT::LeafNodeType::DIM;
964 const RadiusTreeT*
const mMin;
965 const RadiusTreeT& mMax;
966 const Real mMinScale, mMaxScale, mHalfband;
969 template <
typename SdfT,
typename MaskTreeT>
970 inline typename SdfT::Ptr
971 initSdfFromMasks(math::Transform::Ptr& transform,
972 const typename SdfT::ValueType bg,
973 std::unique_ptr<MaskTreeT> on,
974 std::unique_ptr<MaskTreeT> off)
976 typename SdfT::Ptr surface = SdfT::create(bg);
977 surface->setTransform(transform);
981 on->topologyDifference(*off);
984 surface->tree().topologyUnion(*on);
986 tree::ValueAccessor<const MaskTreeT> acc(*off);
987 auto setOffOp = [acc](
auto& iter) {
988 if (acc.isValueOn(iter.getCoord())) {
989 iter.modifyValue([](
auto& v) { v = -v; });
996 surface->tree().topologyUnion(*on);
1001 surface->tree().voxelizeActiveTiles();
1005 template <
typename SdfT,
typename Po
intDataGr
idT>
1006 inline typename SdfT::Ptr
1007 initFixedSdf(
const PointDataGridT& points,
1008 math::Transform::Ptr transform,
1009 const typename SdfT::ValueType bg,
1010 const double minBandRadius,
1011 const double maxBandRadius,
1012 util::NullInterrupter* interrupter)
1014 using LeafManagerT = tree::LeafManager<const typename PointDataGridT::TreeType>;
1015 using MaskTreeT =
typename SdfT::TreeType::template ValueConverter<ValueMask>::Type;
1017 if (interrupter) interrupter->start(
"Generating uniform surface topology");
1019 FixedSurfaceMaskOp<MaskTreeT>
op(points.transform(),
1020 *transform, minBandRadius, maxBandRadius,
nullptr, interrupter);
1022 LeafManagerT manager(points.tree());
1023 tbb::parallel_reduce(manager.leafRange(),
op);
1025 typename SdfT::Ptr surface =
1026 initSdfFromMasks<SdfT, MaskTreeT>(transform, bg,
op.mask(),
op.maskoff());
1028 if (interrupter) interrupter->end();
1032 template <
typename SdfT,
1033 typename PointDataGridT,
1034 typename RadiusTreeT>
1035 inline typename SdfT::Ptr
1036 initVariableSdf(
const PointDataGridT& points,
1037 math::Transform::Ptr transform,
1038 const typename SdfT::ValueType bg,
1039 const RadiusTreeT&
min,
1040 const RadiusTreeT& max,
1042 const Real halfband,
1043 util::NullInterrupter* interrupter)
1045 using LeafManagerT = tree::LeafManager<const typename PointDataGridT::TreeType>;
1046 using MaskTreeT =
typename SdfT::TreeType::template ValueConverter<ValueMask>::Type;
1048 if (interrupter) interrupter->start(
"Generating variable surface topology");
1050 VariableSurfaceMaskOp<RadiusTreeT, MaskTreeT>
1052 nullptr, interrupter);
1054 LeafManagerT manager(points.tree());
1055 tbb::parallel_reduce(manager.leafRange(),
op);
1057 typename SdfT::Ptr surface =
1058 initSdfFromMasks<SdfT, MaskTreeT>(transform, bg,
op.mask(),
op.maskoff());
1060 if (interrupter) interrupter->end();
1064 template <
typename SdfT,
typename Po
intDataGr
idT>
1065 inline typename SdfT::Ptr
1066 initFixedSmoothSdf(
const PointDataGridT& points,
1067 math::Transform::Ptr transform,
1068 const typename SdfT::ValueType bg,
1069 const Real maxBandRadius,
1070 const CoordBBox& bounds,
1071 util::NullInterrupter* interrupter)
1073 using LeafManagerT = tree::LeafManager<const typename PointDataGridT::TreeType>;
1074 using MaskTreeT =
typename SdfT::TreeType::template ValueConverter<ValueMask>::Type;
1076 if (interrupter) interrupter->start(
"Generating uniform surface topology");
1080 FixedSurfaceMaskOp<MaskTreeT>
op(points.transform(),
1081 *transform, 0.0, maxBandRadius, &bounds, interrupter);
1083 LeafManagerT manager(points.tree());
1084 tbb::parallel_reduce(manager.leafRange(),
op);
1086 typename SdfT::Ptr surface =
1087 initSdfFromMasks<SdfT, MaskTreeT>(transform, bg,
op.mask(),
op.maskoff());
1089 if (interrupter) interrupter->end();
1093 template <
typename SdfT,
1094 typename PointDataGridT,
1095 typename RadiusTreeT>
1096 inline typename SdfT::Ptr
1097 initVariableSmoothSdf(
const PointDataGridT& points,
1098 math::Transform::Ptr transform,
1099 const typename SdfT::ValueType bg,
1100 const RadiusTreeT& maxTree,
1102 const Real halfband,
1103 const CoordBBox& bounds,
1104 util::NullInterrupter* interrupter)
1106 using LeafManagerT = tree::LeafManager<const typename PointDataGridT::TreeType>;
1107 using MaskTreeT =
typename SdfT::TreeType::template ValueConverter<ValueMask>::Type;
1109 if (interrupter) interrupter->start(
"Generating variable surface topology");
1113 VariableSurfaceMaskOp<RadiusTreeT, MaskTreeT>
1114 op(points.transform(), *transform,
nullptr, maxTree, 1.0,
1115 scale, halfband, &bounds, interrupter);
1117 LeafManagerT manager(points.tree());
1118 tbb::parallel_reduce(manager.leafRange(),
op);
1120 typename SdfT::Ptr surface =
1121 initSdfFromMasks<SdfT, MaskTreeT>(transform, bg,
op.mask(),
op.maskoff());
1123 if (interrupter) interrupter->end();
1127 template <
typename PointDataTreeT,
1130 transferAttributes(
const tree::LeafManager<const PointDataTreeT>& manager,
1131 const std::vector<std::string>& attributes,
1133 const math::Transform::Ptr transform)
1143 const tree::LeafManager<const Int64Tree> cpmanager(cpg);
1145 auto transfer = [&](
auto& tree,
const size_t attrIdx) {
1146 using TreeType =
typename std::decay<decltype(tree)>::type;
1147 using HandleT = AttributeHandle<typename TreeType::ValueType>;
1150 tree.topologyUnion(cpg);
1151 tree::LeafManager<TreeType> lm(tree);
1154 lm.foreach([&manager, &cpmanager, attrIdx]
1155 (
auto& leaf,
const size_t idx) {
1156 auto voxel = leaf.beginValueOn();
1159 auto* data = leaf.buffer().data();
1160 const Int64* ids = cpmanager.leaf(idx).buffer().data();
1162 typename HandleT::UniquePtr handle =
1163 std::make_unique<HandleT>(manager.leaf(prev).constAttributeArray(attrIdx));
1165 for (; voxel; ++voxel) {
1170 handle = std::make_unique<HandleT>(manager.leaf(lfid).constAttributeArray(attrIdx));
1173 data[voxel.pos()] = handle->get(ptid);
1179 grids.reserve(attributes.size());
1180 const auto& attrSet = manager.leaf(0).attributeSet();
1181 tbb::task_group tasks;
1183 for (
const auto& name : attributes) {
1184 const size_t attrIdx = attrSet.find(name);
1185 if (attrIdx == points::AttributeSet::INVALID_POS)
continue;
1186 if (attrSet.get(attrIdx)->stride() != 1) {
1187 OPENVDB_THROW(RuntimeError,
"Transfer of attribute " + name +
1188 " not supported since it is strided");
1191 const std::string& type = attrSet.descriptor().valueType(attrIdx);
1194 using ValueType =
typename std::remove_const<typename std::decay<decltype(v)>::type>::type;
1195 using TreeT =
typename PointDataTreeT::template ValueConverter<ValueType>::Type;
1196 if (!grid && typeNameAsString<ValueType>() == type) {
1199 typed->setName(name);
1200 typed->setTransform(transform);
1201 tasks.run([typed, attrIdx, transfer] { transfer(typed->tree(), attrIdx); });
1202 grids.emplace_back(grid);
1207 OPENVDB_THROW(RuntimeError,
"No support for attribute type " + type +
1208 " built during closest point surface transfer");
1216 template <
typename SdfT,
1217 template <
typename,
typename,
typename,
typename,
bool>
class TransferInterfaceT,
1220 typename PointDataGridT,
1223 doRasterizeSurface(
const PointDataGridT& points,
1224 const std::vector<std::string>& attributes,
1228 using RadRefT =
typename std::tuple_element<1, std::tuple<Args...>>::type;
1229 using RadT =
typename std::remove_reference<RadRefT>::type;
1232 const auto leaf = points.constTree().cbeginLeaf();
1233 if (!leaf)
return grids;
1235 const size_t pidx = leaf->attributeSet().find(
"P");
1236 if (pidx == AttributeSet::INVALID_POS) {
1237 OPENVDB_THROW(RuntimeError,
"Failed to find position attribute");
1242 const NamePair& ptype = leaf->attributeSet().descriptor().type(pidx);
1244 if (attributes.empty()) {
1245 if (ptype.second == NullCodec::name()) {
1246 using TransferT = TransferInterfaceT<SdfT, NullCodec, RadT, FilterT, false>;
1247 TransferT transfer(pidx, args...);
1248 rasterize<PointDataGridT, TransferT>(points, transfer);
1251 using TransferT = TransferInterfaceT<SdfT, UnknownCodec, RadT, FilterT, false>;
1252 TransferT transfer(pidx, args...);
1253 rasterize<PointDataGridT, TransferT>(points, transfer);
1258 cpg.topologyUnion(surface.tree());
1259 tree::LeafManager<const PointDataTree> manager(points.tree());
1262 std::unordered_map<const PointDataTree::LeafNodeType*, Index> ids;
1263 manager.foreach([&](
auto& leafnode,
size_t idx) { ids[&leafnode] =
Index(idx); },
false);
1265 if (ptype.second == NullCodec::name()) {
1266 using TransferT = TransferInterfaceT<SdfT, NullCodec, RadT, FilterT, true>;
1267 TransferT transfer(pidx, args..., &cpg, &ids);
1268 rasterize<PointDataGridT, TransferT>(points, transfer);
1271 using TransferT = TransferInterfaceT<SdfT, UnknownCodec, RadT, FilterT, true>;
1272 TransferT transfer(pidx, args..., &cpg, &ids);
1273 rasterize<PointDataGridT, TransferT>(points, transfer);
1279 grids = transferAttributes
1280 <
typename PointDataGrid::TreeType, AttributeTypes>
1281 (manager, attributes, cpg, surface.transformPtr());
1287 template <
typename PointDataGridT,
1292 const SettingsT& settings,
1293 const typename SettingsT::FilterType& filter)
1295 static_assert(IsSpecializationOf<PointDataGridT, Grid>::value);
1296 static_assert(IsSpecializationOf<SettingsT, SphereSettings>::value);
1299 using FilterT =
typename SettingsT::FilterType;
1301 const std::vector<std::string>& attributes = settings.attributes;
1302 const Real halfband = settings.halfband;
1303 auto* interrupter = settings.interrupter;
1305 math::Transform::Ptr transform = settings.transform;
1306 if (!transform) transform = points.transform().copy();
1307 const Real vs = transform->voxelSize()[0];
1308 const typename SdfT::ValueType background =
1309 static_cast<typename SdfT::ValueType
>(vs * halfband);
1311 typename SdfT::Ptr surface;
1314 if (settings.radius.empty()) {
1316 const Real radiusIndexSpace = settings.radiusScale / vs;
1317 const FixedBandRadius<Real> rad(radiusIndexSpace,
float(halfband));
1318 const Real minBandRadius = rad.min();
1319 const Real maxBandRadius = rad.max();
1320 const size_t width =
static_cast<size_t>(
math::RoundUp(maxBandRadius));
1322 surface = initFixedSdf<SdfT>
1323 (points, transform, background, minBandRadius, maxBandRadius, interrupter);
1325 if (interrupter) interrupter->start(
"Rasterizing particles to level set using constant Spheres");
1327 grids = doRasterizeSurface<SdfT, SphericalTransfer, AttributeTypes, FilterT>
1328 (points, attributes, *surface,
1329 width, rad, points.transform(), filter, interrupter, *surface);
1332 using RadiusT =
typename SettingsT::RadiusAttributeType;
1333 using PointDataTreeT =
typename PointDataGridT::TreeType;
1334 using RadTreeT =
typename PointDataTreeT::template ValueConverter<RadiusT>::Type;
1337 typename RadTreeT::Ptr mintree(
new RadTreeT), maxtree(
new RadTreeT);
1338 points::evalMinMax<RadiusT, UnknownCodec>
1339 (points.tree(), settings.radius,
min,
max, filter, mintree.get(), maxtree.get());
1342 const RadiusT indexSpaceScale = RadiusT(settings.radiusScale / vs);
1343 surface = initVariableSdf<SdfT>
1344 (points, transform, background, *mintree, *maxtree,
1345 indexSpaceScale, halfband, interrupter);
1349 const auto leaf = points.constTree().cbeginLeaf();
1353 const size_t width =
static_cast<size_t> 1356 const size_t ridx = leaf->attributeSet().find(settings.radius);
1357 if (ridx == AttributeSet::INVALID_POS) {
1358 OPENVDB_THROW(RuntimeError,
"Failed to find radius attribute \"" + settings.radius +
"\"");
1360 VaryingBandRadius<RadiusT> rad(ridx, RadiusT(halfband), indexSpaceScale);
1362 if (interrupter) interrupter->start(
"Rasterizing particles to level set using variable Spheres");
1364 grids = doRasterizeSurface<SdfT, SphericalTransfer, AttributeTypes, FilterT>
1365 (points, attributes, *surface,
1366 width, rad, points.transform(), filter, interrupter, *surface);
1369 if (interrupter) interrupter->end();
1372 grids.insert(grids.begin(), surface);
1377 template <
typename PointDataGridT,
1382 const SettingsT& settings,
1383 const typename SettingsT::FilterType& filter)
1385 static_assert(IsSpecializationOf<PointDataGridT, Grid>::value);
1386 static_assert(IsSpecializationOf<SettingsT, SmoothSphereSettings>::value);
1389 using FilterT =
typename SettingsT::FilterType;
1391 const std::vector<std::string>& attributes = settings.attributes;
1392 const Real halfband = settings.halfband;
1393 auto* interrupter = settings.interrupter;
1395 math::Transform::Ptr transform = settings.transform;
1396 if (!transform) transform = points.transform().copy();
1397 const Real vs = transform->voxelSize()[0];
1398 const typename SdfT::ValueType background =
1399 static_cast<typename SdfT::ValueType
>(vs * halfband);
1401 const Real indexSpaceSearch = settings.searchRadius / vs;
1403 const size_t width =
static_cast<size_t>(
math::RoundUp(indexSpaceSearch));
1411 const Real maxActivationRadius =
std::max(settings.searchRadius, settings.radiusScale) / vs;
1412 const auto leaf = points.constTree().cbeginLeaf();
1419 points.tree().evalLeafBoundingBox(bounds);
1421 typename SdfT::Ptr surface;
1424 if (settings.radius.empty()) {
1428 const FixedBandRadius<Real> bands(maxActivationRadius,
float(halfband));
1429 const Real max = bands.max();
1432 bounds.expand(static_cast<Coord::ValueType>(halfband +
math::Round(settings.radiusScale / vs)));
1434 surface = initFixedSmoothSdf<SdfT>
1435 (points, transform, background,
max, bounds, interrupter);
1439 const FixedRadius<Real> rad(settings.radiusScale / vs);
1440 if (interrupter) interrupter->start(
"Rasterizing particles to level set using constant Zhu-Bridson");
1442 grids = doRasterizeSurface<SdfT, AveragePositionTransfer, AttributeTypes, FilterT>
1443 (points, attributes, *surface,
1444 width, rad, indexSpaceSearch, points.transform(), filter, interrupter, *surface);
1447 using RadiusT =
typename SettingsT::RadiusAttributeType;
1448 using PointDataTreeT =
typename PointDataGridT::TreeType;
1449 using RadTreeT =
typename PointDataTreeT::template ValueConverter<RadiusT>::Type;
1455 typename RadTreeT::Ptr maxtree(
new RadTreeT);
1456 points::evalMinMax<RadiusT, UnknownCodec>
1457 (points.tree(), settings.radius,
min,
max, filter,
nullptr, maxtree.get());
1459 if ((settings.searchRadius > settings.radiusScale) && (min < settings.searchRadius)) {
1467 iter.modifyValue([&](
auto& r) {
1468 if (r < settings.searchRadius) {
1472 r = static_cast<RadiusT>(settings.searchRadius / settings.radiusScale);
1478 const RadiusT indexSpaceScale = RadiusT(settings.radiusScale / vs);
1480 bounds.expand(static_cast<Coord::ValueType>(halfband +
math::Round(max * indexSpaceScale)));
1483 surface = initVariableSmoothSdf<SdfT>
1484 (points, transform, background, *maxtree,
1485 indexSpaceScale, halfband, bounds, interrupter);
1490 const size_t ridx = leaf->attributeSet().find(settings.radius);
1491 if (ridx == AttributeSet::INVALID_POS) {
1492 OPENVDB_THROW(RuntimeError,
"Failed to find radius attribute");
1495 VaryingRadius<RadiusT> rad(ridx, indexSpaceScale);
1496 if (interrupter) interrupter->start(
"Rasterizing particles to level set using variable Zhu-Bridson");
1498 grids = doRasterizeSurface<SdfT, AveragePositionTransfer, AttributeTypes, FilterT>
1499 (points, attributes, *surface,
1500 width, rad, indexSpaceSearch, points.transform(), filter, interrupter, *surface);
1503 if (interrupter) interrupter->end();
1506 grids.insert(grids.begin(), surface);
1511 template <
typename Po
intDataGr
idT,
typename SdfT,
typename SettingsT>
1521 template <
typename PointDataGridT,
1527 const typename SettingsT::FilterType* filter = settings.filter;
1529 if constexpr (!std::is_same<typename SettingsT::FilterType, NullFilter>::value) {
1536 "A nullptr for a custom point-filter cannot be passed to rasterizeSdf().");
1544 filter = &sNullFilter;
1550 return rasterize_sdf_internal::rasterizeSpheres<PointDataGridT, SdfT, SettingsT>(points, settings, *filter);
1553 return rasterize_sdf_internal::rasterizeSmoothSpheres<PointDataGridT, SdfT, SettingsT>(points, settings, *filter);
1556 return rasterize_sdf_internal::rasterizeEllipsoids<PointDataGridT, SdfT, SettingsT>(points, settings, *filter);
1559 static_assert(!
sizeof(SettingsT),
1560 "No valid implementation for provided rasterization settings exists.");
1574 template <
typename PointDataGridT,
1575 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1586 rasterizeSpheres<PointDataGridT, TypeList<>, SdfT, FilterT>
1587 (points, radius, {}, halfband, transform, filter, interrupter);
1588 return StaticPtrCast<SdfT>(grids.front());
1591 template <
typename PointDataGridT,
1592 typename RadiusT = float,
1593 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1597 const std::string& radius,
1598 const Real scale = 1.0,
1605 rasterizeSpheres<PointDataGridT, TypeList<>, RadiusT, SdfT, FilterT>
1606 (points, radius, {},
scale, halfband, transform, filter, interrupter);
1607 return StaticPtrCast<SdfT>(grids.front());
1610 template <
typename PointDataGridT,
1612 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1617 const std::vector<std::string>& attributes,
1631 return rasterizeSdf<PointDataGridT, SdfT>(points, s);
1634 template <
typename PointDataGridT,
1636 typename RadiusT = float,
1637 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1641 const std::string& radius,
1642 const std::vector<std::string>& attributes,
1643 const Real scale = 1.0,
1651 if (
auto leaf = points.constTree().cbeginLeaf()) {
1652 const size_t ridx = leaf->attributeSet().find(radius);
1653 if (ridx == AttributeSet::INVALID_POS) {
1665 return rasterizeSdf<PointDataGridT, SdfT>(points, s);
1670 template <
typename PointDataGridT,
1671 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1676 const Real searchRadius,
1683 rasterizeSmoothSpheres<PointDataGridT, TypeList<>, SdfT, FilterT>
1684 (points, radius, searchRadius, {}, halfband, transform, filter, interrupter);
1685 return StaticPtrCast<SdfT>(grids.front());
1688 template <
typename PointDataGridT,
1689 typename RadiusT = float,
1690 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1694 const std::string& radius,
1695 const Real radiusScale,
1696 const Real searchRadius,
1703 rasterizeSmoothSpheres<PointDataGridT, TypeList<>, RadiusT, SdfT, FilterT>
1704 (points, radius, radiusScale, searchRadius, {}, halfband, transform, filter, interrupter);
1705 return StaticPtrCast<SdfT>(grids.front());
1708 template <
typename PointDataGridT,
1710 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1715 const Real searchRadius,
1716 const std::vector<std::string>& attributes,
1731 return rasterizeSdf<PointDataGridT, SdfT>(points, s);
1734 template <
typename PointDataGridT,
1736 typename RadiusT = float,
1737 typename SdfT =
typename PointDataGridT::template ValueConverter<float>::Type,
1741 const std::string& radius,
1742 const Real radiusScale,
1743 const Real searchRadius,
1744 const std::vector<std::string>& attributes,
1752 if (
auto leaf = points.constTree().cbeginLeaf()) {
1753 const size_t ridx = leaf->attributeSet().find(radius);
1754 if (ridx == AttributeSet::INVALID_POS) {
1767 return rasterizeSdf<PointDataGridT, SdfT>(points, s);
1775 #endif //OPENVDB_POINTS_RASTERIZE_SDF_IMPL_HAS_BEEN_INCLUDED Helper metafunction used to determine if the first template parameter is a specialization of the clas...
Definition: Types.h:263
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
uint64_t Index64
Definition: Types.h:53
OPENVDB_IMPORT void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1343
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:761
Real searchRadius
Definition: PointRasterizeSDF.h:266
void foreach(T &&t, const F &func, std::integer_sequence< size_t, Is... >)
Definition: PointTransfer.h:416
tree::Tree4< int64_t, 5, 4, 3 >::Type Int64Tree
Definition: openvdb.h:57
Index32 Index
Definition: Types.h:54
GridPtrVec rasterizeSdf(const PointDataGridT &points, const SettingsT &settings)
Perform point rasterzation to produce a signed distance field.
Definition: PointRasterizeSDFImpl.h:1525
std::string radius
Definition: PointRasterizeSDF.h:169
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition: Math.h:787
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
Vec3< int32_t > Vec3i
Definition: Vec3.h:662
const FilterT * filter
Definition: PointRasterizeSDF.h:221
Base class for interrupters.
Definition: NullInterrupter.h:25
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:615
math::BBox< Vec3d > BBoxd
Definition: Types.h:84
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
GridPtrVec rasterizeSpheres(const PointDataGridT &points, const std::string &radius, const std::vector< std::string > &attributes, const Real scale=1.0, const Real halfband=LEVEL_SET_HALF_WIDTH, math::Transform::Ptr transform=nullptr, const FilterT &filter=NullFilter(), util::NullInterrupter *interrupter=nullptr)
Definition: PointRasterizeSDFImpl.h:1640
Definition: Exceptions.h:63
Smoothed point distribution based sphere stamping with a uniform radius or varying radius and optiona...
Definition: PointRasterizeSDF.h:235
math::Vec3< float > Vec3f
Definition: Types.h:74
Type Pow2(Type x)
Return x2.
Definition: Math.h:548
NumericAttributeTypes::Append< Vec3AttributeTypes >::Append< Mat3AttributeTypes >::Append< Mat4AttributeTypes >::Append< QuatAttributeTypes >::Append< points::GroupAttributeArray >::Append< points::StringAttributeArray >::Append< points::TypedAttributeArray< bool >> AttributeTypes
The attribute array types which OpenVDB will register by default.
Definition: openvdb.h:186
Definition: Exceptions.h:13
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:819
RadiusScaleT radiusScale
Definition: PointRasterizeSDF.h:180
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:40
GridPtrVec rasterizeEllipsoids(const PointDataGridT &points, const SettingsT &settings, const typename SettingsT::FilterType &filter)
Definition: PointRasterizeEllipsoidsSDFImpl.h:582
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:532
__hostdev__ uint32_t hash(uint32_t x)
Definition: common.h:14
typename T::ValueType ElementType
Definition: Types.h:318
double Real
Definition: Types.h:60
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
Vec3< double > Vec3d
Definition: Vec3.h:665
std::vector< std::string > attributes
Definition: PointRasterizeSDF.h:216
math::Transform::Ptr transform
Definition: PointRasterizeSDF.h:187
GridPtrVec rasterizeSmoothSpheres(const PointDataGridT &points, const std::string &radius, const Real radiusScale, const Real searchRadius, const std::vector< std::string > &attributes, const Real halfband=LEVEL_SET_HALF_WIDTH, math::Transform::Ptr transform=nullptr, const FilterT &filter=NullFilter(), util::NullInterrupter *interrupter=nullptr)
Definition: PointRasterizeSDFImpl.h:1740
int64_t Int64
Definition: Types.h:57
Type Pow3(Type x)
Return x3.
Definition: Math.h:552
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:595
Generic settings for narrow band spherical stamping with a uniform or varying radius and optionally w...
Definition: PointRasterizeSDF.h:156
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
Real halfband
Definition: PointRasterizeSDF.h:183
util::NullInterrupter * interrupter
Definition: PointRasterizeSDF.h:224
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218