--- ray/src/ot/wfconv.c 2013/11/08 16:49:04 2.10 +++ ray/src/ot/wfconv.c 2014/06/10 23:19:00 2.13 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: wfconv.c,v 2.10 2013/11/08 16:49:04 greg Exp $"; +static const char RCSid[] = "$Id: wfconv.c,v 2.13 2014/06/10 23:19:00 greg Exp $"; #endif /* * Load Wavefront .OBJ file and convert to triangles with mesh info. @@ -9,6 +9,7 @@ static const char RCSid[] = "$Id: wfconv.c,v 2.10 2013 #include "copyright.h" #include "standard.h" #include "cvmesh.h" +#include "triangulate.h" #include typedef int VNDX[3]; /* vertex index (point,map,normal) */ @@ -31,15 +32,15 @@ static char group[256]; /* current group name */ static int lineno; /* current line number */ static int faceno; /* current face number */ -static int getstmt(char *av[MAXARG], FILE *fp); -static int cvtndx(VNDX vi, char *vs); -static int putface(int ac, char **av); +static int getstmt(char *av[MAXARG], FILE *fp); +static int cvtndx(VNDX vi, char *vs); +static int putface(int ac, char **av); static OBJECT getmod(void); -static int puttri(char *v1, char *v2, char *v3); +static int puttri(char *v1, char *v2, char *v3); static void freeverts(void); -static int newv(double x, double y, double z); -static int newvn(double x, double y, double z); -static int newvt(double x, double y); +static int newv(double x, double y, double z); +static int newvn(double x, double y, double z); +static int newvt(double x, double y); static void syntax(char *er); @@ -244,26 +245,71 @@ cvtndx( /* convert vertex string to index */ return(1); } +/* determine dominant axis for triangle */ +static int +dominant_axis(char *v1, char *v2, char *v3) +{ + VNDX v1i, v2i, v3i; + FVECT e1, e2, vn; + int i, imax; + if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) + return(-1); + VSUB(e1, vlist[v2i[0]], vlist[v1i[0]]); + VSUB(e2, vlist[v3i[0]], vlist[v2i[0]]); + VCROSS(vn, e1, e2); + for (i = imax = 2; i--; ) + if (vn[i]*vn[i] > vn[imax]*vn[imax]) + imax = i; + return(vn[imax]*vn[imax] > FTINY ? imax : -1); +} + +/* callback for triangle output from polygon */ static int +tri_out(const Vert2_list *tp, int a, int b, int c) +{ + return( puttri( ((char **)tp->p)[a], + ((char **)tp->p)[b], + ((char **)tp->p)[c] ) ); +} + +static int putface( /* put out an N-sided polygon */ int ac, char **av ) { - char *cp; - int i; + Vert2_list *poly = polyAlloc(ac); + int i, ax, ay; - while (ac > 3) { /* break into triangles */ - if (!puttri(av[0], av[1], av[2])) + if (poly == NULL) + return(0); + poly->p = (void *)av; + for (i = ac-3; i >= 0; i--) /* identify dominant axis */ + if ((ax = dominant_axis(av[i], av[i+1], av[i+2])) >= 0) + break; + if (ax < 0) + return(1); /* ignore degenerate face */ + if (++ax >= 3) ax = 0; + ay = ax; + if (++ay >= 3) ay = 0; + for (i = 0; i < ac; i++) { /* convert to 2-D polygon */ + VNDX vi; + if (!cvtndx(vi, av[i])) { + error(WARNING, "bad vertex reference"); + polyFree(poly); return(0); - ac--; /* remove vertex & rotate */ - cp = av[0]; - for (i = 0; i < ac-1; i++) - av[i] = av[i+2]; - av[i] = cp; + } + poly->v[i].mX = vlist[vi[0]][ax]; + poly->v[i].mY = vlist[vi[0]][ay]; } - return(puttri(av[0], av[1], av[2])); + /* break into triangles & output */ + if (!polyTriangulate(poly, &tri_out)) { + sprintf(errmsg, "self-intersecting face with %d vertices", ac); + error(WARNING, errmsg); + } + polyFree(poly); + return(1); }