[Bf-blender-cvs] [6c6f591f909] master: Curves: Port realize instances node to the new data-block
Hans Goudey
noreply at git.blender.org
Wed Mar 9 16:58:21 CET 2022
Commit: 6c6f591f909a02967daff87ab348601953f61670
Author: Hans Goudey
Date: Wed Mar 9 09:56:14 2022 -0600
Branches: master
https://developer.blender.org/rB6c6f591f909a02967daff87ab348601953f61670
Curves: Port realize instances node to the new data-block
This commit replaces the temporary conversion to `CurveEval` with
use of the new curves data-block. The end result is that the
process looks more like the other components-- somewhere in between
meshes and point clouds in terms of complexity.
The final result is that the logic between meshes and curves is
very similar. There are a few different strategies to reduce
duplication here, so I'll investigate that separately.
There is some special behavior for the radius and handle position
attributes. I used the attribute API to store spans of these
attributes temporarily. Using access methods on `CurvesGeometry`
would be reasonable to, storing spans separately feels a bit more
predictable for now though.
There should be significant performance improvements in some cases,
I haven't tested that specifically though.
Differential Revision: https://developer.blender.org/D14247
===================================================================
M source/blender/geometry/intern/realize_instances.cc
===================================================================
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index 4f7024eea82..c2337c37d1f 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -121,15 +121,37 @@ struct RealizeMeshTask {
struct RealizeCurveInfo {
const Curves *curves;
/**
- * Matches the order in #AllCurvesInfo.attributes. For point attributes, the `std::optional`
- * will be empty.
+ * Matches the order in #AllCurvesInfo.attributes.
*/
- Array<std::optional<GVArray_GSpan>> spline_attributes;
+ Array<std::optional<GVArray_GSpan>> attributes;
+
+ /** ID attribute on the curves. If there are no ids, this #Span is empty. */
+ Span<int> stored_ids;
+
+ /**
+ * Handle position attributes must be transformed along with positions. Accessing them in
+ * advance isn't necessary theoretically, but is done to simplify other code and to avoid
+ * some overhead.
+ */
+ Span<float3> handle_left;
+ Span<float3> handle_right;
+
+ /**
+ * The radius attribute must be filled with a default of 1.0 if it
+ * doesn't exist on some (but not all) of the input curves data-blocks.
+ */
+ Span<float> radius;
+};
+
+/** Start indices in the final output curves data-block. */
+struct CurvesElementStartIndices {
+ int point = 0;
+ int curve = 0;
};
struct RealizeCurveTask {
- /* Start index in the final curve. */
- int start_spline_index = 0;
+ CurvesElementStartIndices start_indices;
+
const RealizeCurveInfo *curve_info;
/* Transformation applied to the position of control points and handles. */
float4x4 transform;
@@ -168,6 +190,8 @@ struct AllCurvesInfo {
/** Preprocessed data about every original curve. This is ordered by #order. */
Array<RealizeCurveInfo> realize_info;
bool create_id_attribute = false;
+ bool create_handle_postion_attributes = false;
+ bool create_radius_attribute = false;
};
/** Collects all tasks that need to be executed to realize all instances. */
@@ -185,7 +209,7 @@ struct GatherTasks {
struct GatherOffsets {
int pointcloud_offset = 0;
MeshElementStartIndices mesh_offsets;
- int spline_offset = 0;
+ CurvesElementStartIndices curves_offsets;
};
struct GatherTasksInfo {
@@ -230,6 +254,17 @@ struct InstanceContext {
}
};
+static void copy_transformed_positions(const Span<float3> src,
+ const float4x4 &transform,
+ MutableSpan<float3> dst)
+{
+ threading::parallel_for(src.index_range(), 1024, [&](const IndexRange range) {
+ for (const int i : range) {
+ dst[i] = transform * src[i];
+ }
+ });
+}
+
/* -------------------------------------------------------------------- */
/** \name Gather Realize Tasks
* \{ */
@@ -448,12 +483,13 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
if (curves != nullptr && curves->geometry.curve_size > 0) {
const int curve_index = gather_info.curves.order.index_of(curves);
const RealizeCurveInfo &curve_info = gather_info.curves.realize_info[curve_index];
- gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.spline_offset,
+ gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.curves_offsets,
&curve_info,
base_transform,
base_instance_context.curves,
base_instance_context.id});
- gather_info.r_offsets.spline_offset += curves->geometry.curve_size;
+ gather_info.r_offsets.curves_offsets.point += curves->geometry.point_size;
+ gather_info.r_offsets.curves_offsets.curve += curves->geometry.curve_size;
}
break;
}
@@ -571,12 +607,8 @@ static void execute_realize_pointcloud_task(const RealizeInstancesOptions &optio
pointcloud.totpoint};
MutableSpan<int> dst_ids = all_dst_ids.slice(task.start_index, pointcloud.totpoint);
- /* Copy transformed positions. */
- threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) {
- for (const int i : range) {
- dst_positions[i] = task.transform * src_positions[i];
- }
- });
+ copy_transformed_positions(src_positions, task.transform, dst_positions);
+
/* Create point ids. */
if (!all_dst_ids.is_empty()) {
if (options.keep_original_ids) {
@@ -1007,7 +1039,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Curve
+/** \name Curves
* \{ */
static OrderedAttributes gather_generic_curve_attributes_to_propagate(
@@ -1023,9 +1055,6 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
in_geometry_set.gather_attributes_for_propagation(
src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate);
attributes_to_propagate.remove("position");
- attributes_to_propagate.remove("cyclic");
- attributes_to_propagate.remove("resolution");
- attributes_to_propagate.remove("tilt");
attributes_to_propagate.remove("radius");
attributes_to_propagate.remove("handle_right");
attributes_to_propagate.remove("handle_left");
@@ -1071,19 +1100,43 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
/* Access attributes. */
CurveComponent component;
component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly);
- curve_info.spline_attributes.reinitialize(info.attributes.size());
+ curve_info.attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) {
const AttributeDomain domain = info.attributes.kinds[attribute_index].domain;
- if (domain != ATTR_DOMAIN_CURVE) {
- continue;
- }
const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index];
const CustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
if (component.attribute_exists(attribute_id)) {
GVArray attribute = component.attribute_get_for_read(attribute_id, domain, data_type);
- curve_info.spline_attributes[attribute_index].emplace(std::move(attribute));
+ curve_info.attributes[attribute_index].emplace(std::move(attribute));
+ }
+ }
+ if (info.create_id_attribute) {
+ ReadAttributeLookup ids_lookup = component.attribute_try_get_for_read("id");
+ if (ids_lookup) {
+ curve_info.stored_ids = ids_lookup.varray.get_internal_span().typed<int>();
}
}
+
+ /* Retrieve the radius attribute, if it exists. */
+ if (component.attribute_exists("radius")) {
+ curve_info.radius = component
+ .attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 0.0f)
+ .get_internal_span();
+ info.create_radius_attribute = true;
+ }
+
+ /* Retrieve handle position attributes, if they exist. */
+ if (component.attribute_exists("handle_right")) {
+ curve_info.handle_left = component
+ .attribute_get_for_read<float3>(
+ "handle_left", ATTR_DOMAIN_POINT, float3(0))
+ .get_internal_span();
+ curve_info.handle_right = component
+ .attribute_get_for_read<float3>(
+ "handle_right", ATTR_DOMAIN_POINT, float3(0))
+ .get_internal_span();
+ info.create_handle_postion_attributes = true;
+ }
}
return info;
}
@@ -1092,108 +1145,129 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
const AllCurvesInfo &all_curves_info,
const RealizeCurveTask &task,
const OrderedAttributes &ordered_attributes,
- MutableSpan<SplinePtr> dst_splines,
- MutableSpan<GMutableSpan> dst_spline_attributes)
+ bke::CurvesGeometry &dst_curves,
+ MutableSpan<GMutableSpan> dst_attribute_spans,
+ MutableSpan<int> all_dst_ids,
+ MutableSpan<float3> all_handle_left,
+ MutableSpan<float3> all_handle_right,
+ MutableSpan<float> all_radii)
{
- const RealizeCurveInfo &curve_info = *task.curve_info;
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_info.curves);
-
- const Span<SplinePtr> src_splines = curve->splines();
-
- /* Initialize point attributes. */
- threading::parallel_for(src_splines.index_range(), 100, [&](const IndexRange src_spline_range) {
- for (const int src_spline_index : src_spline_range) {
- const int dst_spline_index = src_spline_index + task.start_spline_index;
- const Spline &src_spline = *src_splines[src_spline_index];
- SplinePtr dst_spline = src_spline.copy_without_attributes();
- dst_spline->transform(task.transform);
- const int spline_size = dst_spline->size();
-
- const CustomDataAttributes &src_point_attributes = src_spline.attributes;
- CustomDataAttributes &dst_point_attributes = dst_spline->attributes;
-
- /* Create point ids. */
- if (all_curves_info.create_id_attribute) {
- dst_point_attributes.create("id", CD_PROP_INT32);
- MutableSpan<int> dst_point_ids = dst_point_attributes.get_for_write("id")->typed<int>();
- std::optional<GSpan> src_point_ids_opt = src_point_attributes.get_for_read("id");
- if (options.keep_original_ids) {
- if (src_point_ids_opt.has_value()) {
- const Span<int> src_point_ids = src_point_ids_opt->typed<int>();
- dst_point_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list