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));

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to