[Bf-blender-cvs] [34eaf62536f] temp-geometry-nodes-normal-attribute: Geometry Nodes: Support the "normal" attribute

Hans Goudey noreply at git.blender.org
Fri Jan 22 01:07:30 CET 2021


Commit: 34eaf62536ff5de318cc4e10f30c457c196f4655
Author: Hans Goudey
Date:   Thu Jan 21 18:07:23 2021 -0600
Branches: temp-geometry-nodes-normal-attribute
https://developer.blender.org/rB34eaf62536ff5de318cc4e10f30c457c196f4655

Geometry Nodes: Support the "normal" attribute

The `normal` attribute is a bit special for a few reasons:
 - It has the special CD_NORMAL custom data type even though
   it is just a float3.
 - It is sometimes stored in the `MVert` array as a vector of
   shorts instead of in a separate custom data layer.
 - The custom data layer does not have a default name, so we
   can't count on addressing it by name.
 - It can exist on multiple domains, meaning that polys, vertices,
   and corners can all have the "normal" attribute.

All of these combined raise a lot of questions about how to properly
support reading and writing from this attribute. The whole idea that
it should be valid to address an attribute with the same name on
multiple domains is challenging for the attribute code.

This branch currently supports reading normals stored in the `MVert`
layer and in `CD_NORMAL` layers. I'm not at all sure that this is the
ideal way of dealing with this situation, but it's a start.

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

M	source/blender/blenkernel/intern/attribute_access.cc

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

diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 21ab7f61447..499ae366c29 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -498,44 +498,128 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
 /** \name Utilities for Accessing Attributes
  * \{ */
 
