[Bf-blender-cvs] [ba3a0dc9ba9] master: Geometry Nodes: Add "normal" attribute for face normals

Hans Goudey noreply at git.blender.org
Sat Mar 13 20:13:36 CET 2021


Commit: ba3a0dc9ba91e2f55e3632a69f8671079d871a94
Author: Hans Goudey
Date:   Sat Mar 13 14:13:16 2021 -0500
Branches: master
https://developer.blender.org/rBba3a0dc9ba91e2f55e3632a69f8671079d871a94

Geometry Nodes: Add "normal" attribute for face normals

This commit adds a `normal` attribute on the polygon domain. Since
normal data is derived data purely based off of the location of each
face's vertices, it is exposed as a read-only attribute. After
rB80f7f1070f17, this attribute can be interpolated to the other domains.

Since this attribute is a special case compared to the others, the
implementation subclasses `BuiltinAttributeProvider`. It's possible
there is a better way to abstract this. Something else might also
become apparent if we add similar read-only attributes.

See rB2966871a7a891bf36 for why this is preferred over the previous
implementation.

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

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

M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/blenkernel/intern/geometry_set_instances.cc
M	source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc

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

diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index b25f5286cab..c6e32c3e8bd 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -766,6 +766,65 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
   }
 };
 
+/**
+ * This provider makes face normals available as a read-only float3 attribute.
+ */
+class NormalAttributeProvider final : public BuiltinAttributeProvider {
+ public:
+  NormalAttributeProvider()
+      : BuiltinAttributeProvider(
+            "normal", ATTR_DOMAIN_POLYGON, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable)
+  {
+  }
+
+  ReadAttributePtr try_get_for_read(const GeometryComponent &component) const
+  {
+    const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
+    const Mesh *mesh = mesh_component.get_for_read();
+    if (mesh == nullptr) {
+      return {};
+    }
+
+    /* Use existing normals if possible. */
+    if (!(mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
+        CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
+      const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
+
+      return std::make_unique<ArrayReadAttribute<float3>>(
+          ATTR_DOMAIN_POLYGON, Span<float3>((const float3 *)data, mesh->totpoly));
+    }
+
+    Array<float3> normals(mesh->totpoly);
+    for (const int i : IndexRange(mesh->totpoly)) {
+      const MPoly *poly = &mesh->mpoly[i];
+      BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
+    }
+
+    return std::make_unique<OwnedArrayReadAttribute<float3>>(ATTR_DOMAIN_POLYGON,
+                                                             std::move(normals));
+  }
+
+  WriteAttributePtr try_get_for_write(GeometryComponent &UNUSED(component)) const
+  {
+    return {};
+  }
+
+  bool try_delete(GeometryComponent &UNUSED(component)) const
+  {
+    return false;
+  }
+
+  bool try_create(GeometryComponent &UNUSED(component)) const
+  {
+    return false;
+  }
+
+  bool exists(const GeometryComponent &component) const
+  {
+    return component.attribute_domain_size(ATTR_DOMAIN_POLYGON) != 0;
+  }
+};
+
 /**
  * In this function all the attribute providers for a mesh component are created. Most data in this
  * function is statically allocated, because it does not change over time.
@@ -818,6 +877,8 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
                                                  make_vertex_position_write_attribute,
                                                  tag_normals_dirty_when_writing_position);
 
+  static NormalAttributeProvider normal;
+
   static BuiltinCustomDataLayerProvider material_index("material_index",
                                                        ATTR_DOMAIN_POLYGON,
                                                        CD_PROP_INT32,
@@ -862,7 +923,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
   static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access);
   static CustomDataAttributeProvider polygon_custom_data(ATTR_DOMAIN_POLYGON, polygon_access);
 
-  return ComponentAttributeProviders({&position, &material_index, &shade_smooth},
+  return ComponentAttributeProviders({&position, &material_index, &shade_smooth, &normal},
                                      {&uvs,
                                       &vertex_colors,
                                       &corner_custom_data,
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 70b48a253ed..fc9d793c119 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -381,7 +381,7 @@ static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups,
   gather_attribute_info(attributes,
                         component_types,
                         set_groups,
-                        {"position", "material_index", "vertex_normal", "shade_smooth"});
+                        {"position", "material_index", "normal", "shade_smooth"});
   join_attributes(
       set_groups, component_types, attributes, static_cast<GeometryComponent &>(dst_component));
 }
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index 45aaf81d63f..54b0c07a0a0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -224,7 +224,7 @@ static void join_components(Span<const MeshComponent *> src_components, Geometry
   /* Don't copy attributes that are stored directly in the mesh data structs. */
   join_attributes(to_base_components(src_components),
                   dst_component,
-                  {"position", "material_index", "vertex_normal", "shade_smooth"});
+                  {"position", "material_index", "normal", "shade_smooth"});
 }
 
 static void join_components(Span<const PointCloudComponent *> src_components, GeometrySet &result)



More information about the Bf-blender-cvs mailing list