OpenVDB  12.1.0
PointRasterizeSDF.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 Nick Avramoussis
5 ///
6 /// @file PointRasterizeSDF.h
7 ///
8 /// @brief Various transfer schemes for rasterizing point positions and radius
9 /// data to signed distance fields with optional closest point attribute
10 /// transfers. All methods support arbitrary target linear transformations,
11 /// fixed or varying point radius, filtering of point data and arbitrary types
12 /// for attribute transferring.
13 ///
14 /// @details There are currently three main transfer implementations:
15 ///
16 /// - Rasterize Spheres
17 ///
18 /// Performs trivial narrow band stamping of spheres for each point. This
19 /// is an extremely fast and efficient way to produce both a valid
20 /// symmetrical narrow band level set and transfer attributes using closest
21 /// point lookups.
22 ///
23 /// - Rasterize Smooth Spheres
24 ///
25 /// Calculates an averaged position of influence per voxel as described in:
26 /// [Animating Sand as a Fluid - Zhu Bridson 2005].
27 ///
28 /// This technique produces smoother, more blended connections between
29 /// points which is ideal for generating a more artistically pleasant
30 /// surface directly from point distributions. It aims to avoid typical
31 /// post filtering operations used to smooth surface volumes. Note however
32 /// that this method can be prone to temporal instabilities (that is, given
33 /// a sequence of frames, consecutive frames may not generate surfaces that
34 /// transition as smoothly) due to changes in point distributions resulting
35 /// in more abrupt surface changes. It may also not necessarily produce a
36 /// *symmetrical* narrow band level set; the exterior band may be smaller
37 /// than desired depending on the search radius - the surface can be rebuilt
38 /// or resized if necessary. The same closet point algorithm is used to
39 /// transfer attributes.
40 ///
41 /// - Rasterize Ellipsoids.
42 ///
43 /// Rasterizes anisotropic ellipses for each point by analyzing point
44 /// neighborhood distributions, as described in:
45 /// [Reconstructing Surfaces of Particle-Based Fluids Using Anisotropic
46 /// Kernel - Yu Turk 2010].
47 ///
48 /// This method uses the rotation and affine matrix attributes built from
49 /// the points::pca() method which model these elliptical distributions
50 /// using principal component analysis. The ellipses create a much tighter,
51 /// more fitted surface that better represents the convex hull of the point
52 /// set. This technique also allows point to smoothly blend from their
53 /// computed ellipse back to a canonical sphere, as well as allowing
54 /// isolated points to be rasterized with their own radius scale. Although
55 /// the rasterization step of this pipeline is relatively fast, it is still
56 /// the slowest of all three methods and depends on the somewhat expensive
57 /// points::pca() method. Still, this technique can be far superior at
58 /// producing fluid surfaces where thin sheets (waterfalls) or sharp edges
59 /// (wave breaks) are desirable.
60 ///
61 ///
62 /// In general, it is recommended to consider post rebuilding/renormalizing
63 /// the generated surface using either tools::levelSetRebuild() or
64 /// tools::LevelSetTracker::normalize() tools::LevelSetTracker::resize().
65 ///
66 /// @note These methods use the framework provided in PointTransfer.h
67 
68 #ifndef OPENVDB_POINTS_RASTERIZE_SDF_HAS_BEEN_INCLUDED
69 #define OPENVDB_POINTS_RASTERIZE_SDF_HAS_BEEN_INCLUDED
70 
71 #include "PointDataGrid.h"
72 #include "PointTransfer.h"
73 #include "PointStatistics.h"
74 
75 #include <openvdb/openvdb.h>
76 #include <openvdb/Types.h>
77 #include <openvdb/tools/Prune.h>
79 #include <openvdb/thread/Threading.h>
81 #include <openvdb/util/Assert.h>
82 
83 #include <unordered_map>
84 
85 #include <tbb/task_group.h>
86 #include <tbb/parallel_reduce.h>
87 
88 namespace openvdb {
90 namespace OPENVDB_VERSION_NAME {
91 namespace points {
92 
93 /// @brief Perform point rasterzation to produce a signed distance field.
94 /// @param point the point data grid to rasterize
95 /// @param settings one of the available transfer setting schemes found below
96 /// in this file.
97 /// @return A vector of grids. The signed distance field is guaranteed to be
98 /// first and at the type specified by SdfT. Successive grids are the closest
99 /// point attribute grids. These grids are guaranteed to have a topology
100 /// and transform equal to the surface.
101 ///
102 /// @code
103 /// points::PointDataGrid g = ...;
104 ///
105 /// // default settings for sphere stamping with a world space radius of 1
106 /// SphereSettings<> spheres;
107 /// FloatGrid::Ptr sdf = StaticPtrCast<FloatGrid>(points::rasterizeSdf(g, spheres)[0]);
108 ///
109 /// // custom linear transform of target sdf, world space radius of 5
110 /// spheres.transform = math::Transform::createLinearTransform(0.3);
111 /// spheres.radiusScale = 5;
112 /// FloatGrid::Ptr sdf = StaticPtrCast<FloatGrid>(points::rasterizeSdf(g, spheres)[0]);
113 ///
114 /// // smooth sphere rasterization with variable double precision radius
115 /// // attribute "pscale" scaled by 2
116 /// SmoothSphereSettings<TypeList<>, double> smooth;
117 /// smooth.radius = "pscale";
118 /// smooth.radiusScale = 2;
119 /// smooth.searchRadius = 3;
120 /// FloatGrid::Ptr sdf = StaticPtrCast<FloatGrid>(points::rasterizeSdf(g, smooth)[0]);
121 ///
122 /// // anisotropic/ellipsoid rasterization with attribute transferring.
123 /// // requires pca attributes to be initialized using points::pca() first
124 /// PcaSettings settings;
125 /// PcaAttributes attribs;
126 /// points::pca(g, settings, attribs);
127 ///
128 /// EllipsoidSettings<TypeList<int32_t, Vec3f>> ellips;
129 /// s.pca = attribs;
130 /// s.attributes.emplace_back("id");
131 /// s.attributes.emplace_back("v");
132 /// GridPtrVec grids = points::rasterizeSdf(g, s);
133 /// FloatGrid::Ptr sdf = StaticPtrCast<FloatGrid>(grids[0]);
134 /// Int32Grid::Ptr id = StaticPtrCast<Int32Grid>(grids[1]);
135 /// Vec3fGrid::Ptr vel = StaticPtrCast<Vec3fGrid>(grids[2]);
136 /// @endcode
137 template <typename PointDataGridT,
138  typename SdfT = typename PointDataGridT::template ValueConverter<float>::Type,
139  typename SettingsT>
141 rasterizeSdf(const PointDataGridT& points, const SettingsT& settings);
142 
143 //
144 
145 /// @brief Generic settings for narrow band spherical stamping with a uniform
146 /// or varying radius and optionally with closest point attribute transfer of
147 /// arbitrary attributes. See the struct member documentation for detailed
148 /// behavior.
149 /// @note There exists other more complex kernels that derive from this struct,
150 /// but on its own it represents the settings needed to perform basic narrow
151 /// band sphere stamping. Parameters are interpreted in the same way across
152 /// derived classes.
153 template <typename AttributeTs = TypeList<>,
154  typename RadiusAttributeT = float,
155  typename FilterT = NullFilter>
157 {
158  using AttributeTypes = AttributeTs;
159  using RadiusAttributeType = RadiusAttributeT;
160  using FilterType = FilterT;
161 
162  /// @param radius the attribute containing the world space radius
163  /// @details if the radius parameter is an empty string then the
164  /// `radiusScale` parameter is used as a uniform world space radius to
165  /// generate a fixed surface mask. Otherwise, a point attribute
166  /// representing the world space radius of each point of type
167  /// `RadiusAttributeT` is expected to exist and radii are scaled by the
168  /// `radiusScale` parameter.
169  std::string radius = "";
170 
171  /// @param radiusScale the scale applied to every world space radius value
172  /// @note If no `radius` attribute is provided, this is used as the
173  /// uniform world space radius for every point. Most surfacing operations
174  /// will perform faster if they are able to assume a uniform radius (so
175  /// use this value instead of setting the `radius` parameter if radii are
176  /// uniform).
177  /// @note Type of the scale is always double precision (the Promote exists
178  /// as this could be a vector scale - see EllipsoidSettings).
180  RadiusScaleT radiusScale = RadiusScaleT(1.0);
181 
182  /// @param halfband the half band width of the generated surface.
184 
185  /// @param transform the target transform for the surface. Most surfacing
186  /// operations impose linear restrictions on the target transform.
187  math::Transform::Ptr transform = nullptr;
188 
189  /// @param attributes list of attributes to transfer
190  /// @details if the attributes vector is empty, only the surface is built.
191  /// Otherwise, every voxel's closest point is used to transfer each
192  /// attribute in the attributes parameter to a new grid of matching
193  /// topology. The built surface is always the first grid returned from
194  /// the surfacing operation, followed by attribute grids in the order
195  /// that they appear in this vector.
196  ///
197  /// The `AttributeTs` template parameter should be a `TypeList` of the
198  /// required or possible attributes types. Example:
199  /// @code
200  /// // compile support for int, double and Vec3f attribute transferring
201  /// using SupportedTypes = TypeList<int, double, Vec3f>;
202  /// SphereSettings<SupportedTypes> s;
203  ///
204  /// // Produce 4 additional grids from the "v", "Cd", "id" and "density"
205  /// // attributes. Their attribute value types must be available in the
206  /// // provided TypeList
207  /// s.attributes = {"v", "Cd", "id", "density"};
208  /// @endcode
209  ///
210  /// A runtime error will be thrown if no equivalent type for a given
211  /// attribute is found in the `AttributeTs` TypeList.
212  ///
213  /// @note The destination types of these grids is equal to the
214  /// `ValueConverter` result of the attribute type applied to the
215  /// PointDataGridT.
216  std::vector<std::string> attributes;
217 
218  /// @param filter a filter to apply to points. Only points that evaluate
219  /// to true using this filter are rasterized, regardless of any other
220  /// filtering derived schemes may use.
221  const FilterT* filter = nullptr;
222 
223  /// @param interrupter optional interrupter
224  util::NullInterrupter* interrupter = nullptr;
225 };
226 
227 /// @brief Smoothed point distribution based sphere stamping with a uniform radius
228 /// or varying radius and optionally with closest point attribute transfer of
229 /// arbitrary attributes. See the struct member documentation for detailed
230 /// behavior.
231 /// @note Protected inheritance prevents accidental struct slicing
232 template <typename AttributeTs = TypeList<>,
233  typename RadiusAttributeT = float,
234  typename FilterT = NullFilter>
236  : protected SphereSettings<AttributeTs, RadiusAttributeT, FilterT>
237 {
241  using FilterType = typename BaseT::FilterType;
242 
243  using BaseT::radius;
244  /// @note See also the searchRadius parameter for SmoothSpehere
245  /// rasterization.
246  using BaseT::radiusScale;
247  /// @warning The width of the exterior half band *may* be smaller than the
248  /// specified half band if the search radius is less than the equivalent
249  /// world space halfband distance.
250  using BaseT::halfband;
251  using BaseT::transform;
252  using BaseT::attributes;
253  using BaseT::filter;
254  using BaseT::interrupter;
255 
256  /// @param searchRadius the maximum search distance of every point
257  /// @details The search radius is each points points maximum contribution
258  /// to the target level set. It should always have a value equal to or
259  /// larger than the point radius. Both this and the `radiusScale`
260  /// parameters are given in world space units and are applied to every
261  /// point to generate a surface mask.
262  /// @warning If this value is less than the sum of the maximum particle
263  /// radius and the half band width, the exterior half band width may be
264  /// smaller than desired. In these cases, consider running a levelset
265  /// renormalize or a levelset rebuild.
266  Real searchRadius = 1.0;
267 };
268 
269 /// @brief Anisotropic point rasterization based on the principal component
270 /// analysis of point neighbours. See the struct member documentation for
271 /// detailed behavior.
272 /// @details This rasterization technique is typically used with the
273 /// accompanying PCA tools in PrincipalComponentAnalysis.h which initializes
274 /// the required attributes. These attributes define the rotational and
275 /// affine transformations which can be used to construct ellipsoids for each
276 /// point. Typically (for our intended surfacing) these transformations are
277 /// built by analysing each points neighbourhood distributions and
278 /// constructing tight ellipsoids that orient themselves to follow these
279 /// point distributions.
280 /// @note Protected inheritance prevents accidental struct slicing
281 template <typename AttributeTs = TypeList<>,
282  typename RadiusAttributeT = Vec3f,
283  typename FilterT = NullFilter>
285  : protected SphereSettings<AttributeTs, RadiusAttributeT, FilterT>
286 {
290  using FilterType = typename BaseT::FilterType;
291 
292  using BaseT::halfband;
293  using BaseT::transform;
294  using BaseT::attributes;
295  using BaseT::filter;
296  using BaseT::interrupter;
297 
298  /// @note For ellipsoid rasterization, the radius attribute and scale
299  /// need to be Vec3f types (RadiusAttributeT defaults to this). This
300  /// represents each ellipsoids stretch and squash coefficients.
301  using BaseT::radius;
302  using BaseT::radiusScale;
303 
304  /// @param rotation the attribute containing each points orthogonal
305  /// rotation matrix.
306  /// @details This attribute must exist and represents the rotation of
307  /// each points ellipse. Must be a Mat3s type.
308  std::string rotation = "rotation";
309 
310  /// @param pws An optional attribute which represents the world space
311  /// position of a point.
312  /// @details This can be useful to override the position of a point in
313  /// index space. If it exists, it must be a Vec3d type.
314  std::string pws = "";
315 };
316 
317 } // namespace points
318 } // namespace OPENVDB_VERSION_NAME
319 } // namespace openvdb
320 
323 
324 #endif //OPENVDB_POINTS_RASTERIZE_SDF_HAS_BEEN_INCLUDED
Framework methods for rasterizing PointDataGrid data to Trees.
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
GridPtrVec rasterizeSdf(const PointDataGridT &points, const SettingsT &settings)
Perform point rasterzation to produce a signed distance field.
Definition: PointRasterizeSDFImpl.h:1525
Anisotropic point rasterization based on the principal component analysis of point neighbours...
Definition: PointRasterizeSDF.h:284
Defined various multi-threaded utility functions for trees.
Base class for interrupters.
Definition: NullInterrupter.h:25
Selectively extract and filter point data using a custom filter operator.
RadiusAttributeT RadiusAttributeType
Definition: PointRasterizeSDF.h:159
SharedPtr< Transform > Ptr
Definition: Transform.h:42
Smoothed point distribution based sphere stamping with a uniform radius or varying radius and optiona...
Definition: PointRasterizeSDF.h:235
NumericAttributeTypes::Append< Vec3AttributeTypes >::Append< Mat3AttributeTypes >::Append< Mat4AttributeTypes >::Append< QuatAttributeTypes >::Append< points::GroupAttributeArray >::Append< points::StringAttributeArray >::Append< points::TypedAttributeArray< bool >> AttributeTypes
The attribute array types which OpenVDB will register by default.
Definition: openvdb.h:186
Definition: Exceptions.h:13
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:532
double Real
Definition: Types.h:60
std::vector< std::string > attributes
Definition: PointRasterizeSDF.h:216
typename PromoteType< RadiusAttributeT >::Highest RadiusScaleT
Definition: PointRasterizeSDF.h:179
Promotion classes which provide an interface for elevating and demoting a scalar or VDB type to a hig...
Definition: Types.h:424
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition: Mat.h:172
AttributeTs AttributeTypes
Definition: PointRasterizeSDF.h:158
Generic settings for narrow band spherical stamping with a uniform or varying radius and optionally w...
Definition: PointRasterizeSDF.h:156
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
FilterT FilterType
Definition: PointRasterizeSDF.h:160
Functions to perform multi threaded reductions and analysis of arbitrary point attribute types...
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218