--- ray/src/ot/wfconv.c 2003/03/11 17:08:55 2.1 +++ ray/src/ot/wfconv.c 2004/04/23 16:20:56 2.9 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: wfconv.c,v 2.1 2003/03/11 17:08:55 greg Exp $"; +static const char RCSid[] = "$Id: wfconv.c,v 2.9 2004/04/23 16:20:56 greg Exp $"; #endif /* * Load Wavefront .OBJ file and convert to triangles with mesh info. @@ -11,32 +11,47 @@ static const char RCSid[] = "$Id: wfconv.c,v 2.1 2003/ #include "cvmesh.h" #include -FVECT *vlist; /* our vertex list */ -int nvs; /* number of vertices in our list */ -FVECT *vnlist; /* vertex normal list */ -int nvns; -FLOAT (*vtlist)[2]; /* map vertex list */ -int nvts; - 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 */ -char *inpfile; /* input file name */ -int lineno; /* current line number */ -int faceno; /* current face number */ +static FVECT *vlist; /* our vertex list */ +static int nvs; /* number of vertices in our list */ +static FVECT *vnlist; /* vertex normal list */ +static int nvns; +static RREAL (*vtlist)[2]; /* map vertex list */ +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 int lineno; /* current line number */ +static int faceno; /* current face number */ -wfreadobj(objfn) /* read in .OBJ file and convert */ -char *objfn; +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 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 void syntax(char *er); + + +void +wfreadobj( /* read in .OBJ file and convert */ + char *objfn +) { FILE *fp; char *argv[MAXARG]; int argc; int nstats, nunknown; - int i; if (objfn == NULL) { inpfile = ""; @@ -45,16 +60,19 @@ char *objfn; sprintf(errmsg, "cannot open \"%s\"", inpfile); error(USER, errmsg); } + havemats = (nobjects > 0); nstats = nunknown = 0; + material[0] = '\0'; + group[0] = '\0'; lineno = 0; faceno = 0; /* scan until EOF */ - while (argc = getstmt(argv, fp)) { + while ( (argc = getstmt(argv, fp)) ) { switch (argv[0][0]) { case 'v': /* vertex */ switch (argv[0][1]) { case '\0': /* point */ if (badarg(argc-1,argv+1,"fff")) - syntax("Bad vertex"); + syntax("bad vertex"); newv(atof(argv[1]), atof(argv[2]), atof(argv[3])); break; @@ -62,12 +80,12 @@ char *objfn; if (argv[0][2]) goto unknown; if (badarg(argc-1,argv+1,"fff")) - syntax("Bad normal"); + syntax("bad normal"); if (!newvn(atof(argv[1]), atof(argv[2]), atof(argv[3]))) - syntax("Zero normal"); + syntax("zero normal"); break; - case 't': /* texture map */ + case 't': /* coordinate */ if (argv[0][2]) goto unknown; if (badarg(argc-1,argv+1,"ff")) @@ -84,30 +102,39 @@ char *objfn; faceno++; switch (argc-1) { case 0: case 1: case 2: - syntax("Too few vertices"); + syntax("too few vertices"); break; case 3: if (!puttri(argv[1], argv[2], argv[3])) - syntax("Bad triangle"); + syntax("bad triangle"); break; default: if (!putface(argc-1, argv+1)) - syntax("Bad face"); + syntax("bad face"); break; } break; - case 'u': - if (strcmp(argv[0], "usemtl") && - strcmp(argv[0], "usemap")) + case 'u': /* usemtl/usemap */ + if (!strcmp(argv[0], "usemap")) + break; + if (strcmp(argv[0], "usemtl")) goto unknown; + if (argc > 1) + strcpy(material, argv[1]); + else + material[0] = '\0'; break; case 'o': /* object name */ if (argv[0][1]) goto unknown; break; - case 'g': /* group name(s) */ + case 'g': /* group name */ if (argv[0][1]) goto unknown; + if (argc > 1) + strcpy(group, argv[1]); + else + group[0] = '\0'; break; case '#': /* comment */ break; @@ -129,12 +156,13 @@ char *objfn; } -int -getstmt(av, fp) /* read the next statement from fp */ -register char *av[MAXARG]; -FILE *fp; +static int +getstmt( /* read the next statement from fp */ + register char *av[MAXARG], + FILE *fp +) { - static char sbuf[MAXARG*10]; + static char sbuf[MAXARG*16]; register char *cp; register int i; @@ -148,8 +176,14 @@ FILE *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)) ; @@ -162,9 +196,11 @@ FILE *fp; } -cvtndx(vi, vs) /* convert vertex string to index */ -register VNDX vi; -register char *vs; +static int +cvtndx( /* convert vertex string to index */ + register VNDX vi, + register char *vs +) { /* get point */ vi[0] = atoi(vs); @@ -209,20 +245,18 @@ register char *vs; } -putface(ac, av) /* put out an N-sided polygon */ -int ac; -register char **av; +static int +putface( /* put out an N-sided polygon */ + int ac, + register char **av +) { - VNDX vi; char *cp; register int i; while (ac > 3) { /* break into triangles */ if (!puttri(av[0], av[1], av[2])) - { - fprintf(stderr, "f %s %s %s\n", av[0], av[1], av[2]); return(0); - } ac--; /* remove vertex & rotate */ cp = av[0]; for (i = 0; i < ac-1; i++) @@ -233,16 +267,47 @@ register char **av; } -puttri(v1, v2, v3) /* convert a triangle */ -char *v1, *v2, *v3; +static OBJECT +getmod(void) /* get current modifier ID */ { - VNDX v1i, v2i, v3i; - FLOAT *v1c, *v2c, *v3c; - FLOAT *v1n, *v2n, *v3n; + char *mnam; + OBJECT mod; - if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) - return(0); + if (!havemats) + return(OVOID); + if (!strcmp(material, VOIDID)) + return(OVOID); + if (material[0]) /* prefer usemtl statements */ + mnam = material; + else if (group[0]) /* else use group name */ + mnam = group; + else + return(OVOID); + mod = modifier(mnam); + if (mod == OVOID) { + sprintf(errmsg, "%s: undefined modifier \"%s\"", + inpfile, mnam); + error(USER, errmsg); + } + return(mod); +} + +static int +puttri( /* convert a triangle */ + char *v1, + char *v2, + char *v3 +) +{ + VNDX v1i, v2i, v3i; + RREAL *v1c, *v2c, *v3c; + RREAL *v1n, *v2n, *v3n; + + if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) { + error(WARNING, "bad vertex reference"); + return(0); + } if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) { v1c = vtlist[v1i[1]]; v2c = vtlist[v2i[1]]; @@ -257,12 +322,13 @@ char *v1, *v2, *v3; } else v1n = v2n = v3n = NULL; - return(cvtri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]], + return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]], v1n, v2n, v3n, v1c, v2c, v3c) >= 0); } -freeverts() /* free all vertices */ +static void +freeverts(void) /* free all vertices */ { if (nvs) { free((void *)vlist); @@ -279,21 +345,21 @@ freeverts() /* free all vertices */ } -int -newv(x, y, z) /* create a new vertex */ -double x, y, z; +static int +newv( /* create a new vertex */ + double x, + double y, + double z +) { if (!(nvs%CHUNKSIZ)) { /* allocate next block */ if (nvs == 0) vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT)); else - vlist = (FVECT *)realloc((char *)vlist, + vlist = (FVECT *)realloc((void *)vlist, (nvs+CHUNKSIZ)*sizeof(FVECT)); - if (vlist == NULL) { - fprintf(stderr, - "Out of memory while allocating vertex %d\n", nvs); - exit(1); - } + if (vlist == NULL) + error(SYSTEM, "out of memory in newv"); } /* assign new vertex */ vlist[nvs][0] = x; @@ -303,21 +369,21 @@ double x, y, z; } -int -newvn(x, y, z) /* create a new vertex normal */ -double x, y, z; +static int +newvn( /* create a new vertex normal */ + double x, + double y, + double z +) { if (!(nvns%CHUNKSIZ)) { /* allocate next block */ if (nvns == 0) vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT)); else - vnlist = (FVECT *)realloc((char *)vnlist, + vnlist = (FVECT *)realloc((void *)vnlist, (nvns+CHUNKSIZ)*sizeof(FVECT)); - if (vnlist == NULL) { - fprintf(stderr, - "Out of memory while allocating normal %d\n", nvns); - exit(1); - } + if (vnlist == NULL) + error(SYSTEM, "out of memory in newvn"); } /* assign new normal */ vnlist[nvns][0] = x; @@ -329,22 +395,20 @@ double x, y, z; } -int -newvt(x, y) /* create a new texture map vertex */ -double x, y; +static int +newvt( /* create a new texture map vertex */ + double x, + double y +) { if (!(nvts%CHUNKSIZ)) { /* allocate next block */ if (nvts == 0) - vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT)); + vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL)); else - vtlist = (FLOAT (*)[2])realloc((char *)vtlist, - (nvts+CHUNKSIZ)*2*sizeof(FLOAT)); - if (vtlist == NULL) { - fprintf(stderr, - "Out of memory while allocating texture vertex %d\n", - nvts); - exit(1); - } + vtlist = (RREAL (*)[2])realloc((void *)vtlist, + (nvts+CHUNKSIZ)*2*sizeof(RREAL)); + if (vtlist == NULL) + error(SYSTEM, "out of memory in newvt"); } /* assign new vertex */ vtlist[nvts][0] = x; @@ -353,10 +417,12 @@ double x, y; } -syntax(er) /* report syntax error and exit */ -char *er; +static void +syntax( /* report syntax error and exit */ + char *er +) { - fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n", + sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n", inpfile, lineno, er); - exit(1); + error(USER, errmsg); }