Changeset View
Changeset View
Standalone View
Standalone View
source/blender/geometry/intern/resample_curves.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #include "BLI_length_parameterize.hh" | #include "BLI_length_parameterize.hh" | ||||
| #include "BLI_task.hh" | #include "BLI_task.hh" | ||||
| #include "FN_field.hh" | #include "FN_field.hh" | ||||
| #include "FN_multi_function_builder.hh" | #include "FN_multi_function_builder.hh" | ||||
| #include "BKE_attribute_math.hh" | #include "BKE_attribute_math.hh" | ||||
| #include "BKE_curves.hh" | #include "BKE_curves.hh" | ||||
| #include "BKE_curves_utils.hh" | |||||
| #include "BKE_geometry_fields.hh" | #include "BKE_geometry_fields.hh" | ||||
| #include "GEO_resample_curves.hh" | #include "GEO_resample_curves.hh" | ||||
| namespace blender::geometry { | namespace blender::geometry { | ||||
| static fn::Field<int> get_count_input_max_one(const fn::Field<int> &count_field) | static fn::Field<int> get_count_input_max_one(const fn::Field<int> &count_field) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | static void copy_between_curves(const bke::CurvesGeometry &src_curves, | ||||
| const GMutableSpan dst) | const GMutableSpan dst) | ||||
| { | { | ||||
| attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { | attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { | ||||
| using T = decltype(dummy); | using T = decltype(dummy); | ||||
| copy_between_curves(src_curves, dst_curves, unselected_ranges, src.typed<T>(), dst.typed<T>()); | copy_between_curves(src_curves, dst_curves, unselected_ranges, src.typed<T>(), dst.typed<T>()); | ||||
| }); | }); | ||||
| } | } | ||||
| /** | |||||
| * Copy the size of every curve in #curve_ranges to the corresponding index in #counts. | |||||
| */ | |||||
| static void fill_curve_counts(const bke::CurvesGeometry &src_curves, | |||||
| const Span<IndexRange> curve_ranges, | |||||
| MutableSpan<int> counts) | |||||
| { | |||||
| threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange ranges_range) { | |||||
| for (const IndexRange curves_range : curve_ranges.slice(ranges_range)) { | |||||
| for (const int i : curves_range) { | |||||
| counts[i] = src_curves.points_for_curve(i).size(); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| /** | |||||
| * Turn an array of sizes into the offset at each index including all previous sizes. | |||||
| */ | |||||
| static void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets) | |||||
| { | |||||
| int total = 0; | |||||
| for (const int i : counts_to_offsets.index_range().drop_back(1)) { | |||||
| const int count = counts_to_offsets[i]; | |||||
| BLI_assert(count > 0); | |||||
| counts_to_offsets[i] = total; | |||||
| total += count; | |||||
| } | |||||
| counts_to_offsets.last() = total; | |||||
| } | |||||
| static Curves *resample_to_uniform(const CurveComponent &src_component, | static Curves *resample_to_uniform(const CurveComponent &src_component, | ||||
| const fn::Field<bool> &selection_field, | const fn::Field<bool> &selection_field, | ||||
| const fn::Field<int> &count_field) | const fn::Field<int> &count_field) | ||||
| { | { | ||||
| const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap( | const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap( | ||||
| src_component.get_for_read()->geometry); | src_component.get_for_read()->geometry); | ||||
| /* Create the new curves without any points and evaluate the final count directly | /* Create the new curves without any points and evaluate the final count directly | ||||
| Show All 14 Lines | static Curves *resample_to_uniform(const CurveComponent &src_component, | ||||
| evaluator.set_selection(selection_field); | evaluator.set_selection(selection_field); | ||||
| evaluator.add_with_destination(count_field, dst_offsets); | evaluator.add_with_destination(count_field, dst_offsets); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); | ||||
| const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert( | const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert( | ||||
| src_curves.curves_range(), nullptr); | src_curves.curves_range(), nullptr); | ||||
| /* Fill the counts for the curves that aren't selected and accumulate the counts into offsets. */ | /* Fill the counts for the curves that aren't selected and accumulate the counts into offsets. */ | ||||
| fill_curve_counts(src_curves, unselected_ranges, dst_offsets); | bke::curves::fill_curve_counts(src_curves, unselected_ranges, dst_offsets); | ||||
| accumulate_counts_to_offsets(dst_offsets); | bke::curves::accumulate_counts_to_offsets(dst_offsets); | ||||
| dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); | dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); | ||||
| /* All resampled curves are poly curves. */ | /* All resampled curves are poly curves. */ | ||||
| dst_curves.fill_curve_types(selection, CURVE_TYPE_POLY); | dst_curves.fill_curve_types(selection, CURVE_TYPE_POLY); | ||||
| VArray<bool> curves_cyclic = src_curves.cyclic(); | VArray<bool> curves_cyclic = src_curves.cyclic(); | ||||
| VArray<int8_t> curve_types = src_curves.curve_types(); | VArray<int8_t> curve_types = src_curves.curve_types(); | ||||
| Span<float3> evaluated_positions = src_curves.evaluated_positions(); | Span<float3> evaluated_positions = src_curves.evaluated_positions(); | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | Curves *resample_to_evaluated(const CurveComponent &src_component, | ||||
| MutableSpan<int> dst_offsets = dst_curves.offsets_for_write(); | MutableSpan<int> dst_offsets = dst_curves.offsets_for_write(); | ||||
| src_curves.ensure_evaluated_offsets(); | src_curves.ensure_evaluated_offsets(); | ||||
| threading::parallel_for(selection.index_range(), 4096, [&](IndexRange range) { | threading::parallel_for(selection.index_range(), 4096, [&](IndexRange range) { | ||||
| for (const int i : selection.slice(range)) { | for (const int i : selection.slice(range)) { | ||||
| dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size(); | dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size(); | ||||
| } | } | ||||
| }); | }); | ||||
| fill_curve_counts(src_curves, unselected_ranges, dst_offsets); | bke::curves::fill_curve_counts(src_curves, unselected_ranges, dst_offsets); | ||||
| accumulate_counts_to_offsets(dst_offsets); | bke::curves::accumulate_counts_to_offsets(dst_offsets); | ||||
| dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); | dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); | ||||
| /* Create the correct number of uniform-length samples for every selected curve. */ | /* Create the correct number of uniform-length samples for every selected curve. */ | ||||
| Span<float3> evaluated_positions = src_curves.evaluated_positions(); | Span<float3> evaluated_positions = src_curves.evaluated_positions(); | ||||
| MutableSpan<float3> dst_positions = dst_curves.positions_for_write(); | MutableSpan<float3> dst_positions = dst_curves.positions_for_write(); | ||||
| AttributesForInterpolation attributes; | AttributesForInterpolation attributes; | ||||
| ▲ Show 20 Lines • Show All 64 Lines • Show Last 20 Lines | |||||