[Bf-blender-cvs] [a94d80716e6] master: Geometry Nodes: Support instances in the delete geometry node

Hans Goudey noreply at git.blender.org
Wed Dec 29 18:32:06 CET 2021


Commit: a94d80716e688aaa5350b63bd49a952fb1fbca97
Author: Hans Goudey
Date:   Wed Dec 29 11:31:58 2021 -0600
Branches: master
https://developer.blender.org/rBa94d80716e688aaa5350b63bd49a952fb1fbca97

Geometry Nodes: Support instances in the delete geometry node

Ever since the instance domain was added, this was exposed, it just
didn't do anything. This patch implements the instances domain in the
delete and separate geometry nodes, where it acts on the top-level
instances.

We act on a mutable instances input, with the idea that eventually
copy on write attribute layers will make this less expensive. It also
allows us to keep the instance references in place and to do less
work in some situations.

Ref T93554

Differential Revision: https://developer.blender.org/D13565

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/geometry_component_instances.cc
M	source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 8e36bda84ce..0f9c2c1062b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -922,6 +922,11 @@ class InstancesComponent : public GeometryComponent {
   int instances_amount() const;
   int references_amount() const;
 
+  /**
+   * Remove the indices in the selection mask and remove unused instance references afterwards.
+   */
+  void remove_instances(const blender::IndexMask selection);
+
   blender::Span<int> almost_unique_ids() const;
 
   blender::bke::CustomDataAttributes &attributes();
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 93a7646fed0..a7e3c5b60dc 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -17,6 +17,7 @@
 #include <mutex>
 
 #include "BLI_float4x4.hh"
+#include "BLI_index_mask.hh"
 #include "BLI_map.hh"
 #include "BLI_rand.hh"
 #include "BLI_set.hh"
@@ -26,6 +27,8 @@
 
 #include "DNA_collection_types.h"
 
+#include "BKE_attribute_access.hh"
+#include "BKE_attribute_math.hh"
 #include "BKE_geometry_set.hh"
 #include "BKE_geometry_set_instances.hh"
 
@@ -34,6 +37,7 @@
 #include "FN_cpp_type_make.hh"
 
 using blender::float4x4;
+using blender::IndexMask;
 using blender::Map;
 using blender::MutableSpan;
 using blender::Set;
@@ -132,6 +136,62 @@ blender::Span<InstanceReference> InstancesComponent::references() const
   return references_;
 }
 
+template<typename T>
+static void copy_data_based_on_mask(Span<T> src, MutableSpan<T> dst, IndexMask mask)
+{
+  BLI_assert(src.data() != dst.data());
+  using namespace blender;
+  threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) {
+    for (const int i : range) {
+      dst[i] = src[mask[i]];
+    }
+  });
+}
+
+void InstancesComponent::remove_instances(const IndexMask selection)
+{
+  using namespace blender;
+  if (selection.is_range() && selection.index_range().first() == 0) {
+    /* Deleting from the end of the array can be much faster since no data has to be shifted. */
+    this->resize(selection.size());
+    this->remove_unused_references();
+    return;
+  }
+
+  Vector<int> new_handles(selection.size());
+  copy_data_based_on_mask<int>(this->instance_reference_handles(), new_handles, selection);
+  instance_reference_handles_ = std::move(new_handles);
+  Vector<float4x4> new_transforms(selection.size());
+  copy_data_based_on_mask<float4x4>(this->instance_transforms(), new_transforms, selection);
+  instance_transforms_ = std::move(new_transforms);
+
+  const bke::CustomDataAttributes &src_attributes = attributes_;
+
+  bke::CustomDataAttributes dst_attributes;
+  dst_attributes.reallocate(selection.size());
+
+  src_attributes.foreach_attribute(
+      [&](const bke::AttributeIDRef &id, const AttributeMetaData &meta_data) {
+        if (!id.should_be_kept()) {
+          return true;
+        }
+
+        GSpan src = *src_attributes.get_for_read(id);
+        dst_attributes.create(id, meta_data.data_type);
+        fn::GMutableSpan dst = *dst_attributes.get_for_write(id);
+
+        attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
+          using T = decltype(dummy);
+          copy_data_based_on_mask<T>(src.typed<T>(), dst.typed<T>(), selection);
+        });
+        return true;
+      },
+      ATTR_DOMAIN_INSTANCE);
+
+  attributes_ = std::move(dst_attributes);
+  this->remove_unused_references();
+}
+
 void InstancesComponent::remove_unused_references()
 {
   using namespace blender;
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 a5197b23adb..7d41242b8bc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -529,6 +529,30 @@ static void separate_point_cloud_selection(GeometrySet &geometry_set,
   geometry_set.replace_pointcloud(pointcloud);
 }
 
+static void separate_instance_selection(GeometrySet &geometry_set,
+                                        const Field<bool> &selection_field,
+                                        const bool invert)
+{
+  InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
+  GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
+
+  const int domain_size = instances.attribute_domain_size(ATTR_DOMAIN_INSTANCE);
+  fn::FieldEvaluator evaluator{field_context, domain_size};
+  evaluator.add(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.size() == 0) {
+    geometry_set.remove<InstancesComponent>();
+    return;
+  }
+
+  instances.remove_instances(mask);
+}
+
 static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection,
                                                             const bool invert,
                                                             MutableSpan<int> r_vertex_map,
@@ -1261,7 +1285,7 @@ void separate_geometry(GeometrySet &geometry_set,
     }
   }
   if (geometry_set.has_mesh()) {
-    if (domain != ATTR_DOMAIN_CURVE) {
+    if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER)) {
       separate_mesh_selection(geometry_set, selection_field, domain, mode, invert);
       some_valid_domain = true;
     }
@@ -1272,6 +1296,12 @@ void separate_geometry(GeometrySet &geometry_set,
       some_valid_domain = true;
     }
   }
+  if (geometry_set.has_instances()) {
+    if (domain == ATTR_DOMAIN_INSTANCE) {
+      separate_instance_selection(geometry_set, selection_field, invert);
+      some_valid_domain = true;
+    }
+  }
   r_is_error = !some_valid_domain && geometry_set.has_realized_data();
 }



More information about the Bf-blender-cvs mailing list