| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | // | ||
| 4 | /// @author Ken Museth | ||
| 5 | /// | ||
| 6 | /// @file tools/PointScatter.h | ||
| 7 | /// | ||
| 8 | /// @brief We offer three different algorithms (each in its own class) | ||
| 9 | /// for scattering of points in active voxels: | ||
| 10 | /// | ||
| 11 | /// 1) UniformPointScatter. Has two modes: Either randomly distributes | ||
| 12 | /// a fixed number of points into the active voxels, or the user can | ||
| 13 | /// specify a fixed probability of having a points per unit of volume. | ||
| 14 | /// | ||
| 15 | /// 2) DenseUniformPointScatter. Randomly distributes points into active | ||
| 16 | /// voxels using a fixed number of points per voxel. | ||
| 17 | /// | ||
| 18 | /// 3) NonIniformPointScatter. Define the local probability of having | ||
| 19 | /// a point in a voxel as the product of a global density and the | ||
| 20 | /// value of the voxel itself. | ||
| 21 | |||
| 22 | #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED | ||
| 23 | #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED | ||
| 24 | |||
| 25 | #include <openvdb/Types.h> | ||
| 26 | #include <openvdb/Grid.h> | ||
| 27 | #include <openvdb/math/Math.h> | ||
| 28 | #include <openvdb/util/NullInterrupter.h> | ||
| 29 | #include <tbb/parallel_sort.h> | ||
| 30 | #include <tbb/parallel_for.h> | ||
| 31 | #include <iostream> | ||
| 32 | #include <memory> | ||
| 33 | #include <string> | ||
| 34 | |||
| 35 | namespace openvdb { | ||
| 36 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 37 | namespace OPENVDB_VERSION_NAME { | ||
| 38 | namespace tools { | ||
| 39 | |||
| 40 | /// Forward declaration of base class | ||
| 41 | template<typename PointAccessorType, | ||
| 42 | typename RandomGenerator, | ||
| 43 | typename InterruptType = util::NullInterrupter> | ||
| 44 | class BasePointScatter; | ||
| 45 | |||
| 46 | /// @brief The two point scatters UniformPointScatter and | ||
| 47 | /// NonUniformPointScatter depend on the following two classes: | ||
| 48 | /// | ||
| 49 | /// The @c PointAccessorType template argument below refers to any class | ||
| 50 | /// with the following interface: | ||
| 51 | /// @code | ||
| 52 | /// class PointAccessor { | ||
| 53 | /// ... | ||
| 54 | /// public: | ||
| 55 | /// void add(const openvdb::Vec3R &pos);// appends point with world positions pos | ||
| 56 | /// }; | ||
| 57 | /// @endcode | ||
| 58 | /// | ||
| 59 | /// | ||
| 60 | /// The @c InterruptType template argument below refers to any class | ||
| 61 | /// with the following interface: | ||
| 62 | /// @code | ||
| 63 | /// class Interrupter { | ||
| 64 | /// ... | ||
| 65 | /// public: | ||
| 66 | /// void start(const char* name = nullptr) // called when computations begin | ||
| 67 | /// void end() // called when computations end | ||
| 68 | /// bool wasInterrupted(int percent=-1) // return true to break computation | ||
| 69 | ///}; | ||
| 70 | /// @endcode | ||
| 71 | /// | ||
| 72 | /// @note If no template argument is provided for this InterruptType | ||
| 73 | /// the util::NullInterrupter is used which implies that all | ||
| 74 | /// interrupter calls are no-ops (i.e. incurs no computational overhead). | ||
| 75 | |||
| 76 | |||
| 77 | /// @brief Uniformly scatters points in the active voxels. | ||
| 78 | /// The point count is either explicitly defined or implicitly | ||
| 79 | /// through the specification of a global density (=points-per-volume) | ||
| 80 | /// | ||
| 81 | /// @note This uniform scattering technique assumes that the number of | ||
| 82 | /// points is generally smaller than the number of active voxels | ||
| 83 | /// (including virtual active voxels in active tiles). | ||
| 84 | template<typename PointAccessorType, | ||
| 85 | typename RandomGenerator, | ||
| 86 | typename InterruptType = util::NullInterrupter> | ||
| 87 | class UniformPointScatter : public BasePointScatter<PointAccessorType, | ||
| 88 | RandomGenerator, | ||
| 89 | InterruptType> | ||
| 90 | { | ||
| 91 | public: | ||
| 92 | using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>; | ||
| 93 | |||
| 94 | 11 | UniformPointScatter(PointAccessorType& points, | |
| 95 | Index64 pointCount, | ||
| 96 | RandomGenerator& randGen, | ||
| 97 | double spread = 1.0, | ||
| 98 | InterruptType* interrupt = nullptr) | ||
| 99 | : BaseT(points, randGen, spread, interrupt) | ||
| 100 | , mTargetPointCount(pointCount) | ||
| 101 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
11 | , mPointsPerVolume(0.0f) |
| 102 | { | ||
| 103 | } | ||
| 104 | 1 | UniformPointScatter(PointAccessorType& points, | |
| 105 | float pointsPerVolume, | ||
| 106 | RandomGenerator& randGen, | ||
| 107 | double spread = 1.0, | ||
| 108 | InterruptType* interrupt = nullptr) | ||
| 109 | : BaseT(points, randGen, spread, interrupt) | ||
| 110 | , mTargetPointCount(0) | ||
| 111 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | , mPointsPerVolume(pointsPerVolume) |
| 112 | { | ||
| 113 | } | ||
| 114 | |||
| 115 | /// This is the main functor method implementing the actual scattering of points. | ||
| 116 | template<typename GridT> | ||
| 117 | 12 | bool operator()(const GridT& grid) | |
| 118 | { | ||
| 119 | 12 | mVoxelCount = grid.activeVoxelCount(); | |
| 120 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
|
12 | if (mVoxelCount == 0) return false; |
| 121 | |||
| 122 | const auto voxelVolume = grid.transform().voxelVolume(); | ||
| 123 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | if (mPointsPerVolume > 0) { |
| 124 | BaseT::start("Uniform scattering with fixed point density"); | ||
| 125 | 1 | mTargetPointCount = Index64(mPointsPerVolume * voxelVolume * double(mVoxelCount)); | |
| 126 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | } else if (mTargetPointCount > 0) { |
| 127 | BaseT::start("Uniform scattering with fixed point count"); | ||
| 128 | 10 | mPointsPerVolume = float(mTargetPointCount) / float(voxelVolume * double(mVoxelCount)); | |
| 129 | } else { | ||
| 130 | return false; | ||
| 131 | } | ||
| 132 | |||
| 133 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | std::unique_ptr<Index64[]> idList{new Index64[mTargetPointCount]}; |
| 134 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
22 | math::RandInt<Index64, RandomGenerator> rand(BaseT::mRand01.engine(), 0, mVoxelCount-1); |
| 135 |
2/2✓ Branch 0 taken 328144 times.
✓ Branch 1 taken 11 times.
|
328155 | for (Index64 i=0; i<mTargetPointCount; ++i) idList[i] = rand(); |
| 136 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | tbb::parallel_sort(idList.get(), idList.get() + mTargetPointCount); |
| 137 | |||
| 138 | 11 | CoordBBox bbox; | |
| 139 | const Vec3R offset(0.5, 0.5, 0.5); | ||
| 140 | typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn(); | ||
| 141 | |||
| 142 |
2/2✓ Branch 0 taken 328144 times.
✓ Branch 1 taken 11 times.
|
328155 | for (Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) { |
| 143 |
2/4✓ Branch 1 taken 328144 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 328144 times.
✗ Branch 4 not taken.
|
328144 | if (BaseT::interrupt()) return false; |
| 144 | 328144 | const Index64 voxelId = idList[i]; | |
| 145 |
2/2✓ Branch 0 taken 650138 times.
✓ Branch 1 taken 328144 times.
|
978282 | while ( n <= voxelId ) { |
| 146 | ++valueIter; | ||
| 147 | 650138 | n += valueIter.getVoxelCount(); | |
| 148 | } | ||
| 149 | if (valueIter.isVoxelValue()) {// a majority is expected to be voxels | ||
| 150 |
1/2✓ Branch 1 taken 321052 times.
✗ Branch 2 not taken.
|
321052 | BaseT::addPoint(grid, valueIter.getCoord() - offset); |
| 151 | } else {// tiles contain multiple (virtual) voxels | ||
| 152 |
1/2✓ Branch 1 taken 7092 times.
✗ Branch 2 not taken.
|
7092 | valueIter.getBoundingBox(bbox); |
| 153 |
1/4✓ Branch 1 taken 7092 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
7092 | BaseT::addPoint(grid, bbox.min() - offset, bbox.extents()); |
| 154 | } | ||
| 155 | }//loop over all the active voxels and tiles | ||
| 156 | //} | ||
| 157 | |||
| 158 | BaseT::end(); | ||
| 159 | return true; | ||
| 160 | } | ||
| 161 | |||
| 162 | // The following methods should only be called after the | ||
| 163 | // the operator() method was called | ||
| 164 | void print(const std::string &name, std::ostream& os = std::cout) const | ||
| 165 | { | ||
| 166 | os << "Uniformly scattered " << mPointCount << " points into " << mVoxelCount | ||
| 167 | << " active voxels in \"" << name << "\" corresponding to " | ||
| 168 | << mPointsPerVolume << " points per volume." << std::endl; | ||
| 169 | } | ||
| 170 | |||
| 171 | float getPointsPerVolume() const { return mPointsPerVolume; } | ||
| 172 | Index64 getTargetPointCount() const { return mTargetPointCount; } | ||
| 173 | |||
| 174 | private: | ||
| 175 | |||
| 176 | using BaseT::mPointCount; | ||
| 177 | using BaseT::mVoxelCount; | ||
| 178 | Index64 mTargetPointCount; | ||
| 179 | float mPointsPerVolume; | ||
| 180 | |||
| 181 | }; // class UniformPointScatter | ||
| 182 | |||
| 183 | /// @brief Scatters a fixed (and integer) number of points in all | ||
| 184 | /// active voxels and tiles. | ||
| 185 | template<typename PointAccessorType, | ||
| 186 | typename RandomGenerator, | ||
| 187 | typename InterruptType = util::NullInterrupter> | ||
| 188 | class DenseUniformPointScatter : public BasePointScatter<PointAccessorType, | ||
| 189 | RandomGenerator, | ||
| 190 | InterruptType> | ||
| 191 | { | ||
| 192 | public: | ||
| 193 | using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>; | ||
| 194 | |||
| 195 | 1 | DenseUniformPointScatter(PointAccessorType& points, | |
| 196 | float pointsPerVoxel, | ||
| 197 | RandomGenerator& randGen, | ||
| 198 | double spread = 1.0, | ||
| 199 | InterruptType* interrupt = nullptr) | ||
| 200 | : BaseT(points, randGen, spread, interrupt) | ||
| 201 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | , mPointsPerVoxel(pointsPerVoxel) |
| 202 | { | ||
| 203 | } | ||
| 204 | |||
| 205 | /// This is the main functor method implementing the actual scattering of points. | ||
| 206 | template<typename GridT> | ||
| 207 | 1 | bool operator()(const GridT& grid) | |
| 208 | { | ||
| 209 | using ValueIter = typename GridT::ValueOnCIter; | ||
| 210 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (mPointsPerVoxel < 1.0e-6) return false; |
| 211 | 1 | mVoxelCount = grid.activeVoxelCount(); | |
| 212 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (mVoxelCount == 0) return false; |
| 213 | BaseT::start("Dense uniform scattering with fixed point count"); | ||
| 214 | 1 | CoordBBox bbox; | |
| 215 | const Vec3R offset(0.5, 0.5, 0.5); | ||
| 216 | |||
| 217 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | const int ppv = math::Floor(mPointsPerVoxel); |
| 218 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | const double delta = mPointsPerVoxel - float(ppv); |
| 219 | const bool fractional = !math::isApproxZero(delta, 1.0e-6); | ||
| 220 | |||
| 221 |
2/2✓ Branch 0 taken 262144 times.
✓ Branch 1 taken 1 times.
|
262145 | for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) { |
| 222 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 262144 times.
|
262144 | if (BaseT::interrupt()) return false; |
| 223 | if (iter.isVoxelValue()) {// a majority is expected to be voxels | ||
| 224 | 262144 | const Vec3R dmin = iter.getCoord() - offset; | |
| 225 |
2/2✓ Branch 0 taken 2097152 times.
✓ Branch 1 taken 262144 times.
|
2359296 | for (int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin); |
| 226 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 262144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
262144 | if (fractional && BaseT::getRand01() < delta) BaseT::addPoint(grid, dmin); |
| 227 | } else {// tiles contain multiple (virtual) voxels | ||
| 228 | ✗ | iter.getBoundingBox(bbox); | |
| 229 | ✗ | const Coord size(bbox.extents()); | |
| 230 | const Vec3R dmin = bbox.min() - offset; | ||
| 231 | ✗ | const double d = mPointsPerVoxel * float(iter.getVoxelCount()); | |
| 232 | const int m = math::Floor(d); | ||
| 233 | ✗ | for (int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size); | |
| 234 | ✗ | if (BaseT::getRand01() < d - m) BaseT::addPoint(grid, dmin, size); | |
| 235 | } | ||
| 236 | }//loop over all the active voxels and tiles | ||
| 237 | //} | ||
| 238 | BaseT::end(); | ||
| 239 | return true; | ||
| 240 | } | ||
| 241 | |||
| 242 | // The following methods should only be called after the | ||
| 243 | // the operator() method was called | ||
| 244 | void print(const std::string &name, std::ostream& os = std::cout) const | ||
| 245 | { | ||
| 246 | os << "Dense uniformly scattered " << mPointCount << " points into " << mVoxelCount | ||
| 247 | << " active voxels in \"" << name << "\" corresponding to " | ||
| 248 | << mPointsPerVoxel << " points per voxel." << std::endl; | ||
| 249 | } | ||
| 250 | |||
| 251 | float getPointsPerVoxel() const { return mPointsPerVoxel; } | ||
| 252 | |||
| 253 | private: | ||
| 254 | using BaseT::mPointCount; | ||
| 255 | using BaseT::mVoxelCount; | ||
| 256 | float mPointsPerVoxel; | ||
| 257 | }; // class DenseUniformPointScatter | ||
| 258 | |||
| 259 | /// @brief Non-uniform scatters of point in the active voxels. | ||
| 260 | /// The local point count is implicitly defined as a product of | ||
| 261 | /// of a global density (called pointsPerVolume) and the local voxel | ||
| 262 | /// (or tile) value. | ||
| 263 | /// | ||
| 264 | /// @note This scattering technique can be significantly slower | ||
| 265 | /// than a uniform scattering since its computational complexity | ||
| 266 | /// is proportional to the active voxel (and tile) count. | ||
| 267 | template<typename PointAccessorType, | ||
| 268 | typename RandomGenerator, | ||
| 269 | typename InterruptType = util::NullInterrupter> | ||
| 270 | class NonUniformPointScatter : public BasePointScatter<PointAccessorType, | ||
| 271 | RandomGenerator, | ||
| 272 | InterruptType> | ||
| 273 | { | ||
| 274 | public: | ||
| 275 | using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>; | ||
| 276 | |||
| 277 | 1 | NonUniformPointScatter(PointAccessorType& points, | |
| 278 | float pointsPerVolume, | ||
| 279 | RandomGenerator& randGen, | ||
| 280 | double spread = 1.0, | ||
| 281 | InterruptType* interrupt = nullptr) | ||
| 282 | : BaseT(points, randGen, spread, interrupt) | ||
| 283 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | , mPointsPerVolume(pointsPerVolume)//note this is merely a |
| 284 | //multiplier for the local point density | ||
| 285 | { | ||
| 286 | } | ||
| 287 | |||
| 288 | /// This is the main functor method implementing the actual scattering of points. | ||
| 289 | template<typename GridT> | ||
| 290 | 1 | bool operator()(const GridT& grid) | |
| 291 | { | ||
| 292 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (mPointsPerVolume <= 0.0f) return false; |
| 293 | 1 | mVoxelCount = grid.activeVoxelCount(); | |
| 294 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (mVoxelCount == 0) return false; |
| 295 | BaseT::start("Non-uniform scattering with local point density"); | ||
| 296 | const Vec3d dim = grid.voxelSize(); | ||
| 297 | 1 | const double volumePerVoxel = dim[0]*dim[1]*dim[2], | |
| 298 | 1 | pointsPerVoxel = mPointsPerVolume * volumePerVoxel; | |
| 299 | 1 | CoordBBox bbox; | |
| 300 | const Vec3R offset(0.5, 0.5, 0.5); | ||
| 301 |
2/2✓ Branch 0 taken 262144 times.
✓ Branch 1 taken 1 times.
|
262145 | for (typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) { |
| 302 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 262144 times.
|
262144 | if (BaseT::interrupt()) return false; |
| 303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 262144 times.
|
262144 | const double d = double(*iter) * pointsPerVoxel * double(iter.getVoxelCount()); |
| 304 |
1/2✓ Branch 0 taken 262144 times.
✗ Branch 1 not taken.
|
262144 | const int n = int(d); |
| 305 | if (iter.isVoxelValue()) { // a majority is expected to be voxels | ||
| 306 | 262144 | const Vec3R dmin =iter.getCoord() - offset; | |
| 307 |
2/2✓ Branch 0 taken 441252 times.
✓ Branch 1 taken 262144 times.
|
703396 | for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin); |
| 308 |
2/2✓ Branch 0 taken 5278 times.
✓ Branch 1 taken 256866 times.
|
262144 | if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin); |
| 309 | } else { // tiles contain multiple (virtual) voxels | ||
| 310 | ✗ | iter.getBoundingBox(bbox); | |
| 311 | ✗ | const Coord size(bbox.extents()); | |
| 312 | const Vec3R dmin = bbox.min() - offset; | ||
| 313 | ✗ | for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size); | |
| 314 | ✗ | if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin, size); | |
| 315 | } | ||
| 316 | }//loop over all the active voxels and tiles | ||
| 317 | BaseT::end(); | ||
| 318 | return true; | ||
| 319 | } | ||
| 320 | |||
| 321 | // The following methods should only be called after the | ||
| 322 | // the operator() method was called | ||
| 323 | void print(const std::string &name, std::ostream& os = std::cout) const | ||
| 324 | { | ||
| 325 | os << "Non-uniformly scattered " << mPointCount << " points into " << mVoxelCount | ||
| 326 | << " active voxels in \"" << name << "\"." << std::endl; | ||
| 327 | } | ||
| 328 | |||
| 329 | float getPointPerVolume() const { return mPointsPerVolume; } | ||
| 330 | |||
| 331 | private: | ||
| 332 | using BaseT::mPointCount; | ||
| 333 | using BaseT::mVoxelCount; | ||
| 334 | float mPointsPerVolume; | ||
| 335 | |||
| 336 | }; // class NonUniformPointScatter | ||
| 337 | |||
| 338 | /// Base class of all the point scattering classes defined above | ||
| 339 | template<typename PointAccessorType, | ||
| 340 | typename RandomGenerator, | ||
| 341 | typename InterruptType> | ||
| 342 | class BasePointScatter | ||
| 343 | { | ||
| 344 | public: | ||
| 345 | |||
| 346 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
5 | Index64 getPointCount() const { return mPointCount; } |
| 347 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
4 | Index64 getVoxelCount() const { return mVoxelCount; } |
| 348 | |||
| 349 | protected: | ||
| 350 | |||
| 351 | PointAccessorType& mPoints; | ||
| 352 | InterruptType* mInterrupter; | ||
| 353 | Index64 mPointCount; | ||
| 354 | Index64 mVoxelCount; | ||
| 355 | Index64 mInterruptCount; | ||
| 356 | const double mSpread; | ||
| 357 | math::Rand01<double, RandomGenerator> mRand01; | ||
| 358 | |||
| 359 | /// This is a base class so the constructor is protected | ||
| 360 | 14 | BasePointScatter(PointAccessorType& points, | |
| 361 | RandomGenerator& randGen, | ||
| 362 | double spread, | ||
| 363 | InterruptType* interrupt = nullptr) | ||
| 364 | : mPoints(points) | ||
| 365 | , mInterrupter(interrupt) | ||
| 366 | , mPointCount(0) | ||
| 367 | , mVoxelCount(0) | ||
| 368 | , mInterruptCount(0) | ||
| 369 | , mSpread(math::Clamp01(spread)) | ||
| 370 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
14 | , mRand01(randGen) |
| 371 | { | ||
| 372 | } | ||
| 373 | |||
| 374 | inline void start(const char* name) | ||
| 375 | { | ||
| 376 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
|
13 | if (mInterrupter) mInterrupter->start(name); |
| 377 | } | ||
| 378 | |||
| 379 | inline void end() | ||
| 380 | { | ||
| 381 |
3/8✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
13 | if (mInterrupter) mInterrupter->end(); |
| 382 | } | ||
| 383 | |||
| 384 | 852432 | inline bool interrupt() | |
| 385 | { | ||
| 386 | //only check interrupter for every 32'th call | ||
| 387 |
3/4✓ Branch 0 taken 26645 times.
✓ Branch 1 taken 825787 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26645 times.
|
852432 | return !(mInterruptCount++ & ((1<<5)-1)) && util::wasInterrupted(mInterrupter); |
| 388 | } | ||
| 389 | |||
| 390 | /// @brief Return a random floating point number between zero and one | ||
| 391 | inline double getRand01() { return mRand01(); } | ||
| 392 | |||
| 393 | /// @brief Return a random floating point number between 0.5 -+ mSpread/2 | ||
| 394 | 8615478 | inline double getRand() { return 0.5 + mSpread * (mRand01() - 0.5); } | |
| 395 | |||
| 396 | template <typename GridT> | ||
| 397 | 2864734 | inline void addPoint(const GridT &grid, const Vec3R &dmin) | |
| 398 | { | ||
| 399 | 2864734 | const Vec3R pos(dmin[0] + this->getRand(), | |
| 400 | 2864734 | dmin[1] + this->getRand(), | |
| 401 | 2864734 | dmin[2] + this->getRand()); | |
| 402 | 2864734 | mPoints.add(grid.indexToWorld(pos)); | |
| 403 | 2864734 | ++mPointCount; | |
| 404 | 2864734 | } | |
| 405 | |||
| 406 | template <typename GridT> | ||
| 407 | 7092 | inline void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size) | |
| 408 | { | ||
| 409 | 7092 | const Vec3R pos(dmin[0] + size[0]*this->getRand(), | |
| 410 | 7092 | dmin[1] + size[1]*this->getRand(), | |
| 411 | 7092 | dmin[2] + size[2]*this->getRand()); | |
| 412 | 7092 | mPoints.add(grid.indexToWorld(pos)); | |
| 413 | 7092 | ++mPointCount; | |
| 414 | 7092 | } | |
| 415 | };// class BasePointScatter | ||
| 416 | |||
| 417 | } // namespace tools | ||
| 418 | } // namespace OPENVDB_VERSION_NAME | ||
| 419 | } // namespace openvdb | ||
| 420 | |||
| 421 | #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED | ||
| 422 |