[Bf-blender-cvs] [0a21a554d5b] master: Fix T103304: Incorrect handling of edge crease in subdivision node

Hans Goudey noreply at git.blender.org
Fri Jan 13 22:34:40 CET 2023


Commit: 0a21a554d5b81791dd7c619610d1855aa23fbf55
Author: Hans Goudey
Date:   Fri Jan 13 15:34:01 2023 -0600
Branches: master
https://developer.blender.org/rB0a21a554d5b81791dd7c619610d1855aa23fbf55

Fix T103304: Incorrect handling of edge crease in subdivision node

The crease custom data layer was added to a mutable version of the mesh,
but that wasn't used in the rest of the operation. Also the layer wasn't
retrieved properly with write access from the custom data API (fixed
separately as part of D14140). Also clean up a bit by retrieving
attributes from the mesh directly and by tweaking naming a bit.

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

M	source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
index 40b49055949..b6e0eeea3ff 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
@@ -69,7 +69,8 @@ static void write_vertex_creases(Mesh &mesh, const VArray<float> &crease_varray)
 {
   float *crease;
   if (CustomData_has_layer(&mesh.vdata, CD_CREASE)) {
-    crease = static_cast<float *>(CustomData_get_layer(&mesh.vdata, CD_CREASE));
+    crease = static_cast<float *>(
+        CustomData_duplicate_referenced_layer(&mesh.vdata, CD_CREASE, mesh.totvert));
   }
   else {
     crease = static_cast<float *>(
@@ -78,11 +79,11 @@ static void write_vertex_creases(Mesh &mesh, const VArray<float> &crease_varray)
   materialize_and_clamp_creases(crease_varray, {crease, mesh.totvert});
 }
 
-static void write_edge_creases(MeshComponent &mesh, const VArray<float> &crease_varray)
+static void write_edge_creases(Mesh &mesh, const VArray<float> &crease_varray)
 {
   bke::SpanAttributeWriter<float> attribute =
-      mesh.attributes_for_write()->lookup_or_add_for_write_only_span<float>("crease",
-                                                                            ATTR_DOMAIN_EDGE);
+      mesh.attributes_for_write().lookup_or_add_for_write_only_span<float>("crease",
+                                                                           ATTR_DOMAIN_EDGE);
   materialize_and_clamp_creases(crease_varray, attribute.span);
   attribute.finish();
 }
@@ -115,23 +116,22 @@ static void node_geo_exec(GeoNodeExecParams params)
   }
 
   geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
-    if (!geometry_set.has_mesh()) {
+    const Mesh *mesh = geometry_set.get_mesh_for_read();
+    if (!mesh) {
       return;
     }
-
-    const Mesh &mesh = *geometry_set.get_mesh_for_read();
-    if (mesh.totvert == 0 || mesh.totedge == 0) {
+    if (mesh->totvert == 0 || mesh->totedge == 0) {
       return;
     }
 
-    bke::MeshFieldContext point_context{mesh, ATTR_DOMAIN_POINT};
-    FieldEvaluator point_evaluator(point_context, mesh.totvert);
+    bke::MeshFieldContext point_context{*mesh, ATTR_DOMAIN_POINT};
+    FieldEvaluator point_evaluator(point_context, mesh->totvert);
     point_evaluator.add(vertex_crease_field);
     point_evaluator.evaluate();
     const VArray<float> vertex_creases = point_evaluator.get_evaluated<float>(0);
 
-    bke::MeshFieldContext edge_context{mesh, ATTR_DOMAIN_EDGE};
-    FieldEvaluator edge_evaluator(edge_context, mesh.totedge);
+    bke::MeshFieldContext edge_context{*mesh, ATTR_DOMAIN_EDGE};
+    FieldEvaluator edge_evaluator(edge_context, mesh->totedge);
     edge_evaluator.add(edge_crease_field);
     edge_evaluator.evaluate();
     const VArray<float> edge_creases = edge_evaluator.get_evaluated<float>(0);
@@ -139,8 +139,13 @@ static void node_geo_exec(GeoNodeExecParams params)
     const bool use_creases = varray_is_nonzero(vertex_creases) || varray_is_nonzero(edge_creases);
 
     if (use_creases) {
-      write_vertex_creases(*geometry_set.get_mesh_for_write(), vertex_creases);
-      write_edge_creases(geometry_set.get_component_for_write<MeshComponent>(), edge_creases);
+      /* Due to the "BKE_subdiv" API, the crease layers must be on the input mesh. But in this node
+       * they are provided as separate inputs, not as custom data layers. When needed, retrieve the
+       * mesh with write access and store the new crease values there. */
+      Mesh &mesh_for_write = *geometry_set.get_mesh_for_write();
+      write_vertex_creases(mesh_for_write, vertex_creases);
+      write_edge_creases(mesh_for_write, edge_creases);
+      mesh = &mesh_for_write;
     }
 
     /* Initialize mesh settings. */
@@ -161,25 +166,23 @@ static void node_geo_exec(GeoNodeExecParams params)
         uv_smooth);
 
     /* Apply subdivision to mesh. */
-    Subdiv *subdiv = BKE_subdiv_update_from_mesh(nullptr, &subdiv_settings, &mesh);
+    Subdiv *subdiv = BKE_subdiv_update_from_mesh(nullptr, &subdiv_settings, mesh);
 
     /* In case of bad topology, skip to input mesh. */
     if (subdiv == nullptr) {
       return;
     }
 
-    Mesh *mesh_out = BKE_subdiv_to_mesh(subdiv, &mesh_settings, &mesh);
-
+    Mesh *result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
+    BKE_subdiv_free(subdiv);
     if (use_creases) {
       /* Remove the layer in case it was created by the node from the field input. The fact
        * that this node uses #CD_CREASE to input creases to the subdivision code is meant to be
        * an implementation detail ideally. */
-      CustomData_free_layers(&mesh_out->edata, CD_CREASE, mesh_out->totedge);
+      CustomData_free_layers(&result->edata, CD_CREASE, result->totedge);
     }
 
-    geometry_set.replace_mesh(mesh_out);
-
-    BKE_subdiv_free(subdiv);
+    geometry_set.replace_mesh(result);
   });
 #endif
   params.set_output("Mesh", std::move(geometry_set));



More information about the Bf-blender-cvs mailing list