| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | // | ||
| 4 | /// @author Nick Avramoussis | ||
| 5 | /// | ||
| 6 | /// @file PointRasterizeTrilinearImpl.h | ||
| 7 | /// | ||
| 8 | |||
| 9 | #ifndef OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
| 10 | #define OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
| 11 | |||
| 12 | namespace openvdb { | ||
| 13 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 14 | namespace OPENVDB_VERSION_NAME { | ||
| 15 | namespace points { | ||
| 16 | |||
| 17 | /// @cond OPENVDB_DOCS_INTERNAL | ||
| 18 | |||
| 19 | namespace rasterize_trilinear_internal { | ||
| 20 | |||
| 21 | template <typename TreeType, | ||
| 22 | typename PositionCodecT, | ||
| 23 | typename SourceValueT, | ||
| 24 | typename SourceCodecT> | ||
| 25 | struct TrilinearTransfer : public VolumeTransfer<TreeType> | ||
| 26 | { | ||
| 27 | using BaseT = VolumeTransfer<TreeType>; | ||
| 28 | using WeightT = typename TreeType::ValueType; | ||
| 29 | using PositionHandleT = points::AttributeHandle<Vec3f, PositionCodecT>; | ||
| 30 | using SourceHandleT = points::AttributeHandle<SourceValueT, SourceCodecT>; | ||
| 31 | |||
| 32 | // precision of kernel arithmetic - aliased to the floating point | ||
| 33 | // element type of the source attribute. | ||
| 34 | using SourceElementT = typename ValueTraits<SourceValueT>::ElementType; | ||
| 35 | using RealT = SourceElementT; | ||
| 36 | |||
| 37 | static_assert(std::is_floating_point<SourceElementT>::value, | ||
| 38 | "Trilinear rasterization only supports floating point values."); | ||
| 39 | |||
| 40 | static const Index NUM_VALUES = TreeType::LeafNodeType::NUM_VALUES; | ||
| 41 | |||
| 42 |
8/64✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
|
8 | TrilinearTransfer(const size_t pidx, |
| 43 | const size_t sidx, TreeType& tree) | ||
| 44 | : BaseT(tree) | ||
| 45 | , mPIdx(pidx) | ||
| 46 | , mSIdx(sidx) | ||
| 47 | , mPHandle() | ||
| 48 | , mSHandle() | ||
| 49 |
8/64✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
|
8 | , mWeights() {} |
| 50 | |||
| 51 | 8 | TrilinearTransfer(const TrilinearTransfer& other) | |
| 52 | : BaseT(other) | ||
| 53 | 8 | , mPIdx(other.mPIdx) | |
| 54 | 8 | , mSIdx(other.mSIdx) | |
| 55 | , mPHandle() | ||
| 56 | , mSHandle() | ||
| 57 | 8 | , mWeights() {} | |
| 58 | |||
| 59 | //// @note Kernel value evaluator | ||
| 60 | static inline RealT value(const RealT x) | ||
| 61 | { | ||
| 62 | 256 | const RealT abs_x = std::fabs(x); | |
| 63 |
36/144✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 4 times.
✓ Branch 37 taken 8 times.
✓ Branch 38 taken 8 times.
✓ Branch 39 taken 4 times.
✓ Branch 40 taken 6 times.
✓ Branch 41 taken 12 times.
✓ Branch 42 taken 12 times.
✓ Branch 43 taken 6 times.
✓ Branch 44 taken 9 times.
✓ Branch 45 taken 18 times.
✓ Branch 46 taken 18 times.
✓ Branch 47 taken 9 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✓ Branch 66 taken 1 times.
✓ Branch 67 taken 1 times.
✓ Branch 68 taken 2 times.
✓ Branch 69 taken 2 times.
✓ Branch 70 taken 4 times.
✓ Branch 71 taken 4 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✓ Branch 108 taken 4 times.
✓ Branch 109 taken 8 times.
✓ Branch 110 taken 8 times.
✓ Branch 111 taken 4 times.
✓ Branch 112 taken 6 times.
✓ Branch 113 taken 12 times.
✓ Branch 114 taken 12 times.
✓ Branch 115 taken 6 times.
✓ Branch 116 taken 9 times.
✓ Branch 117 taken 18 times.
✓ Branch 118 taken 18 times.
✓ Branch 119 taken 9 times.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✓ Branch 138 taken 1 times.
✓ Branch 139 taken 1 times.
✓ Branch 140 taken 2 times.
✓ Branch 141 taken 2 times.
✓ Branch 142 taken 4 times.
✓ Branch 143 taken 4 times.
|
270 | if (abs_x < RealT(1.0)) return RealT(1.0) - abs_x; |
| 64 | return RealT(0.0); | ||
| 65 | } | ||
| 66 | |||
| 67 | inline static Int32 range() { return 1; } | ||
| 68 | inline Int32 range(const Coord&, size_t) const { return this->range(); } | ||
| 69 | |||
| 70 | 96 | inline void initialize(const Coord& origin, const size_t idx, const CoordBBox& bounds) | |
| 71 | { | ||
| 72 | 112 | this->BaseT::initialize(origin, idx, bounds); | |
| 73 | 96 | mWeights.fill(openvdb::zeroVal<WeightT>()); | |
| 74 | } | ||
| 75 | |||
| 76 | 128 | inline bool startPointLeaf(const PointDataTree::LeafNodeType& leaf) | |
| 77 | { | ||
| 78 |
1/2✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
|
128 | mPHandle.reset(new PositionHandleT(leaf.constAttributeArray(mPIdx))); |
| 79 |
1/2✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
|
128 | mSHandle.reset(new SourceHandleT(leaf.constAttributeArray(mSIdx))); |
| 80 | 128 | return true; | |
| 81 | } | ||
| 82 | |||
| 83 | inline bool endPointLeaf(const PointDataTree::LeafNodeType&) { return true; } | ||
| 84 | |||
| 85 | protected: | ||
| 86 | const size_t mPIdx; | ||
| 87 | const size_t mSIdx; | ||
| 88 | typename PositionHandleT::UniquePtr mPHandle; | ||
| 89 | typename SourceHandleT::UniquePtr mSHandle; | ||
| 90 | std::array<WeightT, NUM_VALUES> mWeights; | ||
| 91 | }; | ||
| 92 | |||
| 93 | template <typename TreeType, | ||
| 94 | typename PositionCodecT, | ||
| 95 | typename SourceValueT, | ||
| 96 | typename SourceCodecT> | ||
| 97 | 4 | struct StaggeredTransfer : | |
| 98 | public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT> | ||
| 99 | { | ||
| 100 | using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>; | ||
| 101 | using RealT = typename BaseT::RealT; | ||
| 102 | using BaseT::value; | ||
| 103 | |||
| 104 | static_assert(VecTraits<typename TreeType::ValueType>::IsVec, | ||
| 105 | "Target Tree must be a vector tree for staggered rasterization"); | ||
| 106 | |||
| 107 | static const Index DIM = TreeType::LeafNodeType::DIM; | ||
| 108 | static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM; | ||
| 109 | |||
| 110 | StaggeredTransfer(const size_t pidx, | ||
| 111 | const size_t sidx, TreeType& tree) | ||
| 112 | : BaseT(pidx, sidx, tree) {} | ||
| 113 | |||
| 114 | 64 | void rasterizePoint(const Coord& ijk, | |
| 115 | const Index id, | ||
| 116 | const CoordBBox& bounds) | ||
| 117 | { | ||
| 118 | 64 | CoordBBox intersectBox(ijk.offsetBy(-1), ijk.offsetBy(1)); | |
| 119 | 64 | intersectBox.intersect(bounds); | |
| 120 | ✗ | if (intersectBox.empty()) return; | |
| 121 | |||
| 122 | auto* const data = this->buffer(); | ||
| 123 | const auto& mask = *(this->mask()); | ||
| 124 | |||
| 125 | 64 | const math::Vec3<RealT> P(this->mPHandle->get(id)); | |
| 126 | 64 | const SourceValueT s(this->mSHandle->get(id)); | |
| 127 | |||
| 128 | math::Vec3<RealT> centerw, macw; | ||
| 129 | |||
| 130 | const Coord& a(intersectBox.min()); | ||
| 131 | const Coord& b(intersectBox.max()); | ||
| 132 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 32 times.
|
160 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
| 133 | // @todo can probably simplify the double call to value() in some way | ||
| 134 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
|
96 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); // unsigned bit shift mult |
| 135 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
|
96 | const RealT x = static_cast<RealT>(c.x()-ijk.x()); // distance from ijk to c |
| 136 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
|
96 | centerw[0] = value(P.x() - x); // center dist |
| 137 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
96 | macw.x() = value(P.x() - (x-RealT(0.5))); // mac dist |
| 138 | |||
| 139 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 48 times.
|
240 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
| 140 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 48 times.
|
144 | const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM); |
| 141 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
|
144 | const RealT y = static_cast<RealT>(c.y()-ijk.y()); |
| 142 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 48 times.
|
144 | centerw[1] = value(P.y() - y); |
| 143 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
|
144 | macw.y() = value(P.y() - (y-RealT(0.5))); |
| 144 | |||
| 145 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 72 times.
|
360 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
| 146 | ✗ | assert(bounds.isInside(c)); | |
| 147 | 216 | const Index offset = ij + /*k*/(c.z() & (DIM-1u)); | |
| 148 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
216 | if (!mask.isOn(offset)) continue; |
| 149 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
|
216 | const RealT z = static_cast<RealT>(c.z()-ijk.z()); |
| 150 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 72 times.
|
216 | centerw[2] = value(P.z() - z); |
| 151 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 36 times.
|
216 | macw.z() = value(P.z() - (z-RealT(0.5))); |
| 152 | |||
| 153 | 216 | const math::Vec3<RealT> r { | |
| 154 | 216 | (macw[0] * centerw[1] * centerw[2]), | |
| 155 | 216 | (macw[1] * centerw[0] * centerw[2]), | |
| 156 | 216 | (macw[2] * centerw[0] * centerw[1]) | |
| 157 | }; | ||
| 158 | |||
| 159 | 216 | data[offset] += s * r; | |
| 160 | this->mWeights[offset] += r; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | 64 | inline bool finalize(const Coord&, const size_t) | |
| 167 | { | ||
| 168 | auto* const data = this->buffer(); | ||
| 169 | const auto& mask = *(this->mask()); | ||
| 170 | |||
| 171 |
2/2✓ Branch 1 taken 108 times.
✓ Branch 2 taken 32 times.
|
344 | for (auto iter = mask.beginOn(); iter; ++iter) { |
| 172 | const Index offset = iter.pos(); | ||
| 173 | 216 | const auto& w = this->mWeights[offset]; | |
| 174 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | auto& v = data[offset]; |
| 175 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[0])) v[0] /= w[0]; |
| 176 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[1])) v[1] /= w[1]; |
| 177 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[2])) v[2] /= w[2]; |
| 178 | } | ||
| 179 | |||
| 180 | 64 | return true; | |
| 181 | } | ||
| 182 | }; | ||
| 183 | |||
| 184 | template <typename TreeType, | ||
| 185 | typename PositionCodecT, | ||
| 186 | typename SourceValueT, | ||
| 187 | typename SourceCodecT> | ||
| 188 | 4 | struct CellCenteredTransfer : | |
| 189 | public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT> | ||
| 190 | { | ||
| 191 | using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>; | ||
| 192 | using RealT = typename BaseT::RealT; | ||
| 193 | using BaseT::value; | ||
| 194 | |||
| 195 | static const Index DIM = TreeType::LeafNodeType::DIM; | ||
| 196 | static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM; | ||
| 197 | |||
| 198 | CellCenteredTransfer(const size_t pidx, | ||
| 199 | const size_t sidx, TreeType& tree) | ||
| 200 | : BaseT(pidx, sidx, tree) {} | ||
| 201 | |||
| 202 | 64 | void rasterizePoint(const Coord& ijk, | |
| 203 | const Index id, | ||
| 204 | const CoordBBox& bounds) | ||
| 205 | { | ||
| 206 | 64 | const Vec3f P(this->mPHandle->get(id)); | |
| 207 | |||
| 208 | // build area of influence depending on point position | ||
| 209 | CoordBBox intersectBox(ijk, ijk); | ||
| 210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.x() < 0.0f) intersectBox.min().x() -= 1; |
| 211 | 64 | else intersectBox.max().x() += 1; | |
| 212 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.y() < 0.0f) intersectBox.min().y() -= 1; |
| 213 | 64 | else intersectBox.max().y() += 1; | |
| 214 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.z() < 0.0f) intersectBox.min().z() -= 1; |
| 215 | 64 | else intersectBox.max().z() += 1; | |
| 216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | assert(intersectBox.volume() == 8); |
| 217 | |||
| 218 | 64 | intersectBox.intersect(bounds); | |
| 219 | 56 | if (intersectBox.empty()) return; | |
| 220 | |||
| 221 | auto* const data = this->buffer(); | ||
| 222 | const auto& mask = *(this->mask()); | ||
| 223 | |||
| 224 | 8 | const SourceValueT s(this->mSHandle->get(id)); | |
| 225 | math::Vec3<RealT> centerw; | ||
| 226 | |||
| 227 | const Coord& a(intersectBox.min()); | ||
| 228 | const Coord& b(intersectBox.max()); | ||
| 229 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
|
24 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
| 230 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
16 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); // unsigned bit shift mult |
| 231 | 16 | const RealT x = static_cast<RealT>(c.x()-ijk.x()); // distance from ijk to c | |
| 232 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
16 | centerw[0] = value(P.x() - x); // center dist |
| 233 | |||
| 234 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
48 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
| 235 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
32 | const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM); |
| 236 | 32 | const RealT y = static_cast<RealT>(c.y()-ijk.y()); | |
| 237 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
32 | centerw[1] = value(P.y() - y); |
| 238 | |||
| 239 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
96 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
| 240 | ✗ | assert(bounds.isInside(c)); | |
| 241 | 64 | const Index offset = ij + /*k*/(c.z() & (DIM-1u)); | |
| 242 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
|
64 | if (!mask.isOn(offset)) continue; |
| 243 | 64 | const RealT z = static_cast<RealT>(c.z()-ijk.z()); | |
| 244 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
64 | centerw[2] = value(P.z() - z); |
| 245 | |||
| 246 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[0] >= 0.0f && centerw[0] <= 1.0f); |
| 247 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[1] >= 0.0f && centerw[1] <= 1.0f); |
| 248 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[2] >= 0.0f && centerw[2] <= 1.0f); |
| 249 | |||
| 250 | const RealT weight = centerw.product(); | ||
| 251 | 64 | data[offset] += s * weight; | |
| 252 | 32 | this->mWeights[offset] += weight; | |
| 253 | } | ||
| 254 | } | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | 64 | inline bool finalize(const Coord&, const size_t) | |
| 259 | { | ||
| 260 | auto* const data = this->buffer(); | ||
| 261 | const auto& mask = *(this->mask()); | ||
| 262 | |||
| 263 |
2/2✓ Branch 1 taken 108 times.
✓ Branch 2 taken 32 times.
|
344 | for (auto iter = mask.beginOn(); iter; ++iter) { |
| 264 | const Index offset = iter.pos(); | ||
| 265 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 2 times.
|
216 | const auto& w = this->mWeights[offset]; |
| 266 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
|
216 | auto& v = data[offset]; |
| 267 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52 times.
|
108 | if (!math::isZero(w)) v /= w; |
| 268 | } | ||
| 269 | 64 | return true; | |
| 270 | } | ||
| 271 | }; | ||
| 272 | |||
| 273 | // @note If building with MSVC we have to use auto to deduce the return type | ||
| 274 | // due to a compiler bug. We can also use that for the public API - but | ||
| 275 | // we explicitly define it in non-msvc builds to ensure the API remains | ||
| 276 | // consistent | ||
| 277 | template <bool Staggered, | ||
| 278 | typename ValueT, | ||
| 279 | typename CodecT, | ||
| 280 | typename PositionCodecT, | ||
| 281 | typename FilterT, | ||
| 282 | typename PointDataTreeT> | ||
| 283 | inline | ||
| 284 | #ifndef _MSC_VER | ||
| 285 | typename TrilinearTraits<ValueT, Staggered>::template TreeT<PointDataTreeT>::Ptr | ||
| 286 | #else | ||
| 287 | auto | ||
| 288 | #endif | ||
| 289 | 16 | rasterizeTrilinear(const PointDataTreeT& points, | |
| 290 | const size_t pidx, | ||
| 291 | const size_t sidx, | ||
| 292 | const FilterT& filter) | ||
| 293 | { | ||
| 294 | using TraitsT = TrilinearTraits<ValueT, Staggered>; | ||
| 295 | using TargetTreeT = typename TraitsT::template TreeT<PointDataTree>; | ||
| 296 | using TransferT = typename std::conditional<Staggered, | ||
| 297 | StaggeredTransfer<TargetTreeT, PositionCodecT, ValueT, CodecT>, | ||
| 298 | CellCenteredTransfer<TargetTreeT, PositionCodecT, ValueT, CodecT> | ||
| 299 | >::type; | ||
| 300 | |||
| 301 | 16 | typename TargetTreeT::Ptr tree(new TargetTreeT); | |
| 302 | if (std::is_same<FilterT, NullFilter>::value) { | ||
| 303 | tree->topologyUnion(points); | ||
| 304 | } | ||
| 305 | else { | ||
| 306 | using MaskTreeT = typename PointDataTreeT::template ValueConverter<ValueMask>::Type; | ||
| 307 | auto mask = convertPointsToMask<PointDataTreeT, MaskTreeT>(points, filter); | ||
| 308 | tree->topologyUnion(*mask); | ||
| 309 | } | ||
| 310 | |||
| 311 | TransferT transfer(pidx, sidx, *tree); | ||
| 312 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | tools::dilateActiveValues(*tree, transfer.range(), |
| 313 | tools::NN_FACE_EDGE_VERTEX, tools::EXPAND_TILES); | ||
| 314 | |||
| 315 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | rasterize<PointDataTreeT, TransferT>(points, transfer, filter); |
| 316 | 16 | return tree; | |
| 317 | } | ||
| 318 | |||
| 319 | } // namespace rasterize_trilinear_internal | ||
| 320 | |||
| 321 | /// @endcond | ||
| 322 | |||
| 323 | /////////////////////////////////////////////////// | ||
| 324 | |||
| 325 | template <bool Staggered, | ||
| 326 | typename ValueT, | ||
| 327 | typename FilterT, | ||
| 328 | typename PointDataTreeT> | ||
| 329 | inline auto | ||
| 330 | 8 | rasterizeTrilinear(const PointDataTreeT& points, | |
| 331 | const std::string& attribute, | ||
| 332 | const FilterT& filter) | ||
| 333 | { | ||
| 334 | using TraitsT = TrilinearTraits<ValueT, Staggered>; | ||
| 335 | using TargetTreeT = typename TraitsT::template TreeT<PointDataTree>; | ||
| 336 | |||
| 337 | const auto iter = points.cbeginLeaf(); | ||
| 338 | 8 | if (!iter) return typename TargetTreeT::Ptr(new TargetTreeT); | |
| 339 | |||
| 340 | const AttributeSet::Descriptor& descriptor = iter->attributeSet().descriptor(); | ||
| 341 | 8 | const size_t pidx = descriptor.find("P"); | |
| 342 | 8 | const size_t sidx = descriptor.find(attribute); | |
| 343 | 8 | if (pidx == AttributeSet::INVALID_POS) { | |
| 344 | ✗ | OPENVDB_THROW(RuntimeError, "Failed to find position attribute"); | |
| 345 | } | ||
| 346 | 8 | if (sidx == AttributeSet::INVALID_POS) { | |
| 347 | ✗ | OPENVDB_THROW(RuntimeError, "Failed to find source attribute"); | |
| 348 | } | ||
| 349 | |||
| 350 | 8 | const NamePair& ptype = descriptor.type(pidx); | |
| 351 | 8 | const NamePair& stype = descriptor.type(sidx); | |
| 352 | 8 | if (ptype.second == NullCodec::name()) { | |
| 353 | 8 | if (stype.second == NullCodec::name()) { | |
| 354 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
| 355 | <Staggered, ValueT, NullCodec, NullCodec> | ||
| 356 | 8 | (points, pidx, sidx, filter); | |
| 357 | } | ||
| 358 | else { | ||
| 359 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
| 360 | <Staggered, ValueT, UnknownCodec, NullCodec> | ||
| 361 | ✗ | (points, pidx, sidx, filter); | |
| 362 | } | ||
| 363 | } | ||
| 364 | else { | ||
| 365 | ✗ | if (stype.second == NullCodec::name()) { | |
| 366 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
| 367 | <Staggered, ValueT, NullCodec, UnknownCodec> | ||
| 368 | ✗ | (points, pidx, sidx, filter); | |
| 369 | } | ||
| 370 | else { | ||
| 371 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
| 372 | <Staggered, ValueT, UnknownCodec, UnknownCodec> | ||
| 373 | ✗ | (points, pidx, sidx, filter); | |
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | |||
| 379 | } // namespace points | ||
| 380 | } // namespace OPENVDB_VERSION_NAME | ||
| 381 | } // namespace openvdb | ||
| 382 | |||
| 383 | #endif //OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
| 384 |