OpenVDB 12.0.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 Dan Bailey
5///
6/// @file points/PointAdvect.h
7///
8/// @brief Ability to advect VDB Points through a velocity field.
9
10#ifndef OPENVDB_POINTS_POINT_ADVECT_HAS_BEEN_INCLUDED
11#define OPENVDB_POINTS_POINT_ADVECT_HAS_BEEN_INCLUDED
12
13#include <openvdb/openvdb.h>
14#include <openvdb/tools/Prune.h>
16
17#include "AttributeGroup.h"
18#include "PointDataGrid.h"
19#include "PointGroup.h"
20#include "PointMove.h"
21
22#include <memory>
23
24
25namespace openvdb {
27namespace OPENVDB_VERSION_NAME {
28namespace points {
29
30
31/// @brief Advect points in a PointDataGrid through a velocity grid
32/// @param points the PointDataGrid containing the points to be advected.
33/// @param velocity a velocity grid to be sampled.
34/// @param integrationOrder the integration scheme to use (1 is forward euler, 4 is runge-kutta 4th)
35/// @param dt delta time.
36/// @param timeSteps number of advection steps to perform.
37/// @param advectFilter an optional advection index filter (moves a subset of the points)
38/// @param filter an optional index filter (deletes a subset of the points)
39/// @param cached caches velocity interpolation for faster performance, disable to use
40/// less memory (default is on).
41template <typename PointDataGridT, typename VelGridT,
42 typename AdvectFilterT = NullFilter, typename FilterT = NullFilter>
43inline void advectPoints(PointDataGridT& points, const VelGridT& velocity,
44 const Index integrationOrder, const double dt, const Index timeSteps,
45 const AdvectFilterT& advectFilter = NullFilter(),
46 const FilterT& filter = NullFilter(),
47 const bool cached = true);
48
49
50////////////////////////////////////////
51
52/// @cond OPENVDB_DOCS_INTERNAL
53
54namespace point_advect_internal {
55
56enum IntegrationOrder {
57 INTEGRATION_ORDER_FWD_EULER = 1,
58 INTEGRATION_ORDER_RK_2ND,
59 INTEGRATION_ORDER_RK_3RD,
60 INTEGRATION_ORDER_RK_4TH
61};
62
63template <typename VelGridT, Index IntegrationOrder, bool Staggered, typename FilterT>
64class AdvectionDeformer
65{
66public:
67 using IntegratorT = openvdb::tools::VelocityIntegrator<VelGridT, Staggered>;
68
69 AdvectionDeformer(const VelGridT& velocityGrid, const double timeStep, const int steps,
70 const FilterT& filter)
71 : mIntegrator(velocityGrid)
72 , mTimeStep(timeStep)
73 , mSteps(steps)
74 , mFilter(filter) { }
75
76 template <typename LeafT>
77 void reset(const LeafT& leaf, size_t /*idx*/)
78 {
79 mFilter.reset(leaf);
80 }
81
82 template <typename IndexIterT>
83 void apply(Vec3d& position, const IndexIterT& iter) const
84 {
85 if (mFilter.valid(iter)) {
86 for (int n = 0; n < mSteps; ++n) {
87 mIntegrator.template rungeKutta<IntegrationOrder, openvdb::Vec3d>(
88 static_cast<typename IntegratorT::ElementType>(mTimeStep), position);
89 }
90 }
91 }
92
93private:
94 IntegratorT mIntegrator;
95 double mTimeStep;
96 const int mSteps;
97 FilterT mFilter;
98}; // class AdvectionDeformer
99
100
101template <typename PointDataGridT, typename VelGridT, typename AdvectFilterT, typename FilterT>
102struct AdvectionOp
103{
104 using CachedDeformerT = CachedDeformer<double>;
105
106 AdvectionOp(PointDataGridT& points, const VelGridT& velocity,
107 const Index integrationOrder, const double timeStep, const Index steps,
108 const AdvectFilterT& advectFilter,
109 const FilterT& filter)
110 : mPoints(points)
111 , mVelocity(velocity)
112 , mIntegrationOrder(integrationOrder)
113 , mTimeStep(timeStep)
114 , mSteps(steps)
115 , mAdvectFilter(advectFilter)
116 , mFilter(filter) { }
117
118 void cache()
119 {
120 mCachedDeformer.reset(new CachedDeformerT(mCache));
121 (*this)(true);
122 }
123
124 void advect()
125 {
126 (*this)(false);
127 }
128
129private:
130 template <int IntegrationOrder, bool Staggered>
131 void resolveIntegrationOrder(bool buildCache)
132 {
133 const auto leaf = mPoints.constTree().cbeginLeaf();
134 if (!leaf) return;
135
136 // move points according to the pre-computed cache
137 if (!buildCache && mCachedDeformer) {
138 movePoints(mPoints, *mCachedDeformer, mFilter);
139 return;
140 }
141
142 NullFilter nullFilter;
143
144 if (buildCache) {
145 // disable group filtering from the advection deformer and perform group filtering
146 // in the cache deformer instead, this restricts the cache to just containing
147 // positions from points which are both deforming *and* are not being deleted
148 AdvectionDeformer<VelGridT, IntegrationOrder, Staggered, NullFilter> deformer(
149 mVelocity, mTimeStep, mSteps, nullFilter);
150 if (mFilter.state() == index::ALL && mAdvectFilter.state() == index::ALL) {
151 mCachedDeformer->evaluate(mPoints, deformer, nullFilter);
152 } else {
153 BinaryFilter<AdvectFilterT, FilterT, /*And=*/true> binaryFilter(
154 mAdvectFilter, mFilter);
155 mCachedDeformer->evaluate(mPoints, deformer, binaryFilter);
156 }
157 }
158 else {
159 // revert to NullFilter if all points are being evaluated
160 if (mAdvectFilter.state() == index::ALL) {
161 AdvectionDeformer<VelGridT, IntegrationOrder, Staggered, NullFilter> deformer(
162 mVelocity, mTimeStep, mSteps, nullFilter);
163 movePoints(mPoints, deformer, mFilter);
164 }
165 else {
166 AdvectionDeformer<VelGridT, IntegrationOrder, Staggered, AdvectFilterT> deformer(
167 mVelocity, mTimeStep, mSteps, mAdvectFilter);
168 movePoints(mPoints, deformer, mFilter);
169 }
170 }
171 }
172
173 template <bool Staggered>
174 void resolveStaggered(bool buildCache)
175 {
176 if (mIntegrationOrder == INTEGRATION_ORDER_FWD_EULER) {
177 resolveIntegrationOrder<1, Staggered>(buildCache);
178 } else if (mIntegrationOrder == INTEGRATION_ORDER_RK_2ND) {
179 resolveIntegrationOrder<2, Staggered>(buildCache);
180 } else if (mIntegrationOrder == INTEGRATION_ORDER_RK_3RD) {
181 resolveIntegrationOrder<3, Staggered>(buildCache);
182 } else if (mIntegrationOrder == INTEGRATION_ORDER_RK_4TH) {
183 resolveIntegrationOrder<4, Staggered>(buildCache);
184 }
185 }
186
187 void operator()(bool buildCache)
188 {
189 // early-exit if no leafs
190 if (mPoints.constTree().leafCount() == 0) return;
191
192 if (mVelocity.getGridClass() == openvdb::GRID_STAGGERED) {
193 resolveStaggered<true>(buildCache);
194 } else {
195 resolveStaggered<false>(buildCache);
196 }
197 }
198
199 PointDataGridT& mPoints;
200 const VelGridT& mVelocity;
201 const Index mIntegrationOrder;
202 const double mTimeStep;
203 const Index mSteps;
204 const AdvectFilterT& mAdvectFilter;
205 const FilterT& mFilter;
206 CachedDeformerT::Cache mCache;
207 std::unique_ptr<CachedDeformerT> mCachedDeformer;
208}; // struct AdvectionOp
209
210} // namespace point_advect_internal
211
212/// @endcond
213
214////////////////////////////////////////
215
216
217template <typename PointDataGridT, typename VelGridT, typename AdvectFilterT, typename FilterT>
218inline void advectPoints(PointDataGridT& points, const VelGridT& velocity,
219 const Index integrationOrder, const double timeStep, const Index steps,
220 const AdvectFilterT& advectFilter,
221 const FilterT& filter,
222 const bool cached)
223{
224 using namespace point_advect_internal;
225
226 if (steps == 0) return;
227
228 if (integrationOrder > 4) {
229 throw ValueError{"Unknown integration order for advecting points."};
230 }
231
232 AdvectionOp<PointDataGridT, VelGridT, AdvectFilterT, FilterT> op(
233 points, velocity, integrationOrder, timeStep, steps,
234 advectFilter, filter);
235
236 // if caching is enabled, sample the velocity field using a CachedDeformer to store the
237 // intermediate positions before moving the points, this uses more memory but typically
238 // results in faster overall performance
239 if (cached) op.cache();
240
241 // advect the points
242 op.advect();
243}
244
245} // namespace points
246} // namespace OPENVDB_VERSION_NAME
247} // namespace openvdb
248
249#endif // OPENVDB_POINTS_POINT_ADVECT_HAS_BEEN_INCLUDED
Attribute Group access and filtering for iteration.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Point group manipulation in a VDB Point Grid.
Ability to move VDB Points using a custom deformer.
Defined various multi-threaded utility functions for trees.
Defines two simple wrapper classes for advection velocity fields as well as VelocitySampler and Veloc...
Definition Exceptions.h:65
Definition AttributeArray.h:42
void movePoints(PointDataGridT &points, DeformerT &deformer, const FilterT &filter=NullFilter(), future::Advect *objectNotInUse=nullptr, bool threaded=true)
Move points in a PointDataGrid using a custom deformer.
Definition PointMoveImpl.h:619
void advectPoints(PointDataGridT &points, const VelGridT &velocity, const Index integrationOrder, const double dt, const Index timeSteps, const AdvectFilterT &advectFilter=NullFilter(), const FilterT &filter=NullFilter(), const bool cached=true)
Advect points in a PointDataGrid through a velocity grid.
Definition PointAdvect.h:218
Index32 Index
Definition Types.h:54
@ GRID_STAGGERED
Definition Types.h:457
Definition Exceptions.h:13
#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