diff options
Diffstat (limited to 'source/blender/blenkernel/intern/spline_bezier.cc')
-rw-r--r-- | source/blender/blenkernel/intern/spline_bezier.cc | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index b8f3717c464..ec86c81d7c3 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -331,9 +331,24 @@ void BezierSpline::evaluate_bezier_segment(const int index, } } -void BezierSpline::evaluate_bezier_position_and_mapping(MutableSpan<float3> positions, - MutableSpan<PointMapping> mappings) const +void BezierSpline::evaluate_bezier_position_and_mapping() const { + if (!this->base_cache_dirty_) { + return; + } + + std::lock_guard lock{this->base_cache_mutex_}; + if (!this->base_cache_dirty_) { + return; + } + + const int total = this->evaluated_points_size(); + this->evaluated_positions_cache_.resize(total); + this->evaluated_mappings_cache_.resize(total); + + MutableSpan<float3> positions = this->evaluated_positions_cache_; + MutableSpan<PointMapping> mappings = this->evaluated_mappings_cache_; + /* TODO: It would also be possible to store an array of offsets to facilitate parallelism here, * maybe it is worth it? */ int offset = 0; @@ -354,25 +369,72 @@ void BezierSpline::evaluate_bezier_position_and_mapping(MutableSpan<float3> posi } BLI_assert(offset == positions.size()); + + this->base_cache_dirty_ = false; } -void BezierSpline::ensure_base_cache() const +/** + * Returns non-owning access to the cache of mappings from the evaluated points to + * the corresponing control points. Unless the spline is cyclic, the last control point + * index will never be included as an index. + */ +Span<PointMapping> BezierSpline::evaluated_mappings() const { - if (!this->base_cache_dirty_) { - return; + this->evaluate_bezier_position_and_mapping(); +#ifdef DEBUG + if (evaluated_mappings_cache_.last().control_point_index == this->size() - 1) { + BLI_assert(this->is_cyclic); } +#endif + return this->evaluated_mappings_cache_; +} - std::lock_guard lock{this->base_cache_mutex_}; - if (!this->base_cache_dirty_) { - return; +Span<float3> BezierSpline::evaluated_positions() const +{ + this->evaluate_bezier_position_and_mapping(); + + return this->evaluated_positions_cache_; +} + +template<typename T> +static void interpolate_to_evaluated_points_impl(Span<PointMapping> mappings, + const blender::VArray<T> &source_data, + MutableSpan<T> result_data) +{ + blender::attribute_math::DefaultMixer<T> mixer(result_data); + + for (const int i : result_data.index_range()) { + const PointMapping &mapping = mappings[i]; + const int index = mapping.control_point_index; + const int next_index = (index + 1) % source_data.size(); + const float factor = mapping.factor; + + const T &value = source_data[index]; + const T &next_value = source_data[next_index]; + + mixer.mix_in(i, value, 1.0f - factor); + mixer.mix_in(i, next_value, factor); } - const int total = this->evaluated_points_size(); - this->evaluated_positions_cache_.resize(total); - this->evaluated_mapping_cache_.resize(total); + mixer.finalize(); +} - this->evaluate_bezier_position_and_mapping(this->evaluated_positions_cache_, - this->evaluated_mapping_cache_); +blender::fn::GVArrayPtr BezierSpline::interpolate_to_evaluated_points( + const blender::fn::GVArray &source_data) const +{ + BLI_assert(source_data.size() == this->size()); + Span<PointMapping> mappings = this->evaluated_mappings(); - this->base_cache_dirty_ = false; -}
\ No newline at end of file + blender::fn::GVArrayPtr new_varray; + blender::attribute_math::convert_to_static_type(source_data.type(), [&](auto dummy) { + using T = decltype(dummy); + if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) { + Array<T> values(this->evaluated_points_size()); + interpolate_to_evaluated_points_impl<T>(mappings, source_data.typed<T>(), values); + new_varray = std::make_unique<blender::fn::GVArray_For_ArrayContainer<Array<T>>>( + std::move(values)); + } + }); + + return new_varray; +} |