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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<nverts; i++) {
|
||||
// verts[i][iaxis] = 0.0f;
|
||||
//}
|
||||
int i;
|
||||
|
||||
compute_poly_normal(normal, verts, nverts);
|
||||
|
||||
@@ -354,20 +341,20 @@ void BM_flip_normal(BMesh *bm, BMFace *f)
|
||||
|
||||
|
||||
|
||||
int winding(float *a, float *b, float *c)
|
||||
int winding(double *a, double *b, double *c)
|
||||
{
|
||||
float v1[3], v2[3], v[3];
|
||||
double v1[3], v2[3], v[3];
|
||||
|
||||
VecSubf(v1, b, a);
|
||||
VecSubf(v2, b, c);
|
||||
VECSUB(v1, b, a);
|
||||
VECSUB(v2, b, c);
|
||||
|
||||
v1[2] = 0;
|
||||
v2[2] = 0;
|
||||
|
||||
Normalize(v1);
|
||||
Normalize(v2);
|
||||
Normalize_d(v1);
|
||||
Normalize_d(v2);
|
||||
|
||||
Crossf(v, v1, v2);
|
||||
Crossd(v, v1, v2);
|
||||
|
||||
/*!! (turns nonzero into 1) is likely not necassary,
|
||||
since '>' 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; i<nvert; i++) {
|
||||
//if (i == v1i or i == v3i) continue
|
||||
do {
|
||||
VECCOPY(pv1, projectverts[l->v->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;
|
||||
|
||||
Reference in New Issue
Block a user