diff options
author | Jacques Lucke <jacques@blender.org> | 2021-12-14 17:40:16 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-12-14 17:40:27 +0300 |
commit | 8e2c9f2dd3118bfdb69ccf0ab2b9f968a854aae4 (patch) | |
tree | 7ec789b5e980a9ed572671c3c130db2d125b49de | |
parent | b44a500988f3d6aea631d17ca383c8ced55e4371 (diff) |
Geometry Nodes: simplify using selection when evaluating fields
We often had to use two `FieldEvaluator` instances to first evaluate
the selection and then the remaining fields. Now both can be done
with a single `FieldEvaluator`. This results in less boilerplate code in
many cases.
Performance is not affected by this change. In a separate patch we
could improve performance by reusing evaluated sub-fields that are
used by the selection and the other fields.
Differential Revision: https://developer.blender.org/D13571
19 files changed, 180 insertions, 173 deletions
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh index cf96eff62bd..a591aaed34a 100644 --- a/source/blender/functions/FN_field.hh +++ b/source/blender/functions/FN_field.hh @@ -313,6 +313,9 @@ class FieldEvaluator : NonMovable, NonCopyable { Vector<OutputPointerInfo> output_pointer_infos_; bool is_evaluated_ = false; + Field<bool> selection_field_; + IndexMask selection_mask_; + public: /** Takes #mask by pointer because the mask has to live longer than the evaluator. */ FieldEvaluator(const FieldContext &context, const IndexMask *mask) @@ -333,6 +336,18 @@ class FieldEvaluator : NonMovable, NonCopyable { } /** + * The selection field is evaluated first to determine which indices of the other fields should + * be evaluated. Calling this method multiple times will just replace the previously set + * selection field. Only the elements selected by both this selection and the selection provided + * in the constructor are calculated. If no selection field is set, it is assumed that all + * indices passed to the constructor are selected. + */ + void set_selection(Field<bool> selection) + { + selection_field_ = std::move(selection); + } + + /** * \param field: Field to add to the evaluator. * \param dst: Mutable virtual array that the evaluated result for this field is be written into. */ @@ -403,6 +418,8 @@ class FieldEvaluator : NonMovable, NonCopyable { return this->get_evaluated(field_index).typed<T>(); } + IndexMask get_evaluated_selection_as_mask(); + /** * Retrieve the output of an evaluated boolean field and convert it to a mask, which can be used * to avoid calculations for unnecessary elements later on. The evaluator will own the indices in diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc index 5fa493c8336..604e5c6d13f 100644 --- a/source/blender/functions/intern/field.cc +++ b/source/blender/functions/intern/field.cc @@ -624,7 +624,7 @@ FieldInput::FieldInput(const CPPType &type, std::string debug_name) * FieldEvaluator. */ -static Vector<int64_t> indices_from_selection(const VArray<bool> &selection) +static Vector<int64_t> indices_from_selection(IndexMask mask, const VArray<bool> &selection) { /* If the selection is just a single value, it's best to avoid calling this * function when constructing an IndexMask and use an IndexRange instead. */ @@ -633,14 +633,14 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection) Vector<int64_t> indices; if (selection.is_span()) { Span<bool> span = selection.get_internal_span(); - for (const int64_t i : span.index_range()) { + for (const int64_t i : mask) { if (span[i]) { indices.append(i); } } } else { - for (const int i : selection.index_range()) { + for (const int i : mask) { if (selection[i]) { indices.append(i); } @@ -681,14 +681,36 @@ int FieldEvaluator::add(GField field) return field_index; } +static IndexMask evaluate_selection(const Field<bool> &selection_field, + const FieldContext &context, + IndexMask full_mask, + ResourceScope &scope) +{ + if (selection_field) { + VArray<bool> selection = + evaluate_fields(scope, {selection_field}, full_mask, context)[0].typed<bool>(); + if (selection.is_single()) { + if (selection.get_internal_single()) { + return full_mask; + } + return IndexRange(0); + } + return scope.add_value(indices_from_selection(full_mask, selection)).as_span(); + } + return full_mask; +} + void FieldEvaluator::evaluate() { BLI_assert_msg(!is_evaluated_, "Cannot evaluate fields twice."); + + selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_); + Array<GFieldRef> fields(fields_to_evaluate_.size()); for (const int i : fields_to_evaluate_.index_range()) { fields[i] = fields_to_evaluate_[i]; } - evaluated_varrays_ = evaluate_fields(scope_, fields, mask_, context_, dst_varrays_); + evaluated_varrays_ = evaluate_fields(scope_, fields, selection_mask_, context_, dst_varrays_); BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size()); for (const int i : fields_to_evaluate_.index_range()) { OutputPointerInfo &info = output_pointer_infos_[i]; @@ -710,7 +732,13 @@ IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index) return IndexRange(0); } - return scope_.add_value(indices_from_selection(varray)).as_span(); + return scope_.add_value(indices_from_selection(mask_, varray)).as_span(); +} + +IndexMask FieldEvaluator::get_evaluated_selection_as_mask() +{ + BLI_assert(is_evaluated_); + return selection_mask_; } } // namespace blender::fn diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index adb698b8f7a..3537b62c76e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -399,16 +399,12 @@ static Array<float> calc_full_density_factors_with_selection(const MeshComponent GeometryComponentFieldContext field_context{component, attribute_domain}; const int domain_size = component.attribute_domain_size(attribute_domain); - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection_mask = selection_evaluator.get_evaluated_as_mask(0); - Array<float> densities(domain_size, 0.0f); - fn::FieldEvaluator density_evaluator{field_context, &selection_mask}; - density_evaluator.add_with_destination(density_field, densities.as_mutable_span()); - density_evaluator.evaluate(); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(density_field, densities.as_mutable_span()); + evaluator.evaluate(); return densities; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index 6a661020bd9..486f90760f5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -65,12 +65,24 @@ static void add_instances_from_component( const AttributeDomain domain = ATTR_DOMAIN_POINT; const int domain_size = src_component.attribute_domain_size(domain); + VArray<bool> pick_instance; + VArray<int> indices; + VArray<float3> rotations; + VArray<float3> scales; + GeometryComponentFieldContext field_context{src_component, domain}; const Field<bool> selection_field = params.get_input<Field<bool>>("Selection"); - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + /* The evaluator could use the component's stable IDs as a destination directly, but only the + * selected indices should be copied. */ + evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance); + evaluator.add(params.get_input<Field<int>>("Instance Index"), &indices); + evaluator.add(params.get_input<Field<float3>>("Rotation"), &rotations); + evaluator.add(params.get_input<Field<float3>>("Scale"), &scales); + evaluator.evaluate(); + + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); /* The initial size of the component might be non-zero when this function is called for multiple * component types. */ @@ -83,19 +95,6 @@ static void add_instances_from_component( MutableSpan<float4x4> dst_transforms = dst_component.instance_transforms().slice(start_len, select_len); - FieldEvaluator field_evaluator{field_context, domain_size}; - VArray<bool> pick_instance; - VArray<int> indices; - VArray<float3> rotations; - VArray<float3> scales; - /* The evaluator could use the component's stable IDs as a destination directly, but only the - * selected indices should be copied. */ - field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance); - field_evaluator.add(params.get_input<Field<int>>("Instance Index"), &indices); - field_evaluator.add(params.get_input<Field<float3>>("Rotation"), &rotations); - field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales); - field_evaluator.evaluate(); - VArray<float3> positions = src_component.attribute_get_for_read<float3>( "position", domain, {0, 0, 0}); diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc index 8dc5b4cc7b9..9942e388ba5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc @@ -56,10 +56,12 @@ static void convert_instances_to_points(GeometrySet &geometry_set, GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE}; const int domain_size = instances.attribute_domain_size(ATTR_DOMAIN_INSTANCE); - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(std::move(selection_field)); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(std::move(selection_field)); + evaluator.add(std::move(position_field)); + evaluator.add(std::move(radius_field)); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); if (selection.is_empty()) { return; } @@ -69,10 +71,6 @@ static void convert_instances_to_points(GeometrySet &geometry_set, PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>(); - fn::FieldEvaluator evaluator{field_context, &selection}; - evaluator.add(std::move(position_field)); - evaluator.add(std::move(radius_field)); - evaluator.evaluate(); const VArray<float3> &positions = evaluator.get_evaluated<float3>(0); copy_attribute_to_points(positions, selection, {(float3 *)pointcloud->co, pointcloud->totpoint}); const VArray<float> &radii = evaluator.get_evaluated<float>(1); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index b3aa495536f..77314341fec 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -83,10 +83,15 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES}); return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + /* Evaluating directly into the point cloud doesn't work because we are not using the full + * "min_array_size" array but compressing the selected elements into the final array with no + * gaps. */ + evaluator.add(position_field); + evaluator.add(radius_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); uninitialized_fill_n(pointcloud->radius, pointcloud->totpoint, 0.05f); @@ -94,13 +99,6 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, PointCloudComponent &point_component = geometry_set.get_component_for_write<PointCloudComponent>(); - /* Evaluating directly into the point cloud doesn't work because we are not using the full - * "min_array_size" array but compressing the selected elements into the final array with no - * gaps. */ - fn::FieldEvaluator evaluator{field_context, &selection}; - evaluator.add(position_field); - evaluator.add(radius_field); - evaluator.evaluate(); copy_attribute_to_points(evaluator.get_evaluated<float3>(0), selection, {(float3 *)pointcloud->co, pointcloud->totpoint}); diff --git a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc index 0508ff7a215..335484c62b0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_rotate_instances.cc @@ -35,19 +35,17 @@ static void rotate_instances(GeoNodeExecParams ¶ms, InstancesComponent &inst GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE}; const int domain_size = instances_component.instances_amount(); - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(params.extract_input<Field<bool>>("Selection")); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - - fn::FieldEvaluator transforms_evaluator{field_context, &selection}; - transforms_evaluator.add(params.extract_input<Field<float3>>("Rotation")); - transforms_evaluator.add(params.extract_input<Field<float3>>("Pivot Point")); - transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space")); - transforms_evaluator.evaluate(); - const VArray<float3> &rotations = transforms_evaluator.get_evaluated<float3>(0); - const VArray<float3> &pivots = transforms_evaluator.get_evaluated<float3>(1); - const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(2); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(params.extract_input<Field<bool>>("Selection")); + evaluator.add(params.extract_input<Field<float3>>("Rotation")); + evaluator.add(params.extract_input<Field<float3>>("Pivot Point")); + evaluator.add(params.extract_input<Field<bool>>("Local Space")); + evaluator.evaluate(); + + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<float3> &rotations = evaluator.get_evaluated<float3>(0); + const VArray<float3> &pivots = evaluator.get_evaluated<float3>(1); + const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(2); MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc index 3e0f3160f89..1779ac8bff7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_scale_instances.cc @@ -37,19 +37,17 @@ static void scale_instances(GeoNodeExecParams ¶ms, InstancesComponent &insta { GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE}; - fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()}; - selection_evaluator.add(params.extract_input<Field<bool>>("Selection")); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, instances_component.instances_amount()}; + evaluator.set_selection(params.extract_input<Field<bool>>("Selection")); + evaluator.add(params.extract_input<Field<float3>>("Scale")); + evaluator.add(params.extract_input<Field<float3>>("Center")); + evaluator.add(params.extract_input<Field<bool>>("Local Space")); + evaluator.evaluate(); - fn::FieldEvaluator transforms_evaluator{field_context, &selection}; - transforms_evaluator.add(params.extract_input<Field<float3>>("Scale")); - transforms_evaluator.add(params.extract_input<Field<float3>>("Center")); - transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space")); - transforms_evaluator.evaluate(); - const VArray<float3> &scales = transforms_evaluator.get_evaluated<float3>(0); - const VArray<float3> &pivots = transforms_evaluator.get_evaluated<float3>(1); - const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(2); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<float3> &scales = evaluator.get_evaluated<float3>(0); + const VArray<float3> &pivots = evaluator.get_evaluated<float3>(1); + const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(2); MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc index ae82232c6ed..30a61574e19 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc @@ -60,10 +60,12 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add(position_field); + evaluator.add(offset_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_as_mask(0); CurveComponent *curve_component = static_cast<CurveComponent *>(&component); CurveEval *curve = curve_component->get_for_write(); @@ -113,13 +115,8 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode, } } - fn::FieldEvaluator position_evaluator{field_context, &selection}; - position_evaluator.add(position_field); - position_evaluator.add(offset_field); - position_evaluator.evaluate(); - - const VArray<float3> &positions_input = position_evaluator.get_evaluated<float3>(0); - const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1); + const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0); + const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1); OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>( side, ATTR_DOMAIN_POINT, {0, 0, 0}); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc index fd486f07e69..7d99f42c487 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_radius.cc @@ -40,16 +40,14 @@ static void set_radius_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>( "radius", ATTR_DOMAIN_POINT); - fn::FieldEvaluator radii_evaluator{field_context, &selection}; - radii_evaluator.add_with_destination(radius_field, radii.varray()); - radii_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(radius_field, radii.varray()); + evaluator.evaluate(); + radii.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc index 653ae39b4fa..447310e1ad7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_tilt.cc @@ -36,16 +36,14 @@ static void set_tilt_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<float> tilts = component.attribute_try_get_for_output_only<float>( "tilt", ATTR_DOMAIN_POINT); - fn::FieldEvaluator tilt_evaluator{field_context, &selection}; - tilt_evaluator.add_with_destination(tilt_field, tilts.varray()); - tilt_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(tilt_field, tilts.varray()); + evaluator.evaluate(); + tilts.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc index e2f48edc72d..db4083acd4b 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc @@ -36,26 +36,24 @@ static void set_id_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); /* Since adding the ID attribute can change the result of the field evaluation (the random value * node uses the index if the ID is unavailable), make sure that it isn't added before evaluating * the field. However, as an optimization, use a faster code path when it already exists. */ - fn::FieldEvaluator id_evaluator{field_context, &selection}; if (component.attribute_exists("id")) { OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>( "id", ATTR_DOMAIN_POINT); - id_evaluator.add_with_destination(id_field, id_attribute.varray()); - id_evaluator.evaluate(); + evaluator.add_with_destination(id_field, id_attribute.varray()); + evaluator.evaluate(); id_attribute.save(); } else { - id_evaluator.add(id_field); - id_evaluator.evaluate(); - const VArray<int> &result_ids = id_evaluator.get_evaluated<int>(0); + evaluator.add(id_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<int> &result_ids = evaluator.get_evaluated<int>(0); OutputAttribute_Typed<int> id_attribute = component.attribute_try_get_for_output_only<int>( "id", ATTR_DOMAIN_POINT); result_ids.materialize(selection, id_attribute.as_span()); diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc index 25634311225..4451907132a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_material_index.cc @@ -36,16 +36,13 @@ static void set_material_index_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<int> indices = component.attribute_try_get_for_output_only<int>( "material_index", ATTR_DOMAIN_FACE); - fn::FieldEvaluator material_evaluator{field_context, &selection}; - material_evaluator.add_with_destination(index_field, indices.varray()); - material_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(index_field, indices.varray()); + evaluator.evaluate(); indices.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc index bc7c59f75be..98adff7c939 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_point_radius.cc @@ -40,16 +40,14 @@ static void set_radius_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<float> radii = component.attribute_try_get_for_output_only<float>( "radius", ATTR_DOMAIN_POINT); - fn::FieldEvaluator radii_evaluator{field_context, &selection}; - radii_evaluator.add_with_destination(radius_field, radii.varray()); - radii_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(radius_field, radii.varray()); + evaluator.evaluate(); + radii.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index 218e4d03464..93073c2436d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -119,18 +119,15 @@ static void set_position_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - - fn::FieldEvaluator position_evaluator{field_context, &selection}; - position_evaluator.add(position_field); - position_evaluator.add(offset_field); - position_evaluator.evaluate(); - - const VArray<float3> &positions_input = position_evaluator.get_evaluated<float3>(0); - const VArray<float3> &offsets_input = position_evaluator.get_evaluated<float3>(1); + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add(position_field); + evaluator.add(offset_field); + evaluator.evaluate(); + + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0); + const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1); set_computed_position_and_offset(component, positions_input, offsets_input, domain, selection); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc index a8831130453..879a868cc0e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_shade_smooth.cc @@ -36,16 +36,14 @@ static void set_smooth_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<bool> shades = component.attribute_try_get_for_output_only<bool>( "shade_smooth", ATTR_DOMAIN_FACE); - fn::FieldEvaluator shade_evaluator{field_context, &selection}; - shade_evaluator.add_with_destination(shade_field, shades.varray()); - shade_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(shade_field, shades.varray()); + evaluator.evaluate(); + shades.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc index 7ffda8787e6..694491d7e6d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_cyclic.cc @@ -36,16 +36,14 @@ static void set_cyclic_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<bool> cyclics = component.attribute_try_get_for_output_only<bool>( "cyclic", ATTR_DOMAIN_CURVE); - fn::FieldEvaluator cyclic_evaluator{field_context, &selection}; - cyclic_evaluator.add_with_destination(cyclic_field, cyclics.varray()); - cyclic_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(cyclic_field, cyclics.varray()); + evaluator.evaluate(); + cyclics.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc index 8f3e26ac27b..0f93db5e6f6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc @@ -38,16 +38,14 @@ static void set_resolution_in_component(GeometryComponent &component, return; } - fn::FieldEvaluator selection_evaluator{field_context, domain_size}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); - OutputAttribute_Typed<int> resolutions = component.attribute_try_get_for_output_only<int>( "resolution", ATTR_DOMAIN_CURVE); - fn::FieldEvaluator resolution_evaluator{field_context, &selection}; - resolution_evaluator.add_with_destination(resolution_field, resolutions.varray()); - resolution_evaluator.evaluate(); + + fn::FieldEvaluator evaluator{field_context, domain_size}; + evaluator.set_selection(selection_field); + evaluator.add_with_destination(resolution_field, resolutions.varray()); + evaluator.evaluate(); + resolutions.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc index 8ef80323f99..59049ecf0ed 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_translate_instances.cc @@ -33,17 +33,15 @@ static void translate_instances(GeoNodeExecParams ¶ms, InstancesComponent &i { GeometryComponentFieldContext field_context{instances_component, ATTR_DOMAIN_INSTANCE}; - fn::FieldEvaluator selection_evaluator{field_context, instances_component.instances_amount()}; - selection_evaluator.add(params.extract_input<Field<bool>>("Selection")); - selection_evaluator.evaluate(); - const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0); + fn::FieldEvaluator evaluator{field_context, instances_component.instances_amount()}; + evaluator.set_selection(params.extract_input<Field<bool>>("Selection")); + evaluator.add(params.extract_input<Field<float3>>("Translation")); + evaluator.add(params.extract_input<Field<bool>>("Local Space")); + evaluator.evaluate(); - fn::FieldEvaluator transforms_evaluator{field_context, &selection}; - transforms_evaluator.add(params.extract_input<Field<float3>>("Translation")); - transforms_evaluator.add(params.extract_input<Field<bool>>("Local Space")); - transforms_evaluator.evaluate(); - const VArray<float3> &translations = transforms_evaluator.get_evaluated<float3>(0); - const VArray<bool> &local_spaces = transforms_evaluator.get_evaluated<bool>(1); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray<float3> &translations = evaluator.get_evaluated<float3>(0); + const VArray<bool> &local_spaces = evaluator.get_evaluated<bool>(1); MutableSpan<float4x4> instance_transforms = instances_component.instance_transforms(); |