OpenVDB 13.1.0
Loading...
Searching...
No Matches
PointAdvect.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-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
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
28namespace openvdb {
30namespace OPENVDB_VERSION_NAME {
31namespace 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.
36template<typename CptGridT = Vec3fGrid>
38{
39public:
40 using CptGridType = CptGridT;
41 using CptAccessor = typename CptGridType::ConstAccessor;
42 using CptValueType = typename CptGridType::ValueType;
43
45 mCptIterations(0)
46 {
47 }
48 ClosestPointProjector(const CptGridType& cptGrid, int n):
49 mCptGrid(&cptGrid),
50 mCptAccessor(cptGrid.getAccessor()),
51 mCptIterations(n)
52 {
53 }
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 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 CptValueType result(W[0], W[1],W[2]);
72 for (unsigned int i = 0; i < mCptIterations; ++i) {
73 const Vec3R location = mCptGrid->worldToIndex(Vec3R(result[0], result[1], result[2]));
74 BoxSampler::sample<CptAccessor>(mCptAccessor, location, result);
75 }
76 W[0] = result[0];
77 W[1] = result[1];
78 W[2] = result[2];
79 }
80
81private:
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!
111template<typename GridT = Vec3fGrid,
112 typename PointListT = std::vector<typename GridT::ValueType>,
113 bool StaggeredVelocity = false,
114 typename InterrupterType = util::NullInterrupter>
116{
117public:
118 using GridType = GridT;
119 using PointListType = PointListT;
120 using LocationType = typename PointListT::value_type;
122
123 PointAdvect(const GridT& velGrid, InterrupterType* interrupter = nullptr):
124 mVelGrid(&velGrid),
125 mPoints(nullptr),
126 mIntegrationOrder(1),
127 mThreaded(true),
128 mInterrupter(interrupter)
129 {
130 }
131 PointAdvect(const PointAdvect &other) :
132 mVelGrid(other.mVelGrid),
133 mPoints(other.mPoints),
134 mDt(other.mDt),
135 mAdvIterations(other.mAdvIterations),
136 mIntegrationOrder(other.mIntegrationOrder),
137 mThreaded(other.mThreaded),
138 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 bool earlyOut() const { return (mIntegrationOrder==0);}
146 /// get & set
147 void setThreaded(bool threaded) { mThreaded = threaded; }
148 bool getThreaded() { return mThreaded; }
149 void setIntegrationOrder(unsigned int order) {mIntegrationOrder = order;}
150
151 /// Constrained advection of a list of points over a time = dt * advIterations
152 void advect(PointListT& points, float dt, unsigned int advIterations = 1)
153 {
154 if (this->earlyOut()) return; // nothing to do!
155 mPoints = &points;
156 mDt = dt;
157 mAdvIterations = advIterations;
158
159 if (mInterrupter) mInterrupter->start("Advecting points by OpenVDB velocity field: ");
160 if (mThreaded) {
161 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 if (mInterrupter) mInterrupter->end();
166 }
167
168 /// Never call this method directly - it is use by TBB and has to be public!
169 void operator() (const tbb::blocked_range<size_t> &range) const
170 {
171 if (mInterrupter && mInterrupter->wasInterrupted()) {
173 }
174
175 VelocityFieldIntegrator velField(*mVelGrid);
176 switch (mIntegrationOrder) {
177 case 1:
178 {
179 for (size_t n = range.begin(); n != range.end(); ++n) {
180 LocationType& X0 = (*mPoints)[n];
181 // loop over number of time steps
182 for (unsigned int i = 0; i < mAdvIterations; ++i) {
183 velField.template rungeKutta<1>(mDt, X0);
184 }
185 }
186 }
187 break;
188 case 2:
189 {
190 for (size_t n = range.begin(); n != range.end(); ++n) {
191 LocationType& X0 = (*mPoints)[n];
192 // loop over number of time steps
193 for (unsigned int i = 0; i < mAdvIterations; ++i) {
194 velField.template rungeKutta<2>(mDt, X0);
195 }
196 }
197 }
198 break;
199 case 3:
200 {
201 for (size_t n = range.begin(); n != range.end(); ++n) {
202 LocationType& X0 = (*mPoints)[n];
203 // loop over number of time steps
204 for (unsigned int i = 0; i < mAdvIterations; ++i) {
205 velField.template rungeKutta<3>(mDt, X0);
206 }
207 }
208 }
209 break;
210 case 4:
211 {
212 for (size_t n = range.begin(); n != range.end(); ++n) {
213 LocationType& X0 = (*mPoints)[n];
214 // loop over number of time steps
215 for (unsigned int i = 0; i < mAdvIterations; ++i) {
216 velField.template rungeKutta<4>(mDt, X0);
217 }
218 }
219 }
220 break;
221 }
222 }
223
224private:
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
243template<typename GridT = Vec3fGrid,
244 typename PointListT = std::vector<typename GridT::ValueType>,
245 bool StaggeredVelocity = false,
246 typename CptGridType = GridT,
247 typename InterrupterType = util::NullInterrupter>
249{
250public:
251 using GridType = GridT;
252 using LocationType = typename PointListT::value_type;
255 using PointListType = PointListT;
256
258 const GridType& cptGrid, int cptn, InterrupterType* interrupter = nullptr):
259 mVelGrid(&velGrid),
260 mCptGrid(&cptGrid),
261 mCptIter(cptn),
262 mInterrupter(interrupter)
263 {
264 }
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 }
278
279 void setConstraintIterations(unsigned int cptIter) {mCptIter = cptIter;}
280 void setIntegrationOrder(unsigned int order) {mIntegrationOrder = order;}
281
282 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 void advect(PointListT& points, float dt, unsigned int advIterations = 1)
287 {
288 mPoints = &points;
289 mDt = dt;
290
291 if (mIntegrationOrder==0 && mCptIter == 0) {
292 return; // nothing to do!
293 }
294 (mIntegrationOrder>0) ? mAdvIterations = advIterations : mAdvIterations = 1;
295
296 if (mInterrupter) mInterrupter->start("Advecting points by OpenVDB velocity field: ");
297 const size_t N = mPoints->size();
298
299 if (mThreaded) {
300 tbb::parallel_for(tbb::blocked_range<size_t>(0, N), *this);
301 } else {
302 (*this)(tbb::blocked_range<size_t>(0, N));
303 }
304 if (mInterrupter) mInterrupter->end();
305 }
306
307
308 /// Never call this method directly - it is use by TBB and has to be public!
309 void operator() (const tbb::blocked_range<size_t> &range) const
310 {
311 if (mInterrupter && mInterrupter->wasInterrupted()) {
313 }
314
315 VelocityIntegratorType velField(*mVelGrid);
316 ClosestPointProjectorType cptField(*mCptGrid, mCptIter);
317 switch (mIntegrationOrder) {
318 case 0://pure CPT projection
319 {
320 for (size_t n = range.begin(); n != range.end(); ++n) {
321 LocationType& X0 = (*mPoints)[n];
322 for (unsigned int i = 0; i < mAdvIterations; ++i) {
323 cptField.projectToConstraintSurface(X0);
324 }
325 }
326 }
327 break;
328 case 1://1'th order advection and CPT projection
329 {
330 for (size_t n = range.begin(); n != range.end(); ++n) {
331 LocationType& X0 = (*mPoints)[n];
332 for (unsigned int i = 0; i < mAdvIterations; ++i) {
333 velField.template rungeKutta<1>(mDt, X0);
334 cptField.projectToConstraintSurface(X0);
335 }
336 }
337 }
338 break;
339 case 2://2'nd order advection and CPT projection
340 {
341 for (size_t n = range.begin(); n != range.end(); ++n) {
342 LocationType& X0 = (*mPoints)[n];
343 for (unsigned int i = 0; i < mAdvIterations; ++i) {
344 velField.template rungeKutta<2>(mDt, X0);
345 cptField.projectToConstraintSurface(X0);
346 }
347 }
348 }
349 break;
350
351 case 3://3'rd order advection and CPT projection
352 {
353 for (size_t n = range.begin(); n != range.end(); ++n) {
354 LocationType& X0 = (*mPoints)[n];
355 for (unsigned int i = 0; i < mAdvIterations; ++i) {
356 velField.template rungeKutta<3>(mDt, X0);
357 cptField.projectToConstraintSurface(X0);
358 }
359 }
360 }
361 break;
362 case 4://4'th order advection and CPT projection
363 {
364 for (size_t n = range.begin(); n != range.end(); ++n) {
365 LocationType& X0 = (*mPoints)[n];
366 for (unsigned int i = 0; i < mAdvIterations; ++i) {
367 velField.template rungeKutta<4>(mDt, X0);
368 cptField.projectToConstraintSurface(X0);
369 }
370 }
371 }
372 break;
373 }
374 }
375
376private:
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
Defines two simple wrapper classes for advection velocity fields as well as VelocitySampler and Veloc...
ClosestPointProjector(const ClosestPointProjector &other)
Definition PointAdvect.h:54
CptGridT CptGridType
Definition PointAdvect.h:40
ClosestPointProjector()
Definition PointAdvect.h:44
typename CptGridType::ConstAccessor CptAccessor
Definition PointAdvect.h:41
void projectToConstraintSurface(LocationType &W) const
Definition PointAdvect.h:65
unsigned int numIterations()
Definition PointAdvect.h:61
void setConstraintIterations(unsigned int cptIterations)
Definition PointAdvect.h:60
typename CptGridType::ValueType CptValueType
Definition PointAdvect.h:42
ClosestPointProjector(const CptGridType &cptGrid, int n)
Definition PointAdvect.h:48
ConstrainedPointAdvect(const ConstrainedPointAdvect &other)
Definition PointAdvect.h:265
ClosestPointProjector< CptGridType > ClosestPointProjectorType
Definition PointAdvect.h:254
void setIntegrationOrder(unsigned int order)
Definition PointAdvect.h:280
ConstrainedPointAdvect(const GridType &velGrid, const GridType &cptGrid, int cptn, InterrupterType *interrupter=nullptr)
Definition PointAdvect.h:257
void setThreaded(bool threaded)
Definition PointAdvect.h:282
void advect(PointListT &points, float dt, unsigned int advIterations=1)
Constrained Advection a list of points over a time = dt * advIterations.
Definition PointAdvect.h:286
VelocityIntegrator< GridT, StaggeredVelocity > VelocityIntegratorType
Definition PointAdvect.h:253
typename PointListT::value_type LocationType
Definition PointAdvect.h:252
bool getThreaded()
Definition PointAdvect.h:283
void setConstraintIterations(unsigned int cptIter)
Definition PointAdvect.h:279
GridT GridType
Definition PointAdvect.h:251
PointListT PointListType
Definition PointAdvect.h:255
virtual ~ConstrainedPointAdvect()
Definition PointAdvect.h:277
bool earlyOut() const
If the order of the integration is set to zero no advection is performed.
Definition PointAdvect.h:145
virtual ~PointAdvect()
Definition PointAdvect.h:141
VelocityIntegrator< GridT, StaggeredVelocity > VelocityFieldIntegrator
Definition PointAdvect.h:121
void setIntegrationOrder(unsigned int order)
Definition PointAdvect.h:149
void setThreaded(bool threaded)
get & set
Definition PointAdvect.h:147
void advect(PointListT &points, float dt, unsigned int advIterations=1)
Constrained advection of a list of points over a time = dt * advIterations.
Definition PointAdvect.h:152
typename PointListT::value_type LocationType
Definition PointAdvect.h:120
bool getThreaded()
Definition PointAdvect.h:148
PointAdvect(const GridT &velGrid, InterrupterType *interrupter=nullptr)
Definition PointAdvect.h:123
GridT GridType
Definition PointAdvect.h:118
PointAdvect(const PointAdvect &other)
Definition PointAdvect.h:131
PointListT PointListType
Definition PointAdvect.h:119
Performs Runge-Kutta time integration of variable order in a static velocity field.
Definition VelocityFields.h:216
Definition AttributeArray.h:42
vptr bool cancelGroupExecution()
Definition Threading.h:41
Vec3SGrid Vec3fGrid
Definition openvdb.h:87
math::Vec3< Real > Vec3R
Definition Types.h:53
Definition Exceptions.h:13
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Trilinearly reconstruct inTree at inCoord and store the result in result.
Definition Interpolation.h:745
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:291