[Bf-blender-cvs] [40c3b8836b7] master: Geometry Nodes: Make Random ID a builtin attribute, remove sockets

Hans Goudey noreply at git.blender.org
Wed Oct 20 17:55:38 CEST 2021


Commit: 40c3b8836b7a36303ea9c78b0932758cbf277f93
Author: Hans Goudey
Date:   Wed Oct 20 10:54:54 2021 -0500
Branches: master
https://developer.blender.org/rB40c3b8836b7a36303ea9c78b0932758cbf277f93

Geometry Nodes: Make Random ID a builtin attribute, remove sockets

In order to address feedback that the "Stable ID" was not easy enough
to use, remove the "Stable ID" output from the distribution node and
the input from the instance on points node. Instead, the nodes write
or read a builtin named attribute called `id`. In the future we may
add more attributes like `edge_id` and `face_id`.

The downside is that more behavior is invisible, which is les
expected now that most attributes are passed around with node links.
This behavior will have to be explained in the manual.

The random value node's "ID" input that had an implicit index input
is converted to a special implicit input that uses the `id` attribute
if possible, but otherwise defaults to the index. There is no way to
tell in the UI which it uses, except by knowing that rule and checking
in the spreadsheet for the id attribute.

Because it isn't always possible to create stable randomness, this
attribute does not always exist, and it will be possible to remove it
when we have the attribute remove node back, to improve performance.

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

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenkernel/intern/attribute_access_intern.hh
M	source/blender/blenkernel/intern/geometry_component_curve.cc
M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/blenkernel/intern/geometry_component_pointcloud.cc
M	source/blender/functions/FN_field.hh
M	source/blender/functions/intern/field.cc
M	source/blender/modifiers/intern/MOD_nodes_evaluator.cc
M	source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
M	source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 66466e3972e..f57765e373b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -760,6 +760,24 @@ class AttributeFieldInput : public fn::FieldInput {
   bool is_equal_to(const fn::FieldNode &other) const override;
 };
 
+class IDAttributeFieldInput : public fn::FieldInput {
+ public:
+  IDAttributeFieldInput() : fn::FieldInput(CPPType::get<int>())
+  {
+  }
+
+  static fn::Field<int> Create();
+
+  const GVArray *get_varray_for_context(const fn::FieldContext &context,
+                                        IndexMask mask,
+                                        ResourceScope &scope) const override;
+
+  std::string socket_inspection_name() const override;
+
+  uint64_t hash() const override;
+  bool is_equal_to(const fn::FieldNode &other) const override;
+};
+
 class AnonymousAttributeFieldInput : public fn::FieldInput {
  private:
   /**
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index d0510e0008e..930cabafb00 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -345,11 +345,18 @@ GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
     return {};
   }
 
-  const int domain_size = component.attribute_domain_size(domain_);
-  const void *data = CustomData_get_layer(custom_data, stored_type_);
+  const void *data;
+  if (stored_as_named_attribute_) {
+    data = CustomData_get_layer_named(custom_data, stored_type_, name_.c_str());
+  }
+  else {
+    data = CustomData_get_layer(custom_data, stored_type_);
+  }
   if (data == nullptr) {
     return {};
   }
+
+  const int domain_size = component.attribute_domain_size(domain_);
   return as_read_attribute_(data, domain_size);
 }
 
@@ -368,11 +375,21 @@ GVMutableArrayPtr BuiltinCustomDataLayerProvider::try_get_for_write(
   if (data == nullptr) {
     return {};
   }
-  void *new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size);
+
+  void *new_data;
+  if (stored_as_named_attribute_) {
+    new_data = CustomData_duplicate_referenced_layer_named(
+        custom_data, stored_type_, name_.c_str(), domain_size);
+  }
+  else {
+    new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size);
+  }
+
   if (data != new_data) {
     custom_data_access_.update_custom_data_pointers(component);
     data = new_data;
   }
+
   if (update_on_write_ != nullptr) {
     update_on_write_(component);
   }
@@ -390,7 +407,19 @@ bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) co
   }
 
   const int domain_size = component.attribute_domain_size(domain_);
-  const int layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+  int layer_index;
+  if (stored_as_named_attribute_) {
+    for (const int i : IndexRange(custom_data->totlayer)) {
+      if (custom_data_layer_matches_attribute_id(custom_data->layers[i], name_)) {
+        layer_index = i;
+        break;
+      }
+    }
+  }
+  else {
+    layer_index = CustomData_get_layer_index(custom_data, stored_type_);
+  }
+
   const bool delete_success = CustomData_free_layer(
       custom_data, stored_type_, domain_size, layer_index);
   if (delete_success) {
@@ -409,14 +438,25 @@ bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
   if (custom_data == nullptr) {
     return false;
   }
-  if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
-    /* Exists already. */
-    return false;
-  }
 
   const int domain_size = component.attribute_domain_size(domain_);
