ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.23
Committed: Fri Apr 23 16:20:56 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 2.22: +11 -6 lines
Log Message:
Increased .OBJ face vertex limit to 512 (was 64)

File Contents

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