[Bf-blender-cvs] [4892470a471] master: Fix T70287: Connect vertex path can create duplicate edges/faces

Campbell Barton noreply at git.blender.org
Wed Jun 17 08:43:33 CEST 2020


Commit: 4892470a47196ee5914f57e561432650bc5b49f7
Author: Campbell Barton
Date:   Wed Jun 17 15:24:20 2020 +1000
Branches: master
https://developer.blender.org/rB4892470a47196ee5914f57e561432650bc5b49f7

Fix T70287: Connect vertex path can create duplicate edges/faces

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

M	source/blender/bmesh/operators/bmo_connect.c

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

diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 9969d31a4a5..b52c26a65f0 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -50,6 +50,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
   BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
   BMLoop *l_iter, *l_first;
   uint i;
+  int result = 1;
 
   STACK_INIT(loops_split, pair_split_max);
   STACK_INIT(verts_pair, pair_split_max);
@@ -109,30 +110,60 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera
     v_pair[1] = loops_split[i][1]->v;
   }
 
+  /* Clear and re-use to store duplicate faces, to remove after splitting is finished. */
+  STACK_CLEAR(loops_split);
+
   for (i = 0; i < STACK_SIZE(verts_pair); i++) {
     BMFace *f_new;
     BMLoop *l_new;
-    BMLoop *l_a, *l_b;
-
-    if ((l_a = BM_face_vert_share_loop(f, verts_pair[i][0])) &&
-        (l_b = BM_face_vert_share_loop(f, verts_pair[i][1]))) {
-      f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
+    BMLoop *l_pair[2];
+
+    /* Note that duplicate edges in this case is very unlikely but it can happen, see T70287. */
+    bool edge_exists = (BM_edge_exists(verts_pair[i][0], verts_pair[i][1]) != NULL);
+    if ((l_pair[0] = BM_face_vert_share_loop(f, verts_pair[i][0])) &&
+        (l_pair[1] = BM_face_vert_share_loop(f, verts_pair[i][1]))) {
+      f_new = BM_face_split(bm, f, l_pair[0], l_pair[1], &l_new, NULL, edge_exists);
+
+      /* Check if duplicate faces have been created, store the loops for removal in this case.
+       * Note that this matches how triangulate works (newly created duplicates get removed). */
+      if (UNLIKELY(edge_exists)) {
+        BMLoop **l_pair_deferred_remove = NULL;
+        for (int j = 0; j < 2; j++) {
+          if (BM_face_find_double(l_pair[j]->f)) {
+            if (l_pair_deferred_remove == NULL) {
+              l_pair_deferred_remove = STACK_PUSH_RET(loops_split);
+              l_pair_deferred_remove[0] = NULL;
+              l_pair_deferred_remove[1] = NULL;
+            }
+            l_pair_deferred_remove[j] = l_pair[j];
+          }
+        }
+      }
     }
     else {
       f_new = NULL;
       l_new = NULL;
     }
 
-    f = f_new;
-
     if (!l_new || !f_new) {
-      return -1;
+      result = -1;
+      break;
     }
+
+    f = f_new;
     // BMO_face_flag_enable(bm, f_new, FACE_NEW);
     BMO_edge_flag_enable(bm, l_new->e, EDGE_OUT);
   }
 
-  return 1;
+  for (i = 0; i < STACK_SIZE(loops_split); i++) {
+    for (int j = 0; j < 2; j++) {
+      if (loops_split[i][j] != NULL) {
+        BM_face_kill(bm, loops_split[i][j]->f);
+      }
+    }
+  }
+
+  return result;
 }
 
 void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)



More information about the Bf-blender-cvs mailing list