diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 9f8ab69be98..6afbd374fbd 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -617,65 +617,80 @@ Span CurvesGeometry::evaluated_positions() const [&](Vector &r_data) { r_data.clear_and_shrink(); }); return this->positions(); } - this->ensure_nurbs_basis_cache(); runtime.evaluated_position_cache.ensure([&](Vector &r_data) { r_data.resize(this->evaluated_points_num()); MutableSpan evaluated_positions = r_data; const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve(); - const VArray types = this->curve_types(); - const VArray cyclic = this->cyclic(); - const VArray resolution = this->resolution(); const Span positions = this->positions(); - const Span handle_positions_left = this->handle_positions_left(); - const Span handle_positions_right = this->handle_positions_right(); - const Span all_bezier_offsets = runtime.evaluated_offsets_cache.data().all_bezier_offsets; - - const VArray nurbs_orders = this->nurbs_orders(); - const Span nurbs_weights = this->nurbs_weights(); - const Span nurbs_basis_cache = runtime.nurbs_basis_cache.data(); - - threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) { - for (const int curve_index : curves_range) { - const IndexRange points = points_by_curve[curve_index]; - const IndexRange evaluated_points = evaluated_points_by_curve[curve_index]; - - switch (types[curve_index]) { - case CURVE_TYPE_CATMULL_ROM: - curves::catmull_rom::interpolate_to_evaluated( - positions.slice(points), - cyclic[curve_index], - resolution[curve_index], - evaluated_positions.slice(evaluated_points)); - break; - case CURVE_TYPE_POLY: - evaluated_positions.slice(evaluated_points).copy_from(positions.slice(points)); - break; - case CURVE_TYPE_BEZIER: { - const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index); - curves::bezier::calculate_evaluated_positions( - positions.slice(points), - handle_positions_left.slice(points), - handle_positions_right.slice(points), - all_bezier_offsets.slice(offsets), - evaluated_positions.slice(evaluated_points)); - break; - } - case CURVE_TYPE_NURBS: - curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index], - nurbs_orders[curve_index], - nurbs_weights.slice_safe(points), - positions.slice(points), - evaluated_positions.slice(evaluated_points)); - break; - default: - BLI_assert_unreachable(); - break; + auto evaluate_catmull = [&](const IndexMask selection) { + const VArray cyclic = this->cyclic(); + const VArray resolution = this->resolution(); + threading::parallel_for(selection.index_range(), 128, [&](const IndexRange range) { + for (const int curve_index : selection.slice(range)) { + const IndexRange points = points_by_curve[curve_index]; + const IndexRange evaluated_points = evaluated_points_by_curve[curve_index]; + curves::catmull_rom::interpolate_to_evaluated( + positions.slice(points), + cyclic[curve_index], + resolution[curve_index], + evaluated_positions.slice(evaluated_points)); } + }); + }; + auto evaluate_poly = [&](const IndexMask selection) { + curves::copy_point_data( + points_by_curve, evaluated_points_by_curve, selection, positions, evaluated_positions); + }; + auto evaluate_bezier = [&](const IndexMask selection) { + const Span handle_positions_left = this->handle_positions_left(); + const Span handle_positions_right = this->handle_positions_right(); + if (handle_positions_left.is_empty() || handle_positions_right.is_empty()) { + curves::fill_points(evaluated_points_by_curve, selection, float3(0), evaluated_positions); + return; } - }); + const Span all_bezier_offsets = + runtime.evaluated_offsets_cache.data().all_bezier_offsets; + threading::parallel_for(selection.index_range(), 128, [&](const IndexRange range) { + for (const int curve_index : selection.slice(range)) { + const IndexRange points = points_by_curve[curve_index]; + const IndexRange evaluated_points = evaluated_points_by_curve[curve_index]; + const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index); + curves::bezier::calculate_evaluated_positions( + positions.slice(points), + handle_positions_left.slice(points), + handle_positions_right.slice(points), + all_bezier_offsets.slice(offsets), + evaluated_positions.slice(evaluated_points)); + } + }); + }; + auto evaluate_nurbs = [&](const IndexMask selection) { + this->ensure_nurbs_basis_cache(); + const VArray nurbs_orders = this->nurbs_orders(); + const Span nurbs_weights = this->nurbs_weights(); + const Span nurbs_basis_cache = runtime.nurbs_basis_cache.data(); + threading::parallel_for(selection.index_range(), 128, [&](const IndexRange range) { + for (const int curve_index : selection.slice(range)) { + const IndexRange points = points_by_curve[curve_index]; + const IndexRange evaluated_points = evaluated_points_by_curve[curve_index]; + curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index], + nurbs_orders[curve_index], + nurbs_weights.slice_safe(points), + positions.slice(points), + evaluated_positions.slice(evaluated_points)); + } + }); + }; + curves::foreach_curve_by_type(this->curve_types(), + this->curve_type_counts(), + this->curves_range(), + evaluate_catmull, + evaluate_poly, + evaluate_bezier, + evaluate_nurbs); }); return runtime.evaluated_position_cache.data(); }