Fix T58832: Spin tool creates duplicate faces
authorCampbell Barton <ideasman42@gmail.com>
Thu, 6 Dec 2018 03:50:25 +0000 (14:50 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 6 Dec 2018 03:52:55 +0000 (14:52 +1100)
source/blender/bmesh/intern/bmesh_query.c
source/blender/bmesh/intern/bmesh_query.h
source/blender/bmesh/operators/bmo_dupe.c

index e1f16508b8b1be0effbca62761585ac6b9a1a476..13e2029381e3f2b0dca562513e738612e0e2195b 100644 (file)
@@ -2063,6 +2063,40 @@ BMFace *BM_face_exists(BMVert **varr, int len)
        return NULL;
 }
 
+/**
+ * Check if the face has an exact duplicate (both winding directions).
+ */
+BMFace *BM_face_find_double(BMFace *f)
+{
+       BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+       for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) {
+               if (l_iter->f->len == l_first->f->len) {
+                       if (l_iter->v == l_first->v) {
+                               BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
+                               do {
+                                       if (l_a->e != l_b->e) {
+                                               break;
+                                       }
+                               } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init);
+                               if (l_b == l_b_init) {
+                                       return l_iter->f;
+                               }
+                       }
+                       else {
+                               BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
+                               do {
+                                       if (l_a->e != l_b->e) {
+                                               break;
+                                       }
+                               } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init);
+                               if (l_b == l_b_init) {
+                                       return l_iter->f;
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
 
 /**
  * Given a set of vertices and edges (\a varr, \a earr), find out if
index fb625c9acc8e9f9648a4c92b0e47fae11712144d..17bf0f38d0cc0205f00a71c74e145284d3cc829a 100644 (file)
@@ -141,6 +141,7 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONN
 BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
 BMFace *BM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1);
+BMFace *BM_face_find_double(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
 bool    BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 bool    BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
index c50c7657deb542ecce8fcbc4fa35e0c1d349510e..77019e139697b66e046d49a4a332f21205829503 100644 (file)
@@ -564,6 +564,21 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
                                                i++;
                                        }
                                }
+                               /* Full copies of faces may cause overlap. */
+                               for (int i = 0; i < elem_array_len; ) {
+                                       if (elem_array[i]->head.htype == BM_FACE) {
+                                               BMFace *f_src = (BMFace *)elem_array[i];
+                                               BMFace *f_dst = BM_face_find_double(f_src);
+                                               if (f_dst != NULL) {
+                                                       BM_face_kill(bm, f_src);
+                                                       elem_array_len--;
+                                                       elem_array[i] = elem_array[elem_array_len];
+                                               }
+                                       }
+                                       else {
+                                               i++;
+                                       }
+                               }
                                slot_geom_out->len = elem_array_len;
                        }
                        BMO_op_finish(bm, &extop);