fkey on two broken edge loops will create an ngon now, as will fkey on one broken...
authorJoseph Eagar <joeedh@gmail.com>
Sat, 12 Sep 2009 08:41:39 +0000 (08:41 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Sat, 12 Sep 2009 08:41:39 +0000 (08:41 +0000)
source/blender/bmesh/bmesh_operator_api.h
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators.c
source/blender/bmesh/intern/bmesh_operators_private.h
source/blender/bmesh/operators/createops.c

index 393d71992ce47e22e3492a7005838da8877e0712..67daa3231294ffd2689b2198040e9d05357aa185 100644 (file)
@@ -255,6 +255,10 @@ void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, char *slotn
 int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, char *slotname);
 int BMO_CountSlotMap(struct BMesh *bm, struct BMOperator *op, char *slotname);
 
+/*Counts the number of edges with tool flag toolflag around
+  v*/
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag);
+
 /*inserts a key/value mapping into a mapping slot.  note that it copies the
   value, it doesn't store a reference to it.*/
 //BM_INLINE void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, char *slotname, 
index d297a95799d54c25e96cc5d43e32eb09769aa05e..3b914e769ce19ce1569d11d284b1a3fe9ee6dd02 100644 (file)
@@ -343,7 +343,6 @@ BMOpDefine def_contextual_create= {
        0,
 };
 
