ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/wfconv.c
(Generate patch)

Comparing ray/src/ot/wfconv.c (file contents):
Revision 2.1 by greg, Tue Mar 11 17:08:55 2003 UTC vs.
Revision 2.18 by greg, Fri Apr 30 16:40:10 2021 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   #include "copyright.h"
10   #include "standard.h"
11   #include "cvmesh.h"
12 + #include "triangulate.h"
13   #include <ctype.h>
14  
14 FVECT   *vlist;                 /* our vertex list */
15 int     nvs;                    /* number of vertices in our list */
16 FVECT   *vnlist;                /* vertex normal list */
17 int     nvns;
18 FLOAT   (*vtlist)[2];           /* map vertex list */
19 int     nvts;
20
15   typedef int     VNDX[3];        /* vertex index (point,map,normal) */
16  
17   #define CHUNKSIZ        1024    /* vertex allocation chunk size */
18  
19 < #define MAXARG          64      /* maximum # arguments in a statement */
19 > #define MAXARG          512     /* maximum # arguments in a statement */
20  
21 < char    *inpfile;               /* input file name */
22 < int     lineno;                 /* current line number */
23 < int     faceno;                 /* current face number */
21 > static FVECT    *vlist;         /* our vertex list */
22 > static int      nvs;            /* number of vertices in our list */
23 > static FVECT    *vnlist;        /* vertex normal list */
24 > static int      nvns;
25 > static RREAL    (*vtlist)[2];   /* map vertex list */
26 > static int      nvts;
27  
28 + static char     *inpfile;       /* input file name */
29 + static int      havemats;       /* materials available? */
30 + static char     material[256];  /* current material name */
31 + static char     group[256];     /* current group name */
32 + static int      lineno;         /* current line number */
33 + static int      faceno;         /* current face number */
34  
35 < wfreadobj(objfn)                /* read in .OBJ file and convert */
36 < char    *objfn;
35 > static int getstmt(char *av[MAXARG], FILE *fp);
36 > static int cvtndx(VNDX vi, char *vs);
37 > static int putface(int ac, char **av);
38 > static OBJECT getmod(void);
39 > static int puttri(char  *v1, char *v2, char *v3);
40 > static void freeverts(void);
41 > static int newv(double  x, double y, double z);
42 > static int newvn(double x, double y, double z);
43 > static int newvt(double x, double y);
44 > static void syntax(char *er);
45 >
46 >
47 > void
48 > wfreadobj(              /* read in .OBJ file and convert */
49 >        char    *objfn
50 > )
51   {
52          FILE    *fp;
53          char    *argv[MAXARG];
54          int     argc;
55          int     nstats, nunknown;
39        int     i;
56  
57          if (objfn == NULL) {
58                  inpfile = "<stdin>";
# Line 45 | Line 61 | char   *objfn;
61                  sprintf(errmsg, "cannot open \"%s\"", inpfile);
62                  error(USER, errmsg);
63          }
64 +        havemats = (nobjects > 0);
65          nstats = nunknown = 0;
66 +        material[0] = '\0';
67 +        group[0] = '\0';
68          lineno = 0; faceno = 0;
69                                          /* scan until EOF */
70 <        while (argc = getstmt(argv, fp)) {
70 >        while ( (argc = getstmt(argv, fp)) ) {
71                  switch (argv[0][0]) {
72                  case 'v':               /* vertex */
73                          switch (argv[0][1]) {
74                          case '\0':                      /* point */
75                                  if (badarg(argc-1,argv+1,"fff"))
76 <                                        syntax("Bad vertex");
76 >                                        syntax("bad vertex");
77                                  newv(atof(argv[1]), atof(argv[2]),
78                                                  atof(argv[3]));
79                                  break;
# Line 62 | Line 81 | char   *objfn;
81                                  if (argv[0][2])
82                                          goto unknown;
83                                  if (badarg(argc-1,argv+1,"fff"))
84 <                                        syntax("Bad normal");
84 >                                        syntax("bad normal");
85                                  if (!newvn(atof(argv[1]), atof(argv[2]),
86                                                  atof(argv[3])))
87 <                                        syntax("Zero normal");
87 >                                        syntax("zero normal");
88                                  break;
89 <                        case 't':                       /* texture map */
89 >                        case 't':                       /* coordinate */
90                                  if (argv[0][2])
91                                          goto unknown;
92                                  if (badarg(argc-1,argv+1,"ff"))
# Line 84 | Line 103 | char   *objfn;
103                          faceno++;
104                          switch (argc-1) {
105                          case 0: case 1: case 2:
106 <                                syntax("Too few vertices");
106 >                                syntax("too few vertices");
107                                  break;
108                          case 3:
109                                  if (!puttri(argv[1], argv[2], argv[3]))
110 <                                        syntax("Bad triangle");
110 >                                        syntax("bad triangle");
111                                  break;
112                          default:
113                                  if (!putface(argc-1, argv+1))
114 <                                        syntax("Bad face");
114 >                                        syntax("bad face");
115                                  break;
116                          }
117                          break;
118 <                case 'u':
119 <                        if (strcmp(argv[0], "usemtl") &&
120 <                                        strcmp(argv[0], "usemap"))
118 >                case 'u':                               /* usemtl/usemap */
119 >                        if (!strcmp(argv[0], "usemap"))
120 >                                break;
121 >                        if (strcmp(argv[0], "usemtl"))
122                                  goto unknown;
123 +                        if (argc > 1)
124 +                                strcpy(material, argv[1]);
125 +                        else
126 +                                material[0] = '\0';
127                          break;
128                  case 'o':               /* object name */
129                          if (argv[0][1])
130                                  goto unknown;
131                          break;
132 <                case 'g':               /* group name(s) */
132 >                case 'g':               /* group name */
133                          if (argv[0][1])
134                                  goto unknown;
135 +                        if (argc > 1)
136 +                                strcpy(group, argv[1]);
137 +                        else
138 +                                group[0] = '\0';
139                          break;
140                  case '#':               /* comment */
141                          break;
# Line 129 | Line 157 | char   *objfn;
157   }
158  
159  
160 < int
161 < getstmt(av, fp)                         /* read the next statement from fp */
162 < register char   *av[MAXARG];
163 < FILE    *fp;
160 > static int
161 > getstmt(                                /* read the next statement from fp */
162 >        char    *av[MAXARG],
163 >        FILE    *fp
164 > )
165   {
166 <        static char     sbuf[MAXARG*10];
167 <        register char   *cp;
168 <        register int    i;
166 >        static char     sbuf[MAXARG*16];
167 >        char    *cp;
168 >        int     i;
169  
170          do {
171                  if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
# Line 148 | Line 177 | FILE   *fp;
177                                          lineno++;
178                                  *cp++ = '\0';
179                          }
180 <                        if (!*cp || i >= MAXARG-1)
180 >                        if (!*cp)
181                                  break;
182 +                        if (i >= MAXARG-1) {
183 +                                sprintf(errmsg,
184 +                        "%s: too many arguments near line %d (limit %d)\n",
185 +                                        inpfile, lineno+1, MAXARG-1);
186 +                                break;
187 +                        }
188                          av[i++] = cp;
189                          while (*++cp && !isspace(*cp))
190                                  ;
# Line 162 | Line 197 | FILE   *fp;
197   }
198  
199  
200 < cvtndx(vi, vs)                          /* convert vertex string to index */
201 < register VNDX   vi;
202 < register char   *vs;
200 > static int
201 > cvtndx(                         /* convert vertex string to index */
202 >        VNDX    vi,
203 >        char    *vs
204 > )
205   {
206                                          /* get point */
207          vi[0] = atoi(vs);
# Line 208 | Line 245 | register char  *vs;
245          return(1);
246   }
247  
248 + /* determine dominant axis for triangle */
249 + static int
250 + dominant_axis(char *v1, char *v2, char *v3)
251 + {
252 +        VNDX    v1i, v2i, v3i;
253 +        FVECT   e1, e2, vn;
254 +        int     i, imax;
255  
256 < putface(ac, av)                         /* put out an N-sided polygon */
257 < int     ac;
258 < register char   **av;
256 >        if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
257 >                return(-1);
258 >        VSUB(e1, vlist[v2i[0]], vlist[v1i[0]]);
259 >        VSUB(e2, vlist[v3i[0]], vlist[v2i[0]]);
260 >        VCROSS(vn, e1, e2);
261 >        for (i = imax = 2; i--; )
262 >                if (vn[i]*vn[i] > vn[imax]*vn[imax])
263 >                        imax = i;
264 >        return(vn[imax]*vn[imax] > FTINY*FTINY*FTINY*FTINY ? imax : -1);
265 > }
266 >
267 > /* struct needed for triangulation callback */
268 > typedef struct {
269 >        char    **avl;
270 >        int     rev;
271 > } WFpoly;
272 >
273 > /* callback for triangle output from polygon */
274 > static int
275 > tri_out(const Vert2_list *tp, int a, int b, int c)
276   {
277 <        VNDX            vi;
217 <        char            *cp;
218 <        register int    i;
277 >        WFpoly *        wp = (WFpoly *)tp->p;
278  
279 <        while (ac > 3) {                /* break into triangles */
280 <                if (!puttri(av[0], av[1], av[2]))
281 <                        {
282 <                        fprintf(stderr, "f %s %s %s\n", av[0], av[1], av[2]);
279 >        if (wp->rev)
280 >                return( puttri(wp->avl[c], wp->avl[b], wp->avl[a]) );
281 >
282 >        return( puttri(wp->avl[a], wp->avl[b], wp->avl[c]) );
283 > }
284 >
285 > static int
286 > putface(                                /* put out an N-sided polygon */
287 >        int     ac,
288 >        char    **av
289 > )
290 > {
291 >        Vert2_list      *poly;
292 >        WFpoly          myps;
293 >        int             i, ax, ay;
294 >
295 >        for (i = ac-3; i >= 0; i--)     /* identify dominant axis */
296 >                if ((ax = dominant_axis(av[i], av[i+1], av[i+2])) >= 0)
297 >                        break;
298 >        if (ax < 0)
299 >                return(1);              /* ignore degenerate face */
300 >        poly = polyAlloc(ac);
301 >        if (poly == NULL)
302 >                return(0);
303 >        myps.avl = av;
304 >        poly->p = &myps;
305 >        if (++ax >= 3) ax = 0;
306 >        ay = ax;
307 >        if (++ay >= 3) ay = 0;
308 >        for (i = 0; i < ac; i++) {      /* convert to 2-D polygon */
309 >                VNDX    vi;
310 >                if (!cvtndx(vi, av[i])) {
311 >                        error(WARNING, "bad vertex reference");
312 >                        polyFree(poly);
313                          return(0);
314 <                        }
315 <                ac--;                   /* remove vertex & rotate */
316 <                cp = av[0];
228 <                for (i = 0; i < ac-1; i++)
229 <                        av[i] = av[i+2];
230 <                av[i] = cp;
314 >                }
315 >                poly->v[i].mX = vlist[vi[0]][ax];
316 >                poly->v[i].mY = vlist[vi[0]][ay];
317          }
318 <        return(puttri(av[0], av[1], av[2]));
318 >                                        /* flag for order reversal */
319 >        myps.rev = (polyArea(poly) < .0);
320 >                                        /* break into triangles & output */
321 >        if (!polyTriangulate(poly, &tri_out)) {
322 >                sprintf(errmsg, "self-intersecting face with %d vertices", ac);
323 >                error(WARNING, errmsg);
324 >        }
325 >        polyFree(poly);
326 >        return(1);
327   }
328  
329  
330 < puttri(v1, v2, v3)                      /* convert a triangle */
331 < char    *v1, *v2, *v3;
330 > static OBJECT
331 > getmod(void)                            /* get current modifier ID */
332   {
333 <        VNDX    v1i, v2i, v3i;
334 <        FLOAT   *v1c, *v2c, *v3c;
241 <        FLOAT   *v1n, *v2n, *v3n;
333 >        char    *mnam;
334 >        OBJECT  mod;
335  
336 <        if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
337 <                return(0);
336 >        if (!havemats)
337 >                return(OVOID);
338 >        if (!strcmp(material, VOIDID))
339 >                return(OVOID);
340 >        if (material[0])                /* prefer usemtl statements */
341 >                mnam = material;
342 >        else if (group[0])              /* else use group name */
343 >                mnam = group;
344 >        else
345 >                return(OVOID);
346 >        mod = modifier(mnam);
347 >        if (mod == OVOID) {
348 >                sprintf(errmsg, "%s: undefined modifier \"%s\"",
349 >                                inpfile, mnam);
350 >                error(USER, errmsg);
351 >        }
352 >        return(mod);
353 > }
354  
355 +
356 + static int
357 + puttri(                 /* convert a triangle */
358 +        char    *v1,
359 +        char    *v2,
360 +        char    *v3
361 + )
362 + {
363 +        VNDX    v1i, v2i, v3i;
364 +        RREAL   *v1c, *v2c, *v3c;
365 +        RREAL   *v1n, *v2n, *v3n;
366 +        
367 +        if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) {
368 +                error(WARNING, "bad vertex reference");
369 +                return(0);
370 +        }
371          if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
372                  v1c = vtlist[v1i[1]];
373                  v2c = vtlist[v2i[1]];
# Line 257 | Line 382 | char   *v1, *v2, *v3;
382          } else
383                  v1n = v2n = v3n = NULL;
384          
385 <        return(cvtri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
385 >        return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
386                          v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
387   }
388  
389  
390 < freeverts()                     /* free all vertices */
390 > static void
391 > freeverts(void)                 /* free all vertices */
392   {
393          if (nvs) {
394                  free((void *)vlist);
# Line 279 | Line 405 | freeverts()                    /* free all vertices */
405   }
406  
407  
408 < int
409 < newv(x, y, z)                   /* create a new vertex */
410 < double  x, y, z;
408 > static int
409 > newv(                   /* create a new vertex */
410 >        double  x,
411 >        double  y,
412 >        double  z
413 > )
414   {
415          if (!(nvs%CHUNKSIZ)) {          /* allocate next block */
416                  if (nvs == 0)
417                          vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
418                  else
419 <                        vlist = (FVECT *)realloc((char *)vlist,
419 >                        vlist = (FVECT *)realloc((void *)vlist,
420                                          (nvs+CHUNKSIZ)*sizeof(FVECT));
421 <                if (vlist == NULL) {
422 <                        fprintf(stderr,
294 <                        "Out of memory while allocating vertex %d\n", nvs);
295 <                        exit(1);
296 <                }
421 >                if (vlist == NULL)
422 >                        error(SYSTEM, "out of memory in newv");
423          }
424                                          /* assign new vertex */
425          vlist[nvs][0] = x;
# Line 303 | Line 429 | double x, y, z;
429   }
430  
431  
432 < int
433 < newvn(x, y, z)                  /* create a new vertex normal */
434 < double  x, y, z;
432 > static int
433 > newvn(                  /* create a new vertex normal */
434 >        double  x,
435 >        double  y,
436 >        double  z
437 > )
438   {
439          if (!(nvns%CHUNKSIZ)) {         /* allocate next block */
440                  if (nvns == 0)
441                          vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
442                  else
443 <                        vnlist = (FVECT *)realloc((char *)vnlist,
443 >                        vnlist = (FVECT *)realloc((void *)vnlist,
444                                          (nvns+CHUNKSIZ)*sizeof(FVECT));
445 <                if (vnlist == NULL) {
446 <                        fprintf(stderr,
318 <                        "Out of memory while allocating normal %d\n", nvns);
319 <                        exit(1);
320 <                }
445 >                if (vnlist == NULL)
446 >                        error(SYSTEM, "out of memory in newvn");
447          }
448                                          /* assign new normal */
449          vnlist[nvns][0] = x;
# Line 329 | Line 455 | double x, y, z;
455   }
456  
457  
458 < int
459 < newvt(x, y)                     /* create a new texture map vertex */
460 < double  x, y;
458 > static int
459 > newvt(                  /* create a new texture map vertex */
460 >        double  x,
461 >        double  y
462 > )
463   {
464          if (!(nvts%CHUNKSIZ)) {         /* allocate next block */
465                  if (nvts == 0)
466 <                        vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
466 >                        vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL));
467                  else
468 <                        vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
469 <                                        (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
470 <                if (vtlist == NULL) {
471 <                        fprintf(stderr,
344 <                        "Out of memory while allocating texture vertex %d\n",
345 <                                        nvts);
346 <                        exit(1);
347 <                }
468 >                        vtlist = (RREAL (*)[2])realloc((void *)vtlist,
469 >                                        (nvts+CHUNKSIZ)*2*sizeof(RREAL));
470 >                if (vtlist == NULL)
471 >                        error(SYSTEM, "out of memory in newvt");
472          }
473                                          /* assign new vertex */
474          vtlist[nvts][0] = x;
# Line 353 | Line 477 | double x, y;
477   }
478  
479  
480 < syntax(er)                      /* report syntax error and exit */
481 < char    *er;
480 > static void
481 > syntax(                 /* report syntax error and exit */
482 >        char    *er
483 > )
484   {
485 <        fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
485 >        sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s",
486                          inpfile, lineno, er);
487 <        exit(1);
487 >        error(USER, errmsg);
488   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines