diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 6e0dec8f4f6..2cdb6f2d5e8 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -18,6 +18,7 @@ set(SRC intern/add_curves_on_mesh.cc intern/curve_constraints.cc intern/fillet_curves.cc + intern/join_geometry.cc intern/mesh_merge_by_distance.cc intern/mesh_primitive_cuboid.cc intern/mesh_split_edges.cc @@ -35,6 +36,7 @@ set(SRC GEO_add_curves_on_mesh.hh GEO_curve_constraints.hh GEO_fillet_curves.hh + GEO_join_geometry.hh GEO_mesh_merge_by_distance.hh GEO_mesh_primitive_cuboid.hh GEO_mesh_split_edges.hh diff --git a/source/blender/geometry/GEO_join_geometry.hh b/source/blender/geometry/GEO_join_geometry.hh new file mode 100644 index 00000000000..55dce07668b --- /dev/null +++ b/source/blender/geometry/GEO_join_geometry.hh @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_math_matrix_types.hh" + +#include "BKE_geometry_set.hh" + +namespace blender::geometry { + +/** + * Join all src_components and add the resulting component to result. + */ +template +void join_component_type(Span src_components, + GeometrySet &result, + const bke::AnonymousAttributePropagationInfo &propagation_info); + +/** + * Join InstancesComponents and apply corresponding transforms for each. + */ +void join_transform_instance_components(Span src_components, + Span src_base_transforms, + GeometrySet &result); + +} // namespace blender::geometry diff --git a/source/blender/geometry/GEO_realize_instances.hh b/source/blender/geometry/GEO_realize_instances.hh index b13d764c685..b6250d24f0b 100644 --- a/source/blender/geometry/GEO_realize_instances.hh +++ b/source/blender/geometry/GEO_realize_instances.hh @@ -20,6 +20,16 @@ struct RealizeInstancesOptions { */ bool realize_instance_attributes = true; + /** + * Selection of top-level instances to realize. + */ + IndexMask selection; + + /** + * Depth of realize instances for each selected top-level instance. + */ + VArray depths; + bke::AnonymousAttributePropagationInfo propagation_info; }; diff --git a/source/blender/geometry/intern/join_geometry.cc b/source/blender/geometry/intern/join_geometry.cc new file mode 100644 index 00000000000..bf22c6ea8c7 --- /dev/null +++ b/source/blender/geometry/intern/join_geometry.cc @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "GEO_join_geometry.hh" +#include "GEO_realize_instances.hh" + +#include "BKE_attribute.hh" +#include "BKE_instances.hh" + +namespace blender::geometry { + +using bke::AttributeIDRef; +using bke::AttributeMetaData; +using bke::GSpanAttributeWriter; + +template +static Array to_base_components(Span components) +{ + return components; +} + +static Map get_final_attribute_info( + Span components, Span ignored_attributes) +{ + Map info; + + for (const GeometryComponent *component : components) { + component->attributes()->for_all( + [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { + if (ignored_attributes.contains(attribute_id.name())) { + return true; + } + if (meta_data.data_type == CD_PROP_STRING) { + return true; + } + info.add_or_modify( + attribute_id, + [&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; }, + [&](AttributeMetaData *meta_data_final) { + meta_data_final->data_type = blender::bke::attribute_data_type_highest_complexity( + {meta_data_final->data_type, meta_data.data_type}); + meta_data_final->domain = blender::bke::attribute_domain_highest_priority( + {meta_data_final->domain, meta_data.domain}); + }); + return true; + }); + } + + return info; +} + +static void fill_new_attribute(Span src_components, + const AttributeIDRef &attribute_id, + const eCustomDataType data_type, + const eAttrDomain domain, + GMutableSpan dst_span) +{ + const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type); + BLI_assert(cpp_type != nullptr); + + int offset = 0; + for (const GeometryComponent *component : src_components) { + const int domain_num = component->attribute_domain_size(domain); + if (domain_num == 0) { + continue; + } + GVArray read_attribute = component->attributes()->lookup_or_default( + attribute_id, domain, data_type, nullptr); + + GVArraySpan src_span{read_attribute}; + const void *src_buffer = src_span.data(); + void *dst_buffer = dst_span[offset]; + cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_num); + + offset += domain_num; + } +} + +static void join_attributes(Span src_components, + GeometryComponent &result, + Span ignored_attributes = {}) +{ + const Map info = get_final_attribute_info(src_components, + ignored_attributes); + + for (const Map::Item item : info.items()) { + const AttributeIDRef attribute_id = item.key; + const AttributeMetaData &meta_data = item.value; + + GSpanAttributeWriter write_attribute = + result.attributes_for_write()->lookup_or_add_for_write_only_span( + attribute_id, meta_data.domain, meta_data.data_type); + if (!write_attribute) { + continue; + } + fill_new_attribute( + src_components, attribute_id, meta_data.data_type, meta_data.domain, write_attribute.span); + write_attribute.finish(); + } +} + +static void join_components(Span src_components, + const VArray &src_base_transforms, + GeometrySet &result) +{ + std::unique_ptr dst_instances = std::make_unique(); + + int tot_instances = 0; + for (const InstancesComponent *src_component : src_components) { + tot_instances += src_component->get_for_read()->instances_num(); + } + dst_instances->reserve(tot_instances); + + for (const int i : src_components.index_range()) { + const InstancesComponent *src_component = src_components[i]; + const blender::float4x4 &base_transform = src_base_transforms[i]; + const bke::Instances &src_instances = *src_component->get_for_read(); + + Span src_references = src_instances.references(); + Array handle_map(src_references.size()); + for (const int src_handle : src_references.index_range()) { + handle_map[src_handle] = dst_instances->add_reference(src_references[src_handle]); + } + + Span src_transforms = src_instances.transforms(); + Span src_reference_handles = src_instances.reference_handles(); + + for (const int i : src_transforms.index_range()) { + const int src_handle = src_reference_handles[i]; + const int dst_handle = handle_map[src_handle]; + const float4x4 &transform = base_transform * src_transforms[i]; + dst_instances->add_instance(dst_handle, transform); + } + } + + result.replace_instances(dst_instances.release()); + InstancesComponent &dst_component = result.get_component_for_write(); + join_attributes(to_base_components(src_components), dst_component, {"position"}); +} + +static void join_components(Span /*src_components*/, + VArray /*src_base_transform*/, + GeometrySet & /*result*/) +{ + /* Not yet supported. Joining volume grids with the same name requires resampling of at least one + * of the grids. The cell size of the resulting volume has to be determined somehow. */ +} + +template +void join_component_type(Span src_components, + GeometrySet &result, + const bke::AnonymousAttributePropagationInfo &propagation_info) +{ + if (src_components.size() == 0) { + return; + } + if (src_components.size() == 1) { + result.add(*src_components[0]); + return; + } + + if constexpr (is_same_any_v) { + join_components( + src_components, + VArray::ForSingle(blender::float4x4::identity(), src_components.size()), + result); + } + else { + std::unique_ptr instances = std::make_unique(); + for (const Component *component : src_components) { + GeometrySet tmp_geo; + tmp_geo.add(*component); + const int handle = instances->add_reference(bke::InstanceReference{tmp_geo}); + instances->add_instance(handle, float4x4::identity()); + } + + GeometrySet joined_components = geometry::realize_instances( + GeometrySet::create_with_instances(instances.release()), + {true, + false, + IndexMask(instances->instances_num()), + VArray::ForSingle(-1, instances->instances_num()), + propagation_info}); + result.add(joined_components.get_component_for_write()); + } +} + +void join_transform_instance_components(Span src_components, + Span src_base_transforms, + GeometrySet &result) +{ + BLI_assert(src_components.size() == src_base_transforms.size()); + + if (src_components.size() == 0) { + return; + } + + join_components(src_components, VArray::ForSpan(src_base_transforms), result); +} + +/** Explicit template instantiation for all GeometryComponent subclasses. */ +template void join_component_type(Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); +template void join_component_type( + Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); +template void join_component_type( + Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); +template void join_component_type(Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); +template void join_component_type(Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); +template void join_component_type( + Span, + GeometrySet &, + const bke::AnonymousAttributePropagationInfo &); + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 6b12512aea0..ae558d206eb 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "GEO_join_geometry.hh" #include "GEO_realize_instances.hh" #include "DNA_collection_types.h" @@ -236,6 +237,12 @@ struct GatherTasksInfo { const AllCurvesInfo &curves; bool create_id_attribute_on_any_component = false; + /** Selection for top-level instances to realize. */ + IndexMask selection; + + /** Depth to realize instances for each selected top-level instance. */ + const VArray &depths; + /** * Under some circumstances, temporary arrays need to be allocated during the gather operation. * For example, when an instance attribute has to be realized as a different data type. This @@ -244,6 +251,11 @@ struct GatherTasksInfo { */ Vector>> &r_temporary_arrays; + /** Instance components to merge for output geometry. */ + Vector instances_components_to_merge; + /** Base transform for each instance component. */ + Vector instances_components_transforms; + /** All gathered tasks. */ GatherTasks r_tasks; /** Current offsets while gathering tasks. */ @@ -364,6 +376,8 @@ static void create_result_ids(const RealizeInstancesOptions &options, /* Forward declaration. */ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, + const int current_depth, + const int target_depth, const GeometrySet &geometry_set, const float4x4 &base_transform, const InstanceContext &base_instance_context); @@ -456,6 +470,8 @@ static void foreach_geometry_in_reference( } static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, + const int current_depth, + const int target_depth, const Instances &instances, const float4x4 &base_transform, const InstanceContext &base_instance_context) @@ -481,7 +497,16 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, Vector> curve_attributes_to_override = prepare_attribute_fallbacks( gather_info, instances, gather_info.curves.attributes); - for (const int i : transforms.index_range()) { + /* If at top level, get instance indices from selection field, else use all instances. */ + const IndexMask indices = current_depth == 0 ? gather_info.selection : + IndexMask(IndexRange(instances.instances_num())); + + for (const int mask_index : indices.index_range()) { + const int i = indices[mask_index]; + + /* If at top level, retrieve depth from gather_info, else continue with target_depth. */ + const int depth_target = current_depth == 0 ? gather_info.depths[mask_index] : target_depth; + const int handle = handles[i]; const float4x4 &transform = transforms[i]; const InstanceReference &reference = references[handle]; @@ -518,6 +543,8 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, const uint32_t id) { instance_context.id = id; gather_realize_tasks_recursive(gather_info, + current_depth + 1, + depth_target, instance_geometry_set, transform, instance_context); @@ -529,6 +556,8 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, * Gather tasks for all geometries in the #geometry_set. */ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, + const int current_depth, + const int target_depth, const GeometrySet &geometry_set, const float4x4 &base_transform, const InstanceContext &base_instance_context) @@ -588,12 +617,25 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info, break; } case GEO_COMPONENT_TYPE_INSTANCES: { - const InstancesComponent &instances_component = *static_cast( - component); - const Instances *instances = instances_component.get_for_read(); - if (instances != nullptr && instances->instances_num() > 0) { - gather_realize_tasks_for_instances( - gather_info, *instances, base_transform, base_instance_context); + if (current_depth == target_depth) { + const InstancesComponent *instances_component = static_cast( + component); + + gather_info.instances_components_to_merge.append(instances_component); + gather_info.instances_components_transforms.append(base_transform); + } + else { + const InstancesComponent &instances_component = *static_cast( + component); + const Instances *instances = instances_component.get_for_read(); + if (instances != nullptr && instances->instances_num() > 0) { + gather_realize_tasks_for_instances(gather_info, + current_depth, + target_depth, + *instances, + base_transform, + base_instance_context); + } } break; } @@ -1452,6 +1494,32 @@ static void remove_id_attribute_from_instances(GeometrySet &geometry_set) }); } +/** Propagate instances from the old geometry set to the new geometry set if they are not realized. + */ +static void propagate_instances_to_keep( + const GeometrySet &geometry_set, + IndexMask selection, + GeometrySet &new_geometry_set, + const bke::AnonymousAttributePropagationInfo &propagation_info) +{ + const Instances &instances = *geometry_set.get_instances_for_read(); + + Vector inverse_selection_indices; + const IndexMask inverse_selection = selection.invert(IndexRange(instances.instances_num()), + inverse_selection_indices); + /* Check not all instances are being realized. */ + if (inverse_selection.is_empty()) { + return; + } + + InstancesComponent &new_instances_components = + new_geometry_set.get_component_for_write(); + + std::unique_ptr new_instances = std::make_unique(instances); + new_instances->remove(inverse_selection, propagation_info); + new_instances_components.replace(new_instances.release(), GeometryOwnershipType::Owned); +} + GeometrySet realize_instances(GeometrySet geometry_set, const RealizeInstancesOptions &options) { /* The algorithm works in three steps: @@ -1465,6 +1533,10 @@ GeometrySet realize_instances(GeometrySet geometry_set, const RealizeInstancesOp return geometry_set; } + GeometrySet temp_geometry_set; + propagate_instances_to_keep( + geometry_set, options.selection, temp_geometry_set, options.propagation_info); + if (options.keep_original_ids) { remove_id_attribute_from_instances(geometry_set); } @@ -1481,12 +1553,26 @@ GeometrySet realize_instances(GeometrySet geometry_set, const RealizeInstancesOp all_meshes_info, all_curves_info, create_id_attribute, + options.selection, + options.depths, temporary_arrays}; - const float4x4 transform = float4x4::identity(); - InstanceContext attribute_fallbacks(gather_info); - gather_realize_tasks_recursive(gather_info, geometry_set, transform, attribute_fallbacks); GeometrySet new_geometry_set; + + const float4x4 transform = float4x4::identity(); + InstanceContext attribute_fallbacks(gather_info); + + if (temp_geometry_set.has_instances()) { + gather_info.instances_components_to_merge.append( + &temp_geometry_set.get_component_for_write()); + gather_info.instances_components_transforms.append(float4x4::identity()); + } + + gather_realize_tasks_recursive(gather_info, 0, -1, geometry_set, transform, attribute_fallbacks); + + geometry::join_transform_instance_components(gather_info.instances_components_to_merge, + gather_info.instances_components_transforms, + new_geometry_set); execute_realize_pointcloud_tasks(options, all_pointclouds_info, gather_info.r_tasks.pointcloud_tasks, diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 18a662289aa..a1d024b2b9d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "GEO_realize_instances.hh" - -#include "BKE_instances.hh" +#include "GEO_join_geometry.hh" #include "node_geometry_util.hh" @@ -15,137 +13,8 @@ static void node_declare(NodeDeclarationBuilder &b) } template -static Array to_base_components(Span components) -{ - return components; -} - -static Map get_final_attribute_info( - Span components, Span ignored_attributes) -{ - Map info; - - for (const GeometryComponent *component : components) { - component->attributes()->for_all( - [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - if (ignored_attributes.contains(attribute_id.name())) { - return true; - } - if (meta_data.data_type == CD_PROP_STRING) { - return true; - } - info.add_or_modify( - attribute_id, - [&](AttributeMetaData *meta_data_final) { *meta_data_final = meta_data; }, - [&](AttributeMetaData *meta_data_final) { - meta_data_final->data_type = blender::bke::attribute_data_type_highest_complexity( - {meta_data_final->data_type, meta_data.data_type}); - meta_data_final->domain = blender::bke::attribute_domain_highest_priority( - {meta_data_final->domain, meta_data.domain}); - }); - return true; - }); - } - - return info; -} - -static void fill_new_attribute(Span src_components, - const AttributeIDRef &attribute_id, - const eCustomDataType data_type, - const eAttrDomain domain, - GMutableSpan dst_span) -{ - const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type); - BLI_assert(cpp_type != nullptr); - - int offset = 0; - for (const GeometryComponent *component : src_components) { - const int domain_num = component->attribute_domain_size(domain); - if (domain_num == 0) { - continue; - } - GVArray read_attribute = component->attributes()->lookup_or_default( - attribute_id, domain, data_type, nullptr); - - GVArraySpan src_span{read_attribute}; - const void *src_buffer = src_span.data(); - void *dst_buffer = dst_span[offset]; - cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_num); - - offset += domain_num; - } -} - -static void join_attributes(Span src_components, - GeometryComponent &result, - Span ignored_attributes = {}) -{ - const Map info = get_final_attribute_info(src_components, - ignored_attributes); - - for (const Map::Item item : info.items()) { - const AttributeIDRef attribute_id = item.key; - const AttributeMetaData &meta_data = item.value; - - GSpanAttributeWriter write_attribute = - result.attributes_for_write()->lookup_or_add_for_write_only_span( - attribute_id, meta_data.domain, meta_data.data_type); - if (!write_attribute) { - continue; - } - fill_new_attribute( - src_components, attribute_id, meta_data.data_type, meta_data.domain, write_attribute.span); - write_attribute.finish(); - } -} - -static void join_components(Span src_components, GeometrySet &result) -{ - std::unique_ptr dst_instances = std::make_unique(); - - int tot_instances = 0; - for (const InstancesComponent *src_component : src_components) { - tot_instances += src_component->get_for_read()->instances_num(); - } - dst_instances->reserve(tot_instances); - - for (const InstancesComponent *src_component : src_components) { - const bke::Instances &src_instances = *src_component->get_for_read(); - - Span src_references = src_instances.references(); - Array handle_map(src_references.size()); - for (const int src_handle : src_references.index_range()) { - handle_map[src_handle] = dst_instances->add_reference(src_references[src_handle]); - } - - Span src_transforms = src_instances.transforms(); - Span src_reference_handles = src_instances.reference_handles(); - - for (const int i : src_transforms.index_range()) { - const int src_handle = src_reference_handles[i]; - const int dst_handle = handle_map[src_handle]; - const float4x4 &transform = src_transforms[i]; - dst_instances->add_instance(dst_handle, transform); - } - } - - result.replace_instances(dst_instances.release()); - InstancesComponent &dst_component = result.get_component_for_write(); - join_attributes(to_base_components(src_components), dst_component, {"position"}); -} - -static void join_components(Span /*src_components*/, - GeometrySet & /*result*/) -{ - /* Not yet supported. Joining volume grids with the same name requires resampling of at least one - * of the grids. The cell size of the resulting volume has to be determined somehow. */ -} - -template -static void join_component_type(Span src_geometry_sets, - GeometrySet &result, - const AnonymousAttributePropagationInfo &propagation_info) +Vector get_components_from_geometry_sets( + const Span src_geometry_sets) { Vector components; for (const GeometrySet &geometry_set : src_geometry_sets) { @@ -154,35 +23,7 @@ static void join_component_type(Span src_geometry_sets, components.append(component); } } - - if (components.size() == 0) { - return; - } - if (components.size() == 1) { - result.add(*components[0]); - return; - } - - if constexpr (is_same_any_v) { - join_components(components, result); - } - else { - std::unique_ptr instances = std::make_unique(); - for (const Component *component : components) { - GeometrySet tmp_geo; - tmp_geo.add(*component); - const int handle = instances->add_reference(bke::InstanceReference{tmp_geo}); - instances->add_instance(handle, float4x4::identity()); - } - - geometry::RealizeInstancesOptions options; - options.keep_original_ids = true; - options.realize_instance_attributes = false; - options.propagation_info = propagation_info; - GeometrySet joined_components = geometry::realize_instances( - GeometrySet::create_with_instances(instances.release()), options); - result.add(joined_components.get_component_for_write()); - } + return components; } static void node_geo_exec(GeoNodeExecParams params) @@ -197,13 +38,30 @@ static void node_geo_exec(GeoNodeExecParams params) } GeometrySet geometry_set_result; - join_component_type(geometry_sets, geometry_set_result, propagation_info); - join_component_type(geometry_sets, geometry_set_result, propagation_info); - join_component_type(geometry_sets, geometry_set_result, propagation_info); - join_component_type(geometry_sets, geometry_set_result, propagation_info); - join_component_type(geometry_sets, geometry_set_result, propagation_info); - join_component_type( - geometry_sets, geometry_set_result, propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); + geometry::join_component_type( + get_components_from_geometry_sets(geometry_sets), + geometry_set_result, + propagation_info); params.set_output("Geometry", std::move(geometry_set_result)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc index 18311e9ca58..c15bae8d413 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc @@ -2,6 +2,8 @@ #include "node_geometry_util.hh" +#include "BKE_instances.hh" + #include "GEO_realize_instances.hh" #include "UI_interface.h" @@ -12,6 +14,16 @@ namespace blender::nodes::node_geo_realize_instances_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_input(N_("Geometry")); + b.add_input(N_("Selection")) + .default_value(true) + .hide_value() + .supports_field() + .description(N_("Which top-level instances to realize")); + b.add_input(N_("Depth")) + .default_value(0) + .supports_field() + .description( + N_("Number of levels of nested instances to realize for each top-level instance")); b.add_output(N_("Geometry")).propagate_all(); } @@ -34,12 +46,31 @@ static void node_geo_exec(GeoNodeExecParams params) } GeometrySet geometry_set = params.extract_input("Geometry"); + if (!geometry_set.has_instances()) { + params.set_output("Geometry", std::move(geometry_set)); + return; + } + GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(geometry_set); - geometry::RealizeInstancesOptions options; - options.keep_original_ids = legacy_behavior; - options.realize_instance_attributes = !legacy_behavior; - options.propagation_info = params.get_output_propagation_info("Geometry"); - geometry_set = geometry::realize_instances(geometry_set, options); + + Field selection_field = params.extract_input>("Selection"); + Field depth_field = params.extract_input>("Depth"); + + const bke::Instances &instances = *geometry_set.get_instances_for_read(); + const bke::InstancesFieldContext field_context{instances}; + fn::FieldEvaluator evaluator{field_context, instances.instances_num()}; + evaluator.set_selection(selection_field); + evaluator.add(depth_field); + evaluator.evaluate(); + const VArray depths = evaluator.get_evaluated(0); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + + bke::AnonymousAttributePropagationInfo propagation_info = params.get_output_propagation_info( + "Geometry"); + + geometry_set = geometry::realize_instances( + geometry_set, {legacy_behavior, !legacy_behavior, selection, depths, propagation_info}); + params.set_output("Geometry", std::move(geometry_set)); }