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
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)
64 template<
typename ValueT>
67 const std::string& name,
68 const bool allowMissing)
70 const size_t idx = desc.
find(name);
72 if (allowMissing)
return std::numeric_limits<size_t>::max();
73 throw std::runtime_error(
"Missing attribute - " + name);
76 throw std::runtime_error(
"Wrong attribute type for attribute " + name
83template <
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;
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));
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();
176 const math::Mat3s rotation = mRotationHandle->get(
id);
177 const math::Mat3s ellipsoidTransform = rotation.timesDiagonal(radius);
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
202 const math::Mat3s ellipsoidInverse = invDiag * rotation.transpose();
209 const math::Mat3s ellipsoidInverse = rotation.transpose();
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]);
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]);
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
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
259 d = -ValueT(std::min(radius.
x(), std::min(radius.
y(), radius.
z()))) * ValueT(this->mDx);
262 Vec3d ellipseNormal = (ellipsoidInverse.
transpose() * pointOnUnitSphere);
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();
293 d = -ValueT(std::min(radius.
x(), std::min(radius.
y(), radius.
z()))) * ValueT(this->mDx);
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;
326template<
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) {
383 const Real maxRadius = std::max(maxr.
x(), std::max(maxr.
y(), maxr.
z()));
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()),
402 minPos(std::numeric_limits<Real>::max());
412 Coord::round(this->mSurfaceTransform.worldToIndex(minPos)),
413 Coord::round(this->mSurfaceTransform.worldToIndex(maxPos)));
416 this->activate(surfaceBounds);
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());
442 Vec3d maxPos(std::numeric_limits<Real>::lowest()),
443 minPos(std::numeric_limits<Real>::max());
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)
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()));
489 const math::Mat3s ellipsoidTransform = rotation.timesDiagonal(r);
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]);
511 Coord::round(this->mSurfaceTransform.worldToIndex(minPos)),
512 Coord::round(this->mSurfaceTransform.worldToIndex(maxPos)));
513 surfaceBounds.
min() -= dist;
514 surfaceBounds.
max() += dist;
515 this->activate(surfaceBounds);
517 this->updateMaxLookup(minPos, maxPos, dist.
asVec3i(), leaf);
520 void operator()(
const typename LeafManagerT::LeafRange& range)
522 for (
auto leaf = range.begin(); leaf; ++leaf) {
528 void updateMaxLookup(
const Vec3d& minWs,
531 const typename LeafManagerT::LeafNodeType& leaf)
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);
568 mMaxDist = math::maxComponent(mMaxDist, dist + maxIdx.
asVec3i());
572 const RadiusType& mRadius;
573 const Real mHalfband;
574 const EllipseIndicies& mIndices;
578template <
typename PointDataGridT,
583 const SettingsT& settings,
584 const typename SettingsT::FilterType& filter)
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);
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);
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition Coord.h:51
Definition Exceptions.h:63
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition Coord.h:359
const Coord & min() const
Definition Coord.h:324
const Coord & max() const
Definition Coord.h:325
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition Coord.h:447
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Vec3d asVec3d() const
Definition Coord.h:144
Int32 y() const
Definition Coord.h:132
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition Coord.h:184
Coord & reset(Int32 x, Int32 y, Int32 z)
Reset all three coordinates with the specified arguments.
Definition Coord.h:70
Int32 x() const
Definition Coord.h:131
Vec3i asVec3i() const
Definition Coord.h:146
Int32 z() const
Definition Coord.h:133
Mat3 transpose() const
returns transpose of this
Definition Mat3.h:454
void setSymmetric(const Vec3< T > &vdiag, const Vec3< T > &vtri)
Set diagonal and symmetric triangular components.
Definition Mat3.h:223
T * asPointer()
Definition Mat.h:101
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:86
T & y()
Definition Vec3.h:87
T & z()
Definition Vec3.h:88
T lengthSqr() const
Definition Vec3.h:212
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition Vec3.h:363
Definition AttributeArray.h:764
Index size() const
Definition AttributeArray.h:786
ValueType get(Index n, Index m=0) const
Definition AttributeArray.h:2058
An immutable object that stores name, type and AttributeSet position for a constant collection of att...
Definition AttributeSet.h:311
size_t find(const std::string &name) const
Return the position of the attribute array whose name is name, or INVALID_POS if no match is found.
const Name & valueType(size_t pos) const
Return the name of the attribute array's type.
@ INVALID_POS
Definition AttributeSet.h:42
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition LeafManager.h:346
LeafType LeafNodeType
Definition LeafManager.h:93
typename RootNodeType::LeafNodeType LeafNodeType
Definition Tree.h:203
float Sqrt(float x)
Return the square root of a floating-point value.
Definition Math.h:761
Mat3< float > Mat3s
Definition Mat3.h:832
Vec3< double > Vec3d
Definition Vec3.h:665
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:819
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition Vec2.h:504
Vec3< int32_t > Vec3i
Definition Vec3.h:662
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition Vec2.h:513
Type Pow2(Type x)
Return x2.
Definition Math.h:548
Definition PointRasterizeEllipsoidsSDFImpl.h:24
GridPtrVec rasterizeEllipsoids(const PointDataGridT &points, const SettingsT &settings, const typename SettingsT::FilterType &filter)
Definition PointRasterizeEllipsoidsSDFImpl.h:582
math::Vec3d calcUnitEllipsoidBoundMaxSq(const math::Mat3s &ellipsoidTransform)
Definition PointRasterizeEllipsoidsSDFImpl.h:27
math::Vec3d calcEllipsoidBoundMax(const math::Mat3s &ellipsoidTransform)
Definition PointRasterizeEllipsoidsSDFImpl.h:42
Definition AttributeArray.h:42
std::vector< GridBase::Ptr > GridPtrVec
Definition Grid.h:508
Index32 Index
Definition Types.h:54
math::Vec3< float > Vec3f
Definition Types.h:74
double Real
Definition Types.h:60
@ GRID_LEVEL_SET
Definition Types.h:526
int64_t Int64
Definition Types.h:57
tree::Tree4< int64_t, 5, 4, 3 >::Type Int64Tree
Definition openvdb.h:57
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:178
uint64_t Index64
Definition Types.h:53
const char * typeNameAsString()
Definition Types.h:587
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Helper metafunction used to determine if the first template parameter is a specialization of the clas...
Definition Types.h:263
Definition PointRasterizeEllipsoidsSDFImpl.h:52
bool hasWorldSpacePosition() const
Definition PointRasterizeEllipsoidsSDFImpl.h:59
const size_t positionws
Definition PointRasterizeEllipsoidsSDFImpl.h:61
const size_t rotation
Definition PointRasterizeEllipsoidsSDFImpl.h:61
EllipseIndicies(const points::AttributeSet::Descriptor &desc, const std::string &rotation, const std::string &pws)
Definition PointRasterizeEllipsoidsSDFImpl.h:53
Definition PointRasterizeEllipsoidsSDFImpl.h:329
typename RadiusType::ValueType RadiusT
Definition PointRasterizeEllipsoidsSDFImpl.h:333
void operator()(const typename LeafManagerT::LeafRange &range)
Definition PointRasterizeEllipsoidsSDFImpl.h:520
static const Index DIM
Definition PointRasterizeEllipsoidsSDFImpl.h:334
void join(EllipseSurfaceMaskOp &other)
Definition PointRasterizeEllipsoidsSDFImpl.h:357
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
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
Vec3i getMaxDist() const
Definition PointRasterizeEllipsoidsSDFImpl.h:355
rasterize_sdf_internal::SurfaceMaskOp< MaskTreeT > BaseT
Definition PointRasterizeEllipsoidsSDFImpl.h:330
EllipseSurfaceMaskOp(const EllipseSurfaceMaskOp &other, tbb::split)
Definition PointRasterizeEllipsoidsSDFImpl.h:348
EllipseSurfaceMaskOp(const math::Transform &src, const math::Transform &trg, const RadiusType &rad, const Real halfband, const EllipseIndicies &indices)
Definition PointRasterizeEllipsoidsSDFImpl.h:336
points::PointDataTree::LeafNodeType PointDataLeaf
Definition PointRasterizeEllipsoidsSDFImpl.h:331
tree::LeafManager< const points::PointDataTree > LeafManagerT
Definition PointRasterizeEllipsoidsSDFImpl.h:332
rasterize_sdf_internal::SphericalTransfer< SdfT, PositionCodecT, RadiusType, FilterT, CPG > BaseT
Definition PointRasterizeEllipsoidsSDFImpl.h:91
points::AttributeHandle< math::Mat3s > RotationHandleT
Definition PointRasterizeEllipsoidsSDFImpl.h:100
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
static const Index DIM
Definition PointRasterizeEllipsoidsSDFImpl.h:95
double RealT
Definition PointRasterizeEllipsoidsSDFImpl.h:98
void rasterizePoint(const Coord &ijk, const Index id, const CoordBBox &bounds)
Definition PointRasterizeEllipsoidsSDFImpl.h:135
points::AttributeHandle< Vec3d > PwsHandleT
Definition PointRasterizeEllipsoidsSDFImpl.h:102
bool startPointLeaf(const PointDataTree::LeafNodeType &leaf)
Definition PointRasterizeEllipsoidsSDFImpl.h:125
static const Index LOG2DIM
Definition PointRasterizeEllipsoidsSDFImpl.h:96
EllipsoidTransfer(const EllipsoidTransfer &other)
Definition PointRasterizeEllipsoidsSDFImpl.h:119
points::AttributeHandle< Vec3f > PHandleT
Definition PointRasterizeEllipsoidsSDFImpl.h:101
Base class for interrupters.
Definition NullInterrupter.h:26
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218