diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_spline.hh | 26 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/spline_base.cc | 41 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/spline_nurbs.cc | 8 |
3 files changed, 69 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index fc1292e3620..dfbe82f31fd 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -172,6 +172,25 @@ class Spline { blender::Array<float> sample_uniform_index_factors(const int samples_size) const; LookupResult lookup_data_from_index_factor(const float index_factor) const; + void sample_based_on_index_factors(const blender::fn::GVArray &src, + blender::Span<float> index_factors, + blender::fn::GMutableSpan dst) const; + template<typename T> + void sample_based_on_index_factors(const blender::VArray<T> &src, + blender::Span<float> index_factors, + blender::MutableSpan<T> dst) const + { + this->sample_based_on_index_factors( + blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst)); + } + template<typename T> + void sample_based_on_index_factors(blender::Span<T> src, + blender::Span<float> index_factors, + blender::MutableSpan<T> dst) const + { + this->sample_based_on_index_factors(blender::VArray_For_Span(src), index_factors, dst); + } + /** * Interpolate a virtual array of data with the size of the number of control points to the * evaluated points. For poly splines, the lifetime of the returned virtual array must not @@ -179,6 +198,13 @@ class Spline { */ virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points( const blender::fn::GVArray &source_data) const = 0; + blender::fn::GVArrayPtr interpolate_to_evaluated_points(blender::fn::GSpan data) const; + template<typename T> + blender::fn::GVArray_Typed<T> interpolate_to_evaluated_points(blender::Span<T> data) const + { + return blender::fn::GVArray_Typed<T>( + this->interpolate_to_evaluated_points(blender::fn::GSpan(data))); + } protected: virtual void correct_end_tangents() const = 0; 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]); + } + }); + }); +} diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index cae206341a0..bfb0d652b1a 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -26,6 +26,7 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::fn::GVArray_Typed; SplinePtr NURBSpline::copy() const { @@ -434,10 +435,9 @@ Span<float3> NURBSpline::evaluated_positions() const const int eval_size = this->evaluated_points_size(); evaluated_position_cache_.resize(eval_size); - blender::fn::GVArray_Typed<float3> evaluated_positions{ - this->interpolate_to_evaluated_points(blender::fn::GVArray_For_Span<float3>(positions_))}; - - evaluated_positions->materialize(evaluated_position_cache_); + /* TODO: Avoid copying the evaluated data from the temporary array. */ + GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated_points(positions_.as_span()); + evaluated->materialize(evaluated_position_cache_); position_cache_dirty_ = false; return evaluated_position_cache_; |