ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.29
Committed: Fri Nov 8 16:49:04 2013 UTC (10 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R2P1
Changes since 2.28: +4 -4 lines
Log Message:
Increased maximum identifier name length from 64 to 256

File Contents

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