[Bf-blender-cvs] [c4e11122c53] master: Geometry Nodes: Use fields for delete geometry inversion

Hans Goudey noreply at git.blender.org
Sun Jun 5 16:46:30 CEST 2022


Commit: c4e11122c537e1928dd423574d3e9a7d59cd152b
Author: Hans Goudey
Date:   Sun Jun 5 16:46:09 2022 +0200
Branches: master
https://developer.blender.org/rBc4e11122c537e1928dd423574d3e9a7d59cd152b

Geometry Nodes: Use fields for delete geometry inversion

The separate geometry and delete geometry nodes often invert the
selection so that deleting elements from a geometry can be implemented
as copying the opposite selection of elements. This should make the two
nodes faster in some cases, since the generic versions of selection
creation functions (i.e. from d3a1e9cbb92cca04e) are used instead
of the single threaded code that was used for this node.

The change also makes the deletion/separation code easier to
understand because it doesn't have to pass around the inversion.

===================================================================

M	source/blender/functions/FN_field.hh
M	source/blender/functions/intern/field.cc
M	source/blender/nodes/geometry/node_geometry_util.hh
M	source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_separate_geometry.cc

===================================================================

diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 46051a58e8b..a8136d06c5f 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -476,6 +476,8 @@ template<typename T> T evaluate_constant_field(const Field<T> &field)
   return value;
 }
 
+Field<bool> invert_boolean_field(const Field<bool> &field);
+
 GField make_constant_field(const CPPType &type, const void *value);
 
 template<typename T> Field<T> make_constant_field(T value)
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index a53da717606..47f6a0f19ca 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -518,6 +518,14 @@ GField make_field_constant_if_possible(GField field)
   return new_field;
 }
 
+Field<bool> invert_boolean_field(const Field<bool> &field)
+{
+  static CustomMF_SI_SO<bool, bool> not_fn{
+      "Not", [](bool a) { return !a; }, CustomMF_presets::AllSpanOrSingle()};
+  auto not_op = std::make_shared<FieldOperation>(FieldOperation(not_fn, {field}));
+  return Field<bool>(not_op);
+}
+
 GField make_constant_field(const CPPType &type, const void *value)
 {
   auto constant_node = std::make_shared<FieldConstant>(type, value);
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index d261928d1b8..efb7efaf1cc 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -73,7 +73,6 @@ void separate_geometry(GeometrySet &geometry_set,
                        eAttrDomain domain,
                        GeometryNodeDeleteGeometryMode mode,
                        const Field<bool> &selection_field,
-                       bool invert,
                        bool &r_is_error);
 
 std::optional<eCustomDataType> node_data_type_to_custom_data_type(eNodeSocketDatatype type);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index c29fe9e08eb..fba696b5b95 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -38,19 +38,6 @@ static void copy_data_based_on_map(Span<T> src, MutableSpan<T> dst, Span<int> in
   }
 }
 
-/** Utility function for making an IndexMask from a boolean selection. The indices vector should
- * live at least as long as the returned IndexMask.
- */
-static IndexMask index_mask_indices(Span<bool> mask, const bool invert, Vector<int64_t> &indices)
-{
-  for (const int i : mask.index_range()) {
-    if (mask[i] != invert) {
-      indices.append(i);
-    }
-  }
-  return IndexMask(indices);
-}
-
 /**
  * Copies the attributes with a domain in `domains` to `result_component`.
  */
