Fix: curves have incorrect resolution attribute after realizing instances

If the resolution attribute existed on some curves, but not on others, it
was initialized to zero by default. However, zero is not a valid resolution.
This commit is contained in:
2022-06-18 13:01:41 +02:00
parent 3c2a2a6c96
commit 30f244d96f

View File

@@ -134,6 +134,12 @@ struct RealizeCurveInfo {
* doesn't exist on some (but not all) of the input curves data-blocks. * doesn't exist on some (but not all) of the input curves data-blocks.
*/ */
Span<float> radius; Span<float> radius;
/**
* The resolution attribute must be filled with the default value if it does not exist on some
* curves.
*/
VArray<int> resolution;
}; };
/** Start indices in the final output curves data-block. */ /** Start indices in the final output curves data-block. */
@@ -185,6 +191,7 @@ struct AllCurvesInfo {
bool create_id_attribute = false; bool create_id_attribute = false;
bool create_handle_postion_attributes = false; bool create_handle_postion_attributes = false;
bool create_radius_attribute = false; bool create_radius_attribute = false;
bool create_resolution_attribute = false;
}; };
/** Collects all tasks that need to be executed to realize all instances. */ /** Collects all tasks that need to be executed to realize all instances. */
@@ -1037,6 +1044,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate); src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate);
attributes_to_propagate.remove("position"); attributes_to_propagate.remove("position");
attributes_to_propagate.remove("radius"); attributes_to_propagate.remove("radius");
attributes_to_propagate.remove("resolution");
attributes_to_propagate.remove("handle_right"); attributes_to_propagate.remove("handle_right");
attributes_to_propagate.remove("handle_left"); attributes_to_propagate.remove("handle_left");
r_create_id = attributes_to_propagate.pop_try("id").has_value(); r_create_id = attributes_to_propagate.pop_try("id").has_value();
@@ -1075,12 +1083,13 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
info.realize_info.reinitialize(info.order.size()); info.realize_info.reinitialize(info.order.size());
for (const int curve_index : info.realize_info.index_range()) { for (const int curve_index : info.realize_info.index_range()) {
RealizeCurveInfo &curve_info = info.realize_info[curve_index]; RealizeCurveInfo &curve_info = info.realize_info[curve_index];
const Curves *curves = info.order[curve_index]; const Curves *curves_id = info.order[curve_index];
curve_info.curves = curves; const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
curve_info.curves = curves_id;
/* Access attributes. */ /* Access attributes. */
CurveComponent component; CurveComponent component;
component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly); component.replace(const_cast<Curves *>(curves_id), GeometryOwnershipType::ReadOnly);
curve_info.attributes.reinitialize(info.attributes.size()); curve_info.attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) { for (const int attribute_index : info.attributes.index_range()) {
const eAttrDomain domain = info.attributes.kinds[attribute_index].domain; const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
@@ -1106,6 +1115,12 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
info.create_radius_attribute = true; info.create_radius_attribute = true;
} }
/* Retrieve the resolution attribute, if it exists. */
curve_info.resolution = curves.resolution();
if (component.attribute_exists("resolution")) {
info.create_resolution_attribute = true;
}
/* Retrieve handle position attributes, if they exist. */ /* Retrieve handle position attributes, if they exist. */
if (component.attribute_exists("handle_right")) { if (component.attribute_exists("handle_right")) {
curve_info.handle_left = component curve_info.handle_left = component
@@ -1131,7 +1146,8 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
MutableSpan<int> all_dst_ids, MutableSpan<int> all_dst_ids,
MutableSpan<float3> all_handle_left, MutableSpan<float3> all_handle_left,
MutableSpan<float3> all_handle_right, MutableSpan<float3> all_handle_right,
MutableSpan<float> all_radii) MutableSpan<float> all_radii,
MutableSpan<int> all_resolutions)
{ {
const RealizeCurveInfo &curves_info = *task.curve_info; const RealizeCurveInfo &curves_info = *task.curve_info;
const Curves &curves_id = *curves_info.curves; const Curves &curves_id = *curves_info.curves;
@@ -1171,6 +1187,10 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
} }
} }
if (all_curves_info.create_resolution_attribute) {
curves_info.resolution.materialize(all_resolutions.slice(dst_curve_range));
}
/* Copy curve offsets. */ /* Copy curve offsets. */
const Span<int> src_offsets = curves.offsets(); const Span<int> src_offsets = curves.offsets();
const MutableSpan<int> dst_offsets = dst_curves.offsets_for_write().slice(dst_curve_range); const MutableSpan<int> dst_offsets = dst_curves.offsets_for_write().slice(dst_curve_range);
@@ -1268,6 +1288,15 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
radius_span = radius.as_span(); radius_span = radius.as_span();
} }
/* Prepare resolution attribute if necessary. */
OutputAttribute_Typed<int> resolution;
MutableSpan<int> resolution_span;
if (all_curves_info.create_resolution_attribute) {
resolution = dst_component.attribute_try_get_for_output_only<int>("resolution",
ATTR_DOMAIN_CURVE);
resolution_span = resolution.as_span();
}
/* Actually execute all tasks. */ /* Actually execute all tasks. */
threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) { threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
for (const int task_index : task_range) { for (const int task_index : task_range) {
@@ -1281,7 +1310,8 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
point_ids_span, point_ids_span,
handle_left_span, handle_left_span,
handle_right_span, handle_right_span,
radius_span); radius_span,
resolution_span);
} }
}); });
@@ -1295,6 +1325,9 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
if (radius) { if (radius) {
radius.save(); radius.save();
} }
if (resolution) {
resolution.save();
}
if (all_curves_info.create_handle_postion_attributes) { if (all_curves_info.create_handle_postion_attributes) {
handle_left.save(); handle_left.save();
handle_right.save(); handle_right.save();