-/*this may be unimplemented*/
 BMOpDefine def_edgenet_fill= {
        "edgenet_fill",
        {{BMOP_OPSLOT_ELEMENT_BUF, "edges"},
@@ -353,6 +352,25 @@ BMOpDefine def_edgenet_fill= {
        0,
 };
 
+/*
+  Edgenet Prepare
+
+  Identifies several useful edge loop cases and modifies them so
+  they'll become a face when edgenet_fill is called.  The cases covered are:
+
+  * One single loop; an edge is added to connect the ends
+  * Two loops; two edges are added to connect the endpoints (based on the
+    shortest distance between each endpont).
+*/
+BMOpDefine def_edgenet_prepare= {
+       "edgenet_prepare",
+       {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, //input edges
+        {BMOP_OPSLOT_ELEMENT_BUF, "edgeout"}, //new edges
+       {0, /*null-terminating sentinel*/}},
+       bmesh_edgenet_prepare,
+       0,
+};
+
 /*
   Rotate
 
@@ -777,6 +795,7 @@ BMOpDefine *opdefines[] = {
        &def_meshrotateuvs,
        &def_bmesh_to_mesh,
        &def_meshreverseuvs,
+       &def_edgenet_prepare,
 };
 
 int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
index 55a413c82dcdc2d73c4d7ed38234b06be7c26ec7..37b9ce389ec520d228074287baf9181e89398f96 100644 (file)
@@ -679,6 +679,25 @@ void BMO_UnHeaderFlag_Buffer(BMesh *bm, BMOperator *op, char *slotname, int flag
        }
 }
 
+int BMO_Vert_CountEdgeFlags(BMesh *bm, BMVert *v, int toolflag)
+{
+       BMNode *diskbase;
+       BMEdge *curedge;
+       int i, len=0, count=0;
+       
+       if(v->edge){
+               diskbase = bmesh_disk_getpointer(v->edge, v);
+               len = bmesh_cycle_length(diskbase);
+               
+               for(i = 0, curedge=v->edge; i<len; i++){
+                       if (BMO_TestFlag(bm, curedge, toolflag))
+                               count++;
+                       curedge = bmesh_disk_nextedge(curedge, v);
+               }
+       }
+
+       return count;
+}
 
 /*
  *
index efdf6a6602ed26ae3acf4d55147d28d8342e9385..b5201ae17d60cbd50c650152758f4190ce59e756 100644 (file)
@@ -54,5 +54,6 @@ void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
 void bmesh_rotateuvs_exec(BMesh *bm, BMOperator *op);
 void object_load_bmesh_exec(BMesh *bm, BMOperator *op);
 void bmesh_reverseuvs_exec(BMesh *bm, BMOperator *op);
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op);
 
 #endif
index 95ebf12ba14a3006bdca3505aa277da26ba802f2..56382d18b0060a54ac3f83af5bd079797b5e2a1e 100644 (file)
@@ -38,8 +38,6 @@ typedef struct EdgeData {
 #define EDGE_MARK      1
 #define EDGE_VIS       2
 
-#define VERT_VIS       1
-
 #define FACE_NEW       1
 
 PathBase *edge_pathbase_new(void)
@@ -195,10 +193,9 @@ EPath *edge_find_shortest_path(BMesh *bm, BMEdge *edge, EdgeData *edata, PathBas
 
 void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
 {
-       BMIter iter, liter;
+       BMIter iter;
        BMOIter siter;
        BMEdge *e, *edge;
-       BMLoop *l;
        BMFace *f;
        EPath *path;
        EPathNode *node;
@@ -206,7 +203,7 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op)
        BMEdge **edges = NULL;
        PathBase *pathbase = edge_pathbase_new();
        V_DECLARE(edges);
-       int i, j;
+       int i;
 
        if (!bm->totvert || !bm->totedge)
                return;
@@ -314,16 +311,195 @@ static int convex(float *v1, float *v2, float *v3, float *v4)
        return 0;
 }
 
+BMEdge *edge_next(BMesh *bm, BMEdge *e)
+{
+       BMIter iter;
+       BMEdge *e2;
+       int i;
+
+       for (i=0; i<2; i++) {
+               BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, i?e->v2:e->v1) {
+                       if (BMO_TestFlag(bm, e2, EDGE_MARK) 
+                           && !BMO_TestFlag(bm, e2, EDGE_VIS) && e2 != e)
+                       {
+                               return e2;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+void bmesh_edgenet_prepare(BMesh *bm, BMOperator *op)
+{
+       BMOIter siter;
+       BMIter iter;
+       BMEdge *e, *e2;
+       BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
+       V_DECLARE(edges1);
+       V_DECLARE(edges2);
+       V_DECLARE(edges);
+       int ok = 1;
+       int i, count;
+
+       BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE);
+       
+       /*validate that each edge has at most one other tagged edge in the
+         disk cycle around each of it's vertices*/
+       BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+               for (i=0; i<2; i++) {
+                       count = BMO_Vert_CountEdgeFlags(bm, i?e->v2:e->v1, EDGE_MARK);
+                       if (count > 2) {
+                               ok = 0;
+                               break;
+                       }
+               }
+
+               if (!ok) break;
+       }
+
+       /*we don't have valid edge layouts, return*/
+       if (!ok)
+               return;
+
+
+       /*find connected loops within the input edges*/
+       count = 0;
+       while (1) {
+               BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+                       if (!BMO_TestFlag(bm, e, EDGE_VIS)) {
+                               if (BMO_Vert_CountEdgeFlags(bm, e->v1, EDGE_MARK)==1)
+                                       break;
+                               if (BMO_Vert_CountEdgeFlags(bm, e->v2, EDGE_MARK)==1)
+                                       break;
+                       }
+               }
+               
+               if (!e) break;
+               
+               if (!count)
+                       edges = edges1;
+               else if (count==1)
+                       edges = edges2;
+               else break;
+               
+               i = 0;
+               while (e) {
+                       BMO_SetFlag(bm, e, EDGE_VIS);
+                       V_GROW(edges);
+                       edges[i] = e;
+
+                       e = edge_next(bm, e);
+                       i++;
+               }
+
+               if (!count) {
+                       edges1 = edges;
+                       V_SETCOUNT(edges1, V_COUNT(edges));
+               } else {
+                       edges2 = edges;
+                       V_SETCOUNT(edges2, V_COUNT(edges));
+               }
+
+               V_RESET(edges);
+               count++;
+       }
+
+#define EDGECON(e1, e2) (e1->v1 == e2->v1 || e1->v2 == e2->v2 || e1->v1 == e2->v2)
+
+       if (edges1 && V_COUNT(edges1) > 2 && EDGECON(edges1[0], edges1[V_COUNT(edges1)-1])) {
+               if (edges2 && V_COUNT(edges2) > 2 && EDGECON(edges2[0], edges2[V_COUNT(edges2)-1])) {
+                       V_FREE(edges1);
+                       V_FREE(edges2);
+                       return;
+               } else {
+                       edges1 = edges2;
+                       edges2 = NULL;
+               }
+       }
+
+       if (edges2 && V_COUNT(edges2) > 2 && EDGECON(edges2[0], edges2[V_COUNT(edges2)-1])) {
+               edges2 = NULL;
+       }
+
+       /*two unconnected loops, connect them*/
+       if (edges1 && edges2) {
+               BMVert *v1, *v2, *v3, *v4;
+
+               if (V_COUNT(edges1)==1) {
+                       v1 = edges1[0]->v1;
+                       v2 = edges1[0]->v2;
+               } else {
+                       if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+                               v1 = edges1[0]->v2;
+                       else v1 = edges1[0]->v1;
+
+                       i = V_COUNT(edges1)-1;
+                       if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+                               v2 = edges1[i]->v2;
+                       else v2 = edges1[i]->v1;
+               }
+
+               if (V_COUNT(edges2)==1) {
+                       v3 = edges2[0]->v1;
+                       v4 = edges2[0]->v2;
+               } else {
+                       if (BM_Vert_In_Edge(edges2[1], edges2[0]->v1))
+                               v3 = edges2[0]->v2;
+                       else v3 = edges2[0]->v1;
+
+                       i = V_COUNT(edges2)-1;
+                       if (BM_Vert_In_Edge(edges2[i-1], edges2[i]->v1))
+                               v4 = edges2[i]->v2;
+                       else v4 = edges2[i]->v1;
+               }
+
+               if (VecLenf(v1->co, v3->co) > VecLenf(v1->co, v4->co)) {
+                       BMVert *v;
+                       v = v3;
+                       v3 = v4;
+                       v4 = v;
+               }
+
+               e = BM_Make_Edge(bm, v1, v3, NULL, 1);
+               BMO_SetFlag(bm, e, ELE_NEW);
+               e = BM_Make_Edge(bm, v2, v4, NULL, 1);
+               BMO_SetFlag(bm, e, ELE_NEW);
+       } else if (edges1) {
+               BMVert *v1, *v2;
+               
+               if (V_COUNT(edges1) > 1) {
+                       if (BM_Vert_In_Edge(edges1[1], edges1[0]->v1))
+                               v1 = edges1[0]->v2;
+                       else v1 = edges1[0]->v1;
+
+                       i = V_COUNT(edges1)-1;
+                       if (BM_Vert_In_Edge(edges1[i-1], edges1[i]->v1))
+                               v2 = edges1[i]->v2;
+                       else v2 = edges1[i]->v1;
+
+                       e = BM_Make_Edge(bm, v1, v2, NULL, 1);
+                       BMO_SetFlag(bm, e, ELE_NEW);
+               }
+       }
+       
+       BMO_Flag_To_Slot(bm, op, "edgeout", ELE_NEW, BM_EDGE);
+
+       V_FREE(edges1);
+       V_FREE(edges2);
+
+#undef EDGECON
+}
+
 /*this is essentially new fkey*/
 void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
 {
        BMOperator op2;
        BMOIter oiter;
-       BMIter iter, liter;
+       BMIter iter;
        BMHeader *h;
        BMVert *v, *verts[4];
        BMEdge *e;
-       BMLoop *l;
        BMFace *f;
        int totv=0, tote=0, totf=0, amount;
 
@@ -338,20 +514,13 @@ void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
                BMO_SetFlag(bm, h, ELE_NEW);
        }
        
