diff options
4 files changed, 44 insertions, 22 deletions
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index 95261f29914..02bf7aacd93 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -352,33 +352,37 @@ float transform_brush_radius(const float4x4 &transform, return math::distance(new_position, new_offset_position); } -void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position) +void move_last_point_and_resample(MoveAndResampleBuffers &buffer, + MutableSpan<float3> positions, + const float3 &new_last_position) { /* Find the accumulated length of each point in the original curve, * treating it as a poly curve for performance reasons and simplicity. */ - Array<float> orig_lengths(length_parameterize::segments_num(positions.size(), false)); - length_parameterize::accumulate_lengths<float3>(positions, false, orig_lengths); - const float orig_total_length = orig_lengths.last(); + buffer.orig_lengths.reinitialize(length_parameterize::segments_num(positions.size(), false)); + length_parameterize::accumulate_lengths<float3>(positions, false, buffer.orig_lengths); + const float orig_total_length = buffer.orig_lengths.last(); /* Find the factor by which the new curve is shorter or longer than the original. */ const float new_last_segment_length = math::distance(positions.last(1), new_last_position); - const float new_total_length = orig_lengths.last(1) + new_last_segment_length; + const float new_total_length = buffer.orig_lengths.last(1) + new_last_segment_length; const float length_factor = safe_divide(new_total_length, orig_total_length); /* Calculate the lengths to sample the original curve with by scaling the original lengths. */ - Array<float> new_lengths(positions.size() - 1); - new_lengths.first() = 0.0f; - for (const int i : new_lengths.index_range().drop_front(1)) { - new_lengths[i] = orig_lengths[i - 1] * length_factor; + buffer.new_lengths.reinitialize(positions.size() - 1); + buffer.new_lengths.first() = 0.0f; + for (const int i : buffer.new_lengths.index_range().drop_front(1)) { + buffer.new_lengths[i] = buffer.orig_lengths[i - 1] * length_factor; } - Array<int> indices(positions.size() - 1); - Array<float> factors(positions.size() - 1); - length_parameterize::sample_at_lengths(orig_lengths, new_lengths, indices, factors); + buffer.sample_indices.reinitialize(positions.size() - 1); + buffer.sample_factors.reinitialize(positions.size() - 1); + length_parameterize::sample_at_lengths( + buffer.orig_lengths, buffer.new_lengths, buffer.sample_indices, buffer.sample_factors); - Array<float3> new_positions(positions.size() - 1); - length_parameterize::interpolate<float3>(positions, indices, factors, new_positions); - positions.drop_back(1).copy_from(new_positions); + buffer.new_positions.reinitialize(positions.size() - 1); + length_parameterize::interpolate<float3>( + positions, buffer.sample_indices, buffer.sample_factors, buffer.new_positions); + positions.drop_back(1).copy_from(buffer.new_positions); positions.last() = new_last_position; } diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc index 0ca22004540..bc354ed66f4 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc @@ -141,11 +141,11 @@ class ExtrapolateCurvesEffect : public CurvesEffect { { MutableSpan<float3> positions_cu = curves.positions_for_write(); threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) { + MoveAndResampleBuffers resample_buffer; for (const int influence_i : range) { const int curve_i = curve_indices[influence_i]; const float move_distance_cu = move_distances_cu[influence_i]; const IndexRange points = curves.points_for_curve(curve_i); - if (points.size() <= 1) { continue; } @@ -157,7 +157,7 @@ class ExtrapolateCurvesEffect : public CurvesEffect { const float3 direction = math::normalize(old_last_pos_cu - direction_reference_point); const float3 new_last_pos_cu = old_last_pos_cu + direction * move_distance_cu; - move_last_point_and_resample(positions_cu.slice(points), new_last_pos_cu); + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), new_last_pos_cu); } }); } diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh index 5c8c0cedc6f..61e2559f303 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh @@ -102,7 +102,23 @@ VArray<float> get_curves_selection(const Curves &curves_id); */ VArray<float> get_point_selection(const Curves &curves_id); -void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position); +/** See #move_last_point_and_resample. */ +struct MoveAndResampleBuffers { + Array<float> orig_lengths; + Array<float> new_lengths; + + Array<int> sample_indices; + Array<float> sample_factors; + + Array<float3> new_positions; +}; + +/** + * \param buffer: Reused memory to avoid reallocations when the function is called many times. + */ +void move_last_point_and_resample(MoveAndResampleBuffers &buffer, + MutableSpan<float3> positions, + const float3 &new_last_position); class CurvesSculptCommonContext { public: diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc index 54b81fa221d..67757ce5f4a 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_snake_hook.cc @@ -188,6 +188,7 @@ struct SnakeHookOperatorExecutor { const float brush_radius_sq_re = pow2f(brush_radius_re); threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + MoveAndResampleBuffers resample_buffer; for (const int curve_i : curves_range) { const IndexRange points = curves_->points_for_curve(curve_i); const int last_point_i = points.last(); @@ -221,8 +222,8 @@ struct SnakeHookOperatorExecutor { const float3 translation_orig = deformation.translation_from_deformed_to_original( last_point_i, translation_eval); - move_last_point_and_resample(positions_cu.slice(points), - positions_cu[last_point_i] + translation_orig); + const float3 last_point_cu = positions_cu[last_point_i] + translation_orig; + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu); } }); } @@ -268,6 +269,7 @@ struct SnakeHookOperatorExecutor { const float brush_radius_sq_cu = pow2f(brush_radius_cu); threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange curves_range) { + MoveAndResampleBuffers resample_buffer; for (const int curve_i : curves_range) { const IndexRange points = curves_->points_for_curve(curve_i); const int last_point_i = points.last(); @@ -289,8 +291,8 @@ struct SnakeHookOperatorExecutor { const float3 translation_orig = deformation.translation_from_deformed_to_original( last_point_i, translation_eval); - move_last_point_and_resample(positions_cu.slice(points), - positions_cu[last_point_i] + translation_orig); + const float3 last_point_cu = positions_cu[last_point_i] + translation_orig; + move_last_point_and_resample(resample_buffer, positions_cu.slice(points), last_point_cu); } }); } |