ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.19
Committed: Wed Apr 23 00:52:33 2003 UTC (20 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.18: +3 -3 lines
Log Message:
Added (void *) cast to realloc calls

File Contents

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