Commit: 399aed9a81d17960a0a0cbec7f145bf0bcb1868b Author: Hans Goudey Date: Mon Apr 26 14:17:25 2021 -0500 Branches: geometry-nodes-curve-support https://developer.blender.org/rB399aed9a81d17960a0a0cbec7f145bf0bcb1868b
Splines: Fix interpolation for bezier splines Also parallelize some of the calculations, since I was reworking how the mapping was calculated anyway. I still haven't tuned the grain size. =================================================================== M source/blender/blenkernel/BKE_spline.hh M source/blender/blenkernel/intern/spline_bezier.cc M source/blender/blenkernel/intern/spline_nurbs.cc =================================================================== diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 4e4b6eed156..c06273db828 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -90,18 +90,6 @@ class Spline { Spline(Spline &other) : type_(other.type_), is_cyclic(other.is_cyclic), normal_mode(other.normal_mode) { - if (!other.tangent_cache_dirty_) { - evaluated_tangents_cache_ = other.evaluated_tangents_cache_; - tangent_cache_dirty_ = false; - } - if (!other.normal_cache_dirty_) { - evaluated_normals_cache_ = other.evaluated_normals_cache_; - normal_cache_dirty_ = false; - } - if (!other.length_cache_dirty_) { - evaluated_lengths_cache_ = other.evaluated_lengths_cache_; - length_cache_dirty_ = false; - } } virtual SplinePtr copy() const = 0; @@ -188,12 +176,19 @@ class BezierSpline final : public Spline { blender::Vector<blender::float3> handle_positions_end_; blender::Vector<float> radii_; blender::Vector<float> tilts_; - int resolution_u_; + int resolution_; - mutable bool base_cache_dirty_ = true; - mutable std::mutex base_cache_mutex_; - mutable blender::Vector<blender::float3> evaluated_positions_cache_; - mutable blender::Vector<float> evaluated_mappings_cache_; + mutable bool offset_cache_dirty_ = true; + mutable std::mutex offset_cache_mutex_; + mutable blender::Vector<int> offset_cache_; + + mutable bool position_cache_dirty_ = true; + mutable std::mutex position_cache_mutex_; + mutable blender::Vector<blender::float3> evaluated_position_cache_; + + mutable bool mapping_cache_dirty_ = true; + mutable std::mutex mapping_cache_mutex_; + mutable blender::Vector<float> evaluated_mapping_cache_; public: virtual SplinePtr copy() const final; @@ -207,13 +202,8 @@ class BezierSpline final : public Spline { handle_positions_end_(other.handle_positions_end_), radii_(other.radii_), tilts_(other.tilts_), - resolution_u_(other.resolution_u_) + resolution_(other.resolution_) { - if (!other.base_cache_dirty_) { - evaluated_positions_cache_ = other.evaluated_positions_cache_; - evaluated_mappings_cache_ = other.evaluated_mappings_cache_; - base_cache_dirty_ = false; - } } int size() const final; @@ -256,6 +246,7 @@ class BezierSpline final : public Spline { void mark_cache_invalid() final; int evaluated_points_size() const final; + blender::Span<int> control_point_offsets() const; blender::Span<float> evaluated_mappings() const; blender::Span<blender::float3> evaluated_positions() const final; struct InterpolationData { @@ -268,18 +259,13 @@ class BezierSpline final : public Spline { virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points( const blender::fn::GVArray &source_data) const; - protected: - void correct_final_tangents() const; - private: void correct_end_tangents() const final; bool segment_is_vector(const int start_index) const; void evaluate_bezier_segment(const int index, const int next_index, - int &offset, - blender::MutableSpan<blender::float3> positions, - blender::MutableSpan<float> mappings) const; - void evaluate_bezier_position_and_mapping() const; + blender::MutableSpan<blender::float3> positions) const; + blender::Array<int> evaluated_point_offsets() const; }; /** @@ -307,7 +293,7 @@ class NURBSpline final : public Spline { blender::Vector<float> radii_; blender::Vector<float> tilts_; blender::Vector<float> weights_; - int resolution_u_; + int resolution_; uint8_t order_; mutable bool knots_dirty_ = true; @@ -316,7 +302,7 @@ class NURBSpline final : public Spline { mutable bool position_cache_dirty_ = true; mutable std::mutex position_cache_mutex_; - mutable blender::Vector<blender::float3> evaluated_positions_cache_; + mutable blender::Vector<blender::float3> evaluated_position_cache_; mutable bool basis_cache_dirty_ = true; mutable std::mutex basis_cache_mutex_; @@ -331,7 +317,7 @@ class NURBSpline final : public Spline { radii_(other.radii_), tilts_(other.tilts_), weights_(other.weights_), - resolution_u_(other.resolution_u_), + resolution_(other.resolution_), order_(other.order_) { } diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index dea91b2c0fd..4a3f5cdbf19 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -16,6 +16,7 @@ #include "BLI_array.hh" #include "BLI_span.hh" +#include "BLI_task.hh" #include "BKE_spline.hh" @@ -46,12 +47,12 @@ int BezierSpline::size() const int BezierSpline::resolution() const { - return this->resolution_u_; + return this->resolution_; } void BezierSpline::set_resolution(const int value) { - this->resolution_u_ = value; + this->resolution_ = value; this->mark_cache_invalid(); } @@ -197,7 +198,9 @@ bool BezierSpline::segment_is_vector(const int index) const void BezierSpline::mark_cache_invalid() { - this->base_cache_dirty_ = true; + this->offset_cache_dirty_ = true; + this->position_cache_dirty_ = true; + this->mapping_cache_dirty_ = true; this->tangent_cache_dirty_ = true; this->normal_cache_dirty_ = true; this->length_cache_dirty_ = true; @@ -205,45 +208,15 @@ void BezierSpline::mark_cache_invalid() int BezierSpline::evaluated_points_size() const { - BLI_assert(this->size() > 0); -#ifndef DEBUG - if (!this->base_cache_dirty_) { - /* In a non-debug build, assume that the cache size has not changed, and that any operation - * that would cause the cache to change its length would also mark the cache dirty. This - * assumption is checked at the end of this function in a debug build. */ - return this->evaluated_positions_cache_.size(); - } -#endif - - int total_len = 0; - for (const int i : IndexRange(this->size() - 1)) { - if (this->segment_is_vector(i)) { - total_len += 1; - } - else { - total_len += this->resolution_u_; - } - } + const int points_len = this->size(); + BLI_assert(points_len > 0); + const int last_offset = this->control_point_offsets().last(); if (this->is_cyclic) { - if (segment_is_vector(this->size() - 1)) { - total_len++; - } - else { - total_len += this->resolution_u_; - } - } - else { - /* Since evaulating the bezier doesn't add the final point's position, - * it must be added manually in the non-cyclic case. */ - total_len++; + return last_offset + (this->segment_is_vector(points_len - 1) ? 0 : this->resolution_); } - if (!this->base_cache_dirty_) { - BLI_assert(this->evaluated_positions_cache_.size() == total_len); - } - - return total_len; + return last_offset + 1; } /** @@ -291,95 +264,52 @@ static void bezier_forward_difference_3d(const float3 &point_0, } } -static void evaluate_segment_mapping(Span<float3> evaluated_positions, - MutableSpan<float> mappings, - const int index) -{ - float length = 0.0f; - mappings[0] = index; - for (const int i : IndexRange(1, mappings.size() - 1)) { - length += float3::distance(evaluated_positions[i - 1], evaluated_positions[i]); - mappings[i] = length; - } - - /* To get the factors instead of the accumulated lengths, divide the mapping factors by the - * accumulated length. */ - if (length != 0.0f) { - for (float &mapping : mappings) { - mapping = mapping / length + index; - } - } -} - void BezierSpline::evaluate_bezier_segment(const int index, const int next_index, - int &offset, - MutableSpan<float3> positions, - MutableSpan<float> mappings) const + MutableSpan<float3> positions) const { if (this->segment_is_vector(index)) { - positions[offset] = positions_[index]; - mappings[offset] = index; - offset++; + positions.first() = this->positions_[index]; } else { bezier_forward_difference_3d(this->positions_[index], this->handle_positions_end_[index], this->handle_positions_start_[next_index], this->positions_[next_index], - positions.slice(offset, this->resolution_u_)); - evaluate_segment_mapping(positions.slice(offset, this->resolution_u_), - mappings.slice(offset, this->resolution_u_), - index); - offset += this->resolution_u_; + positions); } } -void BezierSpline::evaluate_bezier_position_and_mapping() const +/** + * Returns access to a cache of offsets into the evaluated point array for each control point. + * This is important because while most control point edges generate the number of edges specified + * by the resolution, vector segments only generate one edge. + */ +Span<int> BezierSpline::control_point_offsets() const { - if (!this->base_cache_dirty_) { - return; + if (!this->offset_cache_dirty_) { + return this->offset_cache_; } - std::lock_guard lock{this->base_cache_mutex_}; - if (!this->base_cache_dirty_) { - return; + std::lock_guard lock{this->offset_cache_mutex_}; + if (!this->offset_cache_dirty_) { + return this->offset_cache_; } - const int total = this->evaluated_points_size(); - this->evaluated_positions_cache_.resize(total); - this->evaluated_mappings_cache_.resize(total); + const int points_len = this->size(); + this->offset_cache_.resize(points_len); - MutableSpan<float3> positions = this->evaluated_positions_cache_; - MutableSpan<float> mappings = this->evaluated_mappings_cache_; + MutableSpan<int> offsets @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs