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:
Diffstat (limited to 'source/blender/geometry/intern/realize_instances.cc')
-rw-r--r--source/blender/geometry/intern/realize_instances.cc359
1 files changed, 196 insertions, 163 deletions
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index ae07e817c67..0544f304283 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -23,12 +23,13 @@
namespace blender::geometry {
using blender::bke::AttributeIDRef;
+using blender::bke::AttributeKind;
+using blender::bke::AttributeMetaData;
using blender::bke::custom_data_type_to_cpp_type;
using blender::bke::CustomDataAttributes;
+using blender::bke::GSpanAttributeWriter;
using blender::bke::object_get_evaluated_geometry_set;
-using blender::bke::OutputAttribute;
-using blender::bke::OutputAttribute_Typed;
-using blender::bke::ReadAttributeLookup;
+using blender::bke::SpanAttributeWriter;
/**
* An ordered set of attribute ids. Attributes are ordered to avoid name lookups in many places.
@@ -66,8 +67,9 @@ struct AttributeFallbacksArray {
struct PointCloudRealizeInfo {
const PointCloud *pointcloud = nullptr;
/** Matches the order stored in #AllPointCloudsInfo.attributes. */
- Array<std::optional<GVArray_GSpan>> attributes;
+ Array<std::optional<GVArraySpan>> attributes;
/** Id attribute on the point cloud. If there are no ids, this #Span is empty. */
+ Span<float3> positions;
Span<int> stored_ids;
};
@@ -96,7 +98,7 @@ struct MeshRealizeInfo {
/** Maps old material indices to new material indices. */
Array<int> material_index_map;
/** Matches the order in #AllMeshesInfo.attributes. */
- Array<std::optional<GVArray_GSpan>> attributes;
+ Array<std::optional<GVArraySpan>> attributes;
/** Vertex ids stored on the mesh. If there are no ids, this #Span is empty. */
Span<int> stored_vertex_ids;
};
@@ -116,7 +118,7 @@ struct RealizeCurveInfo {
/**
* Matches the order in #AllCurvesInfo.attributes.
*/
- Array<std::optional<GVArray_GSpan>> attributes;
+ Array<std::optional<GVArraySpan>> attributes;
/** ID attribute on the curves. If there are no ids, this #Span is empty. */
Span<int> stored_ids;
@@ -134,6 +136,12 @@ struct RealizeCurveInfo {
* doesn't exist on some (but not all) of the input curves data-blocks.
*/
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. */
@@ -185,6 +193,7 @@ struct AllCurvesInfo {
bool create_id_attribute = false;
bool create_handle_postion_attributes = false;
bool create_radius_attribute = false;
+ bool create_resolution_attribute = false;
};
/** Collects all tasks that need to be executed to realize all instances. */
@@ -276,30 +285,31 @@ static void threaded_fill(const GPointer value, GMutableSpan dst)
}
static void copy_generic_attributes_to_result(
- const Span<std::optional<GVArray_GSpan>> src_attributes,
+ const Span<std::optional<GVArraySpan>> src_attributes,
const AttributeFallbacksArray &attribute_fallbacks,
const OrderedAttributes &ordered_attributes,
- const FunctionRef<IndexRange(AttributeDomain)> &range_fn,
- MutableSpan<GMutableSpan> dst_attributes)
+ const FunctionRef<IndexRange(eAttrDomain)> &range_fn,
+ MutableSpan<GSpanAttributeWriter> dst_attribute_writers)
{
- threading::parallel_for(dst_attributes.index_range(), 10, [&](const IndexRange attribute_range) {
- for (const int attribute_index : attribute_range) {
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- const IndexRange element_slice = range_fn(domain);
-
- GMutableSpan dst_span = dst_attributes[attribute_index].slice(element_slice);
- if (src_attributes[attribute_index].has_value()) {
- threaded_copy(*src_attributes[attribute_index], dst_span);
- }
- else {
- const CPPType &cpp_type = dst_span.type();
- const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ?
- cpp_type.default_value() :
- attribute_fallbacks.array[attribute_index];
- threaded_fill({cpp_type, fallback}, dst_span);
- }
- }
- });
+ threading::parallel_for(
+ dst_attribute_writers.index_range(), 10, [&](const IndexRange attribute_range) {
+ for (const int attribute_index : attribute_range) {
+ const eAttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
+ const IndexRange element_slice = range_fn(domain);
+
+ GMutableSpan dst_span = dst_attribute_writers[attribute_index].span.slice(element_slice);
+ if (src_attributes[attribute_index].has_value()) {
+ threaded_copy(*src_attributes[attribute_index], dst_span);
+ }
+ else {
+ const CPPType &cpp_type = dst_span.type();
+ const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ?
+ cpp_type.default_value() :
+ attribute_fallbacks.array[attribute_index];
+ threaded_fill({cpp_type, fallback}, dst_span);
+ }
+ }
+ });
}
static void create_result_ids(const RealizeInstancesOptions &options,
@@ -354,7 +364,7 @@ static Vector<std::pair<int, GSpan>> prepare_attribute_fallbacks(
const OrderedAttributes &ordered_attributes)
{
Vector<std::pair<int, GSpan>> attributes_to_override;
- const CustomDataAttributes &attributes = instances_component.attributes();
+ const CustomDataAttributes &attributes = instances_component.instance_attributes();
attributes.foreach_attribute(
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
const int attribute_index = ordered_attributes.ids.index_of_try(attribute_id);
@@ -363,7 +373,7 @@ static Vector<std::pair<int, GSpan>> prepare_attribute_fallbacks(
return true;
}
GSpan span = *attributes.get_for_read(attribute_id);
- const CustomDataType expected_type = ordered_attributes.kinds[attribute_index].data_type;
+ const eCustomDataType expected_type = ordered_attributes.kinds[attribute_index].data_type;
if (meta_data.data_type != expected_type) {
const CPPType &from_type = span.type();
const CPPType &to_type = *custom_data_type_to_cpp_type(expected_type);
@@ -440,7 +450,7 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info,
Span<int> stored_instance_ids;
if (gather_info.create_id_attribute_on_any_component) {
- std::optional<GSpan> ids = instances_component.attributes().get_for_read("id");
+ std::optional<GSpan> ids = instances_component.instance_attributes().get_for_read("id");
if (ids.has_value()) {
stored_instance_ids = ids->typed<int>();
}
@@ -639,43 +649,44 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set
pointcloud_info.pointcloud = pointcloud;
/* Access attributes. */
- PointCloudComponent component;
- component.replace(const_cast<PointCloud *>(pointcloud), GeometryOwnershipType::ReadOnly);
+ bke::AttributeAccessor attributes = bke::pointcloud_attributes(*pointcloud);
pointcloud_info.attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) {
const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index];
- const CustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
- const AttributeDomain domain = info.attributes.kinds[attribute_index].domain;
- if (component.attribute_exists(attribute_id)) {
- GVArray attribute = component.attribute_get_for_read(attribute_id, domain, data_type);
+ const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
+ const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
+ if (attributes.contains(attribute_id)) {
+ GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
pointcloud_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) {
- pointcloud_info.stored_ids = ids_lookup.varray.get_internal_span().typed<int>();
+ bke::GAttributeReader ids_attribute = attributes.lookup("id");
+ if (ids_attribute) {
+ pointcloud_info.stored_ids = ids_attribute.varray.get_internal_span().typed<int>();
}
}
+ const VArray<float3> position_attribute = attributes.lookup_or_default<float3>(
+ "position", ATTR_DOMAIN_POINT, float3(0));
+ pointcloud_info.positions = position_attribute.get_internal_span();
}
return info;
}
-static void execute_realize_pointcloud_task(const RealizeInstancesOptions &options,
- const RealizePointCloudTask &task,
- const OrderedAttributes &ordered_attributes,
- PointCloud &dst_pointcloud,
- MutableSpan<GMutableSpan> dst_attribute_spans,
- MutableSpan<int> all_dst_ids)
+static void execute_realize_pointcloud_task(
+ const RealizeInstancesOptions &options,
+ const RealizePointCloudTask &task,
+ const OrderedAttributes &ordered_attributes,
+ MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
+ MutableSpan<int> all_dst_ids,
+ MutableSpan<float3> all_dst_positions)
{
const PointCloudRealizeInfo &pointcloud_info = *task.pointcloud_info;
const PointCloud &pointcloud = *pointcloud_info.pointcloud;
- const Span<float3> src_positions{(float3 *)pointcloud.co, pointcloud.totpoint};
const IndexRange point_slice{task.start_index, pointcloud.totpoint};
- MutableSpan<float3> dst_positions{(float3 *)dst_pointcloud.co + task.start_index,
- pointcloud.totpoint};
- copy_transformed_positions(src_positions, task.transform, dst_positions);
+ copy_transformed_positions(
+ pointcloud_info.positions, task.transform, all_dst_positions.slice(point_slice));
/* Create point ids. */
if (!all_dst_ids.is_empty()) {
@@ -687,12 +698,12 @@ static void execute_realize_pointcloud_task(const RealizeInstancesOptions &optio
pointcloud_info.attributes,
task.attribute_fallbacks,
ordered_attributes,
- [&](const AttributeDomain domain) {
+ [&](const eAttrDomain domain) {
BLI_assert(domain == ATTR_DOMAIN_POINT);
UNUSED_VARS_NDEBUG(domain);
return point_slice;
},
- dst_attribute_spans);
+ dst_attribute_writers);
}
static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &options,
@@ -714,42 +725,47 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti
PointCloudComponent &dst_component =
r_realized_geometry.get_component_for_write<PointCloudComponent>();
dst_component.replace(dst_pointcloud);
+ bke::MutableAttributeAccessor dst_attributes = bke::pointcloud_attributes_for_write(
+ *dst_pointcloud);
+
+ SpanAttributeWriter<float3> positions = dst_attributes.lookup_or_add_for_write_only_span<float3>(
+ "position", ATTR_DOMAIN_POINT);
/* Prepare id attribute. */
- OutputAttribute_Typed<int> point_ids;
- MutableSpan<int> point_ids_span;
+ SpanAttributeWriter<int> point_ids;
if (all_pointclouds_info.create_id_attribute) {
- point_ids = dst_component.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_POINT);
- point_ids_span = point_ids.as_span();
+ point_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id", ATTR_DOMAIN_POINT);
}
/* Prepare generic output attributes. */
- Vector<OutputAttribute> dst_attributes;
- Vector<GMutableSpan> dst_attribute_spans;
+ Vector<GSpanAttributeWriter> dst_attribute_writers;
for (const int attribute_index : ordered_attributes.index_range()) {
const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index];
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- attribute_id, ATTR_DOMAIN_POINT, data_type);
- dst_attribute_spans.append(dst_attribute.as_span());
- dst_attributes.append(std::move(dst_attribute));
+ const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
+ dst_attribute_writers.append(dst_attributes.lookup_or_add_for_write_only_span(
+ attribute_id, ATTR_DOMAIN_POINT, data_type));
}
/* Actually execute all tasks. */
threading::parallel_for(tasks.index_range(), 100, [&](const IndexRange task_range) {
for (const int task_index : task_range) {
const RealizePointCloudTask &task = tasks[task_index];
- execute_realize_pointcloud_task(
- options, task, ordered_attributes, *dst_pointcloud, dst_attribute_spans, point_ids_span);
+ execute_realize_pointcloud_task(options,
+ task,
+ ordered_attributes,
+ dst_attribute_writers,
+ point_ids.span,
+ positions.span);
}
});
- /* Save modified attributes. */
- for (OutputAttribute &dst_attribute : dst_attributes) {
- dst_attribute.save();
+ /* Tag modified attributes. */
+ for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
+ dst_attribute.finish();
}
+ positions.finish();
if (point_ids) {
- point_ids.save();
+ point_ids.finish();
}
}
@@ -830,22 +846,21 @@ static AllMeshesInfo preprocess_meshes(const GeometrySet &geometry_set,
}
/* Access attributes. */
- MeshComponent component;
- component.replace(const_cast<Mesh *>(mesh), GeometryOwnershipType::ReadOnly);
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*mesh);
mesh_info.attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) {
const AttributeIDRef &attribute_id = info.attributes.ids[attribute_index];
- const CustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
- const AttributeDomain domain = info.attributes.kinds[attribute_index].domain;
- if (component.attribute_exists(attribute_id)) {
- GVArray attribute = component.attribute_get_for_read(attribute_id, domain, data_type);
+ const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
+ const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
+ if (attributes.contains(attribute_id)) {
+ GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
mesh_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) {
- mesh_info.stored_vertex_ids = ids_lookup.varray.get_internal_span().typed<int>();
+ bke::GAttributeReader ids_attribute = attributes.lookup("id");
+ if (ids_attribute) {
+ mesh_info.stored_vertex_ids = ids_attribute.varray.get_internal_span().typed<int>();
}
}
}
@@ -856,7 +871,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
const RealizeMeshTask &task,
const OrderedAttributes &ordered_attributes,
Mesh &dst_mesh,
- MutableSpan<GMutableSpan> dst_attribute_spans,
+ MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
MutableSpan<int> all_dst_vertex_ids)
{
const MeshRealizeInfo &mesh_info = *task.mesh_info;
@@ -927,7 +942,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
mesh_info.attributes,
task.attribute_fallbacks,
ordered_attributes,
- [&](const AttributeDomain domain) {
+ [&](const eAttrDomain domain) {
switch (domain) {
case ATTR_DOMAIN_POINT:
return IndexRange(task.start_indices.vertex, mesh.totvert);
@@ -942,7 +957,7 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
return IndexRange();
}
},
- dst_attribute_spans);
+ dst_attribute_writers);
}
static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
@@ -966,6 +981,7 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
Mesh *dst_mesh = BKE_mesh_new_nomain(tot_vertices, tot_edges, 0, tot_loops, tot_poly);
MeshComponent &dst_component = r_realized_geometry.get_component_for_write<MeshComponent>();
dst_component.replace(dst_mesh);
+ bke::MutableAttributeAccessor dst_attributes = bke::mesh_attributes_for_write(*dst_mesh);
/* Copy settings from the first input geometry set with a mesh. */
const RealizeMeshTask &first_task = tasks.first();
@@ -979,24 +995,19 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
}
/* Prepare id attribute. */
- OutputAttribute_Typed<int> vertex_ids;
- MutableSpan<int> vertex_ids_span;
+ SpanAttributeWriter<int> vertex_ids;
if (all_meshes_info.create_id_attribute) {
- vertex_ids = dst_component.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_POINT);
- vertex_ids_span = vertex_ids.as_span();
+ vertex_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id", ATTR_DOMAIN_POINT);
}
/* Prepare generic output attributes. */
- Vector<OutputAttribute> dst_attributes;
- Vector<GMutableSpan> dst_attribute_spans;
+ Vector<GSpanAttributeWriter> dst_attribute_writers;
for (const int attribute_index : ordered_attributes.index_range()) {
const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index];
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- attribute_id, domain, data_type);
- dst_attribute_spans.append(dst_attribute.as_span());
- dst_attributes.append(std::move(dst_attribute));
+ const eAttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
+ const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
+ dst_attribute_writers.append(
+ dst_attributes.lookup_or_add_for_write_only_span(attribute_id, domain, data_type));
}
/* Actually execute all tasks. */
@@ -1004,16 +1015,16 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
for (const int task_index : task_range) {
const RealizeMeshTask &task = tasks[task_index];
execute_realize_mesh_task(
- options, task, ordered_attributes, *dst_mesh, dst_attribute_spans, vertex_ids_span);
+ options, task, ordered_attributes, *dst_mesh, dst_attribute_writers, vertex_ids.span);
}
});
- /* Save modified attributes. */
- for (OutputAttribute &dst_attribute : dst_attributes) {
- dst_attribute.save();
+ /* Tag modified attributes. */
+ for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
+ dst_attribute.finish();
}
if (vertex_ids) {
- vertex_ids.save();
+ vertex_ids.finish();
}
}
@@ -1037,6 +1048,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
src_component_types, GEO_COMPONENT_TYPE_CURVE, true, attributes_to_propagate);
attributes_to_propagate.remove("position");
attributes_to_propagate.remove("radius");
+ attributes_to_propagate.remove("resolution");
attributes_to_propagate.remove("handle_right");
attributes_to_propagate.remove("handle_left");
r_create_id = attributes_to_propagate.pop_try("id").has_value();
@@ -1075,47 +1087,48 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
info.realize_info.reinitialize(info.order.size());
for (const int curve_index : info.realize_info.index_range()) {
RealizeCurveInfo &curve_info = info.realize_info[curve_index];
- const Curves *curves = info.order[curve_index];
- curve_info.curves = curves;
+ const Curves *curves_id = info.order[curve_index];
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
+ curve_info.curves = curves_id;
/* Access attributes. */
- CurveComponent component;
- component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly);
+ bke::AttributeAccessor attributes = curves.attributes();
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;
+ const eAttrDomain domain = info.attributes.kinds[attribute_index].domain;
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);
+ const eCustomDataType data_type = info.attributes.kinds[attribute_index].data_type;
+ if (attributes.contains(attribute_id)) {
+ GVArray attribute = attributes.lookup_or_default(attribute_id, domain, data_type);
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>();
+ bke::GAttributeReader id_attribute = attributes.lookup("id");
+ if (id_attribute) {
+ curve_info.stored_ids = id_attribute.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();
+ if (attributes.contains("radius")) {
+ curve_info.radius =
+ attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).get_internal_span();
info.create_radius_attribute = true;
}
+ /* Retrieve the resolution attribute, if it exists. */
+ curve_info.resolution = curves.resolution();
+ if (attributes.contains("resolution")) {
+ info.create_resolution_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();
+ if (attributes.contains("handle_right")) {
+ curve_info.handle_left =
+ attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).get_internal_span();
+ curve_info.handle_right =
+ attributes.lookup<float3>("handle_right", ATTR_DOMAIN_POINT).get_internal_span();
info.create_handle_postion_attributes = true;
}
}
@@ -1127,11 +1140,12 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
const RealizeCurveTask &task,
const OrderedAttributes &ordered_attributes,
bke::CurvesGeometry &dst_curves,
- MutableSpan<GMutableSpan> dst_attribute_spans,
+ MutableSpan<GSpanAttributeWriter> dst_attribute_writers,
MutableSpan<int> all_dst_ids,
MutableSpan<float3> all_handle_left,
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 Curves &curves_id = *curves_info.curves;
@@ -1171,6 +1185,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. */
const Span<int> src_offsets = curves.offsets();
const MutableSpan<int> dst_offsets = dst_curves.offsets_for_write().slice(dst_curve_range);
@@ -1189,7 +1207,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
curves_info.attributes,
task.attribute_fallbacks,
ordered_attributes,
- [&](const AttributeDomain domain) {
+ [&](const eAttrDomain domain) {
switch (domain) {
case ATTR_DOMAIN_POINT:
return IndexRange(task.start_indices.point, curves.points_num());
@@ -1200,7 +1218,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
return IndexRange();
}
},
- dst_attribute_spans);
+ dst_attribute_writers);
}
static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
@@ -1224,48 +1242,50 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
dst_curves.offsets_for_write().last() = points_num;
CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>();
dst_component.replace(dst_curves_id);
+ bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
+
+ /* Copy settings from the first input geometry set with curves. */
+ const RealizeCurveTask &first_task = tasks.first();
+ const Curves &first_curves_id = *first_task.curve_info->curves;
+ bke::curves_copy_parameters(first_curves_id, *dst_curves_id);
/* Prepare id attribute. */
- OutputAttribute_Typed<int> point_ids;
- MutableSpan<int> point_ids_span;
+ SpanAttributeWriter<int> point_ids;
if (all_curves_info.create_id_attribute) {
- point_ids = dst_component.attribute_try_get_for_output_only<int>("id", ATTR_DOMAIN_POINT);
- point_ids_span = point_ids.as_span();
+ point_ids = dst_attributes.lookup_or_add_for_write_only_span<int>("id", ATTR_DOMAIN_POINT);
}
/* Prepare generic output attributes. */
- Vector<OutputAttribute> dst_attributes;
- Vector<GMutableSpan> dst_attribute_spans;
+ Vector<GSpanAttributeWriter> dst_attribute_writers;
for (const int attribute_index : ordered_attributes.index_range()) {
const AttributeIDRef &attribute_id = ordered_attributes.ids[attribute_index];
- const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain;
- const CustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
- OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
- attribute_id, domain, data_type);
- dst_attribute_spans.append(dst_attribute.as_span());
- dst_attributes.append(std::move(dst_attribute));
+ const eAttrDomain domain = ordered_attributes.kinds[attribute_index].domain;
+ const eCustomDataType data_type = ordered_attributes.kinds[attribute_index].data_type;
+ dst_attribute_writers.append(
+ dst_attributes.lookup_or_add_for_write_only_span(attribute_id, domain, data_type));
}
/* Prepare handle position attributes if necessary. */
- OutputAttribute_Typed<float3> handle_left;
- OutputAttribute_Typed<float3> handle_right;
- MutableSpan<float3> handle_left_span;
- MutableSpan<float3> handle_right_span;
+ SpanAttributeWriter<float3> handle_left;
+ SpanAttributeWriter<float3> handle_right;
if (all_curves_info.create_handle_postion_attributes) {
- handle_left = dst_component.attribute_try_get_for_output_only<float3>("handle_left",
- ATTR_DOMAIN_POINT);
- handle_right = dst_component.attribute_try_get_for_output_only<float3>("handle_right",
+ handle_left = dst_attributes.lookup_or_add_for_write_only_span<float3>("handle_left",
ATTR_DOMAIN_POINT);
- handle_left_span = handle_left.as_span();
- handle_right_span = handle_right.as_span();
+ handle_right = dst_attributes.lookup_or_add_for_write_only_span<float3>("handle_right",
+ ATTR_DOMAIN_POINT);
}
/* Prepare radius attribute if necessary. */
- OutputAttribute_Typed<float> radius;
- MutableSpan<float> radius_span;
+ SpanAttributeWriter<float> radius;
if (all_curves_info.create_radius_attribute) {
- radius = dst_component.attribute_try_get_for_output_only<float>("radius", ATTR_DOMAIN_POINT);
- radius_span = radius.as_span();
+ radius = dst_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
+ }
+
+ /* Prepare resolution attribute if necessary. */
+ SpanAttributeWriter<int> resolution;
+ if (all_curves_info.create_resolution_attribute) {
+ resolution = dst_attributes.lookup_or_add_for_write_only_span<int>("resolution",
+ ATTR_DOMAIN_CURVE);
}
/* Actually execute all tasks. */
@@ -1277,27 +1297,40 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
task,
ordered_attributes,
dst_curves,
- dst_attribute_spans,
- point_ids_span,
- handle_left_span,
- handle_right_span,
- radius_span);
+ dst_attribute_writers,
+ point_ids.span,
+ handle_left.span,
+ handle_right.span,
+ radius.span,
+ resolution.span);
}
});
- /* Save modified attributes. */
- for (OutputAttribute &dst_attribute : dst_attributes) {
- dst_attribute.save();
+ /* Type counts have to be updated eagerly. */
+ dst_curves.runtime->type_counts.fill(0);
+ for (const RealizeCurveTask &task : tasks) {
+ for (const int i : IndexRange(CURVE_TYPES_NUM)) {
+ dst_curves.runtime->type_counts[i] +=
+ task.curve_info->curves->geometry.runtime->type_counts[i];
+ }
+ }
+
+ /* Tag modified attributes. */
+ for (GSpanAttributeWriter &dst_attribute : dst_attribute_writers) {
+ dst_attribute.finish();
}
if (point_ids) {
- point_ids.save();
+ point_ids.finish();
}
if (radius) {
- radius.save();
+ radius.finish();
+ }
+ if (resolution) {
+ resolution.finish();
}
if (all_curves_info.create_handle_postion_attributes) {
- handle_left.save();
- handle_right.save();
+ handle_left.finish();
+ handle_right.finish();
}
}
@@ -1312,7 +1345,7 @@ static void remove_id_attribute_from_instances(GeometrySet &geometry_set)
geometry_set.modify_geometry_sets([&](GeometrySet &sub_geometry) {
if (sub_geometry.has<InstancesComponent>()) {
InstancesComponent &component = sub_geometry.get_component_for_write<InstancesComponent>();
- component.attributes().remove("id");
+ component.instance_attributes().remove("id");
}
});
}