@@ -400,8 +387,7 @@ static SplinePtr spline_delete(const Spline &spline, const IndexMask mask)
 
 static std::unique_ptr<CurveEval> curve_separate(const CurveEval &input_curve,
                                                  const Span<bool> selection,
-                                                 const eAttrDomain selection_domain,
-                                                 const bool invert)
+                                                 const eAttrDomain selection_domain)
 {
   Span<SplinePtr> input_splines = input_curve.splines();
   std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>();
@@ -413,7 +399,7 @@ static std::unique_ptr<CurveEval> curve_separate(const CurveEval &input_curve,
     /* Operates on each of the splines as a whole, i.e. not on the points in the splines
      * themselves. */
     for (const int i : selection.index_range()) {
-      if (selection[i] != invert) {
+      if (selection[i]) {
         output_curve->add_spline(input_splines[i]->copy());
         copied_splines.append(i);
       }
@@ -431,7 +417,7 @@ static std::unique_ptr<CurveEval> curve_separate(const CurveEval &input_curve,
 
       indices_to_copy.clear();
       for (const int i_point : IndexRange(spline.size())) {
-        if (selection[selection_index] != invert) {
+        if (selection[selection_index]) {
           /* Append i_point instead of selection_index because we need indices local to the spline
            * for copying. */
           indices_to_copy.append(i_point);
@@ -463,8 +449,7 @@ static std::unique_ptr<CurveEval> curve_separate(const CurveEval &input_curve,
 
 static void separate_curve_selection(GeometrySet &geometry_set,
                                      const Field<bool> &selection_field,
-                                     const eAttrDomain selection_domain,
-                                     const bool invert)
+                                     const eAttrDomain selection_domain)
 {
   const CurveComponent &src_component = *geometry_set.get_component_for_read<CurveComponent>();
   GeometryComponentFieldContext field_context{src_component, selection_domain};
@@ -475,7 +460,7 @@ static void separate_curve_selection(GeometrySet &geometry_set,
   evaluator.evaluate();
   const VArray_Span<bool> &selection = evaluator.get_evaluated<bool>(0);
   std::unique_ptr<CurveEval> r_curve = curve_separate(
-      *curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain, invert);
+      *curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain);
   if (r_curve) {
     geometry_set.replace_curves(curve_eval_to_curves(*r_curve));
   }
@@ -485,28 +470,23 @@ static void separate_curve_selection(GeometrySet &geometry_set,
 }
 
 static void separate_point_cloud_selection(GeometrySet &geometry_set,
-                                           const Field<bool> &selection_field,
-                                           const bool invert)
+                                           const Field<bool> &selection_field)
 {
   const PointCloudComponent &src_points =
       *geometry_set.get_component_for_read<PointCloudComponent>();
   GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT};
 
   fn::FieldEvaluator evaluator{field_context, src_points.attribute_domain_num(ATTR_DOMAIN_POINT)};
-  evaluator.add(selection_field);
+  evaluator.set_selection(selection_field);
   evaluator.evaluate();
-  const VArray_Span<bool> &selection = evaluator.get_evaluated<bool>(0);
-
-  Vector<int64_t> indices;
-  const IndexMask mask = index_mask_indices(selection, invert, indices);
-  const int total = mask.size();
-  PointCloud *pointcloud = BKE_pointcloud_new_nomain(total);
-
-  if (total == 0) {
-    geometry_set.replace_pointcloud(pointcloud);
+  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+  if (selection.is_empty()) {
+    geometry_set.replace_pointcloud(nullptr);
     return;
   }
 
+  PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size());
+
   PointCloudComponent dst_points;
   dst_points.replace(pointcloud, GeometryOwnershipType::Editable);
 
@@ -514,36 +494,30 @@ static void separate_point_cloud_selection(GeometrySet &geometry_set,
   geometry_set.gather_attributes_for_propagation(
       {GEO_COMPONENT_TYPE_POINT_CLOUD}, GEO_COMPONENT_TYPE_POINT_CLOUD, false, attributes);
 
-  copy_attributes_based_on_mask(attributes, src_points, dst_points, ATTR_DOMAIN_POINT, mask);
+  copy_attributes_based_on_mask(attributes, src_points, dst_points, ATTR_DOMAIN_POINT, selection);
   geometry_set.replace_pointcloud(pointcloud);
 }
 
-static void separate_instance_selection(GeometrySet &geometry_set,
-                                        const Field<bool> &selection_field,
-                                        const bool invert)
+static void delete_selected_instances(GeometrySet &geometry_set,
+                                      const Field<bool> &selection_field)
 {
   InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
   GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
 
-  const int domain_num = instances.attribute_domain_num(ATTR_DOMAIN_INSTANCE);
-  fn::FieldEvaluator evaluator{field_context, domain_num};
-  evaluator.add(selection_field);
+  fn::FieldEvaluator evaluator{field_context,
+                               instances.attribute_domain_num(ATTR_DOMAIN_INSTANCE)};
+  evaluator.set_selection(selection_field);
   evaluator.evaluate();
-  const VArray_Span<bool> &selection = evaluator.get_evaluated<bool>(0);
-
-  Vector<int64_t> indices;
-  const IndexMask mask = index_mask_indices(selection, invert, indices);
-
-  if (mask.is_empty()) {
+  const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
+  if (selection.is_empty()) {
     geometry_set.remove<InstancesComponent>();
     return;
   }
 
-  instances.remove_instances(mask);
+  instances.remove_instances(selection);
 }
 
 static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection,
-                                                            const bool invert,
                                                             MutableSpan<int> r_vertex_map,
                                                             int *r_selected_vertices_num)
 {
@@ -551,7 +525,7 @@ static void compute_selected_vertices_from_vertex_selection(const Span<bool> ver
 
   int selected_verts_num = 0;
   for (const int i : r_vertex_map.index_range()) {
-    if (vertex_selection[i] != invert) {
+    if (vertex_selection[i]) {
       r_vertex_map[i] = selected_verts_num;
       selected_verts_num++;
     }
@@ -565,7 +539,6 @@ static void compute_selected_vertices_from_vertex_selection(const Span<bool> ver
 
 static void compute_selected_edges_from_vertex_selection(const Mesh &mesh,
                                                          const Span<bool> vertex_selection,
-                                                         const bool invert,
                                                          MutableSpan<int> r_edge_map,
                                                          int *r_selected_edges_num)
 {
@@ -576,7 +549,7 @@ static void compute_selected_edges_from_vertex_selection(const Mesh &mesh,
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list