ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.22
Committed: Sat Nov 15 17:54:06 2003 UTC (20 years, 5 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.21: +88 -41 lines
Log Message:
Continued ANSIfication and reduced compile warnings.

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 schorsch 2.22 static const char RCSid[] = "$Id: obj2rad.c,v 2.21 2003/07/27 22:12:02 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.3 #define CHUNKSIZ 256 /* vertex allocation chunk size */
41 greg 2.1
42     #define MAXARG 64 /* maximum # arguments in a statement */
43    
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     extern char *fgetline();
314     static char sbuf[MAXARG*10];
315     register char *cp;
316     register int i;
317    
318     do {
319     if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
320     return(0);
321     i = 0;
322     for ( ; ; ) {
323     while (isspace(*cp) || *cp == '\\') {
324     if (*cp == '\n')
325     lineno++;
326     *cp++ = '\0';
327     }
328     if (!*cp || i >= MAXARG-1)
329     break;
330     av[i++] = cp;
331     while (*++cp && !isspace(*cp))
332     ;
333     }
334     av[i] = NULL;
335     lineno++;
336     } while (!i);
337    
338     return(i);
339     }
340    
341 greg 2.3
342     char *
343 schorsch 2.22 getmtl(void) /* figure material for this face */
344 greg 2.3 {
345     register RULEHD *rp = ourmapping;
346    
347 greg 2.6 if (rp == NULL) { /* no rule set */
348     if (matname[0])
349     return(matname);
350     if (group[0][0])
351     return(group[0]);
352     return(defmat);
353     }
354 greg 2.3 /* check for match */
355     do {
356     if (matchrule(rp)) {
357     if (!strcmp(rp->mnam, VOIDID))
358     return(NULL); /* match is null */
359     return(rp->mnam);
360     }
361     rp = rp->next;
362     } while (rp != NULL);
363     /* no match found */
364     return(NULL);
365     }
366    
367    
368     char *
369 schorsch 2.22 getonm(void) /* invent a good name for object */
370 greg 2.3 {
371     static char name[64];
372     register char *cp1, *cp2;
373     register int i;
374 greg 2.6 /* check for preset */
375     if (objname[0])
376     return(objname);
377     if (!group[0][0])
378     return(defobj);
379 greg 2.3 cp1 = name; /* else make name out of groups */
380     for (i = 0; group[i][0]; i++) {
381     cp2 = group[i];
382     if (cp1 > name)
383     *cp1++ = '.';
384 schorsch 2.21 while ( (*cp1 = *cp2++) )
385 greg 2.3 if (++cp1 >= name+sizeof(name)-2) {
386     *cp1 = '\0';
387     return(name);
388     }
389     }
390     return(name);
391     }
392    
393    
394 schorsch 2.22 int
395     matchrule( /* check for a match on this rule */
396     register RULEHD *rp
397     )
398 greg 2.3 {
399     ID tmpid;
400     int gotmatch;
401     register int i;
402    
403     if (rp->qflg & FL(Q_MTL)) {
404 greg 2.6 if (!matname[0])
405     return(0);
406 greg 2.3 tmpid.number = 0;
407     tmpid.name = matname;
408     if (!matchid(&tmpid, &idm(rp)[Q_MTL]))
409     return(0);
410     }
411     if (rp->qflg & FL(Q_MAP)) {
412 greg 2.6 if (!mapname[0])
413     return(0);
414 greg 2.3 tmpid.number = 0;
415     tmpid.name = mapname;
416     if (!matchid(&tmpid, &idm(rp)[Q_MAP]))
417     return(0);
418     }
419     if (rp->qflg & FL(Q_GRP)) {
420     tmpid.number = 0;
421     gotmatch = 0;
422     for (i = 0; group[i][0]; i++) {
423     tmpid.name = group[i];
424     gotmatch |= matchid(&tmpid, &idm(rp)[Q_GRP]);
425     }
426     if (!gotmatch)
427     return(0);
428     }
429     if (rp->qflg & FL(Q_OBJ)) {
430 greg 2.6 if (!objname[0])
431     return(0);
432 greg 2.3 tmpid.number = 0;
433     tmpid.name = objname;
434     if (!matchid(&tmpid, &idm(rp)[Q_OBJ]))
435     return(0);
436     }
437     if (rp->qflg & FL(Q_FAC)) {
438     tmpid.name = NULL;
439     tmpid.number = faceno;
440     if (!matchid(&tmpid, &idm(rp)[Q_FAC]))
441     return(0);
442     }
443     return(1);
444     }
445    
446    
447 schorsch 2.22 int
448     cvtndx( /* convert vertex string to index */
449     register VNDX vi,
450     register char *vs
451     )
452 greg 2.1 {
453     /* get point */
454     vi[0] = atoi(vs);
455     if (vi[0] > 0) {
456     if (vi[0]-- > nvs)
457     return(0);
458     } else if (vi[0] < 0) {
459 greg 2.9 vi[0] += nvs;
460 greg 2.1 if (vi[0] < 0)
461     return(0);
462     } else
463     return(0);
464 greg 2.3 /* get map */
465 greg 2.1 while (*vs)
466     if (*vs++ == '/')
467     break;
468     vi[1] = atoi(vs);
469     if (vi[1] > 0) {
470     if (vi[1]-- > nvts)
471     return(0);
472     } else if (vi[1] < 0) {
473 greg 2.9 vi[1] += nvts;
474 greg 2.1 if (vi[1] < 0)
475     return(0);
476     } else
477     vi[1] = -1;
478     /* get normal */
479     while (*vs)
480     if (*vs++ == '/')
481     break;
482     vi[2] = atoi(vs);
483     if (vi[2] > 0) {
484     if (vi[2]-- > nvns)
485     return(0);
486     } else if (vi[2] < 0) {
487 greg 2.9 vi[2] += nvns;
488 greg 2.1 if (vi[2] < 0)
489     return(0);
490     } else
491     vi[2] = -1;
492     return(1);
493     }
494    
495    
496 schorsch 2.22 int
497     nonplanar( /* are vertices non-planar? */
498     register int ac,
499     register char **av
500     )
501 greg 2.1 {
502     VNDX vi;
503 schorsch 2.20 RREAL *p0, *p1;
504 greg 2.5 FVECT v1, v2, nsum, newn;
505     double d;
506     register int i;
507    
508     if (!cvtndx(vi, av[0]))
509     return(0);
510 greg 2.12 if (!flatten && vi[2] >= 0)
511 greg 2.5 return(1); /* has interpolated normals */
512     if (ac < 4)
513     return(0); /* it's a triangle! */
514     /* set up */
515     p0 = vlist[vi[0]];
516     if (!cvtndx(vi, av[1]))
517     return(0); /* error gets caught later */
518     nsum[0] = nsum[1] = nsum[2] = 0.;
519     p1 = vlist[vi[0]];
520     fvsum(v2, p1, p0, -1.0);
521     for (i = 2; i < ac; i++) {
522     VCOPY(v1, v2);
523     if (!cvtndx(vi, av[i]))
524     return(0);
525     p1 = vlist[vi[0]];
526     fvsum(v2, p1, p0, -1.0);
527     fcross(newn, v1, v2);
528     if (normalize(newn) == 0.0) {
529     if (i < 3)
530     return(1); /* can't deal with this */
531     fvsum(nsum, nsum, nsum, 1./(i-2));
532     continue;
533     }
534     d = fdot(newn,nsum);
535     if (d >= 0) {
536     if (d < (1.0-FTINY)*(i-2))
537     return(1);
538     fvsum(nsum, nsum, newn, 1.0);
539     } else {
540     if (d > -(1.0-FTINY)*(i-2))
541     return(1);
542     fvsum(nsum, nsum, newn, -1.0);
543     }
544     }
545     return(0);
546     }
547    
548    
549 schorsch 2.22 int
550     putface( /* put out an N-sided polygon */
551     int ac,
552     register char **av
553     )
554 greg 2.5 {
555     VNDX vi;
556 greg 2.7 char *cp;
557 greg 2.5 register int i;
558 greg 2.1
559 greg 2.11 if (nonplanar(ac, av)) { /* break into triangles */
560     while (ac > 2) {
561     if (!puttri(av[0], av[1], av[2]))
562 greg 2.5 return(0);
563 greg 2.11 ac--; /* remove vertex & rotate */
564 greg 2.7 cp = av[0];
565     for (i = 0; i < ac-1; i++)
566 greg 2.11 av[i] = av[i+2];
567 greg 2.7 av[i] = cp;
568 greg 2.5 }
569     return(1);
570     }
571 greg 2.7 if ((cp = getmtl()) == NULL)
572 greg 2.3 return(-1);
573 greg 2.7 printf("\n%s polygon %s.%d\n", cp, getonm(), faceno);
574 greg 2.1 printf("0\n0\n%d\n", 3*ac);
575 greg 2.5 for (i = 0; i < ac; i++) {
576     if (!cvtndx(vi, av[i]))
577 greg 2.1 return(0);
578     pvect(vlist[vi[0]]);
579     }
580     return(1);
581     }
582    
583    
584 schorsch 2.22 int
585     puttri( /* put out a triangle */
586     char *v1,
587     char *v2,
588     char *v3
589     )
590 greg 2.1 {
591 greg 2.3 char *mod;
592 greg 2.1 VNDX v1i, v2i, v3i;
593     BARYCCM bvecs;
594 schorsch 2.20 RREAL bcoor[3][3];
595 schorsch 2.22 int texOK = 0, patOK;
596 greg 2.18 int flatness;
597 greg 2.13 register int i;
598 greg 2.1
599 greg 2.3 if ((mod = getmtl()) == NULL)
600     return(-1);
601    
602 greg 2.1 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
603     return(0);
604     /* compute barycentric coordinates */
605 greg 2.18 if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0)
606     flatness = flat_tri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
607     vnlist[v1i[2]], vnlist[v2i[2]], vnlist[v3i[2]]);
608 greg 2.16 else
609 greg 2.18 flatness = ISFLAT;
610    
611     switch (flatness) {
612     case DEGEN: /* zero area */
613     return(-1);
614     case RVFLAT: /* reversed normals, but flat */
615     case ISFLAT: /* smoothing unnecessary */
616     texOK = 0;
617     break;
618     case RVBENT: /* reversed normals with smoothing */
619     case ISBENT: /* proper smoothing */
620     texOK = 1;
621     break;
622     }
623     if (flatten)
624 greg 2.16 texOK = 0;
625 greg 2.7 #ifdef TEXMAPS
626 greg 2.3 patOK = mapname[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0);
627 greg 2.7 #else
628     patOK = 0;
629     #endif
630 greg 2.2 if (texOK | patOK)
631 greg 2.10 if (comp_baryc(&bvecs, vlist[v1i[0]], vlist[v2i[0]],
632 greg 2.1 vlist[v3i[0]]) < 0)
633 greg 2.2 return(-1);
634 greg 2.1 /* put out texture (if any) */
635 greg 2.2 if (texOK) {
636 greg 2.1 printf("\n%s texfunc %s\n", mod, TEXNAME);
637     mod = TEXNAME;
638     printf("4 dx dy dz %s\n", TCALNAME);
639 greg 2.13 printf("0\n");
640     for (i = 0; i < 3; i++) {
641     bcoor[i][0] = vnlist[v1i[2]][i];
642     bcoor[i][1] = vnlist[v2i[2]][i];
643     bcoor[i][2] = vnlist[v3i[2]][i];
644     }
645     put_baryc(&bvecs, bcoor, 3);
646 greg 2.1 }
647 greg 2.7 #ifdef TEXMAPS
648 greg 2.1 /* put out pattern (if any) */
649 greg 2.2 if (patOK) {
650 greg 2.1 printf("\n%s colorpict %s\n", mod, PATNAME);
651     mod = PATNAME;
652 greg 2.3 printf("7 noneg noneg noneg %s %s u v\n", mapname, TCALNAME);
653 greg 2.13 printf("0\n");
654     for (i = 0; i < 2; i++) {
655     bcoor[i][0] = vtlist[v1i[1]][i];
656     bcoor[i][1] = vtlist[v2i[1]][i];
657     bcoor[i][2] = vtlist[v3i[1]][i];
658     }
659     put_baryc(&bvecs, bcoor, 2);
660 greg 2.1 }
661 greg 2.7 #endif
662 greg 2.18 /* put out (reversed) triangle */
663 greg 2.3 printf("\n%s polygon %s.%d\n", mod, getonm(), faceno);
664 greg 2.1 printf("0\n0\n9\n");
665 greg 2.18 if (flatness == RVFLAT || flatness == RVBENT) {
666     pvect(vlist[v3i[0]]);
667     pvect(vlist[v2i[0]]);
668     pvect(vlist[v1i[0]]);
669     } else {
670     pvect(vlist[v1i[0]]);
671     pvect(vlist[v2i[0]]);
672     pvect(vlist[v3i[0]]);
673     }
674 greg 2.1 return(1);
675     }
676    
677    
678 schorsch 2.22 void
679     freeverts(void) /* free all vertices */
680 greg 2.1 {
681     if (nvs) {
682 greg 2.17 free((void *)vlist);
683 greg 2.1 nvs = 0;
684     }
685     if (nvts) {
686 greg 2.17 free((void *)vtlist);
687 greg 2.1 nvts = 0;
688     }
689     if (nvns) {
690 greg 2.17 free((void *)vnlist);
691 greg 2.1 nvns = 0;
692     }
693     }
694    
695    
696     int
697 schorsch 2.22 newv( /* create a new vertex */
698     double x,
699     double y,
700     double z
701     )
702 greg 2.1 {
703     if (!(nvs%CHUNKSIZ)) { /* allocate next block */
704     if (nvs == 0)
705     vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
706     else
707 greg 2.19 vlist = (FVECT *)realloc((void *)vlist,
708 greg 2.1 (nvs+CHUNKSIZ)*sizeof(FVECT));
709     if (vlist == NULL) {
710     fprintf(stderr,
711     "Out of memory while allocating vertex %d\n", nvs);
712     exit(1);
713     }
714     }
715     /* assign new vertex */
716     vlist[nvs][0] = x;
717     vlist[nvs][1] = y;
718     vlist[nvs][2] = z;
719     return(++nvs);
720     }
721    
722    
723     int
724 schorsch 2.22 newvn( /* create a new vertex normal */
725     double x,
726     double y,
727     double z
728     )
729 greg 2.1 {
730     if (!(nvns%CHUNKSIZ)) { /* allocate next block */
731     if (nvns == 0)
732     vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
733     else
734 greg 2.19 vnlist = (FVECT *)realloc((void *)vnlist,
735 greg 2.1 (nvns+CHUNKSIZ)*sizeof(FVECT));
736     if (vnlist == NULL) {
737     fprintf(stderr,
738     "Out of memory while allocating normal %d\n", nvns);
739     exit(1);
740     }
741     }
742     /* assign new normal */
743     vnlist[nvns][0] = x;
744     vnlist[nvns][1] = y;
745     vnlist[nvns][2] = z;
746     if (normalize(vnlist[nvns]) == 0.0)
747     return(0);
748     return(++nvns);
749     }
750    
751    
752     int
753 schorsch 2.22 newvt( /* create a new texture map vertex */
754     double x,
755     double y
756     )
757 greg 2.1 {
758     if (!(nvts%CHUNKSIZ)) { /* allocate next block */
759     if (nvts == 0)
760 schorsch 2.20 vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL));
761 greg 2.1 else
762 schorsch 2.20 vtlist = (RREAL (*)[2])realloc((void *)vtlist,
763     (nvts+CHUNKSIZ)*2*sizeof(RREAL));
764 greg 2.1 if (vtlist == NULL) {
765     fprintf(stderr,
766     "Out of memory while allocating texture vertex %d\n",
767     nvts);
768     exit(1);
769     }
770     }
771 greg 2.3 /* assign new vertex */
772 greg 2.1 vtlist[nvts][0] = x;
773     vtlist[nvts][1] = y;
774     return(++nvts);
775     }
776    
777    
778 schorsch 2.22 void
779     syntax( /* report syntax error and exit */
780     char *er
781     )
782 greg 2.1 {
783     fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
784 greg 2.6 inpfile, lineno, er);
785 greg 2.1 exit(1);
786     }