diff options
author | Hans Goudey <h.goudey@me.com> | 2021-06-09 22:53:39 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2021-06-09 22:53:39 +0300 |
commit | 675677ec67c6b922b3a5e602c8bf3dbb562bd687 (patch) | |
tree | 035269838d3d2e59989d5efe56f068230f947beb /source/blender/blenkernel/intern/spline_base.cc | |
parent | df2a19eac7daf4943b22f74890cebd14eb811f4e (diff) |
Splines: Add API functions for interpolating data
First, expand on the interpolation to evaluated points with a templated
helper function, and a function that takes a GSPan. Next, add a set of
functions to `Spline` for interpolating at arbitrary intervals between
the evaluated points. The code for doing that isn't that complicated
anyway, but it's nice to avoid repeating, and it might make it easier
to unroll the special cases for the first and last points if we require
the index factors to be sorted.
Diffstat (limited to 'source/blender/blenkernel/intern/spline_base.cc')
-rw-r--r-- | source/blender/blenkernel/intern/spline_base.cc | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index 11620a30948..9f8c215b31f 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -16,6 +16,7 @@ #include "BLI_array.hh" #include "BLI_span.hh" +#include "BLI_task.hh" #include "BLI_timeit.hh" #include "BKE_spline.hh" @@ -27,6 +28,12 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::fn::GMutableSpan; +using blender::fn::GSpan; +using blender::fn::GVArray; +using blender::fn::GVArray_For_GSpan; +using blender::fn::GVArray_Typed; +using blender::fn::GVArrayPtr; Spline::Type Spline::type() const { @@ -234,8 +241,7 @@ Span<float3> Spline::evaluated_normals() const calculate_normals_z_up(tangents, normals); /* Rotate the generated normals with the interpolated tilt data. */ - blender::fn::GVArray_Typed<float> tilts{ - this->interpolate_to_evaluated_points(blender::fn::GVArray_For_Span(this->tilts()))}; + GVArray_Typed<float> tilts = this->interpolate_to_evaluated_points(this->tilts()); for (const int i : normals.index_range()) { normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]); } @@ -341,3 +347,34 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) minmax_v3v3_v3(min, max, position); } } + +GVArrayPtr Spline::interpolate_to_evaluated_points(GSpan data) const +{ + return this->interpolate_to_evaluated_points(GVArray_For_GSpan(data)); +} + +/** + * Sample any input data with a value for each evaluated point (already interpolated to evaluated + * points) to arbitrary parameters in betwen the evaluated points. The interpolation is quite + * simple, but this handles the cyclic and end point special cases. + */ +void Spline::sample_based_on_index_factors(const GVArray &src, + Span<float> index_factors, + GMutableSpan dst) const +{ + BLI_assert(src.size() == this->evaluated_points_size()); + + blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + const GVArray_Typed<T> src_typed = src.typed<T>(); + MutableSpan<T> dst_typed = dst.typed<T>(); + blender::parallel_for(dst_typed.index_range(), 1024, [&](IndexRange range) { + for (const int i : range) { + const LookupResult interp = this->lookup_data_from_index_factor(index_factors[i]); + dst_typed[i] = blender::attribute_math::mix2(interp.factor, + src_typed[interp.evaluated_index], + src_typed[interp.next_evaluated_index]); + } + }); + }); +} |