OpenVDB  13.0.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 affine matrix attributes from the points::pca()
49 /// method which model these elliptical distributions using principal
50 /// component analysis. The ellipses create a much tighter, more fitted
51 /// surface that better represents the convex hull of the point set. This
52 /// technique also allows point to smoothly blend from their computed
53 /// ellipse back to a canonical sphere, as well as allowing isolated points
54 /// to be rasterized with their own radius. Although the rasterization step
55 /// of this pipeline is relatively fast, it is still the slowest of all
56 /// three methods, and depends on the somewhat expensive points::pca()
57 /// method if you're not providing your own transformations. Still, this
58 /// technique can be far superior at producing fluid surfaces where thin
59 /// sheets (waterfalls) or sharp edges (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 /// ellips.xform = attribs.xform;
130 /// ellips.radius = attribs.stretch;
131 /// ellips.attributes.emplace_back("id");
132 /// ellips.attributes.emplace_back("v");
133 /// GridPtrVec grids = points::rasterizeSdf(g, ellips);
134 /// FloatGrid::Ptr sdf = StaticPtrCast<FloatGrid>(grids[0]);
135 /// Int32Grid::Ptr id = StaticPtrCast<Int32Grid>(grids[1]);
136 /// Vec3fGrid::Ptr vel = StaticPtrCast<Vec3fGrid>(grids[2]);
137 /// @endcode
138 template <typename PointDataGridT,
139  typename SdfT = typename PointDataGridT::template ValueConverter<float>::Type,
140  typename SettingsT>
142 rasterizeSdf(const PointDataGridT& points, const SettingsT& settings);
143 
144 //
145 
146 /// @brief Generic settings for narrow band spherical stamping with a uniform
147 /// or varying radius and optionally with closest point attribute transfer of
148 /// arbitrary attributes. See the struct member documentation for detailed
149 /// behavior.
150 /// @note There exists other more complex kernels that derive from this struct,
151 /// but on its own it represents the settings needed to perform basic narrow
152 /// band sphere stamping. Parameters are interpreted in the same way across
153 /// derived classes.
154 template <typename AttributeTs = TypeList<>,
155  typename RadiusAttributeT = float,
156  typename FilterT = NullFilter>
158 {
159  using AttributeTypes = AttributeTs;
160  using RadiusAttributeType = RadiusAttributeT;
161  using FilterType = FilterT;
162 
163  /// @param radius the attribute containing the world space radius
164  /// @details if the radius parameter is an empty string then the
165  /// `radiusScale` parameter is used as a uniform world space radius to
166  /// generate a fixed surface mask. Otherwise, a point attribute
167  /// representing the world space radius of each point of type
168  /// `RadiusAttributeT` is expected to exist and radii are scaled by the
169  /// `radiusScale` parameter.
170  std::string radius = "";
171 
172  /// @param radiusScale the scale applied to every world space radius value
173  /// @note If no `radius` attribute is provided, this is used as the
174  /// uniform world space radius for every point. Most surfacing operations
175  /// will perform faster if they are able to assume a uniform radius (so
176  /// use this value instead of setting the `radius` parameter if radii are
177  /// uniform).
178  /// @note Type of the scale is always double precision (the Promote exists
179  /// as this could be a vector scale - see EllipsoidSettings).
181  RadiusScaleT radiusScale = RadiusScaleT(1.0);
182 
183  /// @param halfband the half band width of the generated surface.
185 
186  /// @param transform the target transform for the surface. Most surfacing
187  /// operations impose linear restrictions on the target transform.
188  math::Transform::Ptr transform = nullptr;
189 
190  /// @param attributes list of attributes to transfer
191  /// @details if the attributes vector is empty, only the surface is built.
192  /// Otherwise, every voxel's closest point is used to transfer each
193  /// attribute in the attributes parameter to a new grid of matching
194  /// topology. The built surface is always the first grid returned from
195  /// the surfacing operation, followed by attribute grids in the order
196  /// that they appear in this vector.
197  ///
198  /// The `AttributeTs` template parameter should be a `TypeList` of the
199  /// required or possible attributes types. Example:
200  /// @code
201  /// // compile support for int, double and Vec3f attribute transferring
202  /// using SupportedTypes = TypeList<int, double, Vec3f>;
203  /// SphereSettings<SupportedTypes> s;
204  ///
205  /// // Produce 4 additional grids from the "v", "Cd", "id" and "density"
206  /// // attributes. Their attribute value types must be available in the
207  /// // provided TypeList
208  /// s.attributes = {"v", "Cd", "id", "density"};
209  /// @endcode
210  ///
211  /// A runtime error will be thrown if no equivalent type for a given
212  /// attribute is found in the `AttributeTs` TypeList.
213  ///
214  /// @note The destination types of these grids is equal to the
215  /// `ValueConverter` result of the attribute type applied to the
216  /// PointDataGridT.
217  std::vector<std::string> attributes;
218 
219  /// @param filter a filter to apply to points. Only points that evaluate
220  /// to true using this filter are rasterized, regardless of any other
221  /// filtering derived schemes may use.
222  const FilterT* filter = nullptr;
223 
224  /// @param interrupter optional interrupter
225  util::NullInterrupter* interrupter = nullptr;
226 };
227 
228 /// @brief Smoothed point distribution based sphere stamping with a uniform radius
229 /// or varying radius and optionally with closest point attribute transfer of
230 /// arbitrary attributes. See the struct member documentation for detailed
231 /// behavior.
232 /// @note Protected inheritance prevents accidental struct slicing
233 template <typename AttributeTs = TypeList<>,
234  typename RadiusAttributeT = float,
235  typename FilterT = NullFilter>
237  : protected SphereSettings<AttributeTs, RadiusAttributeT, FilterT>
238 {
242  using FilterType = typename BaseT::FilterType;
243 
244  using BaseT::radius;
245  /// @note See also the searchRadius parameter for SmoothSpehere
246  /// rasterization.
247  using BaseT::radiusScale;
248  /// @warning The width of the exterior half band *may* be smaller than the
249  /// specified half band if the search radius is less than the equivalent
250  /// world space halfband distance.
251  using BaseT::halfband;
252  using BaseT::transform;
253  using BaseT::attributes;
254  using BaseT::filter;
255  using BaseT::interrupter;
256 
257  /// @param searchRadius the maximum search distance of every point
258  /// @details The search radius is each points points maximum contribution
259  /// to the target level set. It should always have a value equal to or
260  /// larger than the point radius. Both this and the `radiusScale`
261  /// parameters are given in world space units and are applied to every
262  /// point to generate a surface mask.
263  /// @warning If this value is less than the sum of the maximum particle
264  /// radius and the half band width, the exterior half band width may be
265  /// smaller than desired. In these cases, consider running a levelset
266  /// renormalize or a levelset rebuild.
267  Real searchRadius = 1.0;
268 };
269 
270 // Suppress spurious warnings on compiler emitted methods (constructors, etc)
271 // due to deprecated members. Accessing said members still generates the warning.
273 
274 /// @brief Anisotropic point rasterization based on the principal component
275 /// analysis of point neighbours. See the struct member documentation for
276 /// detailed behavior.
277 /// @details This rasterization technique is typically used with the
278 /// accompanying PCA tools in PrincipalComponentAnalysis.h which initializes
279 /// the required attributes. These attributes define the rotational and
280 /// affine transformations which can be used to construct ellipsoids for each
281 /// point. Typically (for our intended surfacing) these transformations are
282 /// built by analysing each points neighbourhood distributions and
283 /// constructing tight ellipsoids that orient themselves to follow these
284 /// point distributions.
285 /// @note Protected inheritance prevents accidental struct slicing
286 template <typename AttributeTs = TypeList<>,
287  typename RadiusAttributeT = Vec3f,
288  typename FilterT = NullFilter>
290  : protected SphereSettings<AttributeTs, RadiusAttributeT, FilterT>
291 {
295  using FilterType = typename BaseT::FilterType;
296 
297  using BaseT::halfband;
298  using BaseT::transform;
299  using BaseT::attributes;
300  using BaseT::filter;
301  using BaseT::interrupter;
302 
303  /// @note For ellipsoid rasterization, the radius attribute and scale
304  /// need to be Vec3f types (RadiusAttributeT defaults to this). This
305  /// represents each ellipsoids stretch and squash coefficients.
306  using BaseT::radius;
307  using BaseT::radiusScale;
308 
309  /// @param xform the attribute containing each points transformation
310  /// @details This attribute must exist and represents the xform of
311  /// each points ellipse. Must be a Mat3s (float) or Quatf type. Note
312  /// that if it is a matrix type, any scale represented by the matrix
313  /// is combined with the radius and radiusScale values (and is
314  /// interpreted in world space).
315  std::string xform = "xform";
316 
317  /// @param pws An optional attribute which represents the world space
318  /// position of a point.
319  /// @details This can be useful to override the position of a point in
320  /// index space. If it exists, it must be a Vec3d type.
321  std::string pws = "";
322 
323  /// Old style "xform" attribute which has since been renamed and ONLY
324  /// supported rotation. If set, will be prioritised and infered to only
325  /// hold a rotation. This will be removed and should not be used.
326  OPENVDB_DEPRECATED_MESSAGE("Use EllipsoidSettings::xform") std::string rotation = "";
327 };
328 
330 
331 } // namespace points
332 } // namespace OPENVDB_VERSION_NAME
333 } // namespace openvdb
334 
335 #include "impl/PointRasterizeSDFImpl.h"
337 
338 #endif //OPENVDB_POINTS_RASTERIZE_SDF_HAS_BEEN_INCLUDED
std::vector< std::string > attributes
Definition: PointRasterizeSDF.h:217
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:188
Framework methods for rasterizing PointDataGrid data to Trees.
Promotion classes which provide an interface for elevating and demoting a scalar or VDB type to a hig...
Definition: Types.h:405
#define OPENVDB_NO_DEPRECATION_WARNING_BEGIN
Bracket code with OPENVDB_NO_DEPRECATION_WARNING_BEGIN/_END, to inhibit warnings about deprecated cod...
Definition: Platform.h:217
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
Anisotropic point rasterization based on the principal component analysis of point neighbours...
Definition: PointRasterizeSDF.h:289
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
RadiusAttributeT RadiusAttributeType
Definition: PointRasterizeSDF.h:160
typename PromoteType< RadiusAttributeT >::Highest RadiusScaleT
Definition: PointRasterizeSDF.h:180
Definition: Coord.h:590
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:528
Defined various multi-threaded utility functions for trees.
FilterT FilterType
Definition: PointRasterizeSDF.h:161
GridPtrVec rasterizeSdf(const PointDataGridT &points, const SettingsT &settings)
Perform point rasterzation to produce a signed distance field.
Definition: PointRasterizeSDFImpl.h:1525
Selectively extract and filter point data using a custom filter operator.
AttributeTs AttributeTypes
Definition: PointRasterizeSDF.h:159
Definition: Exceptions.h:13
Smoothed point distribution based sphere stamping with a uniform radius or varying radius and optiona...
Definition: PointRasterizeSDF.h:236
Base class for interrupters.
Definition: NullInterrupter.h:25
#define OPENVDB_NO_DEPRECATION_WARNING_END
Definition: Platform.h:218
Generic settings for narrow band spherical stamping with a uniform or varying radius and optionally w...
Definition: PointRasterizeSDF.h:157
SharedPtr< Transform > Ptr
Definition: Transform.h:42
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
Functions to perform multi threaded reductions and analysis of arbitrary point attribute types...
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:171
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
double Real
Definition: Types.h:40