9#ifndef OPENVDB_POINTS_POINT_RASTERIZE_FRUSTUM_IMPL_HAS_BEEN_INCLUDED
10#define OPENVDB_POINTS_POINT_RASTERIZE_FRUSTUM_IMPL_HAS_BEEN_INCLUDED
19namespace point_rasterize_internal {
23template <
typename FilterT>
24struct RasterGroupTraits
26 using NewFilterT = FilterT;
27 static NewFilterT resolve(
const FilterT& filter,
const points::AttributeSet&)
35struct RasterGroupTraits<RasterGroups>
37 using NewFilterT = points::MultiGroupFilter;
38 static NewFilterT resolve(
const RasterGroups& groups,
const points::AttributeSet& attributeSet)
40 return NewFilterT(groups.includeNames, groups.excludeNames, attributeSet);
46template <
typename T>
struct BoolTraits {
static const bool IsBool =
false; };
47template <>
struct BoolTraits<bool> {
static const bool IsBool =
true; };
48template <>
struct BoolTraits<ValueMask> {
static const bool IsBool =
true; };
53 explicit TrueOp(
double scale) : mOn(
scale > 0.0) { }
54 template<
typename ValueType>
55 void operator()(ValueType& v)
const { v =
static_cast<ValueType
>(mOn); }
59template <
typename ValueT>
60typename std::enable_if<std::is_integral<typename ValueTraits<ValueT>::ElementType>
::value, ValueT>::type
61castValue(
const double value)
63 return ValueT(math::Ceil(
value));
67template <
typename ValueT>
68typename std::enable_if<!std::is_integral<typename ValueTraits<ValueT>::ElementType>
::value, ValueT>::type
69castValue(
const double value)
71 return static_cast<ValueT
>(
value);
75template <
typename ValueT>
76typename std::enable_if<!ValueTraits<ValueT>::IsVec,
bool>::type
77greaterThan(
const ValueT&
value,
const float threshold)
79 return value >=
static_cast<ValueT
>(threshold);
83template <
typename ValueT>
84typename std::enable_if<ValueTraits<ValueT>::IsVec,
bool>::type
85greaterThan(
const ValueT&
value,
const float threshold)
87 return static_cast<double>(
value.lengthSqr()) >= threshold*threshold;
91template <
typename AttributeT,
typename HandleT,
typename Str
idedHandleT>
92typename std::enable_if<!ValueTraits<AttributeT>::IsVec, AttributeT>::type
93getAttributeScale(HandleT& handlePtr, StridedHandleT&, Index index)
96 return handlePtr->get(index);
102template <
typename AttributeT,
typename HandleT,
typename Str
idedHandleT>
103typename std::enable_if<ValueTraits<AttributeT>::IsVec, AttributeT>::type
104getAttributeScale(HandleT& handlePtr, StridedHandleT& stridedHandlePtr, Index index)
107 return handlePtr->get(index);
108 }
else if (stridedHandlePtr) {
110 stridedHandlePtr->get(index, 0),
111 stridedHandlePtr->get(index, 1),
112 stridedHandlePtr->get(index, 2));
114 return AttributeT(1);
118template <
typename ValueT>
121 template <
typename AttributeT>
122 static ValueT mul(
const ValueT& a,
const AttributeT& b)
129struct MultiplyOp<bool>
131 template <
typename AttributeT>
132 static bool mul(
const bool& a,
const AttributeT& b)
134 return a && (b != zeroVal<AttributeT>());
138template <
typename PointDataGridT,
typename AttributeT,
typename GridT,
142 using TreeT =
typename GridT::TreeType;
143 using LeafT =
typename TreeT::LeafNodeType;
144 using ValueT =
typename TreeT::ValueType;
145 using PointLeafT =
typename PointDataGridT::TreeType::LeafNodeType;
146 using PointIndexT =
typename PointLeafT::ValueType;
147 using CombinableT = tbb::combinable<GridT>;
148 using SumOpT = tools::valxform::SumOp<ValueT>;
149 using MaxOpT = tools::valxform::MaxOp<ValueT>;
150 using PositionHandleT = openvdb::points::AttributeHandle<Vec3f>;
151 using VelocityHandleT = openvdb::points::AttributeHandle<Vec3f>;
152 using RadiusHandleT = openvdb::points::AttributeHandle<float>;
155 static const int interruptThreshold = 32*32*32;
158 const PointDataGridT& grid,
159 const std::vector<Index64>& offsets,
160 const size_t attributeIndex,
161 const Name& velocityAttribute,
162 const Name& radiusAttribute,
163 CombinableT& combinable,
164 CombinableT* weightCombinable,
165 const bool dropBuffers,
167 const FilterT& filter,
168 const bool computeMax,
169 const bool alignedTransform,
170 const bool staticCamera,
171 const FrustumRasterizerSettings& settings,
172 const FrustumRasterizerMask& mask,
173 util::NullInterrupter* interrupt)
176 , mAttributeIndex(attributeIndex)
177 , mVelocityAttribute(velocityAttribute)
178 , mRadiusAttribute(radiusAttribute)
179 , mCombinable(combinable)
180 , mWeightCombinable(weightCombinable)
181 , mDropBuffers(dropBuffers)
184 , mComputeMax(computeMax)
185 , mAlignedTransform(alignedTransform)
186 , mStaticCamera(staticCamera)
187 , mSettings(settings)
189 , mInterrupter(interrupt) { }
191 template <
typename Po
intOpT>
192 static void rasterPoint(
const Coord& ijk,
const double scale,
193 const AttributeT& attributeScale, PointOpT& op)
195 op(ijk, scale, attributeScale);
198 template <
typename Po
intOpT>
199 static void rasterPoint(
const Vec3d& position,
const double scale,
200 const AttributeT& attributeScale, PointOpT& op)
202 Coord ijk = Coord::round(position);
203 op(ijk, scale, attributeScale);
206 template <
typename SphereOpT>
207 static void rasterVoxelSphere(
const Vec3d& position,
const double scale,
208 const AttributeT& attributeScale,
const float radius, util::NullInterrupter* interrupter, SphereOpT& op)
210 assert(radius > 0.0f);
211 Coord ijk = Coord::round(position);
212 int &i = ijk[0], &j = ijk[1], &k = ijk[2];
213 const int imin=math::Floor(position[0]-radius), imax=math::Ceil(position[0]+radius);
214 const int jmin=math::Floor(position[1]-radius), jmax=math::Ceil(position[1]+radius);
215 const int kmin=math::Floor(position[2]-radius), kmax=math::Ceil(position[2]+radius);
217 const bool interrupt = interrupter && (imax-imin)*(jmax-jmin)*(kmax-kmin) > interruptThreshold;
219 for (i = imin; i <= imax; ++i) {
220 if (interrupt && interrupter->wasInterrupted())
break;
221 const auto x2 = math::Pow2(i - position[0]);
222 for (j = jmin; j <= jmax; ++j) {
223 if (interrupt && interrupter->wasInterrupted())
break;
224 const auto x2y2 = math::Pow2(j - position[1]) + x2;
225 for (k = kmin; k <= kmax; ++k) {
226 const auto x2y2z2 = x2y2 + math::Pow2(k - position[2]);
227 op(ijk, scale, attributeScale, x2y2z2, radius*radius);
233 template <
typename SphereOpT>
234 static void rasterApproximateFrustumSphere(
const Vec3d& position,
const double scale,
235 const AttributeT& attributeScale,
const float radiusWS,
236 const math::Transform& frustum,
const CoordBBox* clipBBox,
237 util::NullInterrupter* interrupter, SphereOpT& op)
239 Vec3d voxelSize = frustum.voxelSize(position);
241 CoordBBox frustumBBox(Coord::floor(position-radius), Coord::ceil(position+radius));
245 frustumBBox.intersect(*clipBBox);
248 Vec3i outMin = frustumBBox.min().asVec3i();
249 Vec3i outMax = frustumBBox.max().asVec3i();
251 const bool interrupt = interrupter && frustumBBox.volume() > interruptThreshold;
256 int &x = outXYZ.
x(), &y = outXYZ.y(), &z = outXYZ.z();
257 for (x = outMin.x(); x <= outMax.x(); ++x) {
258 if (interrupt && interrupter->wasInterrupted())
break;
260 for (y = outMin.y(); y <= outMax.y(); ++y) {
261 if (interrupt && interrupter->wasInterrupted())
break;
263 for (z = outMin.z(); z <= outMax.z(); ++z) {
268 Vec3d offset = (xyz - position) * voxelSize;
270 double distanceSqr = offset.
dot(offset);
272 op(outXYZ, scale, attributeScale, distanceSqr, radiusWS*radiusWS);
278 template <
typename SphereOpT>
279 static void rasterFrustumSphere(
const Vec3d& position,
const double scale,
280 const AttributeT& attributeScale,
const float radiusWS,
281 const math::Transform& frustum,
const CoordBBox* clipBBox,
282 util::NullInterrupter* interrupter, SphereOpT& op)
284 const Vec3d positionWS = frustum.indexToWorld(position);
286 BBoxd inputBBoxWS(positionWS-radiusWS, positionWS+radiusWS);
291 math::calculateBounds(frustum, inputBBoxWS.min(), inputBBoxWS.max(),
292 frustumMin, frustumMax);
293 CoordBBox frustumBBox(Coord::floor(frustumMin), Coord::ceil(frustumMax));
297 frustumBBox.intersect(*clipBBox);
300 Vec3i outMin = frustumBBox.min().asVec3i();
301 Vec3i outMax = frustumBBox.max().asVec3i();
303 const bool interrupt = interrupter && frustumBBox.volume() > interruptThreshold;
308 int &x = outXYZ.
x(), &y = outXYZ.y(), &z = outXYZ.z();
309 for (x = outMin.x(); x <= outMax.x(); ++x) {
310 if (interrupt && interrupter->wasInterrupted())
break;
312 for (y = outMin.y(); y <= outMax.y(); ++y) {
313 if (interrupt && interrupter->wasInterrupted())
break;
315 for (z = outMin.z(); z <= outMax.z(); ++z) {
318 Vec3R xyzWS = frustum.indexToWorld(xyz);
320 double xDist = xyzWS.
x() - positionWS.x();
321 double yDist = xyzWS.y() - positionWS.y();
322 double zDist = xyzWS.z() - positionWS.z();
324 double distanceSqr = xDist*xDist+yDist*yDist+zDist*zDist;
325 op(outXYZ, scale, attributeScale, distanceSqr, radiusWS*radiusWS);
331 void operator()(
const PointLeafT& leaf,
size_t)
const
333 if (mInterrupter && mInterrupter->wasInterrupted()) {
334 thread::cancelGroupExecution();
338 using AccessorT = tree::ValueAccessor<typename GridT::TreeType>;
339 using MaskAccessorT = tree::ValueAccessor<const MaskTree>;
341 constexpr bool isBool = BoolTraits<ValueT>::IsBool;
342 const bool isFrustum = !mSettings.transform->isLinear();
344 const bool useRaytrace = mSettings.velocityMotionBlur || !mStaticCamera;
345 const bool useRadius = mSettings.useRadius;
346 const float radiusScale = mSettings.radiusScale;
347 const float radiusThreshold = std::sqrt(3.0f);
349 const float threshold = mSettings.threshold;
350 const bool scaleByVoxelVolume = !useRadius && mSettings.scaleByVoxelVolume;
352 const float shutterStartDt = mSettings.camera.shutterStart()/mSettings.framesPerSecond;
353 const float shutterEndDt = mSettings.camera.shutterEnd()/mSettings.framesPerSecond;
354 const int motionSteps = std::max(1, mSettings.motionSamples-1);
356 std::vector<Vec3d> motionPositions(motionSteps+1,
Vec3d());
357 std::vector<Vec2s> frustumRadiusSizes(motionSteps+1,
Vec2s());
359 const auto& pointsTransform = mGrid.constTransform();
361 const float voxelSize =
static_cast<float>(mSettings.transform->voxelSize()[0]);
363 auto& grid = mCombinable.local();
364 auto& tree = grid.tree();
365 const auto& transform = *(mSettings.transform);
367 grid.setTransform(mSettings.transform->copy());
369 AccessorT valueAccessor(tree);
371 std::unique_ptr<MaskAccessorT> maskAccessor;
372 auto maskTree = mMask.getTreePtr();
373 if (maskTree) maskAccessor.reset(
new MaskAccessorT(*maskTree));
375 const CoordBBox* clipBBox = !mMask.clipBBox().empty() ? &mMask.clipBBox() :
nullptr;
377 std::unique_ptr<AccessorT> weightAccessor;
378 if (mWeightCombinable) {
379 auto& weightGrid = mWeightCombinable->local();
380 auto& weightTree = weightGrid.tree();
381 weightAccessor.reset(
new AccessorT(weightTree));
387 std::unique_ptr<TreeT> tempTree;
388 std::unique_ptr<TreeT> tempWeightTree;
389 std::unique_ptr<AccessorT> tempValueAccessor;
390 std::unique_ptr<AccessorT> tempWeightAccessor;
391 if (useRadius && !mComputeMax) {
392 tempTree.reset(
new TreeT(tree.background()));
393 tempValueAccessor.reset(
new AccessorT(*tempTree));
394 if (weightAccessor) {
395 tempWeightTree.reset(
new TreeT(weightAccessor->tree().background()));
396 tempWeightAccessor.reset(
new AccessorT(*tempWeightTree));
403 auto doModifyVoxelOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale,
404 const bool isTemp,
const bool forceSum)
406 if (mMask && !mMask.valid(ijk, maskAccessor.get()))
return;
409 if (!math::isZero<AttributeT>(attributeScale) && !math::isNegative<AttributeT>(attributeScale)) {
410 valueAccessor.modifyValue(ijk, TrueOp(scale));
413 ValueT weightValue = castValue<ValueT>(scale);
414 ValueT newValue = MultiplyOp<ValueT>::mul(weightValue, attributeScale);
415 if (scaleByVoxelVolume) {
416 newValue /=
static_cast<ValueT
>(transform.voxelSize(ijk.asVec3d()).product());
418 if (point_rasterize_internal::greaterThan(newValue, threshold)) {
420 tempValueAccessor->modifyValue(ijk, MaxOpT(newValue));
421 if (tempWeightAccessor) {
422 tempWeightAccessor->modifyValue(ijk, MaxOpT(weightValue));
425 if (mComputeMax && !forceSum) {
426 valueAccessor.modifyValue(ijk, MaxOpT(newValue));
428 valueAccessor.modifyValue(ijk, SumOpT(newValue));
430 if (weightAccessor) {
431 weightAccessor->modifyValue(ijk, SumOpT(weightValue));
439 auto modifyVoxelOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale)
441 doModifyVoxelOp(ijk, scale, attributeScale,
false,
false);
445 auto sumVoxelOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale)
447 doModifyVoxelOp(ijk, scale, attributeScale,
false,
true);
453 auto doModifyVoxelByDistanceOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale,
454 const double distanceSqr,
const double radiusSqr,
const bool isTemp)
456 if (distanceSqr >= radiusSqr)
return;
458 valueAccessor.modifyValue(ijk, TrueOp(scale));
460 double distance = std::sqrt(distanceSqr);
461 double radius = std::sqrt(radiusSqr);
462 double result = 1.0 - distance/radius;
463 doModifyVoxelOp(ijk, result * scale, attributeScale, isTemp,
false);
468 auto modifyVoxelByDistanceOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale,
469 const double distanceSqr,
const double radiusSqr)
471 doModifyVoxelByDistanceOp(ijk, scale, attributeScale, distanceSqr, radiusSqr,
false);
475 auto modifyTempVoxelByDistanceOp = [&](
const Coord& ijk,
const double scale,
const AttributeT& attributeScale,
476 const double distanceSqr,
const double radiusSqr)
478 doModifyVoxelByDistanceOp(ijk, scale, attributeScale, distanceSqr, radiusSqr,
true);
481 typename points::AttributeHandle<AttributeT>::Ptr attributeHandle;
482 using ElementT =
typename ValueTraits<AttributeT>::ElementType;
483 typename points::AttributeHandle<ElementT>::Ptr stridedAttributeHandle;
485 if (mAttributeIndex != points::AttributeSet::INVALID_POS) {
486 const auto& attributeArray = leaf.constAttributeArray(mAttributeIndex);
487 if (attributeArray.stride() == 3) {
488 stridedAttributeHandle = points::AttributeHandle<ElementT>::create(attributeArray);
490 attributeHandle = points::AttributeHandle<AttributeT>::create(attributeArray);
494 size_t positionIndex = leaf.attributeSet().find(
"P");
495 size_t velocityIndex = leaf.attributeSet().find(mVelocityAttribute);
496 size_t radiusIndex = leaf.attributeSet().find(mRadiusAttribute);
498 auto positionHandle = PositionHandleT::create(
499 leaf.constAttributeArray(positionIndex));
500 auto velocityHandle = (useRaytrace && leaf.hasAttribute(velocityIndex)) ?
501 VelocityHandleT::create(leaf.constAttributeArray(velocityIndex)) :
502 VelocityHandleT::Ptr();
503 auto radiusHandle = (useRadius && leaf.hasAttribute(radiusIndex)) ?
504 RadiusHandleT::create(leaf.constAttributeArray(radiusIndex)) :
505 RadiusHandleT::Ptr();
507 for (
auto iter = leaf.beginIndexOn(mFilter); iter; ++iter) {
512 const AttributeT attributeScale = getAttributeScale<AttributeT>(
513 attributeHandle, stridedAttributeHandle, *iter);
515 float radiusWS = 1.0f, radius = 1.0f;
517 radiusWS *= radiusScale;
518 if (radiusHandle) radiusWS *= radiusHandle->get(*iter);
521 }
else if (voxelSize > 0.0f) {
522 radius = radiusWS / voxelSize;
528 bool doRadius = useRadius;
529 if (!isFrustum && radius < radiusThreshold) {
533 float increment = shutterEndDt - shutterStartDt;
538 bool doRaytrace = useRaytrace;
540 if (increment < openvdb::math::Delta<float>::value()) {
543 if (velocityHandle) velocity = velocityHandle->get(*iter);
544 if (mStaticCamera && velocity.lengthSqr() < openvdb::math::Delta<float>::value()) {
550 if (motionSteps > 1) increment /= float(motionSteps);
552 Vec3d position = positionHandle->get(*iter) + iter.getCoord().asVec3d();
556 position = pointsTransform.indexToWorld(position);
558 for (
int motionStep = 0; motionStep <= motionSteps; motionStep++) {
560 float offset = motionStep == motionSteps ? shutterEndDt :
561 (shutterStartDt + increment *
static_cast<float>(motionStep));
562 Vec3d samplePosition = position + velocity * offset;
564 const math::Transform* sampleTransform = &transform;
565 if (!mSettings.camera.isStatic()) {
566 sampleTransform = &mSettings.camera.transform(motionStep);
567 if (mSettings.camera.hasWeight(motionStep)) {
568 const float weight = mSettings.camera.weight(motionStep);
569 const Vec3d referencePosition = transform.worldToIndex(samplePosition);
570 const Vec3d adjustedPosition = sampleTransform->worldToIndex(samplePosition);
571 motionPositions[motionStep] = referencePosition + (adjustedPosition - referencePosition) * weight;
573 motionPositions[motionStep] = sampleTransform->worldToIndex(samplePosition);
576 motionPositions[motionStep] = sampleTransform->worldToIndex(samplePosition);
578 if (doRadius && isFrustum) {
579 Vec3d left = sampleTransform->worldToIndex(samplePosition -
Vec3d(radiusWS, 0, 0));
580 Vec3d right = sampleTransform->worldToIndex(samplePosition +
Vec3d(radiusWS, 0, 0));
581 float width =
static_cast<float>((right - left).length());
582 Vec3d top = sampleTransform->worldToIndex(samplePosition +
Vec3d(0, radiusWS, 0));
583 Vec3d bottom = sampleTransform->worldToIndex(samplePosition -
Vec3d(0, radiusWS, 0));
584 float height =
static_cast<float>((top - bottom).length());
585 frustumRadiusSizes[motionStep].x() = width;
586 frustumRadiusSizes[motionStep].y() = height;
590 double totalDistance = 0.0;
591 for (
size_t i = 0; i < motionPositions.size()-1; i++) {
592 Vec3d direction = motionPositions[i+1] - motionPositions[i];
593 double distance = direction.
length();
594 totalDistance += distance;
597 double distanceWeight = totalDistance > 0.0 ? 1.0 / totalDistance : 1.0;
599 if (doRadius && !mComputeMax) {
601 for (
auto leaf = tempTree->beginLeaf(); leaf; ++leaf) {
602 leaf->setValuesOff();
604 if (tempWeightAccessor) {
605 for (
auto leaf = tempWeightTree->beginLeaf(); leaf; ++leaf) {
606 leaf->setValuesOff();
611 for (
int motionStep = 0; motionStep < motionSteps; motionStep++) {
613 Vec3d startPosition = motionPositions[motionStep];
614 Vec3d endPosition = motionPositions[motionStep+1];
616 Vec3d direction(endPosition - startPosition);
617 double distance = direction.length();
622 float maxRadius = radius;
624 if (doRadius && isFrustum) {
625 const Vec2s& startRadius = frustumRadiusSizes[motionStep];
626 const Vec2s& endRadius = frustumRadiusSizes[motionStep+1];
628 if (startRadius[0] < radiusThreshold && startRadius[1] < radiusThreshold &&
629 endRadius[0] < radiusThreshold && endRadius[1] < radiusThreshold) {
634 maxRadius = std::max(startRadius[0], startRadius[1]);
635 maxRadius = std::max(maxRadius, endRadius[0]);
636 maxRadius = std::max(maxRadius, endRadius[1]);
641 distanceWeight = std::min(distanceWeight, 1.0);
648 double spherePacking = mSettings.accurateSphereMotionBlur ? 4.0 : 2.0;
650 const int steps = std::max(2, math::Ceil(distance * spherePacking /
double(maxRadius)) + 1);
652 Vec3d sample(startPosition);
653 const Vec3d offset(direction / (steps-1));
655 for (
int step = 0; step < steps; step++) {
658 if (mSettings.accurateFrustumRadius) {
659 this->rasterFrustumSphere(sample, mScale * distanceWeight,
660 attributeScale, radiusWS, transform, clipBBox, mInterrupter, modifyVoxelByDistanceOp);
662 this->rasterApproximateFrustumSphere(sample, mScale * distanceWeight,
663 attributeScale, radiusWS, transform, clipBBox, mInterrupter, modifyVoxelByDistanceOp);
666 if (mSettings.accurateFrustumRadius) {
667 this->rasterFrustumSphere(sample, mScale * distanceWeight,
668 attributeScale, radiusWS, transform, clipBBox, mInterrupter, modifyTempVoxelByDistanceOp);
670 this->rasterApproximateFrustumSphere(sample, mScale * distanceWeight,
671 attributeScale, radiusWS, transform, clipBBox, mInterrupter, modifyTempVoxelByDistanceOp);
676 this->rasterVoxelSphere(sample, mScale * distanceWeight,
677 attributeScale, radius, mInterrupter, modifyVoxelByDistanceOp);
679 this->rasterVoxelSphere(sample, mScale * distanceWeight,
680 attributeScale, radius, mInterrupter, modifyTempVoxelByDistanceOp);
683 if (step < (steps-1)) sample += offset;
684 else sample = endPosition;
688 mDdaRay.setMinTime(math::Delta<double>::value());
689 mDdaRay.setMaxTime(std::max(distance, math::Delta<double>::value()*2.0));
692 direction.normalize();
693 mDdaRay.setDir(direction);
696 mDdaRay.setEye(startPosition +
Vec3d(0.5));
700 mDdaRay.clip(*clipBBox);
705 bool forceSum = motionStep > 0;
709 const Coord& voxel = mDda.voxel();
710 double delta = (mDda.next() - mDda.time()) * distanceWeight;
712 this->rasterPoint(voxel, mScale * delta,
713 attributeScale, sumVoxelOp);
716 this->rasterPoint(voxel, mScale * delta,
717 attributeScale, modifyVoxelOp);
719 if (!mDda.step())
break;
724 if (doRadius && !mComputeMax) {
726 for (
auto iter = tempTree->cbeginValueOn(); iter; ++iter) {
727 valueAccessor.modifyValue(iter.getCoord(), SumOpT(*iter));
731 if (weightAccessor) {
732 for (
auto iter = tempWeightTree->cbeginValueOn(); iter; ++iter) {
733 weightAccessor->modifyValue(iter.getCoord(), SumOpT(*iter));
739 if (!mAlignedTransform) {
740 position = transform.worldToIndex(
741 pointsTransform.indexToWorld(position));
746 if (mSettings.accurateFrustumRadius) {
747 this->rasterFrustumSphere(position, mScale, attributeScale,
748 radiusWS, transform, clipBBox, mInterrupter, modifyVoxelByDistanceOp);
750 this->rasterApproximateFrustumSphere(position, mScale, attributeScale,
751 radiusWS, transform, clipBBox, mInterrupter, modifyVoxelByDistanceOp);
754 this->rasterVoxelSphere(position, mScale, attributeScale,
755 radius, mInterrupter, modifyVoxelByDistanceOp);
758 this->rasterPoint(position, mScale, attributeScale, modifyVoxelOp);
767 typename PointLeafT::Buffer emptyBuffer(PartialCreate(), zeroVal<PointIndexT>());
768 (
const_cast<PointLeafT&
>(leaf)).swap(emptyBuffer);
775 mutable math::Ray<double> mDdaRay;
776 mutable math::DDA<openvdb::math::Ray<double>> mDda;
777 const PointDataGridT& mGrid;
778 const std::vector<Index64>& mOffsets;
779 const size_t mAttributeIndex;
780 const Name mVelocityAttribute;
781 const Name mRadiusAttribute;
782 CombinableT& mCombinable;
783 CombinableT* mWeightCombinable;
784 const bool mDropBuffers;
786 const FilterT& mFilter;
787 const bool mComputeMax;
788 const bool mAlignedTransform;
789 const bool mStaticCamera;
790 const FrustumRasterizerSettings& mSettings;
791 const FrustumRasterizerMask& mMask;
792 util::NullInterrupter* mInterrupter;
798template<
typename Gr
idT>
801 using CombinableT =
typename tbb::combinable<GridT>;
803 using TreeT =
typename GridT::TreeType;
804 using LeafT =
typename TreeT::LeafNodeType;
805 using ValueType =
typename TreeT::ValueType;
806 using SumOpT = tools::valxform::SumOp<typename TreeT::ValueType>;
807 using MaxOpT = tools::valxform::MaxOp<typename TreeT::ValueType>;
809 GridCombinerOp(GridT& grid,
bool sum)
813 void operator()(
const GridT& grid)
815 for (
auto leaf = grid.tree().beginLeaf(); leaf; ++leaf) {
816 auto* newLeaf = mTree.probeLeaf(leaf->origin());
819 auto& tree =
const_cast<GridT&
>(grid).tree();
820 mTree.addLeaf(tree.template stealNode<LeafT>(leaf->origin(),
821 zeroVal<ValueType>(),
false));
826 for (
auto iter = leaf->cbeginValueOn(); iter; ++iter) {
827 newLeaf->modifyValue(iter.offset(), SumOpT(ValueType(*iter)));
830 for (
auto iter = leaf->cbeginValueOn(); iter; ++iter) {
831 newLeaf->modifyValue(iter.offset(), MaxOpT(ValueType(*iter)));
844template<
typename Gr
idT>
845struct CombinableTraits {
846 using OpT = GridCombinerOp<GridT>;
847 using T =
typename OpT::CombinableT;
851template <
typename Po
intDataGr
idT>
855 using GridPtr =
typename PointDataGridT::Ptr;
856 using GridConstPtr =
typename PointDataGridT::ConstPtr;
857 using PointDataTreeT =
typename PointDataGridT::TreeType;
858 using PointDataLeafT =
typename PointDataTreeT::LeafNodeType;
860 GridToRasterize(GridPtr& grid,
bool stream,
861 const FrustumRasterizerSettings& settings,
862 const FrustumRasterizerMask& mask)
865 , mSettings(settings)
868 GridToRasterize(GridConstPtr& grid,
const FrustumRasterizerSettings& settings,
869 const FrustumRasterizerMask& mask)
872 , mSettings(settings)
875 const typename PointDataGridT::TreeType& tree()
const
877 return mGrid->constTree();
880 void setLeafPercentage(
int percentage)
882 mLeafPercentage = math::Clamp(percentage, 0, 100);
885 int leafPercentage()
const
887 return mLeafPercentage;
892 return mGrid->memUsage() + mLeafOffsets.capacity();
895 template <
typename AttributeT,
typename Gr
idT,
typename FilterT>
897 typename CombinableTraits<GridT>::T& combiner,
typename CombinableTraits<GridT>::T* weightCombiner,
898 const float scale,
const FilterT& groupFilter,
const bool computeMax,
const bool reduceMemory,
899 util::NullInterrupter* interrupter)
901 using point_rasterize_internal::RasterizeOp;
903 const auto& velocityAttribute = mSettings.velocityMotionBlur ?
904 mSettings.velocityAttribute :
"";
905 const auto& radiusAttribute = mSettings.useRadius ?
906 mSettings.radiusAttribute :
"";
908 bool isPositionAttribute = attribute ==
"P";
909 bool isVelocityAttribute = attribute == mSettings.velocityAttribute;
910 bool isRadiusAttribute = attribute == mSettings.radiusAttribute;
913 const auto& attributeSet = mGrid->constTree().cbeginLeaf()->attributeSet();
914 const size_t attributeIndex = attributeSet.find(attribute);
915 const bool attributeExists = attributeIndex != points::AttributeSet::INVALID_POS;
920 const auto* attributeArray = attributeSet.getConst(attributeIndex);
921 const Index stride = bool(attributeArray) ? attributeArray->stride() :
Index(1);
922 const auto& actualValueType = attributeSet.descriptor().valueType(attributeIndex);
923 const auto requestedValueType =
Name(typeNameAsString<AttributeT>());
924 const bool packVector = stride == 3 &&
925 ((actualValueType == typeNameAsString<float>() &&
926 requestedValueType == typeNameAsString<Vec3f>()) ||
927 (actualValueType == typeNameAsString<double>() &&
928 requestedValueType == typeNameAsString<Vec3d>()) ||
929 (actualValueType == typeNameAsString<int32_t>() &&
930 requestedValueType == typeNameAsString<Vec3I>()));
931 if (!packVector && actualValueType != requestedValueType) {
933 "Attribute type requested for rasterization \"" << requestedValueType <<
"\""
934 " must match attribute value type \"" << actualValueType <<
"\"");
938 tree::LeafManager<PointDataTreeT> leafManager(mGrid->tree());
941 const bool dropBuffers = mStream && reduceMemory;
944 using ResolvedFilterT =
typename point_rasterize_internal::RasterGroupTraits<FilterT>::NewFilterT;
945 auto resolvedFilter = point_rasterize_internal::RasterGroupTraits<FilterT>::resolve(
946 groupFilter, attributeSet);
949 if (mLeafOffsets.empty()) {
950 openvdb::points::pointOffsets(mLeafOffsets, mGrid->constTree(), resolvedFilter,
951 false, mSettings.threaded);
956 if (attributeExists && !isPositionAttribute && !isVelocityAttribute && !isRadiusAttribute) {
958 [&](PointDataLeafT& leaf,
size_t ) {
959 leaf.attributeArray(attributeIndex).setStreaming(
true);
965 size_t positionIndex = attributeSet.find(
"P");
967 [&](PointDataLeafT& leaf,
size_t ) {
968 leaf.attributeArray(positionIndex).setStreaming(
true);
971 if (mSettings.velocityMotionBlur || !mSettings.camera.isStatic()) {
972 size_t velocityIndex = attributeSet.find(velocityAttribute);
973 if (velocityIndex != points::AttributeSet::INVALID_POS) {
975 [&](PointDataLeafT& leaf,
size_t ) {
976 leaf.attributeArray(velocityIndex).setStreaming(
true);
981 if (mSettings.useRadius) {
982 size_t radiusIndex = attributeSet.find(radiusAttribute);
983 if (radiusIndex != points::AttributeSet::INVALID_POS) {
985 [&](PointDataLeafT& leaf,
size_t ) {
986 leaf.attributeArray(radiusIndex).setStreaming(
true);
994 const bool alignedTransform = *(mSettings.transform) == mGrid->constTransform();
996 RasterizeOp<PointDataGridT, AttributeT, GridT, ResolvedFilterT> rasterizeOp(
997 *mGrid, mLeafOffsets, attributeIndex, velocityAttribute, radiusAttribute, combiner, weightCombiner,
998 dropBuffers, scale, resolvedFilter, computeMax, alignedTransform, mSettings.camera.isStatic(),
999 mSettings, mMask, interrupter);
1000 leafManager.foreach(rasterizeOp, mSettings.threaded);
1003 if (reduceMemory && !mLeafOffsets.empty()) {
1004 mLeafOffsets.clear();
1006 mLeafOffsets.shrink_to_fit();
1013 const FrustumRasterizerSettings& mSettings;
1014 const FrustumRasterizerMask& mMask;
1015 int mLeafPercentage = -1;
1016 std::vector<Index64> mLeafOffsets;
1020template <
typename ValueT>
1021typename std::enable_if<!ValueTraits<ValueT>::IsVec, ValueT>::type
1022computeWeightedValue(
const ValueT&
value,
const ValueT& weight)
1024 constexpr bool isSignedInt = std::is_integral<ValueT>() && std::is_signed<ValueT>();
1026 if (!math::isFinite(weight) || math::isApproxZero(weight) ||
1027 (isSignedInt && math::isNegative(weight))) {
1028 return zeroVal<ValueT>();
1030 return value / weight;
1035template <
typename ValueT>
1036typename std::enable_if<ValueTraits<ValueT>::IsVec, ValueT>::type
1037computeWeightedValue(
const ValueT&
value,
const ValueT& weight)
1039 using ElementT =
typename ValueTraits<ValueT>::ElementType;
1041 constexpr bool isSignedInt = std::is_integral<ElementT>() && std::is_signed<ElementT>();
1043 ValueT result(
value);
1044 for (
int i=0; i<ValueTraits<ValueT>::Size; ++i) {
1045 if (!math::isFinite(weight[i]) || math::isApproxZero(weight[i]) ||
1046 (isSignedInt && math::isNegative(weight[i]))) {
1047 result[i] = zeroVal<ElementT>();
1049 result[i] =
value[i] / weight[i];
1062RasterCamera::RasterCamera(
const math::Transform& transform)
1063 : mTransforms{transform}
1066bool RasterCamera::isStatic()
const
1068 return mTransforms.size() <= 1;
1071void RasterCamera::clear()
1073 mTransforms.clear();
1077void RasterCamera::appendTransform(
const math::Transform& transform,
float weight)
1079 mTransforms.push_back(transform);
1080 mWeights.push_back(weight);
1083size_t RasterCamera::size()
const
1085 return mTransforms.size();
1088void RasterCamera::simplify()
1091 if (mTransforms.size() >= 2) {
1092 const auto& transform = mTransforms.front();
1093 bool isStatic =
true;
1094 for (
const auto& testTransform : mTransforms) {
1095 if (transform != testTransform) {
1100 while (mTransforms.size() > 1) {
1101 mTransforms.pop_back();
1106 if (!mWeights.empty()) {
1107 bool hasWeight =
false;
1108 for (Index i = 0; i < mWeights.size(); i++) {
1109 if (this->hasWeight(i)) {
1114 if (!hasWeight) mWeights.clear();
1118bool RasterCamera::hasWeight(Index i)
const
1120 if (mWeights.empty())
return false;
1121 assert(i < mWeights.size());
1122 return !openvdb::math::isApproxEqual(mWeights[i], 1.0f, 1e-3f);
1125float RasterCamera::weight(Index i)
const
1127 if (mWeights.empty()) {
1130 assert(i < mWeights.size());
1135const math::Transform& RasterCamera::transform(Index i)
const
1137 if (mTransforms.size() == 1) {
1138 return mTransforms.front();
1140 assert(i < mTransforms.size());
1141 return mTransforms[i];
1145const math::Transform& RasterCamera::firstTransform()
const
1147 assert(!mTransforms.empty());
1148 return mTransforms.front();
1151const math::Transform& RasterCamera::lastTransform()
const
1153 assert(!mTransforms.empty());
1154 return mTransforms.back();
1157void RasterCamera::setShutter(
float start,
float end)
1159 mShutterStart = start;
1163float RasterCamera::shutterStart()
const
1165 return mShutterStart;
1168float RasterCamera::shutterEnd()
const
1177FrustumRasterizerMask::FrustumRasterizerMask(
const math::Transform& transform,
1178 const MaskGrid* mask,
1180 const bool clipToFrustum,
1181 const bool invertMask)
1184 , mInvert(invertMask)
1194 mMask = MaskGrid::create();
1195 mMask->setTransform(transform.copy());
1196 tools::resampleToMatch<tools::PointSampler>(*mask, *mMask);
1199 tools::prune(mMask->tree());
1203 if (!bbox.empty()) {
1205 MaskGrid::Ptr tempMask = MaskGrid::create();
1206 CoordBBox coordBBox(Coord::floor(bbox.min()),
1207 Coord::ceil(bbox.max()));
1208 tempMask->sparseFill(coordBBox,
true,
true);
1211 MaskGrid::Ptr bboxMask = MaskGrid::create();
1212 bboxMask->setTransform(mMask ? mMask->transformPtr() : transform.copy());
1213 tools::resampleToMatch<tools::PointSampler>(*tempMask, *bboxMask);
1217 mMask->topologyUnion(*bboxMask);
1223 if (clipToFrustum) {
1224 auto frustumMap = transform.template constMap<math::NonlinearFrustumMap>();
1226 const auto& frustumBBox = frustumMap->getBBox();
1227 mClipBBox.reset(Coord::floor(frustumBBox.min()),
1228 Coord::ceil(frustumBBox.max()));
1233FrustumRasterizerMask::operator bool()
const
1235 return mMask || !mClipBBox.empty();
1239FrustumRasterizerMask::getTreePtr()
const
1241 return mMask ? mMask->treePtr() : MaskTree::ConstPtr();
1245FrustumRasterizerMask::clipBBox()
const
1251FrustumRasterizerMask::valid(
const Coord& ijk,
const tree::ValueAccessor<const MaskTree>* acc)
const
1253 const bool maskValue = acc ? acc->isValueOn(ijk) :
true;
1254 const bool insideMask = mInvert ? !maskValue : maskValue;
1255 const bool insideFrustum = mClipBBox.empty() ? true : mClipBBox.isInside(ijk);
1256 return insideMask && insideFrustum;
1263template <
typename Po
intDataGr
idT>
1264FrustumRasterizer<PointDataGridT>::FrustumRasterizer(
const FrustumRasterizerSettings& settings,
1265 const FrustumRasterizerMask& mask,
1266 util::NullInterrupter* interrupt)
1267 : mSettings(settings)
1269 , mInterrupter(interrupt)
1271 if (mSettings.velocityAttribute.empty() && mSettings.velocityMotionBlur) {
1273 "Using velocity motion blur during rasterization requires a velocity attribute.");
1277template <
typename Po
intDataGr
idT>
1279FrustumRasterizer<PointDataGridT>::addPoints(GridConstPtr& grid)
1282 if (!grid || grid->tree().empty())
return;
1285 mPointGrids.emplace_back(grid, mSettings, mMask);
1288template <
typename Po
intDataGr
idT>
1290FrustumRasterizer<PointDataGridT>::addPoints(GridPtr& grid,
bool stream)
1293 if (!grid || grid->tree().empty())
return;
1295 mPointGrids.emplace_back(grid, stream, mSettings, mMask);
1298template <
typename Po
intDataGr
idT>
1300FrustumRasterizer<PointDataGridT>::clear()
1302 mPointGrids.clear();
1305template <
typename Po
intDataGr
idT>
1307FrustumRasterizer<PointDataGridT>::size()
const
1309 return mPointGrids.size();
1312template <
typename Po
intDataGr
idT>
1314FrustumRasterizer<PointDataGridT>::memUsage()
const
1316 size_t mem =
sizeof(*this) +
sizeof(mPointGrids);
1317 for (
const auto& grid : mPointGrids) {
1318 mem += grid.memUsage();
1323template <
typename Po
intDataGr
idT>
1324template <
typename FilterT>
1326FrustumRasterizer<PointDataGridT>::rasterizeUniformDensity(
1327 RasterMode mode,
bool reduceMemory,
float scale,
const FilterT& filter)
1330 auto density = rasterizeAttribute<FloatGrid, float>(
"", mode, reduceMemory, scale, filter);
1332 density->setName(
"density");
1336template <
typename Po
intDataGr
idT>
1337template <
typename FilterT>
1339FrustumRasterizer<PointDataGridT>::rasterizeDensity(
1340 const openvdb::Name& attribute, RasterMode mode,
bool reduceMemory,
float scale,
const FilterT& filter)
1342 auto density = rasterizeAttribute<FloatGrid, float>(attribute, mode, reduceMemory, scale, filter);
1344 density->setName(
"density");
1348template <
typename Po
intDataGr
idT>
1349template <
typename FilterT>
1351FrustumRasterizer<PointDataGridT>::rasterizeAttribute(
1352 const Name& attribute, RasterMode mode,
bool reduceMemory,
float scale,
const FilterT& filter)
1358 for (
const auto& points : mPointGrids) {
1359 auto leaf = points.tree().cbeginLeaf();
1360 const auto& descriptor = leaf->attributeSet().descriptor();
1361 const size_t targetIndex = descriptor.find(attribute);
1363 if (targetIndex == points::AttributeSet::INVALID_POS)
continue;
1364 const auto* attributeArray = leaf->attributeSet().getConst(attribute);
1365 if (!attributeArray)
continue;
1366 stride = attributeArray->stride();
1367 sourceType = descriptor.valueType(targetIndex);
1368 if (!sourceType.empty())
break;
1373 if (sourceType.empty())
return {};
1375 if (stride == 1 && sourceType == typeNameAsString<float>()) {
1376 using GridT =
typename PointDataGridT::template ValueConverter<float>::Type;
1377 return rasterizeAttribute<GridT, float>(attribute, mode, reduceMemory, scale, filter);
1380#ifndef ONLY_RASTER_FLOAT
1381 }
else if ( sourceType == typeNameAsString<Vec3f>() ||
1382 (stride == 3 && sourceType == typeNameAsString<float>())) {
1383 using GridT =
typename PointDataGridT::template ValueConverter<Vec3f>::Type;
1384 return rasterizeAttribute<GridT, Vec3f>(attribute, mode, reduceMemory, scale, filter);
1385 }
else if ( sourceType == typeNameAsString<Vec3d>() ||
1386 (stride == 3 && sourceType == typeNameAsString<double>())) {
1387 using GridT =
typename PointDataGridT::template ValueConverter<Vec3d>::Type;
1388 return rasterizeAttribute<GridT, Vec3d>(attribute, mode, reduceMemory, scale, filter);
1389 }
else if ( sourceType == typeNameAsString<Vec3i>() ||
1390 (stride == 3 && sourceType == typeNameAsString<int32_t>())) {
1391 using GridT =
typename PointDataGridT::template ValueConverter<Vec3i>::Type;
1392 return rasterizeAttribute<GridT, Vec3i>(attribute, mode, reduceMemory, scale, filter);
1393 }
else if (stride == 1 && sourceType == typeNameAsString<int16_t>()) {
1394 using GridT =
typename PointDataGridT::template ValueConverter<Int32>::Type;
1395 return rasterizeAttribute<GridT, int16_t>(attribute, mode, reduceMemory, scale, filter);
1396 }
else if (stride == 1 && sourceType == typeNameAsString<int32_t>()) {
1397 using GridT =
typename PointDataGridT::template ValueConverter<Int32>::Type;
1398 return rasterizeAttribute<GridT, int32_t>(attribute, mode, reduceMemory, scale, filter);
1399 }
else if (stride == 1 && sourceType == typeNameAsString<int64_t>()) {
1400 using GridT =
typename PointDataGridT::template ValueConverter<Int64>::Type;
1401 return rasterizeAttribute<GridT, int64_t>(attribute, mode, reduceMemory, scale, filter);
1402 }
else if (stride == 1 && sourceType == typeNameAsString<double>()) {
1403 using GridT =
typename PointDataGridT::template ValueConverter<double>::Type;
1404 return rasterizeAttribute<GridT, double>(attribute, mode, reduceMemory, scale, filter);
1405 }
else if (stride == 1 && sourceType == typeNameAsString<bool>()) {
1406 using GridT =
typename PointDataGridT::template ValueConverter<bool>::Type;
1407 return rasterizeAttribute<GridT, bool>(attribute, mode, reduceMemory,
true, filter);
1410 std::ostringstream ostr;
1411 ostr <<
"Cannot rasterize attribute of type - " << sourceType;
1412 if (stride > 1) ostr <<
" x " << stride;
1417template <
typename Po
intDataGr
idT>
1418template <
typename Gr
idT,
typename AttributeT,
typename FilterT>
1420FrustumRasterizer<PointDataGridT>::rasterizeAttribute(
const Name& attribute, RasterMode mode,
1421 bool reduceMemory,
float scale,
const FilterT& filter)
1423 if (attribute ==
"P") {
1424 OPENVDB_THROW(ValueError,
"Cannot rasterize position attribute.")
1427 auto grid = GridT::create();
1428 grid->setName(attribute);
1429 grid->setTransform(mSettings.transform->copy());
1431 this->performRasterization<AttributeT>(*grid, mode, attribute, reduceMemory, scale, filter);
1436template <
typename Po
intDataGr
idT>
1437template <
typename Gr
idT,
typename FilterT>
1439FrustumRasterizer<PointDataGridT>::rasterizeMask(
bool reduceMemory,
const FilterT& filter)
1441 using ValueT =
typename GridT::ValueType;
1443 static_assert(point_rasterize_internal::BoolTraits<ValueT>::IsBool,
1444 "Value type of mask to be rasterized must be bool or ValueMask.");
1446 auto grid = rasterizeAttribute<GridT, ValueT>(
"", RasterMode::ACCUMULATE, reduceMemory,
true, filter);
1447 grid->setName(
"mask");
1452template <
typename Po
intDataGr
idT>
1453template <
typename AttributeT,
typename Gr
idT,
typename FilterT>
1455FrustumRasterizer<PointDataGridT>::performRasterization(
1456 GridT& grid, RasterMode mode,
const openvdb::Name& attribute,
bool reduceMemory,
1457 float scale,
const FilterT& filter)
1459 using openvdb::points::point_mask_internal::GridCombinerOp;
1460 using point_rasterize_internal::computeWeightedValue;
1462 using TreeT =
typename GridT::TreeType;
1463 using LeafT =
typename TreeT::LeafNodeType;
1464 using ValueT =
typename TreeT::ValueType;
1465 using CombinerOpT =
typename point_rasterize_internal::CombinableTraits<GridT>::OpT;
1466 using CombinableT =
typename point_rasterize_internal::CombinableTraits<GridT>::T;
1470 std::stringstream ss;
1471 ss <<
"Rasterizing Points ";
1472 if (!mSettings.camera.isStatic() || mSettings.velocityMotionBlur) {
1473 ss <<
"with Motion Blur ";
1475 if (mSettings.transform->isLinear()) {
1476 ss <<
"to Linear Volume";
1478 ss <<
"to Frustum Volume";
1480 mInterrupter->start(ss.str().c_str());
1483 const bool useMaximum = mode == RasterMode::MAXIMUM;
1484 const bool useWeight = mode == RasterMode::AVERAGE;
1486 if (useMaximum && VecTraits<ValueT>::IsVec) {
1488 "Cannot use maximum mode when rasterizing vector attributes.");
1491 if ((useMaximum || useWeight) && point_rasterize_internal::BoolTraits<ValueT>::IsBool) {
1493 "Cannot use maximum or average modes when rasterizing bool attributes.");
1496 CombinableT combiner;
1497 CombinableT weightCombiner;
1498 CombinableT* weightCombinerPtr = useWeight ? &weightCombiner :
nullptr;
1504 if (mPointGrids.size() == 1) {
1505 mPointGrids[0].setLeafPercentage(100);
1510 std::vector<Index64> leafCounts;
1511 leafCounts.reserve(mPointGrids.size());
1512 for (
auto& points : mPointGrids) {
1513 leafCount += points.tree().leafCount();
1514 leafCounts.push_back(leafCount);
1518 if (leafCount ==
Index64(0)) leafCount++;
1521 for (
size_t i = 0; i < leafCounts.size(); i++) {
1522 int percentage =
static_cast<int>(math::Round((
static_cast<float>(leafCounts[i]))/
1523 static_cast<float>(leafCount)));
1524 mPointGrids[i].setLeafPercentage(percentage);
1531 for (
auto& points : mPointGrids) {
1533 points.template rasterize<AttributeT, GridT>(
1534 attribute, combiner, weightCombinerPtr, scale, filter, mode == RasterMode::MAXIMUM, reduceMemory, mInterrupter);
1541 mInterrupter->wasInterrupted(points.leafPercentage())) {
1548 CombinerOpT combineOp(grid, mode != RasterMode::MAXIMUM);
1549 combiner.combine_each(combineOp);
1555 auto weightGrid = GridT::create(ValueT(1));
1556 CombinerOpT weightCombineOp(*weightGrid,
true);
1557 weightCombiner.combine_each(weightCombineOp);
1559 tree::LeafManager<TreeT> leafManager(grid.tree());
1560 leafManager.foreach(
1561 [&](LeafT& leaf,
size_t ) {
1562 auto weightAccessor = weightGrid->getConstAccessor();
1563 for (
auto iter = leaf.beginValueOn(); iter; ++iter) {
1564 auto weight = weightAccessor.getValue(iter.getCoord());
1565 iter.setValue(computeWeightedValue(iter.getValue(), weight));
1568 mSettings.threaded);
1571 if (mInterrupter) mInterrupter->end();
ValueT value
Definition: GridBuilder.h:1287
T length() const
Definition: NanoVDB.h:1093
T dot(const Vec3T &v) const
Definition: NanoVDB.h:1081
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:89
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
Vec2< float > Vec2s
Definition: Vec2.h:536
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
Vec3< double > Vec3d
Definition: Vec3.h:668
Vec3< int32_t > Vec3i
Definition: Vec3.h:665
void rasterize(const PointDataTreeOrGridT &points, TransferT &transfer, const FilterT &filter=NullFilter(), InterrupterT *interrupter=nullptr)
Perform potentially complex rasterization from a user defined transfer scheme.
Definition: PointTransfer.h:556
std::string Name
Definition: Name.h:17
Index32 Index
Definition: Types.h:54
SharedPtr< T > ConstPtrCast(const SharedPtr< U > &ptr)
Return a new shared pointer that points to the same object as the given pointer but with possibly dif...
Definition: Types.h:126
math::BBox< Vec3d > BBoxd
Definition: Types.h:84
math::Vec3< Real > Vec3R
Definition: Types.h:72
uint64_t Index64
Definition: Types.h:53
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:35
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202