diff options
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.cc | 35 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc | 23 |
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; |