[Bf-blender-cvs] [e142387b2fb] temp-deform-curves-on-surface: Threadsafe access to face corner normals

Hans Goudey noreply at git.blender.org
Fri Jul 8 00:09:49 CEST 2022


Commit: e142387b2fb3ec1f6a01b043dbc421abef2e5584
Author: Hans Goudey
Date:   Thu Jul 7 17:09:47 2022 -0500
Branches: temp-deform-curves-on-surface
https://developer.blender.org/rBe142387b2fb3ec1f6a01b043dbc421abef2e5584

Threadsafe access to face corner normals

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

M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/intern/mesh.cc
M	source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc

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

diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 66e0ff8e81a..847fb05fb92 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -710,7 +710,8 @@ void BKE_mesh_calc_normals_split(struct Mesh *mesh);
  * to split geometry along sharp edges.
  */
 void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
-                                    struct MLoopNorSpaceArray *r_lnors_spacearr);
+                                    struct MLoopNorSpaceArray *r_lnors_spacearr,
+                                    float (*r_corner_normals)[3]);
 
 /**
  * Higher level functions hiding most of the code needed around call to
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index ffbd824712a..9d02ae2d0fa 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -1922,9 +1922,25 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
   BKE_mesh_tag_coords_changed(mesh);
 }
 
-void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
+static float (*ensure_corner_normal_layer(Mesh &mesh))[3]
 {
   float(*r_loopnors)[3];
+  if (CustomData_has_layer(&mesh.ldata, CD_NORMAL)) {
+    r_loopnors = (float(*)[3])CustomData_get_layer(&mesh.ldata, CD_NORMAL);
+    memset(r_loopnors, 0, sizeof(float[3]) * mesh.totloop);
+  }
+  else {
+    r_loopnors = (float(*)[3])CustomData_add_layer(
+        &mesh.ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh.totloop);
+    CustomData_set_layer_flag(&mesh.ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
+  }
+  return r_loopnors;
+}
+
+void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
+                                    MLoopNorSpaceArray *r_lnors_spacearr,
+                                    float (*r_corner_normals)[3])
+{
   short(*clnors)[2] = nullptr;
 
   /* Note that we enforce computing clnors when the clnor space array is requested by caller here.
@@ -1934,16 +1950,6 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
                                  ((mesh->flag & ME_AUTOSMOOTH) != 0);
   const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : (float)M_PI;
 
-  if (CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
-    r_loopnors = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
-    memset(r_loopnors, 0, sizeof(float[3]) * mesh->totloop);
-  }
-  else {
-    r_loopnors = (float(*)[3])CustomData_add_layer(
-        &mesh->ldata, CD_NORMAL, CD_CALLOC, nullptr, mesh->totloop);
-    CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
-  }
-
   /* may be nullptr */
   clnors = (short(*)[2])CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
 
@@ -1953,7 +1959,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
                               mesh->medge,
                               mesh->totedge,
                               mesh->mloop,
-                              r_loopnors,
+                              r_corner_normals,
                               mesh->totloop,
                               mesh->mpoly,
                               BKE_mesh_poly_normals_ensure(mesh),
@@ -1969,7 +1975,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
 
 void BKE_mesh_calc_normals_split(Mesh *mesh)
 {
-  BKE_mesh_calc_normals_split_ex(mesh, nullptr);
+  BKE_mesh_calc_normals_split_ex(mesh, nullptr, ensure_corner_normal_layer(*mesh));
 }
 
 /* Split faces helper functions. */
@@ -2188,7 +2194,8 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
 
   MLoopNorSpaceArray lnors_spacearr = {nullptr};
   /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
-  BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr);
+
+  BKE_mesh_calc_normals_split_ex(mesh, &lnors_spacearr, ensure_corner_normal_layer(*mesh));
   /* Stealing memarena from loop normals space array. */
   MemArena *memarena = lnors_spacearr.mem;
 
diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc
index 00866bca48f..7557023aef7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc
@@ -266,19 +266,16 @@ static void node_geo_exec(GeoNodeExecParams params)
   const ReverseUVSampler reverse_uv_sampler_orig{uv_map_orig, looptris_orig};
   const ReverseUVSampler reverse_uv_sampler_eval{uv_map_eval, looptris_eval};
 
-  /* TODO: Figure out how to get this data in a thread-safe way. */
-  if (!CustomData_has_layer(&surface_mesh_orig.ldata, CD_NORMAL)) {
-    BKE_mesh_calc_normals_split(&surface_mesh_orig);
-  }
-  if (!CustomData_has_layer(&surface_mesh_eval->ldata, CD_NORMAL)) {
-    BKE_mesh_calc_normals_split(surface_mesh_eval);
-  }
-  const Span<float3> corner_normals_orig = {
-      reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_mesh_orig.ldata, CD_NORMAL)),
-      surface_mesh_orig.totloop};
-  const Span<float3> corner_normals_eval = {
-      reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_mesh_eval->ldata, CD_NORMAL)),
-      surface_mesh_eval->totloop};
+  /* Retrieve face corner normals from each mesh. It's necessary to use face corner normals
+   * because face normals or vertex normals may lose information (custom normals, auto smooth) in
+   * some cases. It isn't yet possible to retrieve lazily calculated face corner normals from a
+   * const mesh, so they are calculated here every time. */
+  Array<float3> corner_normals_orig(surface_mesh_orig.totloop);
+  Array<float3> corner_normals_eval(surface_mesh_eval->totloop);
+  BKE_mesh_calc_normals_split_ex(
+      &surface_mesh_orig, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_orig.data()));
+  BKE_mesh_calc_normals_split_ex(
+      surface_mesh_eval, nullptr, reinterpret_cast<float(*)[3]>(corner_normals_eval.data()));
 
   std::atomic<int> invalid_uv_count = 0;



More information about the Bf-blender-cvs mailing list