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)
 
  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];
 
 1069    return mTransforms.size() <= 1;
 
 
 1074    mTransforms.clear();
 
 
 1081    mWeights.push_back(
weight);
 
 
 1086    return mTransforms.size();
 
 
 1092    if (mTransforms.size() >= 2) {
 
 1093        const auto& 
transform = mTransforms.front();
 
 1095        for (
const auto& testTransform : mTransforms) {
 
 1101            while (mTransforms.size() > 1) {
 
 1102                mTransforms.pop_back();
 
 1107    if (!mWeights.empty()) {
 
 1109        for (
Index i = 0; i < mWeights.size(); i++) {
 
 
 1121    if (mWeights.empty())  
return false;
 
 1123    return !openvdb::math::isApproxEqual(mWeights[i], 1.0f, 1e-3f);
 
 
 1128    if (mWeights.empty()) {
 
 
 1138    if (mTransforms.size() == 1) {
 
 1139        return mTransforms.front();
 
 1142        return mTransforms[i];
 
 
 1149    return mTransforms.front();
 
 
 1155    return mTransforms.back();
 
 
 1160    mShutterStart = start;
 
 
 1166    return mShutterStart;
 
 
 1181                                            const bool clipToFrustum,
 
 1182                                            const bool invertMask)
 
 1185    , mInvert(invertMask)
 
 1196        mMask->setTransform(transform.
copy());
 
 1204    if (!bbox.
empty()) {
 
 1206        MaskGrid::Ptr tempMask = MaskGrid::create();
 
 1207        CoordBBox coordBBox(Coord::floor(bbox.min()),
 
 1208                            Coord::ceil(bbox.max()));
 
 1209        tempMask->sparseFill(coordBBox, true, true);
 
 1212        MaskGrid::Ptr bboxMask = MaskGrid::create();
 
 1213        bboxMask->setTransform(mMask ? mMask->transformPtr() : transform.copy());
 
 1214        tools::resampleToMatch<tools::PointSampler>(*tempMask, *bboxMask);
 
 1218            mMask->topologyUnion(*bboxMask);
 
 1224    if (clipToFrustum) {
 
 1225        auto frustumMap = transform.template constMap<math::NonlinearFrustumMap>();
 
 1227            const auto& frustumBBox = frustumMap->getBBox();
 
 
 1234FrustumRasterizerMask::operator bool()
 const 
 1236    return mMask || !mClipBBox.empty();
 
 
 1254    const bool maskValue = acc ? acc->
isValueOn(ijk) : 
true;
 
 1255    const bool insideMask = mInvert ? !maskValue : maskValue;
 
 1256    const bool insideFrustum = mClipBBox.empty() ? true : mClipBBox.isInside(ijk);
 
 1257    return insideMask && insideFrustum;
 
 
 1264template <
typename Po
intDataGr
idT>
 
 1268    : mSettings(settings)
 
 1270    , mInterrupter(interrupt)
 
 1272    if (mSettings.velocityAttribute.empty() && mSettings.velocityMotionBlur) {
 
 1273        OPENVDB_THROW(ValueError,
 
 1274            "Using velocity motion blur during rasterization requires a velocity attribute.");
 
 
 1278template <
typename Po
intDataGr
idT>
 
 1283    if (!grid || grid->tree().empty())     
return;
 
 1286    mPointGrids.emplace_back(grid, mSettings, mMask);
 
 
 1289template <
typename Po
intDataGr
idT>
 
 1294    if (!grid || grid->tree().empty())     
return;
 
 1296    mPointGrids.emplace_back(grid, stream, mSettings, mMask);
 
 
 1299template <
typename Po
intDataGr
idT>
 
 1303    mPointGrids.clear();
 
 
 1306template <
typename Po
intDataGr
idT>
 
 1310    return mPointGrids.size();
 
 
 1313template <
typename Po
intDataGr
idT>
 
 1317    size_t mem = 
sizeof(*this) + 
sizeof(mPointGrids);
 
 1318    for (
const auto& grid : mPointGrids) {
 
 1319        mem += grid.memUsage();
 
 
 1324template <
typename Po
intDataGr
idT>
 
 1325template <
typename FilterT>
 
 1328    RasterMode mode, 
bool reduceMemory, 
float scale, 
const FilterT& filter)
 
 1333    density->setName(
"density");
 
 
 1337template <
typename Po
intDataGr
idT>
 
 1338template <
typename FilterT>
 
 1345    density->setName(
"density");
 
 
 1349template <
typename Po
intDataGr
idT>
 
 1350template <
typename FilterT>
 
 1353    const Name& attribute, 
RasterMode mode, 
bool reduceMemory, 
float scale, 
const FilterT& filter)
 
 1359    for (
const auto& 
points : mPointGrids) {
 
 1360        auto leaf = 
points.tree().cbeginLeaf();
 
 1361        const auto& descriptor = leaf->attributeSet().descriptor();
 
 1362        const size_t targetIndex = descriptor.find(attribute);
 
 1365        const auto* attributeArray = leaf->attributeSet().getConst(attribute);
 
 1366        if (!attributeArray)    
continue;
 
 1367        stride = attributeArray->stride();
 
 1368        sourceType = descriptor.valueType(targetIndex);
 
 1369        if (!sourceType.empty())    
break;
 
 1374    if (sourceType.empty())     
return {};
 
 1377        using GridT = 
typename PointDataGridT::template ValueConverter<float>::Type;
 
 1381#ifndef ONLY_RASTER_FLOAT 
 1384        using GridT = 
typename PointDataGridT::template ValueConverter<Vec3f>::Type;
 
 1388        using GridT = 
typename PointDataGridT::template ValueConverter<Vec3d>::Type;
 
 1392        using GridT = 
typename PointDataGridT::template ValueConverter<Vec3i>::Type;
 
 1395        using GridT = 
typename PointDataGridT::template ValueConverter<Int32>::Type;
 
 1398        using GridT = 
typename PointDataGridT::template ValueConverter<Int32>::Type;
 
 1401        using GridT = 
typename PointDataGridT::template ValueConverter<Int64>::Type;
 
 1404        using GridT = 
typename PointDataGridT::template ValueConverter<double>::Type;
 
 1407        using GridT = 
typename PointDataGridT::template ValueConverter<bool>::Type;
 
 1411        std::ostringstream ostr;
 
 1412        ostr << 
"Cannot rasterize attribute of type - " << sourceType;
 
 1413        if (stride > 1)    ostr << 
" x " << stride;
 
 
 1418template <
typename Po
intDataGr
idT>
 
 1419template <
typename Gr
idT, 
typename AttributeT, 
typename FilterT>
 
 1422    bool reduceMemory, 
float scale, 
const FilterT& filter)
 
 1424    if (attribute == 
"P") {
 
 1428    auto grid = GridT::create();
 
 1429    grid->setName(attribute);
 
 1430    grid->setTransform(mSettings.transform->copy());
 
 1432    this->performRasterization<AttributeT>(*grid, mode, attribute, reduceMemory, scale, filter);
 
 
 1437template <
typename Po
intDataGr
idT>
 
 1438template <
typename Gr
idT, 
typename FilterT>
 
 1442    using ValueT = 
typename GridT::ValueType;
 
 1444    static_assert(point_rasterize_internal::BoolTraits<ValueT>::IsBool,
 
 1445        "Value type of mask to be rasterized must be bool or ValueMask.");
 
 1448    grid->setName(
"mask");
 
 
 1453template <
typename Po
intDataGr
idT>
 
 1454template <
typename AttributeT, 
typename Gr
idT, 
typename FilterT>
 
 1456FrustumRasterizer<PointDataGridT>::performRasterization(
 
 1458    float scale, 
const FilterT& filter)
 
 1460    using openvdb::points::point_mask_internal::GridCombinerOp;
 
 1461    using point_rasterize_internal::computeWeightedValue;
 
 1463    using TreeT = 
typename GridT::TreeType;
 
 1464    using LeafT = 
typename TreeT::LeafNodeType;
 
 1465    using ValueT = 
typename TreeT::ValueType;
 
 1466    using CombinerOpT = 
typename point_rasterize_internal::CombinableTraits<GridT>::OpT;
 
 1467    using CombinableT = 
typename point_rasterize_internal::CombinableTraits<GridT>::T;
 
 1471        std::stringstream ss;
 
 1472        ss << 
"Rasterizing Points ";
 
 1473        if (!mSettings.camera.isStatic() || mSettings.velocityMotionBlur) {
 
 1474            ss << 
"with Motion Blur ";
 
 1476        if (mSettings.transform->isLinear()) {
 
 1477            ss << 
"to Linear Volume";
 
 1479            ss << 
"to Frustum Volume";
 
 1481        mInterrupter->start(ss.str().c_str());
 
 1489            "Cannot use maximum mode when rasterizing vector attributes.");
 
 1492    if ((useMaximum || useWeight) && point_rasterize_internal::BoolTraits<ValueT>::IsBool) {
 
 1494            "Cannot use maximum or average modes when rasterizing bool attributes.");
 
 1497    CombinableT combiner;
 
 1498    CombinableT weightCombiner;
 
 1499    CombinableT* weightCombinerPtr = useWeight ? &weightCombiner : 
nullptr;
 
 1505        if (mPointGrids.size() == 1) {
 
 1506            mPointGrids[0].setLeafPercentage(100);
 
 1511            std::vector<Index64> leafCounts;
 
 1512            leafCounts.reserve(mPointGrids.size());
 
 1513            for (
auto& points : mPointGrids) {
 
 1514                leafCount += points.tree().leafCount();
 
 1515                leafCounts.push_back(leafCount);
 
 1519            if (leafCount == 
Index64(0))    leafCount++;
 
 1522            for (
size_t i = 0; i < leafCounts.size(); i++) {
 
 1523                int percentage = 
static_cast<int>(
math::Round((
static_cast<float>(leafCounts[i]))/
 
 1524                    static_cast<float>(leafCount)));
 
 1525                mPointGrids[i].setLeafPercentage(percentage);
 
 1532    for (
auto& points : mPointGrids) {
 
 1535            attribute, combiner, weightCombinerPtr, scale, filter, mode == 
RasterMode::MAXIMUM, reduceMemory, mInterrupter);
 
 1542            mInterrupter->wasInterrupted(points.leafPercentage())) {
 
 1550    combiner.combine_each(combineOp);
 
 1556        auto weightGrid = GridT::create(ValueT(1));
 
 1557        CombinerOpT weightCombineOp(*weightGrid, 
true);
 
 1558        weightCombiner.combine_each(weightCombineOp);
 
 1560        tree::LeafManager<TreeT> leafManager(grid.tree());
 
 1561        leafManager.foreach(
 
 1562            [&](LeafT& leaf, 
size_t ) {
 
 1563                auto weightAccessor = weightGrid->getConstAccessor();
 
 1564                for (
auto iter = leaf.beginValueOn(); iter; ++iter) {
 
 1565                    auto weight = weightAccessor.getValue(iter.getCoord());
 
 1566                    iter.setValue(computeWeightedValue(iter.getValue(), weight));
 
 1569        mSettings.threaded);
 
 1572    if (mInterrupter)   mInterrupter->end();
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
static Coord ceil(const Vec3< T > &xyz)
Return the largest integer coordinates that are not greater than xyz+1 (node centered conversion).
Definition Coord.h:64
static Coord floor(const Vec3< T > &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition Coord.h:57
SharedPtr< GridBase > Ptr
Definition Grid.h:80
SharedPtr< Grid > Ptr
Definition Grid.h:573
Definition Exceptions.h:64
Definition Exceptions.h:65
bool empty() const
Return true if this bounding box is empty, i.e., it has no (positive) volume.
Definition BBox.h:196
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:86
T length() const
Length of the vector.
Definition Vec3.h:201
T dot(const Vec3< T > &v) const
Dot product.
Definition Vec3.h:192
@ INVALID_POS
Definition AttributeSet.h:42
typename PointDataGridT::ConstPtr GridConstPtr
Definition PointRasterizeFrustum.h:168
size_t memUsage() const
Return memory usage of the rasterizer.
Definition PointRasterizeFrustumImpl.h:1315
size_t size() const
Return number of PointDataGrids in the rasterizer.
Definition PointRasterizeFrustumImpl.h:1308
FrustumRasterizer(const FrustumRasterizerSettings &settings, const FrustumRasterizerMask &mask=FrustumRasterizerMask(), util::NullInterrupter *interrupt=nullptr)
main constructor
Definition PointRasterizeFrustumImpl.h:1265
FloatGrid::Ptr rasterizeDensity(const openvdb::Name &attribute, RasterMode mode=RasterMode::MAXIMUM, bool reduceMemory=false, float scale=1.0f, const FilterT &filter=FilterT())
Definition PointRasterizeFrustumImpl.h:1340
void addPoints(GridConstPtr &points)
Append a PointDataGrid to the rasterizer (but don't rasterize yet).
Definition PointRasterizeFrustumImpl.h:1280
GridT::Ptr rasterizeMask(bool reduceMemory=false, const FilterT &filter=FilterT())
Definition PointRasterizeFrustumImpl.h:1440
typename PointDataGridT::Ptr GridPtr
Definition PointRasterizeFrustum.h:167
void clear()
Clear all PointDataGrids in the rasterizer.
Definition PointRasterizeFrustumImpl.h:1301
GridBase::Ptr rasterizeAttribute(const Name &attribute, RasterMode mode=RasterMode::ACCUMULATE, bool reduceMemory=false, float scale=1.0f, const FilterT &filter=FilterT())
Definition PointRasterizeFrustumImpl.h:1352
FloatGrid::Ptr rasterizeUniformDensity(RasterMode mode=RasterMode::MAXIMUM, bool reduceMemory=false, float scale=1.0f, const FilterT &filter=FilterT())
Definition PointRasterizeFrustumImpl.h:1327
float weight(Index i) const
Definition PointRasterizeFrustumImpl.h:1126
void simplify()
Definition PointRasterizeFrustumImpl.h:1089
const math::Transform & transform(Index i) const
Definition PointRasterizeFrustumImpl.h:1136
size_t size() const
Definition PointRasterizeFrustumImpl.h:1084
const math::Transform & firstTransform() const
Definition PointRasterizeFrustumImpl.h:1146
bool isStatic() const
Definition PointRasterizeFrustumImpl.h:1067
void setShutter(float start, float end)
Definition PointRasterizeFrustumImpl.h:1158
void appendTransform(const math::Transform &, float weight=1.0f)
Definition PointRasterizeFrustumImpl.h:1078
float shutterEnd() const
Definition PointRasterizeFrustumImpl.h:1169
bool hasWeight(Index i) const
Definition PointRasterizeFrustumImpl.h:1119
RasterCamera(const math::Transform &transform)
Definition PointRasterizeFrustumImpl.h:1063
void clear()
Definition PointRasterizeFrustumImpl.h:1072
const math::Transform & lastTransform() const
Definition PointRasterizeFrustumImpl.h:1152
float shutterStart() const
Definition PointRasterizeFrustumImpl.h:1164
SharedPtr< const Tree > ConstPtr
Definition Tree.h:198
bool isValueOn(const Coord &xyz) const
Return the active state of the voxel at the given coordinates.
Definition ValueAccessor.h:480
Vec2< float > Vec2s
Definition Vec2.h:532
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition Mat.h:615
Vec3< double > Vec3d
Definition Vec3.h:665
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:819
Vec3< int32_t > Vec3i
Definition Vec3.h:662
Definition AttributeArray.h:42
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:557
RasterMode
How to composite points into a volume.
Definition PointRasterizeFrustum.h:31
@ MAXIMUM
Definition PointRasterizeFrustum.h:33
@ AVERAGE
Definition PointRasterizeFrustum.h:34
@ ACCUMULATE
Definition PointRasterizeFrustum.h:32
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
std::string Name
Definition Name.h:19
Index32 Index
Definition Types.h:54
math::Vec3< float > Vec3f
Definition Types.h:74
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
Grid< MaskTree > MaskGrid
Definition openvdb.h:78
math::Vec3< Real > Vec3R
Definition Types.h:72
uint64_t Index64
Definition Types.h:53
const char * typeNameAsString()
Definition Types.h:516
openvdb::GridBase::Ptr GridPtr
Definition Utils.h:35
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
static const bool IsVec
Definition Types.h:245
Definition PointRasterizeFrustum.h:113
FrustumRasterizerMask()=default
bool valid(const Coord &ijk, AccessorT *acc) const
Definition PointRasterizeFrustumImpl.h:1252
MaskTree::ConstPtr getTreePtr() const
Definition PointRasterizeFrustumImpl.h:1240
const CoordBBox & clipBBox() const
Definition PointRasterizeFrustumImpl.h:1246
A group of shared settings to be used in the Volume Rasterizer.
Definition PointRasterizeFrustum.h:88
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