--- ray/src/ot/wfconv.c 2004/03/27 12:41:45 2.8 +++ ray/src/ot/wfconv.c 2014/01/24 02:22:49 2.12 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: wfconv.c,v 2.8 2004/03/27 12:41:45 schorsch Exp $"; +static const char RCSid[] = "$Id: wfconv.c,v 2.12 2014/01/24 02:22:49 greg Exp $"; #endif /* * Load Wavefront .OBJ file and convert to triangles with mesh info. @@ -9,13 +9,14 @@ static const char RCSid[] = "$Id: wfconv.c,v 2.8 2004/ #include "copyright.h" #include "standard.h" #include "cvmesh.h" +#include "triangulate.h" #include typedef int VNDX[3]; /* vertex index (point,map,normal) */ #define CHUNKSIZ 1024 /* vertex allocation chunk size */ -#define MAXARG 64 /* maximum # arguments in a statement */ +#define MAXARG 512 /* maximum # arguments in a statement */ static FVECT *vlist; /* our vertex list */ static int nvs; /* number of vertices in our list */ @@ -26,8 +27,8 @@ static int nvts; static char *inpfile; /* input file name */ static int havemats; /* materials available? */ -static char material[64]; /* current material name */ -static char group[64]; /* current group name */ +static char material[256]; /* current material name */ +static char group[256]; /* current group name */ static int lineno; /* current line number */ static int faceno; /* current face number */ @@ -158,13 +159,13 @@ wfreadobj( /* read in .OBJ file and convert */ static int getstmt( /* read the next statement from fp */ - register char *av[MAXARG], + char *av[MAXARG], FILE *fp ) { static char sbuf[MAXARG*16]; - register char *cp; - register int i; + char *cp; + int i; do { if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL) @@ -176,8 +177,14 @@ getstmt( /* read the next statement from fp */ lineno++; *cp++ = '\0'; } - if (!*cp || i >= MAXARG-1) + if (!*cp) break; + if (i >= MAXARG-1) { + sprintf(errmsg, + "%s: too many arguments near line %d (limit %d)\n", + inpfile, lineno+1, MAXARG-1); + break; + } av[i++] = cp; while (*++cp && !isspace(*cp)) ; @@ -192,8 +199,8 @@ getstmt( /* read the next statement from fp */ static int cvtndx( /* convert vertex string to index */ - register VNDX vi, - register char *vs + VNDX vi, + char *vs ) { /* get point */ @@ -238,26 +245,69 @@ 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, - register char **av + char **av ) { - char *cp; - register 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)) + error(WARNING, "self-intersecting face"); + polyFree(poly); + return(1); }