Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-07-08 01:09:47 +0300
committerHans Goudey <h.goudey@me.com>2022-07-08 01:09:47 +0300
commite142387b2fb3ec1f6a01b043dbc421abef2e5584 (patch)
tree495ff426afbfe4fce5567e8d26fa77063ee4423f
parent349682e5bf97112581de8e116210f94adeaa5dc1 (diff)
Threadsafe access to face corner normals
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/intern/mesh.cc35
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc23
3 files changed, 33 insertions, 28 deletions
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;