-  const bool success = add_builtin_type_custom_data_layer_from_init(
-      *custom_data, stored_type_, domain_size, initializer);
+  bool success;
+  if (stored_as_named_attribute_) {
+    if (CustomData_get_layer_named(custom_data, data_type_, name_.c_str())) {
+      /* Exists already. */
+      return false;
+    }
+    success = add_custom_data_layer_from_attribute_init(
+        name_, *custom_data, stored_type_, domain_size, initializer);
+  }
+  else {
+    if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
+      /* Exists already. */
+      return false;
+    }
+    success = add_builtin_type_custom_data_layer_from_init(
+        *custom_data, stored_type_, domain_size, initializer);
+  }
   if (success) {
     custom_data_access_.update_custom_data_pointers(component);
   }
@@ -429,8 +469,10 @@ bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component)
   if (custom_data == nullptr) {
     return false;
   }
-  const void *data = CustomData_get_layer(custom_data, stored_type_);
-  return data != nullptr;
+  if (stored_as_named_attribute_) {
+    return CustomData_get_layer_named(custom_data, stored_type_, name_.c_str()) != nullptr;
+  }
+  return CustomData_get_layer(custom_data, stored_type_) != nullptr;
 }
 
 ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
@@ -1353,6 +1395,54 @@ bool AttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
   return false;
 }
 
+static StringRef get_random_id_attribute_name(const AttributeDomain domain)
+{
+  switch (domain) {
+    case ATTR_DOMAIN_POINT:
+      return "id";
+    default:
+      return "";
+  }
+}
+
+const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
+                                                             IndexMask mask,
+                                                             ResourceScope &scope) const
+{
+  if (const GeometryComponentFieldContext *geometry_context =
+          dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
+    const GeometryComponent &component = geometry_context->geometry_component();
+    const AttributeDomain domain = geometry_context->domain();
+    const StringRef name = get_random_id_attribute_name(domain);
+    GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
+    if (attribute) {
+      BLI_assert(attribute->size() == component.attribute_domain_size(domain));
+      return scope.add(std::move(attribute));
+    }
+
+    /* Use the index as the fallback if no random ID attribute exists. */
+    return fn::IndexFieldInput::get_index_varray(mask, scope);
+  }
+  return nullptr;
+}
+
+std::string IDAttributeFieldInput::socket_inspection_name() const
+{
+  return TIP_("ID / Index");
+}
+
+uint64_t IDAttributeFieldInput::hash() const
+{
+  /* All random ID attribute inputs are the same within the same evaluation context. */
+  return 92386459827;
+}
+
+bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
+{
+  /* All random ID attribute inputs are the same within the same evaluation context. */
+  return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
+}
+
 const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
     const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
 {
diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh
index 6e5cdd6faba..5cedcf69953 100644
--- a/source/blender/blenkernel/intern/attribute_access_intern.hh
+++ b/source/blender/blenkernel/intern/attribute_access_intern.hh
@@ -227,6 +227,9 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
  * This provider is used to provide access to builtin attributes. It supports making internal types
  * available as different types. For example, the vertex position attribute is stored as part of
  * the #MVert struct, but is exposed as float3 attribute.
+ *
+ * It also supports named builtin attributes, and will look up attributes in #CustomData by name
+ * if the stored type is the same as the attribute type.
  */
 class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
   using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
@@ -238,6 +241,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
   const AsReadAttribute as_read_attribute_;
   const AsWriteAttribute as_write_attribute_;
   const UpdateOnWrite update_on_write_;
+  bool stored_as_named_attribute_;
 
  public:
   BuiltinCustomDataLayerProvider(std::string attribute_name,
@@ -257,7 +261,8 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
         custom_data_access_(custom_data_access),
         as_read_attribute_(as_read_attribute),
         as_write_attribute_(as_write_attribute),
-        update_on_write_(update_on_write)
+        update_on_write_(update_on_write),
+        stored_as_named_attribute_(data_type_ == stored_type_)
   {
   }
 
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index 50c0f06b12c..c3d7eff4e6f 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -623,6 +623,103 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data,
   }
 }
 
+static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
+                                          const CustomDataType data_type,
+                                          const Span<SplinePtr> splines)
+{
+  switch (initializer.type) {
+    case AttributeInit::Type::Default:
+      /* This function shouldn't be called in this case, since there
+       * is no need to copy anything to the new custom data array. */
+      BLI_assert_unreachable();
+      return {};
+    case AttributeInit::Type::VArray:
+      return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
+    case AttributeInit::Type::MoveArray:
+      int total_size = 0;
+      for (const SplinePtr &spline : splines) {
+        total_size += spline->size();
+      }
+      return std::make_unique<fn::GVArray_For_GSpan>(
+          GSpan(*bke::custom_data_type_to_cpp_type(data_type),
+              

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list