| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | // | ||
| 4 | /// @author Ken Museth, D.J. Hill (openvdb port, added staggered grid support) | ||
| 5 | /// | ||
| 6 | /// @file tools/PointAdvect.h | ||
| 7 | /// | ||
| 8 | /// @brief Class PointAdvect advects points (with position) in a static velocity field | ||
| 9 | |||
| 10 | #ifndef OPENVDB_TOOLS_POINT_ADVECT_HAS_BEEN_INCLUDED | ||
| 11 | #define OPENVDB_TOOLS_POINT_ADVECT_HAS_BEEN_INCLUDED | ||
| 12 | |||
| 13 | #include "openvdb/openvdb.h" | ||
| 14 | #include "openvdb/Types.h" // Vec3 types and version number | ||
| 15 | #include "openvdb/Grid.h" // grid | ||
| 16 | #include "openvdb/math/Math.h" // min | ||
| 17 | #include "openvdb/util/NullInterrupter.h" | ||
| 18 | #include "openvdb/thread/Threading.h" | ||
| 19 | #include "Interpolation.h" // sampling | ||
| 20 | #include "VelocityFields.h" // VelocityIntegrator | ||
| 21 | |||
| 22 | #include <tbb/blocked_range.h> // threading | ||
| 23 | #include <tbb/parallel_for.h> // threading | ||
| 24 | |||
| 25 | #include <vector> | ||
| 26 | |||
| 27 | |||
| 28 | namespace openvdb { | ||
| 29 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 30 | namespace OPENVDB_VERSION_NAME { | ||
| 31 | namespace tools { | ||
| 32 | |||
| 33 | /// Class that holds a Vec3 grid, to be interpreted as the closest point to a constraint | ||
| 34 | /// surface. Supports a method to allow a point to be projected onto the closest point | ||
| 35 | /// on the constraint surface. Uses Caching. | ||
| 36 | template<typename CptGridT = Vec3fGrid> | ||
| 37 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | class ClosestPointProjector |
| 38 | { | ||
| 39 | public: | ||
| 40 | using CptGridType = CptGridT; | ||
| 41 | using CptAccessor = typename CptGridType::ConstAccessor; | ||
| 42 | using CptValueType = typename CptGridType::ValueType; | ||
| 43 | |||
| 44 | ClosestPointProjector(): | ||
| 45 | mCptIterations(0) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | 5 | ClosestPointProjector(const CptGridType& cptGrid, int n): | |
| 49 | mCptGrid(&cptGrid), | ||
| 50 | mCptAccessor(cptGrid.getAccessor()), | ||
| 51 | 10 | mCptIterations(n) | |
| 52 | { | ||
| 53 | } | ||
| 54 | ClosestPointProjector(const ClosestPointProjector &other): | ||
| 55 | mCptGrid(other.mCptGrid), | ||
| 56 | mCptAccessor(mCptGrid->getAccessor()), | ||
| 57 | mCptIterations(other.mCptIterations) | ||
| 58 | { | ||
| 59 | } | ||
| 60 | void setConstraintIterations(unsigned int cptIterations) { mCptIterations = cptIterations; } | ||
| 61 | unsigned int numIterations() { return mCptIterations; } | ||
| 62 | |||
| 63 | // point constraint | ||
| 64 | template <typename LocationType> | ||
| 65 | 20 | inline void projectToConstraintSurface(LocationType& W) const | |
| 66 | { | ||
| 67 | /// Entries in the CPT tree are the closest point to the constraint surface. | ||
| 68 | /// The interpolation step in sample introduces error so that the result | ||
| 69 | /// of a single sample may not lie exactly on the surface. The iterations | ||
| 70 | /// in the loop exist to minimize this error. | ||
| 71 | 20 | CptValueType result(W[0], W[1],W[2]); | |
| 72 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 20 times.
|
120 | for (unsigned int i = 0; i < mCptIterations; ++i) { |
| 73 | 100 | const Vec3R location = mCptGrid->worldToIndex(Vec3R(result[0], result[1], result[2])); | |
| 74 | 100 | BoxSampler::sample<CptAccessor>(mCptAccessor, location, result); | |
| 75 | } | ||
| 76 | 20 | W[0] = result[0]; | |
| 77 | 20 | W[1] = result[1]; | |
| 78 | 20 | W[2] = result[2]; | |
| 79 | 20 | } | |
| 80 | |||
| 81 | private: | ||
| 82 | const CptGridType* mCptGrid; // Closest-Point-Transform vector field | ||
| 83 | CptAccessor mCptAccessor; | ||
| 84 | unsigned int mCptIterations; | ||
| 85 | };// end of ClosestPointProjector class | ||
| 86 | |||
| 87 | //////////////////////////////////////// | ||
| 88 | |||
| 89 | |||
| 90 | /// Performs passive or constrained advection of points in a velocity field | ||
| 91 | /// represented by an OpenVDB grid and an optional closest-point-transform (CPT) | ||
| 92 | /// represented in another OpenVDB grid. Note the CPT is assumed to be | ||
| 93 | /// in world coordinates and NOT index coordinates! | ||
| 94 | /// Supports both collocated velocity grids and staggered velocity grids | ||
| 95 | /// | ||
| 96 | /// The @c PointListT template argument refers to any class with the following | ||
| 97 | /// interface (e.g., std::vector<openvdb::Vec3f>): | ||
| 98 | /// @code | ||
| 99 | /// class PointList { | ||
| 100 | /// ... | ||
| 101 | /// public: | ||
| 102 | /// using value_type = internal_vector3_type; // must support [] component access | ||
| 103 | /// openvdb::Index size() const; // number of points in list | ||
| 104 | /// value_type& operator[](int n); // world space position of nth point | ||
| 105 | /// }; | ||
| 106 | /// @endcode | ||
| 107 | /// | ||
| 108 | /// @note All methods (except size) are assumed to be thread-safe and | ||
| 109 | /// the positions are returned as non-const references since the | ||
| 110 | /// advection method needs to modify them! | ||
| 111 | template<typename GridT = Vec3fGrid, | ||
| 112 | typename PointListT = std::vector<typename GridT::ValueType>, | ||
| 113 | bool StaggeredVelocity = false, | ||
| 114 | typename InterrupterType = util::NullInterrupter> | ||
| 115 | class PointAdvect | ||
| 116 | { | ||
| 117 | public: | ||
| 118 | using GridType = GridT; | ||
| 119 | using PointListType = PointListT; | ||
| 120 | using LocationType = typename PointListT::value_type; | ||
| 121 | using VelocityFieldIntegrator = VelocityIntegrator<GridT, StaggeredVelocity>; | ||
| 122 | |||
| 123 | 1 | PointAdvect(const GridT& velGrid, InterrupterType* interrupter = nullptr): | |
| 124 | mVelGrid(&velGrid), | ||
| 125 | mPoints(nullptr), | ||
| 126 | mIntegrationOrder(1), | ||
| 127 | mThreaded(true), | ||
| 128 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | mInterrupter(interrupter) |
| 129 | { | ||
| 130 | } | ||
| 131 | 101 | PointAdvect(const PointAdvect &other) : | |
| 132 | 101 | mVelGrid(other.mVelGrid), | |
| 133 | 101 | mPoints(other.mPoints), | |
| 134 | 101 | mDt(other.mDt), | |
| 135 | 101 | mAdvIterations(other.mAdvIterations), | |
| 136 | 101 | mIntegrationOrder(other.mIntegrationOrder), | |
| 137 | 101 | mThreaded(other.mThreaded), | |
| 138 | 5 | mInterrupter(other.mInterrupter) | |
| 139 | { | ||
| 140 | } | ||
| 141 | ✗ | virtual ~PointAdvect() | |
| 142 | { | ||
| 143 | } | ||
| 144 | /// If the order of the integration is set to zero no advection is performed | ||
| 145 | 4 | bool earlyOut() const { return (mIntegrationOrder==0);} | |
| 146 | /// get & set | ||
| 147 | void setThreaded(bool threaded) { mThreaded = threaded; } | ||
| 148 | bool getThreaded() { return mThreaded; } | ||
| 149 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | void setIntegrationOrder(unsigned int order) {mIntegrationOrder = order;} |
| 150 | |||
| 151 | /// Constrained advection of a list of points over a time = dt * advIterations | ||
| 152 | 4 | void advect(PointListT& points, float dt, unsigned int advIterations = 1) | |
| 153 | { | ||
| 154 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (this->earlyOut()) return; // nothing to do! |
| 155 | 4 | mPoints = &points; | |
| 156 | 4 | mDt = dt; | |
| 157 | 4 | mAdvIterations = advIterations; | |
| 158 | |||
| 159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (mInterrupter) mInterrupter->start("Advecting points by OpenVDB velocity field: "); |
| 160 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (mThreaded) { |
| 161 | 4 | tbb::parallel_for(tbb::blocked_range<size_t>(0, mPoints->size()), *this); | |
| 162 | } else { | ||
| 163 | ✗ | (*this)(tbb::blocked_range<size_t>(0, mPoints->size())); | |
| 164 | } | ||
| 165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (mInterrupter) mInterrupter->end(); |
| 166 | } | ||
| 167 | |||
| 168 | /// Never call this method directly - it is use by TBB and has to be public! | ||
| 169 | 520 | void operator() (const tbb::blocked_range<size_t> &range) const | |
| 170 | { | ||
| 171 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 520 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
520 | if (mInterrupter && mInterrupter->wasInterrupted()) { |
| 172 | ✗ | thread::cancelGroupExecution(); | |
| 173 | } | ||
| 174 | |||
| 175 | 520 | VelocityFieldIntegrator velField(*mVelGrid); | |
| 176 |
4/5✓ Branch 0 taken 128 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 128 times.
✗ Branch 4 not taken.
|
520 | switch (mIntegrationOrder) { |
| 177 | case 1: | ||
| 178 | { | ||
| 179 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 128 times.
|
2000128 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 180 | 2000000 | LocationType& X0 = (*mPoints)[n]; | |
| 181 | // loop over number of time steps | ||
| 182 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 2000000 times.
|
4000000 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 183 |
1/2✓ Branch 1 taken 2000000 times.
✗ Branch 2 not taken.
|
2000000 | velField.template rungeKutta<1>(mDt, X0); |
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | break; | ||
| 188 | case 2: | ||
| 189 | { | ||
| 190 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 128 times.
|
2000128 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 191 | 2000000 | LocationType& X0 = (*mPoints)[n]; | |
| 192 | // loop over number of time steps | ||
| 193 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 2000000 times.
|
4000000 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 194 |
1/2✓ Branch 1 taken 2000000 times.
✗ Branch 2 not taken.
|
2000000 | velField.template rungeKutta<2>(mDt, X0); |
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | break; | ||
| 199 | case 3: | ||
| 200 | { | ||
| 201 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 136 times.
|
2000136 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 202 | 2000000 | LocationType& X0 = (*mPoints)[n]; | |
| 203 | // loop over number of time steps | ||
| 204 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 2000000 times.
|
4000000 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 205 |
1/2✓ Branch 1 taken 2000000 times.
✗ Branch 2 not taken.
|
2000000 | velField.template rungeKutta<3>(mDt, X0); |
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | break; | ||
| 210 | case 4: | ||
| 211 | { | ||
| 212 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 128 times.
|
2000128 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 213 | 2000000 | LocationType& X0 = (*mPoints)[n]; | |
| 214 | // loop over number of time steps | ||
| 215 |
2/2✓ Branch 0 taken 2000000 times.
✓ Branch 1 taken 2000000 times.
|
4000000 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 216 |
1/2✓ Branch 1 taken 2000000 times.
✗ Branch 2 not taken.
|
2000000 | velField.template rungeKutta<4>(mDt, X0); |
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | 520 | } | |
| 223 | |||
| 224 | private: | ||
| 225 | // the velocity field | ||
| 226 | const GridType* mVelGrid; | ||
| 227 | |||
| 228 | // vertex list of all the points | ||
| 229 | PointListT* mPoints; | ||
| 230 | |||
| 231 | // time integration parameters | ||
| 232 | float mDt; // time step | ||
| 233 | unsigned int mAdvIterations; // number of time steps | ||
| 234 | unsigned int mIntegrationOrder; | ||
| 235 | |||
| 236 | // operational parameters | ||
| 237 | bool mThreaded; | ||
| 238 | InterrupterType* mInterrupter; | ||
| 239 | |||
| 240 | };//end of PointAdvect class | ||
| 241 | |||
| 242 | |||
| 243 | template<typename GridT = Vec3fGrid, | ||
| 244 | typename PointListT = std::vector<typename GridT::ValueType>, | ||
| 245 | bool StaggeredVelocity = false, | ||
| 246 | typename CptGridType = GridT, | ||
| 247 | typename InterrupterType = util::NullInterrupter> | ||
| 248 | class ConstrainedPointAdvect | ||
| 249 | { | ||
| 250 | public: | ||
| 251 | using GridType = GridT; | ||
| 252 | using LocationType = typename PointListT::value_type; | ||
| 253 | using VelocityIntegratorType = VelocityIntegrator<GridT, StaggeredVelocity>; | ||
| 254 | using ClosestPointProjectorType = ClosestPointProjector<CptGridType>; | ||
| 255 | using PointListType = PointListT; | ||
| 256 | |||
| 257 | 1 | ConstrainedPointAdvect(const GridType& velGrid, | |
| 258 | const GridType& cptGrid, int cptn, InterrupterType* interrupter = nullptr): | ||
| 259 | mVelGrid(&velGrid), | ||
| 260 | mCptGrid(&cptGrid), | ||
| 261 | mCptIter(cptn), | ||
| 262 | 1 | mInterrupter(interrupter) | |
| 263 | { | ||
| 264 | } | ||
| 265 | ✗ | ConstrainedPointAdvect(const ConstrainedPointAdvect& other): | |
| 266 | ✗ | mVelGrid(other.mVelGrid), | |
| 267 | ✗ | mCptGrid(other.mCptGrid), | |
| 268 | ✗ | mCptIter(other.mCptIter), | |
| 269 | ✗ | mPoints(other.mPoints), | |
| 270 | ✗ | mDt(other.mDt), | |
| 271 | ✗ | mAdvIterations(other.mAdvIterations), | |
| 272 | ✗ | mIntegrationOrder(other.mIntegrationOrder), | |
| 273 | ✗ | mThreaded(other.mThreaded), | |
| 274 | ✗ | mInterrupter(other.mInterrupter) | |
| 275 | { | ||
| 276 | } | ||
| 277 |
1/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | virtual ~ConstrainedPointAdvect(){} |
| 278 | |||
| 279 | 1 | void setConstraintIterations(unsigned int cptIter) {mCptIter = cptIter;} | |
| 280 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | void setIntegrationOrder(unsigned int order) {mIntegrationOrder = order;} |
| 281 | |||
| 282 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | void setThreaded(bool threaded) { mThreaded = threaded; } |
| 283 | bool getThreaded() { return mThreaded; } | ||
| 284 | |||
| 285 | /// Constrained Advection a list of points over a time = dt * advIterations | ||
| 286 | 5 | void advect(PointListT& points, float dt, unsigned int advIterations = 1) | |
| 287 | { | ||
| 288 | 5 | mPoints = &points; | |
| 289 | 5 | mDt = dt; | |
| 290 | |||
| 291 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
5 | if (mIntegrationOrder==0 && mCptIter == 0) { |
| 292 | return; // nothing to do! | ||
| 293 | } | ||
| 294 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | (mIntegrationOrder>0) ? mAdvIterations = advIterations : mAdvIterations = 1; |
| 295 | |||
| 296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (mInterrupter) mInterrupter->start("Advecting points by OpenVDB velocity field: "); |
| 297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | const size_t N = mPoints->size(); |
| 298 | |||
| 299 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (mThreaded) { |
| 300 | ✗ | tbb::parallel_for(tbb::blocked_range<size_t>(0, N), *this); | |
| 301 | } else { | ||
| 302 | 5 | (*this)(tbb::blocked_range<size_t>(0, N)); | |
| 303 | } | ||
| 304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (mInterrupter) mInterrupter->end(); |
| 305 | } | ||
| 306 | |||
| 307 | |||
| 308 | /// Never call this method directly - it is use by TBB and has to be public! | ||
| 309 | 5 | void operator() (const tbb::blocked_range<size_t> &range) const | |
| 310 | { | ||
| 311 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
5 | if (mInterrupter && mInterrupter->wasInterrupted()) { |
| 312 | ✗ | thread::cancelGroupExecution(); | |
| 313 | } | ||
| 314 | |||
| 315 | 5 | VelocityIntegratorType velField(*mVelGrid); | |
| 316 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | ClosestPointProjectorType cptField(*mCptGrid, mCptIter); |
| 317 |
5/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
5 | switch (mIntegrationOrder) { |
| 318 | case 0://pure CPT projection | ||
| 319 | { | ||
| 320 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 321 | 4 | LocationType& X0 = (*mPoints)[n]; | |
| 322 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 323 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | cptField.projectToConstraintSurface(X0); |
| 324 | } | ||
| 325 | } | ||
| 326 | } | ||
| 327 | break; | ||
| 328 | case 1://1'th order advection and CPT projection | ||
| 329 | { | ||
| 330 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 331 | 4 | LocationType& X0 = (*mPoints)[n]; | |
| 332 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 333 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | velField.template rungeKutta<1>(mDt, X0); |
| 334 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | cptField.projectToConstraintSurface(X0); |
| 335 | } | ||
| 336 | } | ||
| 337 | } | ||
| 338 | break; | ||
| 339 | case 2://2'nd order advection and CPT projection | ||
| 340 | { | ||
| 341 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 342 | 4 | LocationType& X0 = (*mPoints)[n]; | |
| 343 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 344 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | velField.template rungeKutta<2>(mDt, X0); |
| 345 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | cptField.projectToConstraintSurface(X0); |
| 346 | } | ||
| 347 | } | ||
| 348 | } | ||
| 349 | break; | ||
| 350 | |||
| 351 | case 3://3'rd order advection and CPT projection | ||
| 352 | { | ||
| 353 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 354 | 4 | LocationType& X0 = (*mPoints)[n]; | |
| 355 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 356 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | velField.template rungeKutta<3>(mDt, X0); |
| 357 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | cptField.projectToConstraintSurface(X0); |
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | break; | ||
| 362 | case 4://4'th order advection and CPT projection | ||
| 363 | { | ||
| 364 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (size_t n = range.begin(); n != range.end(); ++n) { |
| 365 | 4 | LocationType& X0 = (*mPoints)[n]; | |
| 366 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (unsigned int i = 0; i < mAdvIterations; ++i) { |
| 367 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | velField.template rungeKutta<4>(mDt, X0); |
| 368 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | cptField.projectToConstraintSurface(X0); |
| 369 | } | ||
| 370 | } | ||
| 371 | } | ||
| 372 | break; | ||
| 373 | } | ||
| 374 | 5 | } | |
| 375 | |||
| 376 | private: | ||
| 377 | const GridType* mVelGrid; // the velocity field | ||
| 378 | const GridType* mCptGrid; | ||
| 379 | int mCptIter; | ||
| 380 | PointListT* mPoints; // vertex list of all the points | ||
| 381 | |||
| 382 | // time integration parameters | ||
| 383 | float mDt; // time step | ||
| 384 | unsigned int mAdvIterations; // number of time steps | ||
| 385 | unsigned int mIntegrationOrder; // order of Runge-Kutta integration | ||
| 386 | // operational parameters | ||
| 387 | bool mThreaded; | ||
| 388 | InterrupterType* mInterrupter; | ||
| 389 | };// end of ConstrainedPointAdvect class | ||
| 390 | |||
| 391 | } // namespace tools | ||
| 392 | } // namespace OPENVDB_VERSION_NAME | ||
| 393 | } // namespace openvdb | ||
| 394 | |||
| 395 | #endif // OPENVDB_TOOLS_POINT_ADVECT_HAS_BEEN_INCLUDED | ||
| 396 |