diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 8a83ce58eb4..fceaddf82a3 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -321,25 +321,6 @@ void BKE_mesh_recalc_looptri(const int *corner_verts, */ const float (*BKE_mesh_vert_normals_ensure(const struct Mesh *mesh))[3]; -/** - * Retrieve write access to the cached vertex normals, ensuring that they are allocated but *not* - * that they are calculated. The provided vertex normals should be the same as if they were - * calculated automatically. - * - * \note In order to clear the dirty flag, this function should be followed by a call to - * #BKE_mesh_vert_normals_clear_dirty. This is separate so that normals are still tagged dirty - * while they are being assigned. - * - * \warning The memory returned by this function is not initialized if it was not previously - * allocated. - */ -float (*BKE_mesh_vert_normals_for_write(struct Mesh *mesh))[3]; - -/** - * Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually. - */ -void BKE_mesh_vert_normals_clear_dirty(struct Mesh *mesh); - /** * Return true if the mesh vertex normals either are not stored or are dirty. * This can be used to help decide whether to transfer them when copying a mesh. diff --git a/source/blender/blenkernel/BKE_mesh.hh b/source/blender/blenkernel/BKE_mesh.hh index d835d8e575f..384f6155a9a 100644 --- a/source/blender/blenkernel/BKE_mesh.hh +++ b/source/blender/blenkernel/BKE_mesh.hh @@ -277,6 +277,12 @@ inline int edge_other_vert(const int2 &edge, const int vert) void mesh_flip_faces(Mesh &mesh, const IndexMask &selection); +/** Set mesh vertex normals to known-correct values, avoiding future lazy computation. */ +void mesh_vert_normals_assign(Mesh &mesh, Span vert_normals); + +/** Set mesh vertex normals to known-correct values, avoiding future lazy computation. */ +void mesh_vert_normals_assign(Mesh &mesh, Vector vert_normals); + } // namespace blender::bke /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/mball_tessellate.cc b/source/blender/blenkernel/intern/mball_tessellate.cc index 0f8edf38a4a..8be457f3a6e 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.cc +++ b/source/blender/blenkernel/intern/mball_tessellate.cc @@ -1488,10 +1488,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) for (int i = 0; i < mesh->totvert; i++) { normalize_v3(process.no[i]); } - memcpy(BKE_mesh_vert_normals_for_write(mesh), - process.no.data(), - sizeof(float[3]) * size_t(mesh->totvert)); - BKE_mesh_vert_normals_clear_dirty(mesh); + blender::bke::mesh_vert_normals_assign(*mesh, std::move(process.no)); BKE_mesh_calc_edges(mesh, false, false); diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 2f243abfae6..0e6c2dd5dc7 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -89,18 +89,23 @@ static void add_v3_v3_atomic(float r[3], const float a[3]) * Related to managing normals but not directly related to calculating normals. * \{ */ -float (*BKE_mesh_vert_normals_for_write(Mesh *mesh))[3] +namespace blender::bke { + +void mesh_vert_normals_assign(Mesh &mesh, Span vert_normals) { - mesh->runtime->vert_normals.reinitialize(mesh->totvert); - return reinterpret_cast(mesh->runtime->vert_normals.data()); + mesh.runtime->vert_normals.clear(); + mesh.runtime->vert_normals.extend(vert_normals); + mesh.runtime->vert_normals_dirty = false; } -void BKE_mesh_vert_normals_clear_dirty(Mesh *mesh) +void mesh_vert_normals_assign(Mesh &mesh, Vector vert_normals) { - mesh->runtime->vert_normals_dirty = false; - BLI_assert(mesh->runtime->vert_normals.size() == mesh->totvert); + mesh.runtime->vert_normals = std::move(vert_normals); + mesh.runtime->vert_normals_dirty = false; } +} // namespace blender::bke + bool BKE_mesh_vert_normals_are_dirty(const Mesh *mesh) { return mesh->runtime->vert_normals_dirty; diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 2a04d473dbd..b651234b8f2 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -174,12 +174,12 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa BKE_mesh_tag_positions_changed(&mesh); if (normals) { - float(*vert_normals)[3] = BKE_mesh_vert_normals_for_write(&mesh); + Vector vert_normals(mesh.totvert); for (const int64_t i : IndexRange(normals->size())) { Imath::V3f nor_in = (*normals)[i]; copy_zup_from_yup(vert_normals[i], nor_in.getValue()); } - BKE_mesh_vert_normals_clear_dirty(&mesh); + bke::mesh_vert_normals_assign(mesh, std::move(vert_normals)); } } diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 71343eab24a..20012fffe44 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -656,10 +656,9 @@ void USDMeshReader::process_normals_vertex_varying(Mesh *mesh) return; } - MutableSpan vert_normals{(float3 *)BKE_mesh_vert_normals_for_write(mesh), mesh->totvert}; BLI_STATIC_ASSERT(sizeof(normals_[0]) == sizeof(float3), "Expected float3 normals size"); - vert_normals.copy_from({(float3 *)normals_.data(), int64_t(normals_.size())}); - BKE_mesh_vert_normals_clear_dirty(mesh); + bke::mesh_vert_normals_assign( + *mesh, Span(reinterpret_cast(normals_.data()), int64_t(normals_.size()))); } void USDMeshReader::process_normals_face_varying(Mesh *mesh) diff --git a/source/blender/modifiers/intern/MOD_array.cc b/source/blender/modifiers/intern/MOD_array.cc index 9f3bcab82af..daa15880d55 100644 --- a/source/blender/modifiers/intern/MOD_array.cc +++ b/source/blender/modifiers/intern/MOD_array.cc @@ -282,7 +282,7 @@ static void mesh_merge_transform(Mesh *result, int cap_nfaces, int *remap, int remap_len, - const bool recalc_normals_later) + MutableSpan dst_vert_normals) { using namespace blender; int *index_orig; @@ -305,8 +305,7 @@ static void mesh_merge_transform(Mesh *result, } /* We have to correct normals too, if we do not tag them as dirty later! */ - if (!recalc_normals_later) { - float(*dst_vert_normals)[3] = BKE_mesh_vert_normals_for_write(result); + if (!dst_vert_normals.is_empty()) { for (i = 0; i < cap_nverts; i++) { mul_mat3_m4_v3(cap_offset, dst_vert_normals[cap_verts_index + i]); normalize_v3(dst_vert_normals[cap_verts_index + i]); @@ -583,11 +582,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, unit_m4(current_offset); blender::Span src_vert_normals; - float(*dst_vert_normals)[3] = nullptr; + Vector dst_vert_normals; if (!use_recalc_normals) { src_vert_normals = mesh->vert_normals(); - dst_vert_normals = BKE_mesh_vert_normals_for_write(result); - BKE_mesh_vert_normals_clear_dirty(result); + dst_vert_normals.reinitialize(result->totvert); } for (c = 1; c < count; c++) { @@ -608,7 +606,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, mul_m4_v3(current_offset, result_positions[i_dst]); /* We have to correct normals too, if we do not tag them as dirty! */ - if (!use_recalc_normals) { + if (!dst_vert_normals.is_empty()) { copy_v3_v3(dst_vert_normals[i_dst], src_vert_normals[i]); mul_mat3_m4_v3(current_offset, dst_vert_normals[i_dst]); normalize_v3(dst_vert_normals[i_dst]); @@ -758,7 +756,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, start_cap_nfaces, vgroup_start_cap_remap, vgroup_start_cap_remap_len, - use_recalc_normals); + dst_vert_normals); /* Identify doubles with first chunk */ if (use_merge) { dm_mvert_map_doubles(full_doubles_map, @@ -788,7 +786,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, end_cap_nfaces, vgroup_end_cap_remap, vgroup_end_cap_remap_len, - use_recalc_normals); + dst_vert_normals); /* Identify doubles with last chunk */ if (use_merge) { dm_mvert_map_doubles(full_doubles_map, @@ -802,6 +800,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } /* done capping */ + blender::bke::mesh_vert_normals_assign(*result, std::move(dst_vert_normals)); + /* Handle merging */ tot_doubles = 0; if (use_merge) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index be80c10756e..7705061cc7d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -318,10 +318,9 @@ static Mesh *create_uv_sphere_mesh(const float radius, threading::parallel_invoke( 1024 < segments * rings, [&]() { - MutableSpan vert_normals{reinterpret_cast(BKE_mesh_vert_normals_for_write(mesh)), - mesh->totvert}; + Vector vert_normals(mesh->totvert); calculate_sphere_vertex_data(positions, vert_normals, radius, segments, rings); - BKE_mesh_vert_normals_clear_dirty(mesh); + bke::mesh_vert_normals_assign(*mesh, std::move(vert_normals)); }, [&]() { calculate_sphere_edge_indices(edges, segments, rings); }, [&]() { calculate_sphere_faces(face_offsets, segments); },