improved BM_face_copy_shared to copy from more possible connected loops and add filte...
authorCampbell Barton <ideasman42@gmail.com>
Sun, 18 Aug 2013 11:44:51 +0000 (11:44 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 18 Aug 2013 11:44:51 +0000 (11:44 +0000)
source/blender/bmesh/bmesh_class.h
source/blender/bmesh/intern/bmesh_construct.c
source/blender/bmesh/intern/bmesh_construct.h
source/blender/bmesh/intern/bmesh_queries.h
source/blender/bmesh/operators/bmo_hull.c
source/blender/bmesh/operators/bmo_inset.c

index 0e4c014..23e5c97 100644 (file)
@@ -254,6 +254,8 @@ enum {
 struct BPy_BMGeneric;
 extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
 
+typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
+
 /* defines */
 #define BM_ELEM_CD_GET_VOID_P(ele, offset) \
        (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
index f5856ee..aa37a68 100644 (file)
@@ -127,33 +127,61 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa
 
 /**
  * \brief copies face loop data from shared adjacent faces.
+ *
+ * \param filter_fn  A function that filters the source loops before copying (don't always want to copy all)
+ *
  * \note when a matching edge is found, both loops of that edge are copied
  * this is done since the face may not be completely surrounded by faces,
- * this way: a quad with 2 connected quads on either side will still get all 4 loops updated */
-void BM_face_copy_shared(BMesh *bm, BMFace *f)
+ * this way: a quad with 2 connected quads on either side will still get all 4 loops updated
+ */
+void BM_face_copy_shared(BMesh *bm, BMFace *f,
+                         BMElemFilterFunc filter_fn, void *user_data)
 {
        BMLoop *l_first;
        BMLoop *l_iter;
 
+#ifdef DEBUG
+       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+       do {
+               BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0);
+       } while ((l_iter = l_iter->next) != l_first);
+#endif
+
        l_iter = l_first = BM_FACE_FIRST_LOOP(f);
        do {
                BMLoop *l_other = l_iter->radial_next;
 
                if (l_other && l_other != l_iter) {
+                       BMLoop *l_src[2];
+                       BMLoop *l_dst[2] = {l_iter, l_iter->next};
+                       unsigned int j;
+
                        if (l_other->v == l_iter->v) {
-                               bm_loop_attrs_copy(bm, bm, l_other, l_iter);
-                               bm_loop_attrs_copy(bm, bm, l_other->next, l_iter->next);
+                               l_src[0] = l_other;
+                               l_src[1] = l_other->next;
                        }
                        else {
-                               bm_loop_attrs_copy(bm, bm, l_other->next, l_iter);
-                               bm_loop_attrs_copy(bm, bm, l_other, l_iter->next);
+                               l_src[0] = l_other->next;
+                               l_src[1] = l_other;
                        }
-                       /* since we copy both loops of the shared edge, step over the next loop here */
-                       if ((l_iter = l_iter->next) == l_first) {
-                               break;
+
+                       for (j = 0; j < 2; j++) {
+                               BLI_assert(l_dst[j]->v == l_src[j]->v);
+                               if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
+                                       if ((filter_fn == NULL) || filter_fn((BMElem *)l_src[j], user_data)) {
+                                               bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j]);
+                                               BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
+                                       }
+                               }
                        }
                }
        } while ((l_iter = l_iter->next) != l_first);
+
+
+       l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+       do {
+               BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP);
+       } while ((l_iter = l_iter->next) != l_first);
 }
 
 /**
index f0bd7b3..92ed330 100644 (file)
@@ -36,7 +36,8 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm,
 BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
                                 const BMFace *example, const bool no_double);
 
-void BM_face_copy_shared(BMesh *bm, BMFace *f);
+void BM_face_copy_shared(BMesh *bm, BMFace *f,
+                         BMElemFilterFunc filter_fn, void *user_data);
 
 BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag);
 BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag,
index 38d30b2..e52e591 100644 (file)
@@ -27,8 +27,6 @@
  *  \ingroup bmesh
  */
 
-typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
-
 bool    BM_vert_in_face(BMFace *f, BMVert *v);
 int     BM_verts_in_face_count(BMFace *f, BMVert **varr, int len);
 bool    BM_verts_in_face(BMFace *f, BMVert **varr, int len);
index 500e984..89da386 100644 (file)
@@ -136,7 +136,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles)
 
                                /* Create new hull face */
                                f = BM_face_create_quad_tri_v(bm, t->v, 3, example, true);
-                               BM_face_copy_shared(bm, f);
+                               BM_face_copy_shared(bm, f, NULL, NULL);
                        }
                        /* Mark face for 'geom.out' slot and select */
                        BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
index cffca91..731b895 100644 (file)
@@ -796,7 +796,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
 #if 0
                /* don't use this because face boundaries have no adjacent loops and won't be filled in.
                 * instead copy from the opposite side with the code below */
-               BM_face_copy_shared(bm, f);
+               BM_face_copy_shared(bm, f, NULL, NULL);
 #else
                {
                        /* 2 inner loops on the edge between the new face and the original */