[Bf-blender-cvs] [5767dcbe60c] master: Fix T65809: Blender crash while using the Normal's "merge" option in edit mode.

Bastien Montagne noreply at git.blender.org
Sun Jun 16 18:10:15 CEST 2019


Commit: 5767dcbe60c07cd9ef113e2f54eaad6981a47bce
Author: Bastien Montagne
Date:   Sun Jun 16 18:04:57 2019 +0200
Branches: master
https://developer.blender.org/rB5767dcbe60c07cd9ef113e2f54eaad6981a47bce

Fix T65809: Blender crash while using the Normal's "merge" option in edit mode.

Merge code will generate temp normal editing data for affected loops,
but since it will later (by setting some edges/faces to smooth) alter
and extend affected clnor spaces, it will also need temp normal editing
data for some other loops around those vertices...

Using those clnor editing data in that code is a bit of an abuse, but on
the other hand that struct stores exactly what we need.

So simply added an option to generate that editing data for all clnors
of affected vertices.

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

M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/bmesh/intern/bmesh_mesh.h
M	source/blender/editors/mesh/editmesh_tools.c
M	source/blender/editors/transform/transform.c

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

diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index dc42d86d800..09a39c05565 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -1395,32 +1395,49 @@ void BM_lnorspace_err(BMesh *bm)
 static void bm_loop_normal_mark_indiv_do_loop(BMLoop *l,
                                               BLI_bitmap *loops,
                                               MLoopNorSpaceArray *lnor_spacearr,
-                                              int *totloopsel)
+                                              int *totloopsel,
+                                              const bool do_all_loops_of_vert)
 {
   if (l != NULL) {
     const int l_idx = BM_elem_index_get(l);
 
-    if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
+    if (!BLI_BITMAP_TEST(loops, l_idx)) {
       /* If vert and face selected share a loop, mark it for editing. */
       BLI_BITMAP_ENABLE(loops, l_idx);
       (*totloopsel)++;
 
-      /* Mark all loops in same loop normal space (aka smooth fan). */
-      if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
-        for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) {
-          const int lfan_idx = BM_elem_index_get((BMLoop *)node->link);
+      if (do_all_loops_of_vert) {
+        /* If required, also mark all loops shared by that vertex.
+         * This is needed when loop spaces may change
+         * (i.e. when some faces or edges might change of smooth/sharp status). */
+        BMIter liter;
+        BMLoop *lfan;
+        BM_ITER_ELEM (lfan, &liter, l->v, BM_LOOPS_OF_VERT) {
+          const int lfan_idx = BM_elem_index_get(lfan);
           if (!BLI_BITMAP_TEST(loops, lfan_idx)) {
             BLI_BITMAP_ENABLE(loops, lfan_idx);
             (*totloopsel)++;
           }
         }
       }
+      else {
+        /* Mark all loops in same loop normal space (aka smooth fan). */
+        if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
+          for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) {
+            const int lfan_idx = BM_elem_index_get((BMLoop *)node->link);
+            if (!BLI_BITMAP_TEST(loops, lfan_idx)) {
+              BLI_BITMAP_ENABLE(loops, lfan_idx);
+              (*totloopsel)++;
+            }
+          }
+        }
+      }
     }
   }
 }
 
 /* Mark the individual clnors to be edited, if multiple selection methods are used. */
-static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
+static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert)
 {
   BMEditSelection *ese, *ese_prev;
   int totloopsel = 0;
@@ -1451,19 +1468,22 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
                 BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele),
                 loops,
                 bm->lnor_spacearr,
-                &totloopsel);
+                &totloopsel,
+                do_all_loops_of_vert);
           }
           else if (ese_prev->htype == BM_EDGE) {
             BMEdge *e = (BMEdge *)ese_prev->ele;
             bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v1),
                                               loops,
                                               bm->lnor_spacearr,
-                                              &totloopsel);
+                                              &totloopsel,
+                                              do_all_loops_of_vert);
 
             bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v2),
                                               loops,
                                               bm->lnor_spacearr,
-                                              &totloopsel);
+                                              &totloopsel,
+                                              do_all_loops_of_vert);
           }
         }
       }
@@ -1478,7 +1498,8 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
       BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
         if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
           BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-            bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+            bm_loop_normal_mark_indiv_do_loop(
+                l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert);
           }
         }
       }
@@ -1491,15 +1512,18 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
       BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
         if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
           BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
-            bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+            bm_loop_normal_mark_indiv_do_loop(
+                l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert);
             /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects
              * *two* loops in each of its faces. We have to find the other one too. */
             if (BM_vert_in_edge(e, l->next->v)) {
-              bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel);
+              bm_loop_normal_mark_indiv_do_loop(
+                  l->next, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert);
             }
             else {
               BLI_assert(BM_vert_in_edge(e, l->prev->v));
-              bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel);
+              bm_loop_normal_mark_indiv_do_loop(
+                  l->prev, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert);
             }
           }
         }
@@ -1513,7 +1537,8 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
       BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
         if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
           BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
-            bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+            bm_loop_normal_mark_indiv_do_loop(
+                l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert);
           }
         }
       }
@@ -1546,7 +1571,8 @@ static void loop_normal_editdata_init(
   lnor_ed->loc = v->co;
 }
 
-BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm)
+BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm,
+                                                           const bool do_all_loops_of_vert)
 {
   BMLoop *l;
   BMVert *v;
@@ -1570,7 +1596,7 @@ BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm)
   BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__);
 
   /* This function define loop normals to edit, based on selection modes and history. */
-  totloopsel = bm_loop_normal_mark_indiv(bm, loops);
+  totloopsel = bm_loop_normal_mark_indiv(bm, loops, do_all_loops_of_vert);
 
   if (totloopsel) {
     BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index d0cf50a7894..83575552acc 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -67,7 +67,8 @@ void BM_lnorspace_err(BMesh *bm);
 #endif
 
 /* Loop Generics */
-struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm);
+struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm,
+                                                                  const bool do_all_loops_of_vert);
 void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr);
 int BM_total_loop_select(BMesh *bm);
 
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index c4216d81317..c196a66332d 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -7689,7 +7689,7 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED
 
   BKE_editmesh_ensure_autosmooth(em);
   BKE_editmesh_lnorspace_update(em);
-  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
 
   op->customdata = lnors_ed_arr;
 
@@ -8246,7 +8246,10 @@ static int normals_split_merge(bContext *C, const bool do_merge)
   BKE_editmesh_ensure_autosmooth(em);
   BKE_editmesh_lnorspace_update(em);
 
-  BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL;
+  /* Note that we need temp lnor editing data for all loops of all affected vertices, since by
+   * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809. */
+  BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm, true) :
+                                                    NULL;
 
   mesh_set_smooth_faces(em, do_merge);
 
@@ -8573,7 +8576,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
 
   BKE_editmesh_ensure_autosmooth(em);
   BKE_editmesh_lnorspace_update(em);
-  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
   BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
 
   float *normal_vector = scene->toolsettings->normal_vector;
@@ -8867,7 +8870,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
 
   BKE_editmesh_ensure_autosmooth(em);
   BKE_editmesh_lnorspace_update(em);
-  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
+  BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
 
   float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
 
diff --git a/source/blender/editors/transform/transform.c b/source/

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list