Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Kowalski <makowalski@nvidia.com>2022-09-23 23:56:14 +0300
committerMichael Kowalski <makowalski@nvidia.com>2022-09-23 23:56:14 +0300
commitb2ad97ba97f3e55d1dd463e29ca0b2ec6fe761e1 (patch)
treef94394835c6b731e4e379f4ef48fb78b4af4b9ca /source/blender/geometry/intern/resample_curves.cc
parentb31807c75f0c18c43ac6979e6da57dc9d420167a (diff)
parent7e980f2b8cb96aa6d04dc72899d08473367eeeb9 (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.cc239
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