fix [#29079] New face added with "F" has wrong winding
authorCampbell Barton <ideasman42@gmail.com>
Fri, 25 Nov 2011 01:18:48 +0000 (01:18 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 25 Nov 2011 01:18:48 +0000 (01:18 +0000)
now newly created faces use the best winding order based on surrounding edges.

source/blender/bmesh/bmesh_queries.h
source/blender/bmesh/intern/bmesh_queries.c
source/blender/bmesh/operators/createops.c

index 548fbdf36e10f26baa64b86cd85ee731fa616c1c..0db4a5f7e247d248ec8e92a49379d19283fa4632 100644 (file)
@@ -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);
 
index 9edb8ace5621d1ea56fbabca639e8d6cde2a930e..41c26f6d301b11cd22ecd0b0bc32447f6fdc0e08 100644 (file)
@@ -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
index 6dd7283d4b0ea7dacb56be437e7bb2ce75633905..6cd1d0c27d71e4086a7849b79ab056c2cbe70887 100644 (file)
@@ -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);
                        }