diff --git a/source/blender/bmesh/bmesh_queries.h b/source/blender/bmesh/bmesh_queries.h index 548fbdf36e1..0db4a5f7e24 100644 --- a/source/blender/bmesh/bmesh_queries.h +++ b/source/blender/bmesh/bmesh_queries.h @@ -79,6 +79,9 @@ int BM_Face_Sharededges(struct BMFace *f1, struct BMFace *f2); /*returns number of faces e1 and e2 share.*/ int BM_Edge_Share_Faces(struct BMEdge *e1, struct BMEdge *e2); +/*edge verts in winding order from face*/ +void BM_Edge_OrderedVerts(struct BMEdge *edge, struct BMVert **r_v1, struct BMVert **r_v2); + /*checks if a face is valid in the data structure*/ int BM_Validate_Face(BMesh *bm, BMFace *face, FILE *err); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 9edb8ace562..41c26f6d301 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -443,7 +443,34 @@ int BM_Edge_Share_Faces(BMEdge *e1, BMEdge *e2) return 0; } +/** + * + * BMESH EDGE ORDERED VERTS + * + * Returns the verts of an edge as used in a face + * if used in a face at all, otherwise just assign as used in the edge. + * + * Useful to get a determanistic winding order when calling + * BM_Make_Ngon() on an arbitrary array of verts, + * though be sure to pick an edge which has a face. + * +*/ +void BM_Edge_OrderedVerts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2) +{ + if ( (edge->l == NULL) || + ( ((edge->l->prev->v == edge->v1) && (edge->l->v == edge->v2)) || + ((edge->l->v == edge->v1) && (edge->l->next->v == edge->v2)) ) + ) + { + *r_v1= edge->v1; + *r_v2= edge->v2; + } + else { + *r_v1= edge->v2; + *r_v2= edge->v1; + } +} /** * BMESH FACE ANGLE diff --git a/source/blender/bmesh/operators/createops.c b/source/blender/bmesh/operators/createops.c index 6dd7283d4b0..6cd1d0c27d7 100644 --- a/source/blender/bmesh/operators/createops.c +++ b/source/blender/bmesh/operators/createops.c @@ -840,6 +840,7 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); int use_restrict = BMO_Get_Int(op, "use_restrict"); int i, j, group = 0; + unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */ if (!bm->totvert || !bm->totedge) return; @@ -913,6 +914,8 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op) if (!path) continue; + winding[0]= winding[1]= 0; + BLI_array_empty(edges); BLI_array_empty(verts); i = 0; @@ -926,6 +929,16 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op) if (!e) break; + /* check on the winding */ + if (e->l) { + BMVert *test_v1, *test_v2; + /* we want to use the reverse winding to the existing order */ + BM_Edge_OrderedVerts(edge, &test_v2, &test_v1); + + /* edges vote on which winding wins out */ + winding[(test_v1 == node->v)]++; + } + edata[BM_GetIndex(e)].ftag++; BLI_array_growone(edges); edges[i++] = e; @@ -948,7 +961,24 @@ void bmesh_edgenet_fill_exec(BMesh *bm, BMOperator *op) continue; if (i) { - f = BM_Make_Ngon(bm, edge->v1, edge->v2, edges, i, 1); + BMVert *v1, *v2; + + /* to define the winding order must select first edge, + * otherwise we could leave this as-is */ + edge= edges[0]; + + /* if these are even it doesnt really matter what to do, + * with consistent geometry one will be zero, the choice is clear */ + if (winding[0] > winding[1]) { + v1= verts[0]; + v2= verts[1]; + } + else { + v1= verts[1]; + v2= verts[0]; + } + + f = BM_Make_Ngon(bm, v1, v2, edges, i, 1); if (f && !BMO_TestFlag(bm, f, ELE_ORIG)) { BMO_SetFlag(bm, f, FACE_NEW); }