the make ngon function's overlap test needed some work, the API function
[blender.git] / source / blender / bmesh / intern / bmesh_polygon.c
index 841a28614878d1ef2be941bec3f63066e70448e2..3c4b738a84082cd33ee6bb5d0cb5239ee672e3d1 100644 (file)
@@ -287,6 +287,56 @@ void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts)
  *
 */
 
+void BM_Face_UpdateNormal(BMesh *bm, BMFace *f)
+{
+       float projverts[12][3];
+       float (*proj)[3] = f->len < 12 ? projverts : MEM_mallocN(sizeof(float)*f->len*3, "projvertsn");
+       BMLoop *l = f->loopbase;
+       int i=0;
+
+       if (f->len < 3) return;
+       
+       do {
+               VECCOPY(proj[i], l->v->co);
+               i += 1;
+       } while (l != f->loopbase);
+
+       bmesh_update_face_normal(bm, f, proj);
+
+       if (projverts != proj) MEM_freeN(proj);
+}
+
+void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e)
+{
+       BMIter *iter;
+       BMFace *f;
+       
+       f = BMIter_New(&iter, bm, BM_FACES_OF_EDGE, e);
+       for (; f; f=BMIter_Step(&iter)) {
+               BM_Face_UpdateNormal(bm, f);
+       }
+
+       BM_Vert_UpdateNormal(bm, e->v1);
+       BM_Vert_UpdateNormal(bm, e->v2);
+}
+
+void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
+{
+       BMIter iter;
+       BMFace *f;
+       float norm[3] = {0.0f, 0.0f, 0.0f};
+       int len=0;
+
+       f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
+       for (; f; f=BMIter_Step(&iter), len++) {
+               VecAddf(norm, f->no, norm);
+       }
+
+       if (!len) return;
+
+       VecMulf(norm, 1.0f/(int)len);
+}
+
 void bmesh_update_face_normal(BMesh *bm, BMFace *f, float (*projectverts)[3])
 {
        BMLoop *l;
@@ -395,18 +445,23 @@ int goodline(float (*projectverts)[3], BMFace *f, int v1i,
        
        if (testedgeside(v1, v2, v3)) return 0;
        
-       for (i=0; i<nvert; i++) {
-               if (i == v1i || i == v2i || i == v3i) continue;
+       //for (i=0; i<nvert; i++) {
+       do {
+               i = l->v->head.eflag2;
+               if (i == v1i || i == v2i || i == v3i) {
+                       l = l->head.next;
+                       continue;
+               }
                
-               VECCOPY(pv1, projectverts[i]); //l->v->head.eflag2]);
-               VECCOPY(pv2, projectverts[(i+1) % nvert]); //((BMLoop*)l->head.next)->v->head.eflag2]);
+               VECCOPY(pv1, projectverts[l->v->head.eflag2]);
+               VECCOPY(pv2, projectverts[((BMLoop*)l->head.next)->v->head.eflag2]);
                
                //if (linecrosses(pv1, pv2, v1, v3)) return 0;
                if (point_in_triangle(v1, v2, v3, pv1)) return 0;
                if (point_in_triangle(v3, v2, v1, pv1)) return 0;
 
-               //l = l->head.next;
-       } //while (l != f->loopbase);
+               l = l->head.next;
+       } while (l != f->loopbase);
        return 1;
 }
 /*
@@ -499,13 +554,13 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
        
        ///bmesh_update_face_normal(bm, f, projectverts);
 
+       /*this fixes some weird numerical error*/
+       projectverts[0][0] += 0.0001f;
+       projectverts[0][1] += 0.0001f;
+       projectverts[0][2] += 0.0001f;
+
        compute_poly_normal(f->no, projectverts, f->len);
        poly_rotate_plane(f->no, projectverts, i);
-       /*check if we rotated the wrong way*/
-       compute_poly_normal(no, projectverts, f->len);
-       if (no[2] < 0) {
-               poly_rotate_plane(no, projectverts, i);
-       }
 
        nvert = f->len;
 
@@ -513,7 +568,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
        for (i=0; i<nvert; i++) {
                projectverts[i][2] = 0.0f;
        }
-       
+
        done = 0;
        while(!done && f->len > 3){
                done = 1;
@@ -524,6 +579,8 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
                        f = BM_Split_Face(bm, l->f, ((BMLoop*)(l->head.prev))->v, 
                                          ((BMLoop*)(l->head.next))->v, 
                                          &newl, NULL, 0);
+                       VECCOPY(f->no, l->f->no);
+
                        if (!f) {
                                printf("yeek! triangulator failed to split face!\n");
                                break;