diff options
author | Michael Kowalski <makowalski@nvidia.com> | 2022-09-23 23:56:14 +0300 |
---|---|---|
committer | Michael Kowalski <makowalski@nvidia.com> | 2022-09-23 23:56:14 +0300 |
commit | b2ad97ba97f3e55d1dd463e29ca0b2ec6fe761e1 (patch) | |
tree | f94394835c6b731e4e379f4ef48fb78b4af4b9ca /source/blender/geometry/intern/resample_curves.cc | |
parent | b31807c75f0c18c43ac6979e6da57dc9d420167a (diff) | |
parent | 7e980f2b8cb96aa6d04dc72899d08473367eeeb9 (diff) |
Merge branch 'master' into tmp-usd-alab-v2-T100452tmp-usd-alab-v2-T100452
Diffstat (limited to 'source/blender/geometry/intern/resample_curves.cc')
-rw-r--r-- | source/blender/geometry/intern/resample_curves.cc | 239 |
1 files changed, 147 insertions, 92 deletions
diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc index e252e28805e..a7f6ac16f8d 100644 --- a/source/blender/geometry/intern/resample_curves.cc +++ b/source/blender/geometry/intern/resample_curves.cc @@ -88,20 +88,20 @@ 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::GSpanAttributeWriter> &dst_attributes) { for (const int i : ids.index_range()) { - GVArray src_attribute = src_component.attributes()->lookup(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::GSpanAttributeWriter dst_attribute = - dst_component.attributes_for_write()->lookup_or_add_for_write_only_span( + 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)); @@ -116,21 +116,25 @@ struct AttributesForInterpolation : NonCopyable, NonMovable { Vector<GSpan> src_no_interpolation; Vector<GMutableSpan> dst_no_interpolation; + + Span<float3> src_evaluated_tangents; + Span<float3> src_evaluated_normals; + MutableSpan<float3> dst_tangents; + MutableSpan<float3> dst_normals; }; /** * 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, - AttributesForInterpolation &result) +static void gather_point_attributes_to_interpolate( + const CurvesGeometry &src_curves, + CurvesGeometry &dst_curves, + AttributesForInterpolation &result, + const ResampleCurvesOutputAttributeIDs &output_ids) { - 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.attributes()->for_all( + src_curves.attributes().for_all( [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) { if (meta_data.domain != ATTR_DOMAIN_POINT) { return true; @@ -152,29 +156,89 @@ 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 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); + + bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write(); + if (output_ids.tangent_id) { + result.src_evaluated_tangents = src_curves.evaluated_tangents(); + bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( + output_ids.tangent_id, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + result.dst_tangents = dst_attribute.span.typed<float3>(); + result.dst_attributes.append(std::move(dst_attribute)); + } + if (output_ids.normal_id) { + result.src_evaluated_normals = src_curves.evaluated_normals(); + bke::GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( + output_ids.normal_id, ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + result.dst_normals = dst_attribute.span.typed<float3>(); + result.dst_attributes.append(std::move(dst_attribute)); + } } -static Curves *resample_to_uniform(const CurveComponent &src_component, - const fn::Field<bool> &selection_field, - const fn::Field<int> &count_field) +static void copy_or_defaults_for_unselected_curves(const CurvesGeometry &src_curves, + const Span<IndexRange> unselected_ranges, + const AttributesForInterpolation &attributes, + CurvesGeometry &dst_curves) { - const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap( - src_component.get_for_read()->geometry); + bke::curves::copy_point_data(src_curves, + dst_curves, + unselected_ranges, + src_curves.positions(), + dst_curves.positions_for_write()); + for (const int i : attributes.src.index_range()) { + bke::curves::copy_point_data( + src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]); + } + for (const int i : attributes.src_no_interpolation.index_range()) { + bke::curves::copy_point_data(src_curves, + dst_curves, + unselected_ranges, + attributes.src_no_interpolation[i], + attributes.dst_no_interpolation[i]); + } + + if (!attributes.dst_tangents.is_empty()) { + bke::curves::fill_points(dst_curves, unselected_ranges, float3(0), attributes.dst_tangents); + } + if (!attributes.dst_normals.is_empty()) { + bke::curves::fill_points(dst_curves, unselected_ranges, float3(0), attributes.dst_normals); + } +} + +static void normalize_span(MutableSpan<float3> data) +{ + for (const int i : data.index_range()) { + data[i] = math::normalize(data[i]); + } +} + +static void normalize_curve_point_data(const CurvesGeometry &curves, + const IndexMask curve_selection, + MutableSpan<float3> data) +{ + for (const int i_curve : curve_selection) { + normalize_span(data.slice(curves.points_for_curve(i_curve))); + } +} + +static CurvesGeometry resample_to_uniform(const CurvesGeometry &src_curves, + const fn::Field<bool> &selection_field, + const fn::Field<int> &count_field, + const ResampleCurvesOutputAttributeIDs &output_ids) +{ /* 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, @@ -184,7 +248,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); @@ -207,9 +271,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, output_ids); src_curves.ensure_evaluated_lengths(); @@ -281,14 +343,27 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, }); } + auto interpolate_evaluated_data = [&](const Span<float3> src, MutableSpan<float3> dst) { + 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::interpolate(src.slice(src_points), + sample_indices.as_span().slice(dst_points), + sample_factors.as_span().slice(dst_points), + dst.slice(dst_points)); + } + }; + /* Interpolate the evaluated positions to the resampled curves. */ - 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::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)); + interpolate_evaluated_data(evaluated_positions, dst_positions); + + if (!attributes.dst_tangents.is_empty()) { + interpolate_evaluated_data(attributes.src_evaluated_tangents, attributes.dst_tangents); + normalize_curve_point_data(dst_curves, sliced_selection, attributes.dst_tangents); + } + if (!attributes.dst_normals.is_empty()) { + interpolate_evaluated_data(attributes.src_evaluated_normals, attributes.dst_normals); + normalize_curve_point_data(dst_curves, sliced_selection, attributes.dst_normals); } /* Fill the default value for non-interpolating attributes that still must be copied. */ @@ -300,54 +375,40 @@ static Curves *resample_to_uniform(const CurveComponent &src_component, } }); - /* Any attribute data from unselected curve points can be directly copied. */ - for (const int i : attributes.src.index_range()) { - bke::curves::copy_point_data( - src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]); - } - for (const int i : attributes.src_no_interpolation.index_range()) { - bke::curves::copy_point_data(src_curves, - dst_curves, - unselected_ranges, - attributes.src_no_interpolation[i], - attributes.dst_no_interpolation[i]); - } - - /* Copy positions for unselected curves. */ - Span<float3> src_positions = src_curves.positions(); - bke::curves::copy_point_data( - src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); + copy_or_defaults_for_unselected_curves(src_curves, unselected_ranges, attributes, dst_curves); 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, + const ResampleCurvesOutputAttributeIDs &output_ids) { - 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), output_ids); } -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, + const ResampleCurvesOutputAttributeIDs &output_ids) { 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), output_ids); } -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 ResampleCurvesOutputAttributeIDs &output_ids) { - 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(); @@ -355,8 +416,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, @@ -368,7 +428,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(); @@ -380,13 +440,11 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); /* Create the correct number of uniform-length samples for every selected curve. */ - Span<float3> evaluated_positions = src_curves.evaluated_positions(); + const Span<float3> evaluated_positions = src_curves.evaluated_positions(); 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, output_ids); threading::parallel_for(selection.index_range(), 512, [&](IndexRange selection_range) { const IndexMask sliced_selection = selection.slice(selection_range); @@ -407,11 +465,24 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, }); } + auto copy_evaluated_data = [&](const Span<float3> src, MutableSpan<float3> dst) { + 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); + dst.slice(dst_points).copy_from(src.slice(src_points)); + } + }; + /* Copy the evaluated positions to the selected curves. */ - 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); - dst_positions.slice(dst_points).copy_from(evaluated_positions.slice(src_points)); + copy_evaluated_data(evaluated_positions, dst_positions); + + if (!attributes.dst_tangents.is_empty()) { + copy_evaluated_data(attributes.src_evaluated_tangents, attributes.dst_tangents); + normalize_curve_point_data(dst_curves, sliced_selection, attributes.dst_tangents); + } + if (!attributes.dst_normals.is_empty()) { + copy_evaluated_data(attributes.src_evaluated_normals, attributes.dst_normals); + normalize_curve_point_data(dst_curves, sliced_selection, attributes.dst_normals); } /* Fill the default value for non-interpolating attributes that still must be copied. */ @@ -423,29 +494,13 @@ Curves *resample_to_evaluated(const CurveComponent &src_component, } }); - /* Any attribute data from unselected curve points can be directly copied. */ - for (const int i : attributes.src.index_range()) { - bke::curves::copy_point_data( - src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]); - } - for (const int i : attributes.src_no_interpolation.index_range()) { - bke::curves::copy_point_data(src_curves, - dst_curves, - unselected_ranges, - attributes.src_no_interpolation[i], - attributes.dst_no_interpolation[i]); - } - - /* Copy positions for unselected curves. */ - Span<float3> src_positions = src_curves.positions(); - bke::curves::copy_point_data( - src_curves, dst_curves, unselected_ranges, src_positions, dst_positions); + copy_or_defaults_for_unselected_curves(src_curves, unselected_ranges, attributes, dst_curves); for (bke::GSpanAttributeWriter &attribute : attributes.dst_attributes) { attribute.finish(); } - return dst_curves_id; + return dst_curves; } } // namespace blender::geometry |