ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.25
Committed: Mon Nov 10 19:08:18 2008 UTC (15 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R0
Changes since 2.24: +2 -2 lines
Log Message:
Changed ".pic" extension to ".hdr" throughout

File Contents

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