9 #ifndef OPENVDB_POINTS_RASTERIZE_ELLIPSOIDS_SDF_IMPL_HAS_BEEN_INCLUDED 10 #define OPENVDB_POINTS_RASTERIZE_ELLIPSOIDS_SDF_IMPL_HAS_BEEN_INCLUDED 16 #define OPENVDB_ELLIPSOID_KERNEL_MODE 2 23 namespace rasterize_sdf_internal
30 for (
int i = 0; i < 3; i++) {
32 ellipsoidTransform(i,0) * ellipsoidTransform(i,0) +
33 ellipsoidTransform(i,1) * ellipsoidTransform(i,1) +
34 ellipsoidTransform(i,2) * ellipsoidTransform(i,2);
45 boundMax[0] = std::sqrt(boundMax[0]);
46 boundMax[1] = std::sqrt(boundMax[1]);
47 boundMax[2] = std::sqrt(boundMax[2]);
55 const std::string& pws)
57 , positionws(
EllipseIndicies::getAttributeIndex<Vec3d>(desc, pws, true)) {}
64 template<
typename ValueT>
66 getAttributeIndex(
const points::AttributeSet::Descriptor& desc,
67 const std::string& name,
68 const bool allowMissing)
70 const size_t idx = desc.find(name);
71 if (idx == points::AttributeSet::INVALID_POS) {
73 throw std::runtime_error(
"Missing attribute - " + name);
75 if (typeNameAsString<ValueT>() != desc.valueType(idx)) {
76 throw std::runtime_error(
"Wrong attribute type for attribute " + name
77 +
", expected " + typeNameAsString<ValueT>());
83 template <
typename SdfT,
84 typename PositionCodecT,
89 public rasterize_sdf_internal::SphericalTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>
91 using BaseT = rasterize_sdf_internal::SphericalTransfer<SdfT, PositionCodecT, RadiusType, FilterT, CPG>;
92 using typename BaseT::TreeT;
93 using typename BaseT::ValueT;
95 static const Index DIM = TreeT::LeafNodeType::DIM;
96 static const Index LOG2DIM = TreeT::LeafNodeType::LOG2DIM;
106 const RadiusType& rt,
108 const FilterT& filter,
113 const std::unordered_map<const PointDataTree::LeafNodeType*, Index>* ids =
nullptr)
114 :
BaseT(pidx, width, rt, source, filter, interrupt, surface, cpg, ids)
117 , mPositionWSHandle() {}
121 , mIndices(other.mIndices)
123 , mPositionWSHandle() {}
127 const bool ret = this->BaseT::startPointLeaf(leaf);
128 mRotationHandle = std::make_unique<RotationHandleT>(leaf.constAttributeArray(mIndices.rotation));
129 if (mIndices.hasWorldSpacePosition()) {
130 mPositionWSHandle = std::make_unique<PwsHandleT>(leaf.constAttributeArray(mIndices.positionws));
137 const CoordBBox& bounds)
139 if (!BaseT::filter(
id))
return;
142 if (this->mPositionWSHandle) {
144 P = this->targetTransform().worldToIndex(this->mPositionWSHandle->get(
id));
147 const Vec3d PWS = this->sourceTransform().indexToWorld(ijk.asVec3d() + Vec3d(this->mPosition->get(
id)));
148 P = this->targetTransform().worldToIndex(PWS);
151 const auto& r = this->mRadius.eval(
id);
152 Vec3f radius = r.get();
156 if ((radius.
x() == radius.
y()) && (radius.
x() == radius.
z())) {
157 const FixedBandRadius<float> fixed(radius.
x(), r.halfband());
158 this->BaseT::rasterizePoint(P,
id, bounds, fixed);
162 #if OPENVDB_ELLIPSOID_KERNEL_MODE == 0 163 const FixedBandRadius<RealT> fbr(1.0, r.halfband());
172 const RealT min2 = fbr.minSq() == 0.0 ? -1.0 : fbr.minSq();
173 const RealT max2 = fbr.maxSq();
184 CoordBBox intersectBox(Coord::round(P - max), Coord::round(P + max));
185 intersectBox.intersect(bounds);
186 if (intersectBox.empty())
return;
188 auto*
const data = this->
template buffer<0>();
189 [[maybe_unused]]
auto*
const cpg = CPG ? this->
template buffer<CPG ? 1 : 0>() :
nullptr;
190 auto& mask = *(this->
template mask<0>());
193 const Vec3d radInv = 1.0f / radius;
195 #if OPENVDB_ELLIPSOID_KERNEL_MODE != 2 208 const Vec3d radInv2 = 1.0f /
math::Pow2(radius);
216 const Coord& a(intersectBox.min());
217 const Coord& b(intersectBox.max());
218 const float* inv = ellipsoidInverse.
asPointer();
219 for (Coord c = a; c.x() <= b.x(); ++c.x()) {
220 const RealT x =
static_cast<RealT>(c.x() - P[0]);
221 const Vec3d xradial(x*inv[0], x*inv[3], x*inv[6]);
222 const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM);
223 for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
224 const RealT y =
static_cast<RealT>(c.y() - P[1]);
225 const Vec3d xyradial = xradial + Vec3d(y*inv[1], y*inv[4], y*inv[7]);
226 const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM);
227 for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
228 const Index offset = ij + (c.z() & (DIM-1u));
229 if (!mask.isOn(offset))
continue;
230 const RealT z =
static_cast<RealT>(c.z() - P[2]);
233 const Vec3d pointOnUnitSphere = (xyradial + Vec3d(z*inv[2], z*inv[5], z*inv[8]));
237 #if OPENVDB_ELLIPSOID_KERNEL_MODE == 0 238 RealT len = pointOnUnitSphere.lengthSqr();
242 if (len >= max2)
continue;
244 data[offset] = -(this->mBackground);
248 d = ValueT(this->mDx * (
math::Sqrt(len) - 1.0));
249 #elif OPENVDB_ELLIPSOID_KERNEL_MODE == 1 250 RealT len = pointOnUnitSphere.lengthSqr();
262 Vec3d ellipseNormal = (ellipsoidInverse.
transpose() * pointOnUnitSphere);
263 ellipseNormal.normalize();
273 d =
static_cast<ValueT
>(
274 ((x * ellipseNormal.x()) +
275 (y * ellipseNormal.y()) +
276 (z * ellipseNormal.z()))
277 * (1.0 - (
RealT(1.0)/len))
281 if (d >= this->mBackground)
continue;
282 if (d <= -this->mBackground) {
283 data[offset] = -(this->mBackground);
287 #elif OPENVDB_ELLIPSOID_KERNEL_MODE == 2 288 const RealT k2 = (pointOnUnitSphere * radInv2).length();
296 const RealT k1 = (pointOnUnitSphere * radInv).length();
299 d =
static_cast<ValueT
>((k1 * (k1 -
RealT(1.0)) / k2) * this->mDx);
301 if (d >= this->mBackground)
continue;
302 if (d <= -this->mBackground) {
303 data[offset] = -(this->mBackground);
309 ValueT& v = data[offset];
312 if constexpr(CPG) cpg[offset] =
Int64(this->mPLeafMask |
Index64(
id));
321 std::unique_ptr<RotationHandleT> mRotationHandle;
322 std::unique_ptr<PwsHandleT> mPositionWSHandle;
326 template<
typename RadiusType,
typename MaskTreeT>
328 :
public rasterize_sdf_internal::SurfaceMaskOp<MaskTreeT>
330 using BaseT = rasterize_sdf_internal::SurfaceMaskOp<MaskTreeT>;
333 using RadiusT =
typename RadiusType::ValueType;
334 static const Index DIM = points::PointDataTree::LeafNodeType::DIM;
339 const RadiusType& rad,
342 :
BaseT(src, trg, nullptr)
344 , mHalfband(halfband)
350 , mRadius(other.mRadius)
351 , mHalfband(other.mHalfband)
352 , mIndices(other.mIndices)
360 this->BaseT::join(other);
369 RadiusType rad(mRadius);
371 if constexpr(RadiusType::Fixed) {
372 maxr = rad.eval(0).get();
375 for (
Index i = 0; i <
Index(rad.size()); ++i) {
392 if (!mIndices.hasWorldSpacePosition()) {
393 if (!this->
activate(leaf, dist))
return;
400 if (pwsHandle.size() == 0)
return;
401 Vec3d maxPos(std::numeric_limits<Real>::lowest()),
403 for (
Index i = 0; i <
Index(pwsHandle.size()); ++i)
405 const Vec3d Pws = pwsHandle.get(i);
411 CoordBBox surfaceBounds(
412 Coord::round(this->mSurfaceTransform.worldToIndex(minPos)),
413 Coord::round(this->mSurfaceTransform.worldToIndex(maxPos)));
414 surfaceBounds.min() -= Coord(dist);
415 surfaceBounds.max() += Coord(dist);
418 this->updateMaxLookup(minPos, maxPos, dist, leaf);
428 RadiusType rad(mRadius);
430 const Vec3f radius0 = rad.eval(0).get();
432 if constexpr(RadiusType::Fixed) {
435 const bool isSphere = (radius0.
x() == radius0.
y()) && (radius0.
x() == radius0.
z());
437 this->fillFromStretch(leaf);
442 Vec3d maxPos(std::numeric_limits<Real>::lowest()),
446 if (!mIndices.hasWorldSpacePosition())
448 const CoordBBox box = this->getActiveBoundingBox(leaf);
449 if (box.empty())
return;
450 minPos = this->mPointsTransform.indexToWorld(box.min().asVec3d() - 0.5);
451 maxPos = this->mPointsTransform.indexToWorld(box.max().asVec3d() + 0.5);
457 if (pwsHandle.size() == 0)
return;
458 for (
Index i = 0; i < pwsHandle.size(); ++i)
460 const Vec3d Pws = pwsHandle.get(i);
468 float maxUniformRadius(0);
472 for (
Index i = 0; i < rotHandle.size(); ++i)
476 if constexpr(!RadiusType::Fixed)
478 r = rad.eval(i).get();
479 const bool isSphere = (r.
x() == r.
y()) && (r.
x() == r.
z());
482 maxUniformRadius =
std::max(maxUniformRadius,
float(r.
x()));
494 for (
size_t i = 0; i < 3; ++i) {
496 maxBounds[i] = std::sqrt(maxBounds[i]);
499 maxBounds[i] =
std::max(
double(maxUniformRadius), maxBounds[i]);
508 const Coord dist = Coord::round(maxBounds + mHalfband);
510 CoordBBox surfaceBounds(
511 Coord::round(this->mSurfaceTransform.worldToIndex(minPos)),
512 Coord::round(this->mSurfaceTransform.worldToIndex(maxPos)));
513 surfaceBounds.min() -= dist;
514 surfaceBounds.max() += dist;
517 this->updateMaxLookup(minPos, maxPos, dist.asVec3i(), leaf);
522 for (
auto leaf = range.
begin(); leaf; ++leaf) {
523 this->fillFromStretchAndRotation(*leaf);
528 void updateMaxLookup(
const Vec3d& minWs,
536 Coord minIdx = this->mPointsTransform.worldToIndexCellCentered(minWs);
537 Coord maxIdx = this->mPointsTransform.worldToIndexCellCentered(maxWs);
538 const auto bounds = leaf.getNodeBoundingBox();
544 if (!bounds.isInside(maxIdx)) {
545 maxIdx -= leaf.origin();
546 if (maxIdx.x() > 0) maxIdx.x() -= DIM;
547 if (maxIdx.y() > 0) maxIdx.y() -= DIM;
548 if (maxIdx.z() > 0) maxIdx.z() -= DIM;
549 maxIdx =
Abs(maxIdx);
554 if (!bounds.isInside(minIdx))
556 minIdx -= leaf.origin();
557 if (minIdx.x() > 0) minIdx.x() -= DIM;
558 if (minIdx.y() > 0) minIdx.y() -= DIM;
559 if (minIdx.z() > 0) minIdx.z() -= DIM;
560 minIdx =
Abs(minIdx);
567 maxIdx.maxComponent(minIdx);
572 const RadiusType& mRadius;
573 const Real mHalfband;
578 template <
typename PointDataGridT,
583 const SettingsT& settings,
584 const typename SettingsT::FilterType& filter)
589 using namespace rasterize_sdf_internal;
591 using PointDataTreeT =
typename PointDataGridT::TreeType;
592 using MaskTreeT =
typename SdfT::TreeType::template ValueConverter<ValueMask>::Type;
594 using FilterT =
typename SettingsT::FilterType;
596 const std::vector<std::string>& attributes = settings.attributes;
597 const Real halfband = settings.halfband;
598 const Vec3d radiusScale = settings.radiusScale;
599 auto* interrupter = settings.interrupter;
602 if (!transform) transform = points.transform().copy();
603 const Real vs = transform->voxelSize()[0];
604 const typename SdfT::ValueType background =
605 static_cast<typename SdfT::ValueType
>(vs * halfband);
608 const auto leaf = points.constTree().cbeginLeaf();
610 typename SdfT::Ptr surface = SdfT::create(background);
611 surface->setTransform(transform);
621 typename SdfT::Ptr surface;
624 if (settings.radius.empty()) {
626 FixedBandRadius<Vec3f> rad(
Vec3f(radiusScale / vs),
float(halfband));
637 if (interrupter) interrupter->start(
"Generating ellipsoidal surface topology");
643 op(points.transform(), *transform, rad, halfband, indices);
644 tbb::parallel_reduce(manager.leafRange(),
op);
646 surface = rasterize_sdf_internal::initSdfFromMasks<SdfT, MaskTreeT>
647 (transform, background,
op.mask(),
op.maskoff());
649 width =
op.getMaxDist();
651 if (interrupter) interrupter->end();
654 if (interrupter) interrupter->start(
"Rasterizing particles to level set using ellipses and fixed spheres");
656 grids = doRasterizeSurface<SdfT, EllipsoidTransfer, AttributeTypes, FilterT>
657 (points, attributes, *surface,
658 width, rad, points.transform(), filter, interrupter, *surface, indices);
661 using RadiusT =
typename SettingsT::RadiusAttributeType;
663 const size_t ridx = leaf->attributeSet().find(settings.radius);
664 if (ridx == AttributeSet::INVALID_POS) {
669 VaryingBandRadius<RadiusT, Vec3f> rad(ridx,
float(halfband),
Vec3f(radiusScale / vs));
680 if (interrupter) interrupter->start(
"Generating variable ellipsoidal surface topology");
686 op(points.transform(), *transform, rad, halfband, indices);
687 tbb::parallel_reduce(manager.leafRange(),
op);
689 surface = rasterize_sdf_internal::initSdfFromMasks<SdfT, MaskTreeT>
690 (transform, background,
op.mask(),
op.maskoff());
692 width =
op.getMaxDist();
694 if (interrupter) interrupter->end();
697 if (interrupter) interrupter->start(
"Rasterizing particles to level set using variable ellipses");
699 grids = doRasterizeSurface<SdfT, EllipsoidTransfer, AttributeTypes, FilterT>
700 (points, attributes, *surface,
701 width, rad, points.transform(), filter, interrupter, *surface, indices);
704 if (interrupter) interrupter->end();
706 grids.insert(grids.begin(), surface);
716 #endif // OPENVDB_POINTS_RASTERIZE_ELLIPSOIDS_SDF_IMPL_HAS_BEEN_INCLUDED EllipseIndicies(const points::AttributeSet::Descriptor &desc, const std::string &rotation, const std::string &pws)
Definition: PointRasterizeEllipsoidsSDFImpl.h:53
typename RadiusType::ValueType RadiusT
Definition: PointRasterizeEllipsoidsSDFImpl.h:333
Helper metafunction used to determine if the first template parameter is a specialization of the clas...
Definition: Types.h:263
T & y()
Definition: Vec3.h:87
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:504
points::PointDataTree::LeafNodeType PointDataLeaf
Definition: PointRasterizeEllipsoidsSDFImpl.h:331
Iterator begin() const
Definition: LeafManager.h:156
EllipsoidTransfer(const size_t pidx, const Vec3i width, const RadiusType &rt, const math::Transform &source, const FilterT &filter, util::NullInterrupter *interrupt, SdfT &surface, const EllipseIndicies &indices, Int64Tree *cpg=nullptr, const std::unordered_map< const PointDataTree::LeafNodeType *, Index > *ids=nullptr)
Definition: PointRasterizeEllipsoidsSDFImpl.h:104
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: LeafManager.h:102
uint64_t Index64
Definition: Types.h:53
void operator()(const typename LeafManagerT::LeafRange &range)
Definition: PointRasterizeEllipsoidsSDFImpl.h:520
Coord Abs(const Coord &xyz)
Definition: Coord.h:518
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
Definition: PointRasterizeEllipsoidsSDFImpl.h:88
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:761
EllipseSurfaceMaskOp(const EllipseSurfaceMaskOp &other, tbb::split)
Definition: PointRasterizeEllipsoidsSDFImpl.h:348
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:203
Mat3 transpose() const
returns transpose of this
Definition: Mat3.h:454
math::Vec3d calcEllipsoidBoundMax(const math::Mat3s &ellipsoidTransform)
Definition: PointRasterizeEllipsoidsSDFImpl.h:42
Index32 Index
Definition: Types.h:54
void setSymmetric(const Vec3< T > &vdiag, const Vec3< T > &vtri)
Set diagonal and symmetric triangular components.
Definition: Mat3.h:223
T & z()
Definition: Vec3.h:88
double RealT
Definition: PointRasterizeEllipsoidsSDFImpl.h:98
bool startPointLeaf(const PointDataTree::LeafNodeType &leaf)
Definition: PointRasterizeEllipsoidsSDFImpl.h:125
rasterize_sdf_internal::SurfaceMaskOp< MaskTreeT > BaseT
Definition: PointRasterizeEllipsoidsSDFImpl.h:330
Mat3< float > Mat3s
Definition: Mat3.h:832
Vec3< int32_t > Vec3i
Definition: Vec3.h:662
EllipsoidTransfer(const EllipsoidTransfer &other)
Definition: PointRasterizeEllipsoidsSDFImpl.h:119
void fillFromStretchAndRotation(const typename LeafManagerT::LeafNodeType &leaf)
Fill activity by analyzing the axis aligned ellipse bounding boxes on points in this leaf...
Definition: PointRasterizeEllipsoidsSDFImpl.h:426
Base class for interrupters.
Definition: NullInterrupter.h:25
Definition: AttributeArray.h:763
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:86
EllipseSurfaceMaskOp(const math::Transform &src, const math::Transform &trg, const RadiusType &rad, const Real halfband, const EllipseIndicies &indices)
Definition: PointRasterizeEllipsoidsSDFImpl.h:336
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: PointRasterizeEllipsoidsSDFImpl.h:51
Definition: Exceptions.h:63
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
GridPtrVec rasterizeEllipsoids(const PointDataGridT &points, const SettingsT &settings, const typename SettingsT::FilterType &filter)
Definition: PointRasterizeEllipsoidsSDFImpl.h:582
void rasterizePoint(const Coord &ijk, const Index id, const CoordBBox &bounds)
Definition: PointRasterizeEllipsoidsSDFImpl.h:135
LeafType LeafNodeType
Definition: LeafManager.h:93
double Real
Definition: Types.h:60
rasterize_sdf_internal::SphericalTransfer< SdfT, PositionCodecT, RadiusType, FilterT, CPG > BaseT
Definition: PointRasterizeEllipsoidsSDFImpl.h:91
const size_t rotation
Definition: PointRasterizeEllipsoidsSDFImpl.h:61
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:513
T * asPointer()
Direct access to the internal data.
Definition: Mat.h:101
int64_t Int64
Definition: Types.h:57
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition: Mat.h:172
math::Vec3d calcUnitEllipsoidBoundMaxSq(const math::Mat3s &ellipsoidTransform)
Definition: PointRasterizeEllipsoidsSDFImpl.h:27
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
void join(EllipseSurfaceMaskOp &other)
Definition: PointRasterizeEllipsoidsSDFImpl.h:357
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
Mat3 timesDiagonal(const Vec3< T > &diag) const
Treat diag as a diagonal matrix and return the product of this matrix with diag (from the right)...
Definition: Mat3.h:521
bool hasWorldSpacePosition() const
Definition: PointRasterizeEllipsoidsSDFImpl.h:59
Definition: PointRasterizeEllipsoidsSDFImpl.h:327
void fillFromStretch(const typename LeafManagerT::LeafNodeType &leaf)
Fill activity by analyzing the radius values on points in this leaf. Ignored ellipsoid rotations whic...
Definition: PointRasterizeEllipsoidsSDFImpl.h:366
Vec3i getMaxDist() const
Definition: PointRasterizeEllipsoidsSDFImpl.h:355
3x3 matrix class.
Definition: Mat3.h:28
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218