From 6c481af15c6ca275241b2309780dcd9846bfa8bb Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 6 Mar 2009 07:17:56 +0000 Subject: [PATCH] BM_SplitFace now copies header flags to the new face. kindof hackish right now, need to consider how to solve this correctly. also cleaned up tesselator a little and corrected some optimizations that were causing problems. the tesselators now use doubles for internal calculations, should hopefully be more accurate. --- source/blender/blenlib/BLI_arithb.h | 2 + source/blender/blenlib/intern/arithb.c | 27 ++++++++ source/blender/bmesh/intern/bmesh_mods.c | 2 + source/blender/bmesh/intern/bmesh_polygon.c | 77 +++++++++------------ 4 files changed, 65 insertions(+), 43 deletions(-) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 3c0a41e1591..1f4f6d2e920 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -75,6 +75,7 @@ void CalcCent3f(float *cent, float *v1, float *v2, float *v3); void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4); void Crossf(float *c, float *a, float *b); +void Crossd(double *c, double *a, double *b); void Projf(float *c, float *v1, float *v2); float Inpf(float *v1, float *v2); @@ -82,6 +83,7 @@ float Inp2f(float *v1, float *v2); float Normalize(float *n); float Normalize2(float *n); +double Normalize_d(double *n); float Sqrt3f(float f); double Sqrt3d(double d); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 7d8bcbe2e7e..ebefd94da9c 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -111,6 +111,26 @@ float Normalize(float *n) return d; } + +double Normalize_d(double *n) +{ + double d; + + d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2]; + /* A larger value causes normalize errors in a scaled down models with camera xtreme close */ + if(d>1.0e-35F) { + d= sqrt(d); + + n[0]/=d; + n[1]/=d; + n[2]/=d; + } else { + n[0]=n[1]=n[2]= 0.0; + d= 0.0; + } + return d; +} + void Crossf(float *c, float *a, float *b) { c[0] = a[1] * b[2] - a[2] * b[1]; @@ -118,6 +138,13 @@ void Crossf(float *c, float *a, float *b) c[2] = a[0] * b[1] - a[1] * b[0]; } +void Crossd(double *c, double *a, double *b) +{ + c[0] = a[1] * b[2] - a[2] * b[1]; + c[1] = a[2] * b[0] - a[0] * b[2]; + c[2] = a[0] * b[1] - a[1] * b[0]; +} + /* Inpf returns the dot product, also called the scalar product and inner product */ float Inpf( float *v1, float *v2) { diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 29653b24b61..378c29e3f9a 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -276,6 +276,8 @@ BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMFace *nf; nf = bmesh_sfme(bm,f,v1,v2,nl); + BM_Copy_Attributes(bm, bm, f, nf); + /* nf->flag = f->flag; if (example->flag & SELECT) f->flag |= BM_SELECT; diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index fc8a67df5ae..53bbbc2ca68 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -36,10 +36,10 @@ * */ -static short testedgeside(float *v1, float *v2, float *v3) +static short testedgeside(double *v1, double *v2, double *v3) /* is v3 to the right of v1-v2 ? With exception: v3==v1 || v3==v2 */ { - float inp; + double inp; //inp= (v2[cox]-v1[cox])*(v1[coy]-v3[coy]) +(v1[coy]-v2[coy])*(v1[cox]-v3[cox]); inp= (v2[0]-v1[0])*(v1[1]-v3[1]) +(v1[1]-v2[1])*(v1[0]-v3[0]); @@ -52,7 +52,7 @@ static short testedgeside(float *v1, float *v2, float *v3) return 1; } -static int point_in_triangle(float *v1, float *v2, float *v3, float *pt) +static int point_in_triangle(double *v1, double *v2, double *v3, double *pt) { if(testedgeside(v1,v2,pt) && testedgeside(v2,v3,pt) && testedgeside(v3,v1,pt)) return 1; @@ -254,22 +254,9 @@ void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts) { float up[3] = {0.0f,0.0f,1.0f}, axis[3], q[4]; - float mat[3][3], axes[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + float mat[3][3]; double angle; - int i, iaxis=0, bestangle=180.0f; - - for (i=0; i<3; i++) { - angle = saacos(normal[0]*axes[i][0]+normal[1]*axes[i][1] + - normal[2]*axes[i][2]); - if (angle < bestangle) { - iaxis = i; - bestangle = angle; - } - } - - //for (i=0; i' I *think* should always @@ -377,7 +364,7 @@ int winding(float *a, float *b, float *c) /* detects if two line segments cross each other (intersects). note, there could be more winding cases then there needs to be. */ -int linecrosses(float *v1, float *v2, float *v3, float *v4) +int linecrosses(double *v1, double *v2, double *v3, double *v4) { int w1, w2, w3, w4, w5; @@ -396,27 +383,27 @@ int linecrosses(float *v1, float *v2, float *v3, float *v4) return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5; } -int goodline(float (*projectverts)[3], int v1i, +int goodline(float (*projectverts)[3], BMFace *f, int v1i, int v2i, int v3i, int nvert) { - float v1[3], v2[3], v3[3], *pv1, *pv2; + BMLoop *l = f->loopbase; + double v1[3], v2[3], v3[3], pv1[3], pv2[3]; int i; VECCOPY(v1, projectverts[v1i]); VECCOPY(v2, projectverts[v2i]); VECCOPY(v3, projectverts[v3i]); - if (winding(v1, v2, v3)) return 0; + if (testedgeside(v1, v2, v3)) return 0; - for (i=0; iv->head.eflag2]); + VECCOPY(pv2, projectverts[((BMLoop*)l->head.next)->v->head.eflag2]); - pv1 = projectverts[i]; - pv2 = projectverts[(i+1)%nvert]; - - if (linecrosses(pv1, pv2, v1, v3)) return 0l; - } + if (linecrosses(pv1, pv2, v1, v3)) return 0; + + l = l->head.next; + } while (l != f->loopbase); return 1; - } /* * FIND EAR @@ -450,18 +437,19 @@ static BMLoop *find_ear(BMesh *bm, BMFace *f, float (*verts)[3], if (BM_Edge_Exist(v1, v3)) isear = 0; - if (isear && !goodline(verts, v1->head.eflag2, v2->head.eflag2, + if (isear && !goodline(verts, f, v1->head.eflag2, v2->head.eflag2, v3->head.eflag2, nvert)) isear = 0; if(isear){ angle = VecAngle3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]); - if(!bestear || ABS(angle-40.0f) < bestangle){ + if(!bestear || ABS(angle-45.0f) < bestangle){ bestear = l; - bestangle = ABS(40.0f-angle); + bestangle = ABS(45.0f-angle); } - if ((angle > 10 && angle < 140) || i > 5) break; + if (angle > 20 && angle < 90) break; + if (angle < 100 && i > 5) break; i += 1; } l = (BMLoop*)(l->head.next); @@ -529,7 +517,9 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], if(l) { done = 0; v = l->v; - f = bmesh_sfme(bm, f, ((BMLoop*)(l->head.prev))->v, ((BMLoop*)(l->head.next))->v, &newl); + f = BM_Split_Face(bm, l->f, ((BMLoop*)(l->head.prev))->v, + ((BMLoop*)(l->head.next))->v, + &newl, NULL, 0); if (!f) { printf("yeek! triangulator failed to split face!\n"); break; @@ -553,7 +543,8 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], l = f->loopbase; while (l->f->len > 3){ nextloop = ((BMLoop*)(l->head.next->next)); - f = bmesh_sfme(bm, l->f, l->v,nextloop->v, &newl); + f = BM_Split_Face(bm, l->f, l->v, nextloop->v, + &newl, NULL, 0); if (!f) { printf("triangle fan step of triangulator failed.\n"); return;