diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-09-12 12:41:39 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-09-12 12:41:39 +0400 |
commit | a54a9d5d4e2d06a95e4f1ca01fc0857d2bef6602 (patch) | |
tree | 4cdfb3095d7acb95a04e4011264b008db854aff5 /source/blender | |
parent | 186603c2ff1e41b75d9b9eee33b88fa804c75207 (diff) |
fkey on two broken edge loops will create an ngon now, as will fkey on one broken edge loop
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/bmesh/bmesh_operator_api.h | 4 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 21 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators.c | 19 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators_private.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/createops.c | 218 |
5 files changed, 244 insertions, 19 deletions
diff --git a/source/blender/bmesh/bmesh_operator_api.h b/source/blender/bmesh/bmesh_operator_api.h index 393d71992ce..67daa323129 100644 --- a/source/blender/bmesh/bmesh_operator_api.h +++ b/source/blender/bmesh/bmesh_operator_api.h @@ -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, diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d297a95799d..3b914e769ce 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -343,7 +343,6 @@ BMOpDefine def_contextual_create= { 0, }; -/*this may be unimplemented*/ BMOpDefine def_edgenet_fill= { "edgenet_fill", {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, @@ -354,6 +353,25 @@ BMOpDefine def_edgenet_fill= { }; /* + 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 Rotate vertices around a center, using a 3x3 rotation @@ -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*)); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 55a413c82dc..37b9ce389ec 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -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; +} /* * diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index efdf6a6602e..b5201ae17d6 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -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 diff --git a/source/blender/bmesh/operators/createops.c b/source/blender/bmesh/operators/createops.c index 95ebf12ba14..56382d18b00 100644 --- a/source/blender/bmesh/operators/createops.c +++ b/source/blender/bmesh/operators/createops.c @@ -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) { |