+static CustomDataType attribute_name_to_custom_data_type_extra(const StringRef attribute_name,
+                                                               bool &use_data_type_layer)
+{
+  if (attribute_name == "normal") {
+    use_data_type_layer = true;
+    return CD_NORMAL;
+  }
+  use_data_type_layer = false;
+  return CD_PROP_BOOL;
+}
+
+static ReadAttributePtr read_attribute_from_custom_data_layer(const CustomDataLayer &layer,
+                                                              const AttributeDomain domain,
+                                                              const int size)
+{
+  using namespace blender;
+  using namespace blender::bke;
+  switch (layer.type) {
+    case CD_PROP_FLOAT:
+      return std::make_unique<ArrayReadAttribute<float>>(
+          domain, Span(static_cast<float *>(layer.data), size));
+    case CD_PROP_FLOAT2:
+      return std::make_unique<ArrayReadAttribute<float2>>(
+          domain, Span(static_cast<float2 *>(layer.data), size));
+    case CD_NORMAL:
+    case CD_PROP_FLOAT3:
+      return std::make_unique<ArrayReadAttribute<float3>>(
+          domain, Span(static_cast<float3 *>(layer.data), size));
+    case CD_PROP_INT32:
+      return std::make_unique<ArrayReadAttribute<int>>(domain,
+                                                       Span(static_cast<int *>(layer.data), size));
+    case CD_PROP_COLOR:
+      return std::make_unique<ArrayReadAttribute<Color4f>>(
+          domain, Span(static_cast<Color4f *>(layer.data), size));
+    case CD_PROP_BOOL:
+      return std::make_unique<ArrayReadAttribute<bool>>(
+          domain, Span(static_cast<bool *>(layer.data), size));
+    case CD_MLOOPUV:
+      auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
+      return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, decltype(get_uv)>>(
+          domain, Span(static_cast<MLoopUV *>(layer.data), size), get_uv);
+  }
+  return {};
+}
+
 static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom_data,
                                                         const int size,
                                                         const StringRef attribute_name,
                                                         const AttributeDomain domain)
 {
-  using namespace blender;
-  using namespace blender::bke;
-  for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) {
-    if (layer.name != nullptr && layer.name == attribute_name) {
-      switch (layer.type) {
-        case CD_PROP_FLOAT:
-          return std::make_unique<ArrayReadAttribute<float>>(
-              domain, Span(static_cast<float *>(layer.data), size));
-        case CD_PROP_FLOAT2:
-          return std::make_unique<ArrayReadAttribute<float2>>(
-              domain, Span(static_cast<float2 *>(layer.data), size));
-        case CD_PROP_FLOAT3:
-          return std::make_unique<ArrayReadAttribute<float3>>(
-              domain, Span(static_cast<float3 *>(layer.data), size));
-        case CD_PROP_INT32:
-          return std::make_unique<ArrayReadAttribute<int>>(
-              domain, Span(static_cast<int *>(layer.data), size));
-        case CD_PROP_COLOR:
-          return std::make_unique<ArrayReadAttribute<Color4f>>(
-              domain, Span(static_cast<Color4f *>(layer.data), size));
-        case CD_PROP_BOOL:
-          return std::make_unique<ArrayReadAttribute<bool>>(
-              domain, Span(static_cast<bool *>(layer.data), size));
-        case CD_MLOOPUV:
-          auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
-          return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, decltype(get_uv)>>(
-              domain, Span(static_cast<MLoopUV *>(layer.data), size), get_uv);
+  bool use_data_type_layer;
+  CustomDataType special_type = attribute_name_to_custom_data_type_extra(attribute_name,
+                                                                         use_data_type_layer);
+  if (use_data_type_layer) {
+    const int layer_index = CustomData_get_active_layer_index(&custom_data, special_type);
+    if (layer_index != -1) {
+      const CustomDataLayer &layer = custom_data.layers[layer_index];
+      return read_attribute_from_custom_data_layer(layer, domain, size);
+    }
+  }
+  else {
+    for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) {
+      if (layer.name != nullptr && layer.name == attribute_name) {
+        return read_attribute_from_custom_data_layer(layer, domain, size);
       }
     }
   }
   return {};
 }
 
+static WriteAttributePtr write_attribute_from_custom_data_layer(const CustomDataLayer &layer,
+                                                                const AttributeDomain domain,
+                                                                const int size)
+{
+  using namespace blender;
+  using namespace blender::bke;
+  switch (layer.type) {
+    case CD_PROP_FLOAT:
+      return std::make_unique<ArrayWriteAttribute<float>>(
+          domain, MutableSpan(static_cast<float *>(layer.data), size));
+    case CD_PROP_FLOAT2:
+      return std::make_unique<ArrayWriteAttribute<float2>>(
+          domain, MutableSpan(static_cast<float2 *>(layer.data), size));
+    case CD_PROP_FLOAT3:
+      return std::make_unique<ArrayWriteAttribute<float3>>(
+          domain, MutableSpan(static_cast<float3 *>(layer.data), size));
+    case CD_PROP_INT32:
+      return std::make_unique<ArrayWriteAttribute<int>>(
+          domain, MutableSpan(static_cast<int *>(layer.data), size));
+    case CD_PROP_COLOR:
+      return std::make_unique<ArrayWriteAttribute<Color4f>>(
+          domain, MutableSpan(static_cast<Color4f *>(layer.data), size));
+    case CD_PROP_BOOL:
+      return std::make_unique<ArrayWriteAttribute<bool>>(
+          domain, MutableSpan(static_cast<bool *>(layer.data), size));
+    case CD_MLOOPUV:
+      auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
+      auto set_uv = [](MLoopUV &uv, const float2 value) { copy_v2_v2(uv.uv, value); };
+      return std::make_unique<
+          DerivedArrayWriteAttribute<MLoopUV, float2, decltype(get_uv), decltype(set_uv)>>(
+          domain, MutableSpan(static_cast<MLoopUV *>(layer.data), size), get_uv, set_uv);
+  }
+  return {};
+}
+
+/**
+ * The data layer might be shared with someone else.
+ * Since the caller wants to modify it, we copy it first.
+ */
+static void custom_data_layer_ensure_writable(
+    CustomData &custom_data,
+    const int size,
+    const CustomDataLayer &layer,
+    const std::function<void()> &update_customdata_pointers)
+{
+  const void *data_before = layer.data;
+  CustomData_duplicate_referenced_layer_named(&custom_data, layer.type, layer.name, size);
+  if (data_before != layer.data) {
+    update_customdata_pointers();
+  }
+}
+
 static WriteAttributePtr write_attribute_from_custom_data(
     CustomData &custom_data,
     const int size,
@@ -543,44 +627,22 @@ static WriteAttributePtr write_attribute_from_custom_data(
     const AttributeDomain domain,
     const std::function<void()> &update_customdata_pointers)
 {
+  bool use_data_type_layer;
+  CustomDataType special_type = attribute_name_to_custom_data_type_extra(attribute_name,
+                                                                         use_data_type_layer);
+  if (use_data_type_layer) {
+    const int layer_index = CustomData_get_active_layer_index(&custom_data, special_type);
+    if (layer_index != -1) {
+      const CustomDataLayer &layer = custom_data.layers[layer_index];
+      custom_data_layer_ensure_writable(custom_data, size, layer, update_customdata_pointers);
+      return write_attribute_from_custom_data_layer(layer, domain, size);
+    }
+  }
 
-  using namespace blender;
-  using namespace blender::bke;
-  for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) {
+  for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) {
     if (layer.name != nullptr && layer.name == attribute_name) {
-      const void *data_before = layer.data;
-      /* The data layer might be shared with someone else. Since the caller wants to modify it, we
-       * copy it first. */
-      CustomData_duplicate_referenced_layer_named(&custom_data, layer.type, layer.name, size);
-      if (data_before != layer.data) {
-        update_customdata_pointers();
-      }
-      switch (layer.type) {
-        case CD_PROP_FLOAT:
-          return std::make_unique<ArrayWriteAttribute<float>>(
-              domain, MutableSpan(static_cast<float *>(layer.data), size));
-        case CD_PROP_FLOAT2:
-          return std::make_unique<ArrayWriteAttribute<float2>>(
-              domain, MutableSpan(static_cast<float2 *>(layer.data), size));
-        case CD_PROP_FLOAT3:
-          return std::make_unique<ArrayWriteAttribute<float3>>(
-              domain, MutableSpan(static_cast<float3 *>(layer.data), size));
-        case CD_PROP_INT32:
-          return std::make_unique<ArrayWriteAttribute<int>>(
-              domain, MutableSpan(static_cast<int *>(layer.data), size));
-        case CD_PROP_COLOR:
-          return std::make_unique<ArrayWriteAttribute<Color4f>>(
-              domain, MutableSpan(static_cast<Color4f *>(layer.data), size));
-        case CD_PROP_BOOL:
-          return std::make_unique<ArrayWriteAttribute<bool>>(
-              domain, MutableSpan(static_cast<bool *>(layer.data), size));
-        case CD_MLOOPUV:
-          auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
-          auto set_uv = [](MLoopUV &uv, const float2 value) { copy_v2_v2(uv.uv, value); };
-          return std::make_unique<
-              DerivedArrayWriteAttribute<MLoopUV, float2,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list