diff options
Diffstat (limited to 'source/blender/geometry/intern/resample_curves.cc')
-rw-r--r-- | source/blender/geometry/intern/resample_curves.cc | 147 |
1 files changed, 70 insertions, 77 deletions
diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc index 36525e1bdf0..d5560a95a18 100644 --- a/source/blender/geometry/intern/resample_curves.cc +++ b/source/blender/geometry/intern/resample_curves.cc @@ -77,8 +77,8 @@ static bool interpolate_attribute_to_poly_curve(const bke::AttributeIDRef &attri static const Set<StringRef> no_interpolation{{ "handle_type_left", "handle_type_right", - "handle_position_right", - "handle_position_left", + "handle_right", + "handle_left", "nurbs_weight", }}; return !(attribute_id.is_named() && no_interpolation.contains(attribute_id.name())); @@ -88,21 +88,22 @@ static bool interpolate_attribute_to_poly_curve(const bke::AttributeIDRef &attri * Retrieve spans from source and result attributes. */ static void retrieve_attribute_spans(const Span<bke::AttributeIDRef> ids, - const CurveComponent &src_component, - CurveComponent &dst_component, + const CurvesGeometry &src_curves, + CurvesGeometry &dst_curves, Vector<GSpan> &src, Vector<GMutableSpan> &dst, - Vector<bke::OutputAttribute> &dst_attributes) + Vector<bke::GSpanAttributeWriter> &dst_attributes) { for (const int i : ids.index_range()) { - GVArray src_attribute = src_component.attribute_try_get_for_read(ids[i], ATTR_DOMAIN_POINT); + GVArray src_attribute = src_curves.attributes().lookup(ids[i], ATTR_DOMAIN_POINT); BLI_assert(src_attribute); src.append(src_attribute.get_internal_span()); const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(src_attribute.type()); - bke::OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only( - ids[i], ATTR_DOMAIN_POINT, data_type); - dst.append(dst_attribute.as_span()); + bke::GSpanAttributeWriter dst_attribute = + dst_curves.attributes_for_write().lookup_or_add_for_write_only_span( + ids[i], ATTR_DOMAIN_POINT, data_type); + dst.append(dst_attribute.span); dst_attributes.append(std::move(dst_attribute)); } } @@ -111,7 +112,7 @@ struct AttributesForInterpolation : NonCopyable, NonMovable { Vector<GSpan> src; Vector<GMutableSpan> dst; - Vector<bke::OutputAttribute> dst_attributes; + Vector<bke::GSpanAttributeWriter> dst_attributes; Vector<GSpan> src_no_interpolation; Vector<GMutableSpan> dst_no_interpolation; @@ -120,17 +121,14 @@ struct AttributesForInterpolation : NonCopyable, NonMovable { /** * Gather a set of all generic attribute IDs to copy to the result curves. */ -static void gather_point_attributes_to_interpolate(const CurveComponent &src_component, - CurveComponent &dst_component, +static void gather_point_attributes_to_interpolate(const CurvesGeometry &src_curves, + CurvesGeometry &dst_curves, AttributesForInterpolation &result) { - bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap( - dst_component.get_for_write()->geometry); - VectorSet<bke::AttributeIDRef> ids; VectorSet<bke::AttributeIDRef> ids_no_interpolation; - src_component.attribute_foreach( - [&](const bke::AttributeIDRef &id, const AttributeMetaData meta_data) { + src_curves.attributes().for_all( + [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) { if (meta_data.domain != ATTR_DOMAIN_POINT) { return true; } @@ -151,31 +149,25 @@ static void gather_point_attributes_to_interpolate(const CurveComponent &src_com ids.remove_contained("position"); retrieve_attribute_spans( - ids, src_component, dst_component, result.src, result.dst, result.dst_attributes); + ids, src_curves, dst_curves, result.src, result.dst, result.dst_attributes); - /* Attributes that aren't interpolated like Bezier handles still have to be be copied + /* Attributes that aren't interpolated like Bezier handles still have to be copied * to the result when there are any unselected curves of the corresponding type. */ retrieve_attribute_spans(ids_no_interpolation, - src_component, - dst_component, + src_curves, + dst_curves, result.src_no_interpolation, result.dst_no_interpolation, result.dst_attributes); - - dst_curves.update_customdata_pointers(); } -static Curves *resample_to_uniform(const CurveComponent &src_component, - const fn::Field<bool> &selection_field, - const fn::Field<int> &count_field) +static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves, + const fn::Field<bool> &selection_field, + const fn::Field<int> &count_field) { - const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap( - src_component.get_for_read()->geometry); - /* Create the new curves without any points and evaluate the final count directly * into the offsets array, in order to be accumulated into offsets later. */ - Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num()); - bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry); + CurvesGeometry dst_curves = CurvesGeometry(0, src_curves.curves_num()); /* Directly copy curve attributes, since they stay the same (except for curve types). */ CustomData_copy(&src_curves.curve_data, @@ -185,7 +177,7 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, src_curves.curves_num()); MutableSpan<int> dst_offsets = dst_curves.offsets_for_write(); - bke::GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE}; + bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE}; fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; evaluator.set_selection(selection_field); evaluator.add_with_destination(count_field, dst_offsets); @@ -208,9 +200,7 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, MutableSpan<float3> dst_positions = dst_curves.positions_for_write(); AttributesForInterpolation attributes; - CurveComponent dst_component; - dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable); - gather_point_attributes_to_interpolate(src_component, dst_component, attributes); + gather_point_attributes_to_interpolate(src_curves, dst_curves, attributes); src_curves.ensure_evaluated_lengths(); @@ -234,11 +224,18 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, for (const int i_curve : sliced_selection) { const bool cyclic = curves_cyclic[i_curve]; const IndexRange dst_points = dst_curves.points_for_curve(i_curve); - length_parameterize::create_uniform_samples( - src_curves.evaluated_lengths_for_curve(i_curve, cyclic), - curves_cyclic[i_curve], - sample_indices.as_mutable_span().slice(dst_points), - sample_factors.as_mutable_span().slice(dst_points)); + const Span<float> lengths = src_curves.evaluated_lengths_for_curve(i_curve, cyclic); + if (lengths.is_empty()) { + /* Handle curves with only one evaluated point. */ + sample_indices.as_mutable_span().slice(dst_points).fill(0); + sample_factors.as_mutable_span().slice(dst_points).fill(0.0f); + } + else { + length_parameterize::sample_uniform(lengths, + !curves_cyclic[i_curve], + sample_indices.as_mutable_span().slice(dst_points), + sample_factors.as_mutable_span().slice(dst_points)); + } } /* For every attribute, evaluate attributes from every curve in the range in the original @@ -254,10 +251,10 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, const IndexRange dst_points = dst_curves.points_for_curve(i_curve); if (curve_types[i_curve] == CURVE_TYPE_POLY) { - length_parameterize::linear_interpolation(src.slice(src_points), - sample_indices.as_span().slice(dst_points), - sample_factors.as_span().slice(dst_points), - dst.slice(dst_points)); + length_parameterize::interpolate(src.slice(src_points), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst.slice(dst_points)); } else { const int evaluated_size = src_curves.evaluated_points_for_curve(i_curve).size(); @@ -266,10 +263,10 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>(); src_curves.interpolate_to_evaluated(i_curve, src.slice(src_points), evaluated); - length_parameterize::linear_interpolation(evaluated.as_span(), - sample_indices.as_span().slice(dst_points), - sample_factors.as_span().slice(dst_points), - dst.slice(dst_points)); + length_parameterize::interpolate(evaluated.as_span(), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst.slice(dst_points)); } } }); @@ -279,10 +276,10 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, for (const int i_curve : sliced_selection) { const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve); const IndexRange dst_points = dst_curves.points_for_curve(i_curve); - length_parameterize::linear_interpolation(evaluated_positions.slice(src_points), - sample_indices.as_span().slice(dst_points), - sample_factors.as_span().slice(dst_points), - dst_positions.slice(dst_points)); + length_parameterize::interpolate(evaluated_positions.slice(src_points), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst_positions.slice(dst_points)); } /* Fill the default value for non-interpolating attributes that still must be copied. */ @@ -312,35 +309,34 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, bke::curves::copy_point_data( src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); - for (bke::OutputAttribute &attribute : attributes.dst_attributes) { - attribute.save(); + for (bke::GSpanAttributeWriter &attribute : attributes.dst_attributes) { + attribute.finish(); } - return dst_curves_id; + return dst_curves; } -Curves *resample_to_count(const CurveComponent &src_component, - const fn::Field<bool> &selection_field, - const fn::Field<int> &count_field) +CurvesGeometry resample_to_count(const CurvesGeometry &src_curves, + const fn::Field<bool> &selection_field, + const fn::Field<int> &count_field) { - return resample_to_uniform(src_component, selection_field, get_count_input_max_one(count_field)); + return resample_to_uniform(src_curves, selection_field, get_count_input_max_one(count_field)); } -Curves *resample_to_length(const CurveComponent &src_component, - const fn::Field<bool> &selection_field, - const fn::Field<float> &segment_length_field) +CurvesGeometry resample_to_length(const CurvesGeometry &src_curves, + const fn::Field<bool> &selection_field, + const fn::Field<float> &segment_length_field) { return resample_to_uniform( - src_component, selection_field, get_count_input_from_length(segment_length_field)); + src_curves, selection_field, get_count_input_from_length(segment_length_field)); } -Curves *resample_to_evaluated(const CurveComponent &src_component, - const fn::Field<bool> &selection_field) +CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves, + const fn::Field<bool> &selection_field) { - const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap( - src_component.get_for_read()->geometry); + src_curves.ensure_evaluated_offsets(); - bke::GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE}; + bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE}; fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()}; evaluator.set_selection(selection_field); evaluator.evaluate(); @@ -348,8 +344,7 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert( src_curves.curves_range(), nullptr); - Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num()); - bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry); + CurvesGeometry dst_curves(0, src_curves.curves_num()); /* Directly copy curve attributes, since they stay the same (except for curve types). */ CustomData_copy(&src_curves.curve_data, @@ -361,7 +356,7 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, dst_curves.fill_curve_types(selection, CURVE_TYPE_POLY); MutableSpan<int> dst_offsets = dst_curves.offsets_for_write(); - src_curves.ensure_evaluated_offsets(); + src_curves.ensure_can_interpolate_to_evaluated(); threading::parallel_for(selection.index_range(), 4096, [&](IndexRange range) { for (const int i : selection.slice(range)) { dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size(); @@ -377,9 +372,7 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, MutableSpan<float3> dst_positions = dst_curves.positions_for_write(); AttributesForInterpolation attributes; - CurveComponent dst_component; - dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable); - gather_point_attributes_to_interpolate(src_component, dst_component, attributes); + gather_point_attributes_to_interpolate(src_curves, dst_curves, attributes); threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) { const IndexMask sliced_selection = selection.slice(selection_range); @@ -434,11 +427,11 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, bke::curves::copy_point_data( src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); - for (bke::OutputAttribute &attribute : attributes.dst_attributes) { - attribute.save(); + for (bke::GSpanAttributeWriter &attribute : attributes.dst_attributes) { + attribute.finish(); } - return dst_curves_id; + return dst_curves; } } // namespace blender::geometry |