-       /*first call dissolve faces*/
-       BMO_InitOpf(bm, &op2, "dissolvefaces faces=%ff", ELE_NEW);
+       /*call edgenet create*/
+       /*  call edgenet prepare op so additional face creation cases work*/
+       BMO_InitOpf(bm, &op2, "edgenet_prepare edges=%fe", ELE_NEW);
        BMO_Exec_Op(bm, &op2);
-       
-       /*if we dissolved anything, then return.*/
-       if (BMO_CountSlotBuf(bm, &op2, "regionout")) {
-               BMO_CopySlot(&op2, op, "regionout", "faceout");
-               BMO_Finish_Op(bm, &op2);
-               return;
-       }
-
+       BMO_Flag_Buffer(bm, &op2, "edgeout", ELE_NEW, BM_EDGE);
        BMO_Finish_Op(bm, &op2);
 
-       /*call edgenet create*/
        BMO_InitOpf(bm, &op2, "edgenet_fill edges=%fe", ELE_NEW);
        BMO_Exec_Op(bm, &op2);
 
@@ -364,6 +533,19 @@ void bmesh_contextual_create_exec(BMesh *bm, BMOperator *op)
 
        BMO_Finish_Op(bm, &op2);
        
+       /*now call dissolve faces*/
+       BMO_InitOpf(bm, &op2, "dissolvefaces faces=%ff", ELE_NEW);
+       BMO_Exec_Op(bm, &op2);
+       
+       /*if we dissolved anything, then return.*/
+       if (BMO_CountSlotBuf(bm, &op2, "regionout")) {
+               BMO_CopySlot(&op2, op, "regionout", "faceout");
+               BMO_Finish_Op(bm, &op2);
+               return;
+       }
+
+       BMO_Finish_Op(bm, &op2);
+
        /*now, count how many verts we have*/
        amount = 0;
        BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {