ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.32
Committed: Thu Apr 15 23:51:04 2021 UTC (3 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.31: +3 -3 lines
Log Message:
feat(genbox,robjutil): Added Radiance normal smoothing support to wfobj library

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.32 static const char RCSid[] = "$Id: obj2rad.c,v 2.31 2020/01/28 21:18:02 greg Exp $";
3 greg 2.1 #endif
4     /*
5 greg 2.28 * Convert a Wavefront .OBJ file to Radiance format.
6 greg 2.1 *
7 greg 2.5 * Currently, we support only polygonal geometry. Non-planar
8     * faces are broken rather haphazardly into triangles.
9 greg 2.3 * Also, texture map indices only work for triangles, though
10 greg 2.7 * I'm not sure they work correctly. (Taken out -- see TEXMAPS defines.)
11 greg 2.1 */
12    
13 schorsch 2.22 #include <stdlib.h>
14     #include <ctype.h>
15 greg 2.1
16 schorsch 2.22 #include "rtmath.h"
17     #include "rtio.h"
18     #include "resolu.h"
19 greg 2.3 #include "trans.h"
20 greg 2.15 #include "tmesh.h"
21    
22 greg 2.1
23     #define PATNAME "M-pat" /* mesh pattern name (reused) */
24     #define TEXNAME "M-nor" /* mesh texture name (reused) */
25 greg 2.3 #define DEFOBJ "unnamed" /* default object name */
26     #define DEFMAT "white" /* default material name */
27 greg 2.1
28 greg 2.31 #define pvect(v) printf(" %18.12g %18.12g %18.12g\n",(v)[0],(v)[1],(v)[2])
29 greg 2.1
30     FVECT *vlist; /* our vertex list */
31     int nvs; /* number of vertices in our list */
32     FVECT *vnlist; /* vertex normal list */
33     int nvns;
34 schorsch 2.20 RREAL (*vtlist)[2]; /* map vertex list */
35 greg 2.1 int nvts;
36    
37 greg 2.24 int ndegen = 0; /* count of degenerate faces */
38 greg 2.26 int n0norm = 0; /* count of zero normals */
39 greg 2.24
40 greg 2.3 typedef int VNDX[3]; /* vertex index (point,map,normal) */
41 greg 2.1
42 greg 2.23 #define CHUNKSIZ 1024 /* vertex allocation chunk size */
43 greg 2.1
44 greg 2.23 #define MAXARG 512 /* maximum # arguments in a statement */
45 greg 2.1
46 greg 2.3 /* qualifiers */
47     #define Q_MTL 0
48     #define Q_MAP 1
49     #define Q_GRP 2
50     #define Q_OBJ 3
51     #define Q_FAC 4
52     #define NQUALS 5
53 greg 2.1
54 greg 2.3 char *qname[NQUALS] = {
55     "Material",
56     "Map",
57     "Group",
58     "Object",
59     "Face",
60     };
61    
62     QLIST qlist = {NQUALS, qname};
63     /* valid qualifier ids */
64     IDLIST qual[NQUALS];
65     /* mapping rules */
66     RULEHD *ourmapping = NULL;
67    
68     char *defmat = DEFMAT; /* default (starting) material name */
69     char *defobj = DEFOBJ; /* default (starting) object name */
70    
71 greg 2.8 int flatten = 0; /* discard surface normal information */
72    
73 greg 2.29 char mapname[256]; /* current picture file */
74     char matname[256]; /* current material name */
75 greg 2.28 char group[8][256]; /* current group name(s) */
76 greg 2.29 char objname[256]; /* current object name */
77 greg 2.6 char *inpfile; /* input file name */
78 greg 2.1 int lineno; /* current line number */
79 greg 2.6 int faceno; /* current face number */
80 greg 2.1
81 schorsch 2.22 static void getnames(FILE *fp);
82     static void convert(FILE *fp);
83     static int getstmt(char *av[MAXARG], FILE *fp);
84     static char * getmtl(void);
85     static char * getonm(void);
86     static int matchrule(RULEHD *rp);
87     static int cvtndx(VNDX vi, char *vs);
88     static int nonplanar(int ac, char **av);
89     static int putface(int ac, char **av);
90     static int puttri(char *v1, char *v2, char *v3);
91     static void freeverts(void);
92     static int newv(double x, double y, double z);
93     static int newvn(double x, double y, double z);
94     static int newvt(double x, double y);
95     static void syntax(char *er);
96    
97 greg 2.1
98 schorsch 2.22 int
99 greg 2.28 main( /* read in .OBJ file and convert */
100 schorsch 2.22 int argc,
101     char *argv[]
102     )
103 greg 2.1 {
104 greg 2.6 int donames = 0;
105 greg 2.1 int i;
106    
107     for (i = 1; i < argc && argv[i][0] == '-'; i++)
108     switch (argv[i][1]) {
109     case 'o': /* object name */
110     defobj = argv[++i];
111     break;
112 greg 2.3 case 'n': /* just produce name list */
113     donames++;
114 greg 2.1 break;
115 greg 2.3 case 'm': /* use custom mapfile */
116     ourmapping = getmapping(argv[++i], &qlist);
117 greg 2.1 break;
118 greg 2.8 case 'f': /* flatten surfaces */
119     flatten++;
120     break;
121 greg 2.1 default:
122 greg 2.3 goto userr;
123 greg 2.1 }
124 schorsch 2.21 if ((i > argc) | (i < argc-1))
125 greg 2.3 goto userr;
126     if (i == argc)
127 greg 2.6 inpfile = "<stdin>";
128     else if (freopen(inpfile=argv[i], "r", stdin) == NULL) {
129     fprintf(stderr, "%s: cannot open\n", inpfile);
130 greg 2.3 exit(1);
131     }
132     if (donames) { /* scan for ids */
133     getnames(stdin);
134 greg 2.6 printf("filename \"%s\"\n", inpfile);
135 greg 2.3 printf("filetype \"Wavefront\"\n");
136     write_quals(&qlist, qual, stdout);
137     printf("qualifier %s begin\n", qlist.qual[Q_FAC]);
138     printf("[%d:%d]\n", 1, faceno);
139     printf("end\n");
140     } else { /* translate file */
141     printf("# ");
142     printargs(argc, argv, stdout);
143 greg 2.6 convert(stdin);
144 greg 2.3 }
145 greg 2.24 if (ndegen)
146     printf("# %d degenerate faces\n", ndegen);
147 greg 2.26 if (n0norm)
148     printf("# %d invalid (zero) normals\n", n0norm);
149 greg 2.3 exit(0);
150     userr:
151 greg 2.9 fprintf(stderr, "Usage: %s [-o obj][-m mapping][-n][-f] [file.obj]\n",
152 greg 2.3 argv[0]);
153     exit(1);
154     }
155    
156    
157 schorsch 2.22 void
158     getnames( /* get valid qualifier names */
159     FILE *fp
160     )
161 greg 2.3 {
162     char *argv[MAXARG];
163     int argc;
164     ID tmpid;
165 greg 2.28 int i;
166 greg 2.3
167 schorsch 2.21 while ( (argc = getstmt(argv, fp)) )
168 greg 2.3 switch (argv[0][0]) {
169     case 'f': /* face */
170     if (!argv[0][1])
171     faceno++;
172     break;
173     case 'u':
174     if (!strcmp(argv[0], "usemtl")) { /* material */
175     if (argc < 2)
176     break; /* not fatal */
177     tmpid.number = 0;
178     tmpid.name = argv[1];
179     findid(&qual[Q_MTL], &tmpid, 1);
180     } else if (!strcmp(argv[0], "usemap")) {/* map */
181     if (argc < 2 || !strcmp(argv[1], "off"))
182     break; /* not fatal */
183     tmpid.number = 0;
184     tmpid.name = argv[1];
185     findid(&qual[Q_MAP], &tmpid, 1);
186 greg 2.1 }
187 greg 2.3 break;
188     case 'o': /* object name */
189     if (argv[0][1] || argc < 2)
190     break;
191     tmpid.number = 0;
192     tmpid.name = argv[1];
193     findid(&qual[Q_OBJ], &tmpid, 1);
194     break;
195     case 'g': /* group name(s) */
196     if (argv[0][1])
197     break;
198     tmpid.number = 0;
199     for (i = 1; i < argc; i++) {
200     tmpid.name = argv[i];
201     findid(&qual[Q_GRP], &tmpid, 1);
202     }
203     break;
204 greg 2.1 }
205     }
206    
207    
208 schorsch 2.22 void
209 greg 2.28 convert( /* convert an OBJ stream */
210 schorsch 2.22 FILE *fp
211     )
212 greg 2.1 {
213     char *argv[MAXARG];
214     int argc;
215     int nstats, nunknown;
216 greg 2.28 int i;
217 greg 2.6
218 greg 2.1 nstats = nunknown = 0;
219     /* scan until EOF */
220 schorsch 2.21 while ( (argc = getstmt(argv, fp)) ) {
221 greg 2.1 switch (argv[0][0]) {
222     case 'v': /* vertex */
223     switch (argv[0][1]) {
224     case '\0': /* point */
225     if (badarg(argc-1,argv+1,"fff"))
226 greg 2.6 syntax("Bad vertex");
227 greg 2.1 newv(atof(argv[1]), atof(argv[2]),
228     atof(argv[3]));
229     break;
230     case 'n': /* normal */
231     if (argv[0][2])
232     goto unknown;
233     if (badarg(argc-1,argv+1,"fff"))
234 greg 2.6 syntax("Bad normal");
235 greg 2.1 if (!newvn(atof(argv[1]), atof(argv[2]),
236     atof(argv[3])))
237 greg 2.6 syntax("Zero normal");
238 greg 2.1 break;
239 greg 2.3 case 't': /* texture map */
240 greg 2.1 if (argv[0][2])
241     goto unknown;
242     if (badarg(argc-1,argv+1,"ff"))
243     goto unknown;
244     newvt(atof(argv[1]), atof(argv[2]));
245     break;
246     default:
247     goto unknown;
248     }
249     break;
250     case 'f': /* face */
251     if (argv[0][1])
252     goto unknown;
253 greg 2.3 faceno++;
254 greg 2.1 switch (argc-1) {
255     case 0: case 1: case 2:
256 greg 2.6 syntax("Too few vertices");
257 greg 2.1 break;
258     case 3:
259     if (!puttri(argv[1], argv[2], argv[3]))
260 greg 2.6 syntax("Bad triangle");
261 greg 2.1 break;
262     default:
263     if (!putface(argc-1, argv+1))
264 greg 2.6 syntax("Bad face");
265 greg 2.1 break;
266     }
267     break;
268     case 'u':
269     if (!strcmp(argv[0], "usemtl")) { /* material */
270     if (argc < 2)
271     break; /* not fatal */
272     strcpy(matname, argv[1]);
273     } else if (!strcmp(argv[0], "usemap")) {/* map */
274     if (argc < 2)
275     break; /* not fatal */
276     if (!strcmp(argv[1], "off"))
277 greg 2.3 mapname[0] = '\0';
278 greg 2.1 else
279 greg 2.25 sprintf(mapname, "%s.hdr", argv[1]);
280 greg 2.1 } else
281     goto unknown;
282     break;
283     case 'o': /* object name */
284     if (argv[0][1])
285     goto unknown;
286     if (argc < 2)
287     break; /* not fatal */
288     strcpy(objname, argv[1]);
289     break;
290     case 'g': /* group name(s) */
291     if (argv[0][1])
292     goto unknown;
293     for (i = 1; i < argc; i++)
294 greg 2.3 strcpy(group[i-1], argv[i]);
295 greg 2.28 group[argc-1][0] = '\0';
296 greg 2.1 break;
297     case '#': /* comment */
298 greg 2.7 printargs(argc, argv, stdout);
299 greg 2.1 break;
300     default:; /* something we don't deal with */
301     unknown:
302     nunknown++;
303     break;
304     }
305     nstats++;
306     }
307 greg 2.6 printf("\n# Done processing file: %s\n", inpfile);
308 greg 2.1 printf("# %d lines, %d statements, %d unrecognized\n",
309     lineno, nstats, nunknown);
310     }
311    
312    
313     int
314 schorsch 2.22 getstmt( /* read the next statement from fp */
315 greg 2.28 char *av[MAXARG],
316 schorsch 2.22 FILE *fp
317     )
318 greg 2.1 {
319 greg 2.23 static char sbuf[MAXARG*16];
320 greg 2.28 char *cp;
321     int i;
322 greg 2.1
323     do {
324     if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
325     return(0);
326     i = 0;
327     for ( ; ; ) {
328     while (isspace(*cp) || *cp == '\\') {
329     if (*cp == '\n')
330     lineno++;
331     *cp++ = '\0';
332     }
333 greg 2.23 if (!*cp)
334 greg 2.1 break;
335 greg 2.23 if (i >= MAXARG-1) {
336     fprintf(stderr,
337     "warning: line %d: too many arguments (limit %d)\n",
338     lineno+1, MAXARG-1);
339     break;
340     }
341 greg 2.1 av[i++] = cp;
342     while (*++cp && !isspace(*cp))
343     ;
344     }
345     av[i] = NULL;
346     lineno++;
347     } while (!i);
348    
349     return(i);
350     }
351    
352 greg 2.3
353     char *
354 schorsch 2.22 getmtl(void) /* figure material for this face */
355 greg 2.3 {
356 greg 2.28 RULEHD *rp = ourmapping;
357 greg 2.3
358 greg 2.6 if (rp == NULL) { /* no rule set */
359     if (matname[0])
360     return(matname);
361     if (group[0][0])
362     return(group[0]);
363     return(defmat);
364     }
365 greg 2.3 /* check for match */
366     do {
367     if (matchrule(rp)) {
368     if (!strcmp(rp->mnam, VOIDID))
369     return(NULL); /* match is null */
370     return(rp->mnam);
371     }
372     rp = rp->next;
373     } while (rp != NULL);
374     /* no match found */
375     return(NULL);
376     }
377    
378    
379     char *
380 schorsch 2.22 getonm(void) /* invent a good name for object */
381 greg 2.3 {
382     static char name[64];
383 greg 2.28 char *cp1, *cp2;
384     int i;
385 greg 2.6 /* check for preset */
386     if (objname[0])
387     return(objname);
388     if (!group[0][0])
389     return(defobj);
390 greg 2.3 cp1 = name; /* else make name out of groups */
391     for (i = 0; group[i][0]; i++) {
392     cp2 = group[i];
393     if (cp1 > name)
394     *cp1++ = '.';
395 schorsch 2.21 while ( (*cp1 = *cp2++) )
396 greg 2.3 if (++cp1 >= name+sizeof(name)-2) {
397     *cp1 = '\0';
398     return(name);
399     }
400     }
401     return(name);
402     }
403    
404    
405 schorsch 2.22 int
406     matchrule( /* check for a match on this rule */
407 greg 2.28 RULEHD *rp
408 schorsch 2.22 )
409 greg 2.3 {
410     ID tmpid;
411     int gotmatch;
412 greg 2.28 int i;
413 greg 2.3
414     if (rp->qflg & FL(Q_MTL)) {
415 greg 2.6 if (!matname[0])
416     return(0);
417 greg 2.3 tmpid.number = 0;
418     tmpid.name = matname;
419     if (!matchid(&tmpid, &idm(rp)[Q_MTL]))
420     return(0);
421     }
422     if (rp->qflg & FL(Q_MAP)) {
423 greg 2.6 if (!mapname[0])
424     return(0);
425 greg 2.3 tmpid.number = 0;
426     tmpid.name = mapname;
427     if (!matchid(&tmpid, &idm(rp)[Q_MAP]))
428     return(0);
429     }
430     if (rp->qflg & FL(Q_GRP)) {
431     tmpid.number = 0;
432     gotmatch = 0;
433     for (i = 0; group[i][0]; i++) {
434     tmpid.name = group[i];
435     gotmatch |= matchid(&tmpid, &idm(rp)[Q_GRP]);
436     }
437     if (!gotmatch)
438     return(0);
439     }
440     if (rp->qflg & FL(Q_OBJ)) {
441 greg 2.6 if (!objname[0])
442     return(0);
443 greg 2.3 tmpid.number = 0;
444     tmpid.name = objname;
445     if (!matchid(&tmpid, &idm(rp)[Q_OBJ]))
446     return(0);
447     }
448     if (rp->qflg & FL(Q_FAC)) {
449     tmpid.name = NULL;
450     tmpid.number = faceno;
451     if (!matchid(&tmpid, &idm(rp)[Q_FAC]))
452     return(0);
453     }
454     return(1);
455     }
456    
457    
458 schorsch 2.22 int
459     cvtndx( /* convert vertex string to index */
460 greg 2.28 VNDX vi,
461     char *vs
462 schorsch 2.22 )
463 greg 2.1 {
464     /* get point */
465     vi[0] = atoi(vs);
466     if (vi[0] > 0) {
467     if (vi[0]-- > nvs)
468     return(0);
469     } else if (vi[0] < 0) {
470 greg 2.9 vi[0] += nvs;
471 greg 2.1 if (vi[0] < 0)
472     return(0);
473     } else
474     return(0);
475 greg 2.3 /* get map */
476 greg 2.1 while (*vs)
477     if (*vs++ == '/')
478     break;
479     vi[1] = atoi(vs);
480     if (vi[1] > 0) {
481     if (vi[1]-- > nvts)
482     return(0);
483     } else if (vi[1] < 0) {
484 greg 2.9 vi[1] += nvts;
485 greg 2.1 if (vi[1] < 0)
486     return(0);
487     } else
488     vi[1] = -1;
489     /* get normal */
490     while (*vs)
491     if (*vs++ == '/')
492     break;
493     vi[2] = atoi(vs);
494     if (vi[2] > 0) {
495     if (vi[2]-- > nvns)
496     return(0);
497     } else if (vi[2] < 0) {
498 greg 2.9 vi[2] += nvns;
499 greg 2.1 if (vi[2] < 0)
500     return(0);
501     } else
502     vi[2] = -1;
503 greg 2.26 /* zero normal is not normal */
504     if (vi[2] >= 0 && DOT(vnlist[vi[2]],vnlist[vi[2]]) <= FTINY)
505     vi[2] = -1;
506 greg 2.1 return(1);
507     }
508    
509    
510 schorsch 2.22 int
511     nonplanar( /* are vertices non-planar? */
512 greg 2.28 int ac,
513     char **av
514 schorsch 2.22 )
515 greg 2.1 {
516     VNDX vi;
517 schorsch 2.20 RREAL *p0, *p1;
518 greg 2.5 FVECT v1, v2, nsum, newn;
519     double d;
520 greg 2.28 int i;
521 greg 2.5
522     if (!cvtndx(vi, av[0]))
523     return(0);
524 greg 2.12 if (!flatten && vi[2] >= 0)
525 greg 2.5 return(1); /* has interpolated normals */
526     if (ac < 4)
527     return(0); /* it's a triangle! */
528     /* set up */
529     p0 = vlist[vi[0]];
530     if (!cvtndx(vi, av[1]))
531     return(0); /* error gets caught later */
532     nsum[0] = nsum[1] = nsum[2] = 0.;
533     p1 = vlist[vi[0]];
534     fvsum(v2, p1, p0, -1.0);
535     for (i = 2; i < ac; i++) {
536     VCOPY(v1, v2);
537     if (!cvtndx(vi, av[i]))
538     return(0);
539     p1 = vlist[vi[0]];
540     fvsum(v2, p1, p0, -1.0);
541     fcross(newn, v1, v2);
542     if (normalize(newn) == 0.0) {
543     if (i < 3)
544     return(1); /* can't deal with this */
545     fvsum(nsum, nsum, nsum, 1./(i-2));
546     continue;
547     }
548     d = fdot(newn,nsum);
549     if (d >= 0) {
550     if (d < (1.0-FTINY)*(i-2))
551     return(1);
552     fvsum(nsum, nsum, newn, 1.0);
553     } else {
554     if (d > -(1.0-FTINY)*(i-2))
555     return(1);
556     fvsum(nsum, nsum, newn, -1.0);
557     }
558     }
559     return(0);
560     }
561    
562    
563 schorsch 2.22 int
564     putface( /* put out an N-sided polygon */
565     int ac,
566 greg 2.28 char **av
567 schorsch 2.22 )
568 greg 2.5 {
569     VNDX vi;
570 greg 2.7 char *cp;
571 greg 2.28 int i;
572 greg 2.1
573 greg 2.11 if (nonplanar(ac, av)) { /* break into triangles */
574     while (ac > 2) {
575     if (!puttri(av[0], av[1], av[2]))
576 greg 2.5 return(0);
577 greg 2.11 ac--; /* remove vertex & rotate */
578 greg 2.7 cp = av[0];
579     for (i = 0; i < ac-1; i++)
580 greg 2.11 av[i] = av[i+2];
581 greg 2.7 av[i] = cp;
582 greg 2.5 }
583     return(1);
584     }
585 greg 2.7 if ((cp = getmtl()) == NULL)
586 greg 2.27 return(-1);
587 greg 2.7 printf("\n%s polygon %s.%d\n", cp, getonm(), faceno);
588 greg 2.1 printf("0\n0\n%d\n", 3*ac);
589 greg 2.5 for (i = 0; i < ac; i++) {
590     if (!cvtndx(vi, av[i]))
591 greg 2.1 return(0);
592     pvect(vlist[vi[0]]);
593     }
594     return(1);
595     }
596    
597    
598 schorsch 2.22 int
599     puttri( /* put out a triangle */
600     char *v1,
601     char *v2,
602     char *v3
603     )
604 greg 2.1 {
605 greg 2.3 char *mod;
606 greg 2.1 VNDX v1i, v2i, v3i;
607     BARYCCM bvecs;
608 schorsch 2.20 RREAL bcoor[3][3];
609 schorsch 2.22 int texOK = 0, patOK;
610 greg 2.18 int flatness;
611 greg 2.28 int i;
612 greg 2.1
613 greg 2.3 if ((mod = getmtl()) == NULL)
614 greg 2.27 return(-1);
615 greg 2.3
616 greg 2.1 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
617     return(0);
618     /* compute barycentric coordinates */
619 greg 2.18 if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0)
620     flatness = flat_tri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
621     vnlist[v1i[2]], vnlist[v2i[2]], vnlist[v3i[2]]);
622 greg 2.16 else
623 greg 2.18 flatness = ISFLAT;
624    
625     switch (flatness) {
626     case DEGEN: /* zero area */
627 greg 2.24 ndegen++;
628 greg 2.18 return(-1);
629     case RVFLAT: /* reversed normals, but flat */
630     case ISFLAT: /* smoothing unnecessary */
631     texOK = 0;
632     break;
633     case RVBENT: /* reversed normals with smoothing */
634     case ISBENT: /* proper smoothing */
635     texOK = 1;
636     break;
637     }
638     if (flatten)
639 greg 2.16 texOK = 0;
640 greg 2.7 #ifdef TEXMAPS
641 greg 2.3 patOK = mapname[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0);
642 greg 2.7 #else
643     patOK = 0;
644     #endif
645 greg 2.2 if (texOK | patOK)
646 greg 2.10 if (comp_baryc(&bvecs, vlist[v1i[0]], vlist[v2i[0]],
647 greg 2.1 vlist[v3i[0]]) < 0)
648 greg 2.24 texOK = patOK = 0;
649 greg 2.1 /* put out texture (if any) */
650 greg 2.2 if (texOK) {
651 greg 2.1 printf("\n%s texfunc %s\n", mod, TEXNAME);
652     mod = TEXNAME;
653     printf("4 dx dy dz %s\n", TCALNAME);
654 greg 2.13 printf("0\n");
655     for (i = 0; i < 3; i++) {
656     bcoor[i][0] = vnlist[v1i[2]][i];
657     bcoor[i][1] = vnlist[v2i[2]][i];
658     bcoor[i][2] = vnlist[v3i[2]][i];
659     }
660 greg 2.32 fput_baryc(&bvecs, bcoor, 3, stdout);
661 greg 2.1 }
662 greg 2.7 #ifdef TEXMAPS
663 greg 2.1 /* put out pattern (if any) */
664 greg 2.2 if (patOK) {
665 greg 2.1 printf("\n%s colorpict %s\n", mod, PATNAME);
666     mod = PATNAME;
667 greg 2.3 printf("7 noneg noneg noneg %s %s u v\n", mapname, TCALNAME);
668 greg 2.13 printf("0\n");
669     for (i = 0; i < 2; i++) {
670     bcoor[i][0] = vtlist[v1i[1]][i];
671     bcoor[i][1] = vtlist[v2i[1]][i];
672     bcoor[i][2] = vtlist[v3i[1]][i];
673     }
674 greg 2.32 fput_baryc(&bvecs, bcoor, 2, stdout);
675 greg 2.1 }
676 greg 2.7 #endif
677 greg 2.18 /* put out (reversed) triangle */
678 greg 2.3 printf("\n%s polygon %s.%d\n", mod, getonm(), faceno);
679 greg 2.1 printf("0\n0\n9\n");
680 greg 2.18 if (flatness == RVFLAT || flatness == RVBENT) {
681     pvect(vlist[v3i[0]]);
682     pvect(vlist[v2i[0]]);
683     pvect(vlist[v1i[0]]);
684     } else {
685     pvect(vlist[v1i[0]]);
686     pvect(vlist[v2i[0]]);
687     pvect(vlist[v3i[0]]);
688     }
689 greg 2.1 return(1);
690     }
691    
692    
693 schorsch 2.22 void
694     freeverts(void) /* free all vertices */
695 greg 2.1 {
696     if (nvs) {
697 greg 2.17 free((void *)vlist);
698 greg 2.1 nvs = 0;
699     }
700     if (nvts) {
701 greg 2.17 free((void *)vtlist);
702 greg 2.1 nvts = 0;
703     }
704     if (nvns) {
705 greg 2.17 free((void *)vnlist);
706 greg 2.1 nvns = 0;
707     }
708     }
709    
710    
711     int
712 schorsch 2.22 newv( /* create a new vertex */
713     double x,
714     double y,
715     double z
716     )
717 greg 2.1 {
718     if (!(nvs%CHUNKSIZ)) { /* allocate next block */
719     if (nvs == 0)
720     vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
721     else
722 greg 2.19 vlist = (FVECT *)realloc((void *)vlist,
723 greg 2.1 (nvs+CHUNKSIZ)*sizeof(FVECT));
724     if (vlist == NULL) {
725     fprintf(stderr,
726     "Out of memory while allocating vertex %d\n", nvs);
727     exit(1);
728     }
729     }
730     /* assign new vertex */
731     vlist[nvs][0] = x;
732     vlist[nvs][1] = y;
733     vlist[nvs][2] = z;
734     return(++nvs);
735     }
736    
737    
738     int
739 schorsch 2.22 newvn( /* create a new vertex normal */
740     double x,
741     double y,
742     double z
743     )
744 greg 2.1 {
745     if (!(nvns%CHUNKSIZ)) { /* allocate next block */
746     if (nvns == 0)
747     vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
748     else
749 greg 2.19 vnlist = (FVECT *)realloc((void *)vnlist,
750 greg 2.1 (nvns+CHUNKSIZ)*sizeof(FVECT));
751     if (vnlist == NULL) {
752     fprintf(stderr,
753     "Out of memory while allocating normal %d\n", nvns);
754     exit(1);
755     }
756     }
757     /* assign new normal */
758     vnlist[nvns][0] = x;
759     vnlist[nvns][1] = y;
760     vnlist[nvns][2] = z;
761 greg 2.26 n0norm += (normalize(vnlist[nvns]) == 0.0);
762 greg 2.1 return(++nvns);
763     }
764    
765    
766     int
767 schorsch 2.22 newvt( /* create a new texture map vertex */
768     double x,
769     double y
770     )
771 greg 2.1 {
772     if (!(nvts%CHUNKSIZ)) { /* allocate next block */
773     if (nvts == 0)
774 schorsch 2.20 vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL));
775 greg 2.1 else
776 schorsch 2.20 vtlist = (RREAL (*)[2])realloc((void *)vtlist,
777     (nvts+CHUNKSIZ)*2*sizeof(RREAL));
778 greg 2.1 if (vtlist == NULL) {
779     fprintf(stderr,
780     "Out of memory while allocating texture vertex %d\n",
781     nvts);
782     exit(1);
783     }
784     }
785 greg 2.3 /* assign new vertex */
786 greg 2.1 vtlist[nvts][0] = x;
787     vtlist[nvts][1] = y;
788     return(++nvts);
789     }
790    
791    
792 schorsch 2.22 void
793     syntax( /* report syntax error and exit */
794     char *er
795     )
796 greg 2.1 {
797     fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
798 greg 2.6 inpfile, lineno, er);
799 greg 2.1 exit(1);
800     }