[Bf-blender-cvs] [e13e629f98f] temp-vert-normals-cleanup: Fix crash restoring undo step mesh to edit mesh
Hans Goudey
noreply at git.blender.org
Wed Jan 5 18:11:27 CET 2022
Commit: e13e629f98f5dad32c33ffd571bafda71fd36388
Author: Hans Goudey
Date: Wed Jan 5 11:11:18 2022 -0600
Branches: temp-vert-normals-cleanup
https://developer.blender.org/rBe13e629f98f5dad32c33ffd571bafda71fd36388
Fix crash restoring undo step mesh to edit mesh
===================================================================
M source/blender/blenkernel/BKE_mesh.h
M source/blender/blenkernel/intern/mesh_normals.cc
M source/blender/bmesh/intern/bmesh_mesh_convert.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 199beb3eef2..68d04778efa 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -373,6 +373,20 @@ void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
/* *** mesh_normals.cc *** */
+/**
+ * Returns the normals for each vertex, which is defined as the weighted average of the normals
+ * from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
+ * \warning May still return null if the mesh is empty.
+ */
+const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
+
+/**
+ * Return the normal direction of every polygon, which is defined by the winding direction of its
+ * corners.
+ * \warning May still return null if the mesh is empty or has no polygons.
+ */
+const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
+
/**
* Tag mesh vertex and face normals to be recalculated when/if they are needed later.
*
@@ -416,6 +430,18 @@ void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh);
*/
void BKE_mesh_poly_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.
+ */
+bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh);
+
+/**
+ * Return true if the mesh polygon normals either are not stored or are dirty.
+ * This can be used to help decide whether to transfer them when copying a mesh.
+ */
+bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
+
/**
* Calculate face normals directly into a result array.
*
@@ -439,20 +465,6 @@ void BKE_mesh_calc_normals_poly(const struct MVert *mvert,
*/
void BKE_mesh_calc_normals(struct Mesh *me);
-/**
- * Returns the normals for each vertex, which is defined as the weighted average of the normals
- * from a vertices surrounding faces, or the normalized position of vertices connected to no faces.
- * \warning May still return null if the mesh is empty.
- */
-const float (*BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3];
-
-/**
- * Return the normal direction of every polygon, which is defined by the winding direction of its
- * corners.
- * \warning May still return null if the mesh is empty or has no polygons.
- */
-const float (*BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3];
-
/**
* Called after calculating all modifiers.
*/
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index ffe6db6a2ee..16241b0f0dd 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -146,6 +146,16 @@ void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
+bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
+{
+ return mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL;
+}
+
+bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
+{
+ return mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL;
+}
+
void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
{
if (!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.c b/source/blender/bmesh/intern/bmesh_mesh_convert.c
index 9d0933b0aa5..d99fefbcd02 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.c
@@ -192,7 +192,6 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
int totloops, i;
CustomData_MeshMasks mask = CD_MASK_BMESH;
CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra);
- const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
if (!me || !me->totvert) {
if (me && is_new) { /* No verts? still copy custom-data layout. */
@@ -209,6 +208,14 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
return; /* Sanity check. */
}
+ /* Only copy normals to the new BMesh if they are not already dirty. This avoids unnecessary
+ * work, but also accessing normals on an incomplete mesh, for example when restoring undo steps
+ * in edit mode. */
+ const float(*vert_normals)[3] = NULL;
+ if (!BKE_mesh_vertex_normals_are_dirty(me)) {
+ vert_normals = BKE_mesh_vertex_normals_ensure(me);
+ }
+
if (is_new) {
CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
@@ -335,7 +342,9 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
BM_vert_select_set(bm, v, true);
}
- copy_v3_v3(v->no, vert_normals[i]);
+ if (vert_normals) {
+ copy_v3_v3(v->no, vert_normals[i]);
+ }
/* Copy Custom Data */
CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
@@ -640,6 +649,8 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+ /* There is no way to tell if BMesh normals are dirty or not. Instead of calculating the normals
+ * on the BMesh possibly unnecessarily, just tag them dirty on the resulting mesh. */
BKE_mesh_normals_tag_dirty(me);
me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
More information about the Bf-blender-cvs
mailing list