ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.8
Committed: Tue Jun 14 14:30:38 1994 UTC (29 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +7 -2 lines
Log Message:
added -f option to flatten faces

File Contents

# Content
1 /* Copyright (c) 1994 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Convert a Wavefront .obj file to Radiance format.
9 *
10 * Currently, we support only polygonal geometry. Non-planar
11 * faces are broken rather haphazardly into triangles.
12 * Also, texture map indices only work for triangles, though
13 * I'm not sure they work correctly. (Taken out -- see TEXMAPS defines.)
14 */
15
16 #include "standard.h"
17
18 #include "trans.h"
19
20 #include <ctype.h>
21
22 #define TCALNAME "tmesh.cal" /* triangle interp. file */
23 #define QCALNAME "surf.cal" /* quad interp. file */
24 #define PATNAME "M-pat" /* mesh pattern name (reused) */
25 #define TEXNAME "M-nor" /* mesh texture name (reused) */
26 #define DEFOBJ "unnamed" /* default object name */
27 #define DEFMAT "white" /* default material name */
28
29 #define ABS(x) ((x)>=0 ? (x) : -(x))
30
31 #define pvect(v) printf("%18.12g %18.12g %18.12g\n",(v)[0],(v)[1],(v)[2])
32
33 FVECT *vlist; /* our vertex list */
34 int nvs; /* number of vertices in our list */
35 FVECT *vnlist; /* vertex normal list */
36 int nvns;
37 FLOAT (*vtlist)[2]; /* map vertex list */
38 int nvts;
39
40 typedef FLOAT BARYCCM[3][4]; /* barycentric coordinate system */
41
42 typedef int VNDX[3]; /* vertex index (point,map,normal) */
43
44 #define CHUNKSIZ 256 /* vertex allocation chunk size */
45
46 #define MAXARG 64 /* maximum # arguments in a statement */
47
48 /* qualifiers */
49 #define Q_MTL 0
50 #define Q_MAP 1
51 #define Q_GRP 2
52 #define Q_OBJ 3
53 #define Q_FAC 4
54 #define NQUALS 5
55
56 char *qname[NQUALS] = {
57 "Material",
58 "Map",
59 "Group",
60 "Object",
61 "Face",
62 };
63
64 QLIST qlist = {NQUALS, qname};
65 /* valid qualifier ids */
66 IDLIST qual[NQUALS];
67 /* mapping rules */
68 RULEHD *ourmapping = NULL;
69
70 char *defmat = DEFMAT; /* default (starting) material name */
71 char *defobj = DEFOBJ; /* default (starting) object name */
72
73 int flatten = 0; /* discard surface normal information */
74
75 char *getmtl(), *getonm();
76
77 char mapname[128]; /* current picture file */
78 char matname[64]; /* current material name */
79 char group[16][32]; /* current group names */
80 char objname[128]; /* current object name */
81 char *inpfile; /* input file name */
82 int lineno; /* current line number */
83 int faceno; /* current face number */
84
85
86 main(argc, argv) /* read in .obj file and convert */
87 int argc;
88 char *argv[];
89 {
90 int donames = 0;
91 int i;
92
93 for (i = 1; i < argc && argv[i][0] == '-'; i++)
94 switch (argv[i][1]) {
95 case 'o': /* object name */
96 defobj = argv[++i];
97 break;
98 case 'n': /* just produce name list */
99 donames++;
100 break;
101 case 'm': /* use custom mapfile */
102 ourmapping = getmapping(argv[++i], &qlist);
103 break;
104 case 'f': /* flatten surfaces */
105 flatten++;
106 break;
107 default:
108 goto userr;
109 }
110 if (i > argc | i < argc-1)
111 goto userr;
112 if (i == argc)
113 inpfile = "<stdin>";
114 else if (freopen(inpfile=argv[i], "r", stdin) == NULL) {
115 fprintf(stderr, "%s: cannot open\n", inpfile);
116 exit(1);
117 }
118 if (donames) { /* scan for ids */
119 getnames(stdin);
120 printf("filename \"%s\"\n", inpfile);
121 printf("filetype \"Wavefront\"\n");
122 write_quals(&qlist, qual, stdout);
123 printf("qualifier %s begin\n", qlist.qual[Q_FAC]);
124 printf("[%d:%d]\n", 1, faceno);
125 printf("end\n");
126 } else { /* translate file */
127 printf("# ");
128 printargs(argc, argv, stdout);
129 convert(stdin);
130 }
131 exit(0);
132 userr:
133 fprintf(stderr, "Usage: %s [-o obj][-m mapping][-n] [file.obj]\n",
134 argv[0]);
135 exit(1);
136 }
137
138
139 getnames(fp) /* get valid qualifier names */
140 FILE *fp;
141 {
142 char *argv[MAXARG];
143 int argc;
144 ID tmpid;
145 register int i;
146
147 while (argc = getstmt(argv, fp))
148 switch (argv[0][0]) {
149 case 'f': /* face */
150 if (!argv[0][1])
151 faceno++;
152 break;
153 case 'u':
154 if (!strcmp(argv[0], "usemtl")) { /* material */
155 if (argc < 2)
156 break; /* not fatal */
157 tmpid.number = 0;
158 tmpid.name = argv[1];
159 findid(&qual[Q_MTL], &tmpid, 1);
160 } else if (!strcmp(argv[0], "usemap")) {/* map */
161 if (argc < 2 || !strcmp(argv[1], "off"))
162 break; /* not fatal */
163 tmpid.number = 0;
164 tmpid.name = argv[1];
165 findid(&qual[Q_MAP], &tmpid, 1);
166 }
167 break;
168 case 'o': /* object name */
169 if (argv[0][1] || argc < 2)
170 break;
171 tmpid.number = 0;
172 tmpid.name = argv[1];
173 findid(&qual[Q_OBJ], &tmpid, 1);
174 break;
175 case 'g': /* group name(s) */
176 if (argv[0][1])
177 break;
178 tmpid.number = 0;
179 for (i = 1; i < argc; i++) {
180 tmpid.name = argv[i];
181 findid(&qual[Q_GRP], &tmpid, 1);
182 }
183 break;
184 }
185 }
186
187
188 convert(fp) /* convert a T-mesh */
189 FILE *fp;
190 {
191 char *argv[MAXARG];
192 int argc;
193 int nstats, nunknown;
194 register int i;
195
196 nstats = nunknown = 0;
197 /* scan until EOF */
198 while (argc = getstmt(argv, fp)) {
199 switch (argv[0][0]) {
200 case 'v': /* vertex */
201 switch (argv[0][1]) {
202 case '\0': /* point */
203 if (badarg(argc-1,argv+1,"fff"))
204 syntax("Bad vertex");
205 newv(atof(argv[1]), atof(argv[2]),
206 atof(argv[3]));
207 break;
208 case 'n': /* normal */
209 if (argv[0][2])
210 goto unknown;
211 if (badarg(argc-1,argv+1,"fff"))
212 syntax("Bad normal");
213 if (!newvn(atof(argv[1]), atof(argv[2]),
214 atof(argv[3])))
215 syntax("Zero normal");
216 break;
217 case 't': /* texture map */
218 if (argv[0][2])
219 goto unknown;
220 if (badarg(argc-1,argv+1,"ff"))
221 goto unknown;
222 newvt(atof(argv[1]), atof(argv[2]));
223 break;
224 default:
225 goto unknown;
226 }
227 break;
228 case 'f': /* face */
229 if (argv[0][1])
230 goto unknown;
231 faceno++;
232 switch (argc-1) {
233 case 0: case 1: case 2:
234 syntax("Too few vertices");
235 break;
236 case 3:
237 if (!puttri(argv[1], argv[2], argv[3]))
238 syntax("Bad triangle");
239 break;
240 case 4:
241 if (!putquad(argv[1], argv[2],
242 argv[3], argv[4]))
243 syntax("Bad quad");
244 break;
245 default:
246 if (!putface(argc-1, argv+1))
247 syntax("Bad face");
248 break;
249 }
250 break;
251 case 'u':
252 if (!strcmp(argv[0], "usemtl")) { /* material */
253 if (argc < 2)
254 break; /* not fatal */
255 strcpy(matname, argv[1]);
256 } else if (!strcmp(argv[0], "usemap")) {/* map */
257 if (argc < 2)
258 break; /* not fatal */
259 if (!strcmp(argv[1], "off"))
260 mapname[0] = '\0';
261 else
262 sprintf(mapname, "%s.pic", argv[1]);
263 } else
264 goto unknown;
265 break;
266 case 'o': /* object name */
267 if (argv[0][1])
268 goto unknown;
269 if (argc < 2)
270 break; /* not fatal */
271 strcpy(objname, argv[1]);
272 break;
273 case 'g': /* group name(s) */
274 if (argv[0][1])
275 goto unknown;
276 for (i = 1; i < argc; i++)
277 strcpy(group[i-1], argv[i]);
278 group[i-1][0] = '\0';
279 break;
280 case '#': /* comment */
281 printargs(argc, argv, stdout);
282 break;
283 default:; /* something we don't deal with */
284 unknown:
285 nunknown++;
286 break;
287 }
288 nstats++;
289 }
290 printf("\n# Done processing file: %s\n", inpfile);
291 printf("# %d lines, %d statements, %d unrecognized\n",
292 lineno, nstats, nunknown);
293 }
294
295
296 int
297 getstmt(av, fp) /* read the next statement from fp */
298 register char *av[MAXARG];
299 FILE *fp;
300 {
301 extern char *fgetline();
302 static char sbuf[MAXARG*10];
303 register char *cp;
304 register int i;
305
306 do {
307 if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
308 return(0);
309 i = 0;
310 for ( ; ; ) {
311 while (isspace(*cp) || *cp == '\\') {
312 if (*cp == '\n')
313 lineno++;
314 *cp++ = '\0';
315 }
316 if (!*cp || i >= MAXARG-1)
317 break;
318 av[i++] = cp;
319 while (*++cp && !isspace(*cp))
320 ;
321 }
322 av[i] = NULL;
323 lineno++;
324 } while (!i);
325
326 return(i);
327 }
328
329
330 char *
331 getmtl() /* figure material for this face */
332 {
333 register RULEHD *rp = ourmapping;
334
335 if (rp == NULL) { /* no rule set */
336 if (matname[0])
337 return(matname);
338 if (group[0][0])
339 return(group[0]);
340 return(defmat);
341 }
342 /* check for match */
343 do {
344 if (matchrule(rp)) {
345 if (!strcmp(rp->mnam, VOIDID))
346 return(NULL); /* match is null */
347 return(rp->mnam);
348 }
349 rp = rp->next;
350 } while (rp != NULL);
351 /* no match found */
352 return(NULL);
353 }
354
355
356 char *
357 getonm() /* invent a good name for object */
358 {
359 static char name[64];
360 register char *cp1, *cp2;
361 register int i;
362 /* check for preset */
363 if (objname[0])
364 return(objname);
365 if (!group[0][0])
366 return(defobj);
367 cp1 = name; /* else make name out of groups */
368 for (i = 0; group[i][0]; i++) {
369 cp2 = group[i];
370 if (cp1 > name)
371 *cp1++ = '.';
372 while (*cp1 = *cp2++)
373 if (++cp1 >= name+sizeof(name)-2) {
374 *cp1 = '\0';
375 return(name);
376 }
377 }
378 return(name);
379 }
380
381
382 matchrule(rp) /* check for a match on this rule */
383 register RULEHD *rp;
384 {
385 ID tmpid;
386 int gotmatch;
387 register int i;
388
389 if (rp->qflg & FL(Q_MTL)) {
390 if (!matname[0])
391 return(0);
392 tmpid.number = 0;
393 tmpid.name = matname;
394 if (!matchid(&tmpid, &idm(rp)[Q_MTL]))
395 return(0);
396 }
397 if (rp->qflg & FL(Q_MAP)) {
398 if (!mapname[0])
399 return(0);
400 tmpid.number = 0;
401 tmpid.name = mapname;
402 if (!matchid(&tmpid, &idm(rp)[Q_MAP]))
403 return(0);
404 }
405 if (rp->qflg & FL(Q_GRP)) {
406 tmpid.number = 0;
407 gotmatch = 0;
408 for (i = 0; group[i][0]; i++) {
409 tmpid.name = group[i];
410 gotmatch |= matchid(&tmpid, &idm(rp)[Q_GRP]);
411 }
412 if (!gotmatch)
413 return(0);
414 }
415 if (rp->qflg & FL(Q_OBJ)) {
416 if (!objname[0])
417 return(0);
418 tmpid.number = 0;
419 tmpid.name = objname;
420 if (!matchid(&tmpid, &idm(rp)[Q_OBJ]))
421 return(0);
422 }
423 if (rp->qflg & FL(Q_FAC)) {
424 tmpid.name = NULL;
425 tmpid.number = faceno;
426 if (!matchid(&tmpid, &idm(rp)[Q_FAC]))
427 return(0);
428 }
429 return(1);
430 }
431
432
433 cvtndx(vi, vs) /* convert vertex string to index */
434 register VNDX vi;
435 register char *vs;
436 {
437 /* get point */
438 vi[0] = atoi(vs);
439 if (vi[0] > 0) {
440 if (vi[0]-- > nvs)
441 return(0);
442 } else if (vi[0] < 0) {
443 vi[0] = nvs + vi[0];
444 if (vi[0] < 0)
445 return(0);
446 } else
447 return(0);
448 /* get map */
449 while (*vs)
450 if (*vs++ == '/')
451 break;
452 vi[1] = atoi(vs);
453 if (vi[1] > 0) {
454 if (vi[1]-- > nvts)
455 return(0);
456 } else if (vi[1] < 0) {
457 vi[1] = nvts + vi[1];
458 if (vi[1] < 0)
459 return(0);
460 } else
461 vi[1] = -1;
462 /* get normal */
463 while (*vs)
464 if (*vs++ == '/')
465 break;
466 vi[2] = atoi(vs);
467 if (vi[2] > 0) {
468 if (vi[2]-- > nvns)
469 return(0);
470 } else if (vi[2] < 0) {
471 vi[2] = nvns + vi[2];
472 if (vi[2] < 0)
473 return(0);
474 } else
475 vi[2] = -1;
476 return(1);
477 }
478
479
480 nonplanar(ac, av) /* are vertices are non-planar? */
481 register int ac;
482 register char **av;
483 {
484 VNDX vi;
485 FLOAT *p0, *p1;
486 FVECT v1, v2, nsum, newn;
487 double d;
488 register int i;
489
490 if (!cvtndx(vi, av[0]))
491 return(0);
492 if (vi[2] >= 0)
493 return(1); /* has interpolated normals */
494 if (ac < 4)
495 return(0); /* it's a triangle! */
496 /* set up */
497 p0 = vlist[vi[0]];
498 if (!cvtndx(vi, av[1]))
499 return(0); /* error gets caught later */
500 nsum[0] = nsum[1] = nsum[2] = 0.;
501 p1 = vlist[vi[0]];
502 fvsum(v2, p1, p0, -1.0);
503 for (i = 2; i < ac; i++) {
504 VCOPY(v1, v2);
505 if (!cvtndx(vi, av[i]))
506 return(0);
507 p1 = vlist[vi[0]];
508 fvsum(v2, p1, p0, -1.0);
509 fcross(newn, v1, v2);
510 if (normalize(newn) == 0.0) {
511 if (i < 3)
512 return(1); /* can't deal with this */
513 fvsum(nsum, nsum, nsum, 1./(i-2));
514 continue;
515 }
516 d = fdot(newn,nsum);
517 if (d >= 0) {
518 if (d < (1.0-FTINY)*(i-2))
519 return(1);
520 fvsum(nsum, nsum, newn, 1.0);
521 } else {
522 if (d > -(1.0-FTINY)*(i-2))
523 return(1);
524 fvsum(nsum, nsum, newn, -1.0);
525 }
526 }
527 return(0);
528 }
529
530
531 putface(ac, av) /* put out an N-sided polygon */
532 int ac;
533 register char **av;
534 {
535 VNDX vi;
536 char *cp;
537 register int i;
538
539 if (nonplanar(ac, av)) { /* break into quads and triangles */
540 while (ac > 3) {
541 if (!putquad(av[0], av[1], av[2], av[3]))
542 return(0);
543 ac -= 2; /* remove two vertices & rotate */
544 cp = av[0];
545 for (i = 0; i < ac-1; i++)
546 av[i] = av[i+3];
547 av[i] = cp;
548 }
549 if (ac == 3 && !puttri(av[0], av[1], av[2]))
550 return(0);
551 return(1);
552 }
553 if ((cp = getmtl()) == NULL)
554 return(-1);
555 printf("\n%s polygon %s.%d\n", cp, getonm(), faceno);
556 printf("0\n0\n%d\n", 3*ac);
557 for (i = 0; i < ac; i++) {
558 if (!cvtndx(vi, av[i]))
559 return(0);
560 pvect(vlist[vi[0]]);
561 }
562 return(1);
563 }
564
565
566 puttri(v1, v2, v3) /* put out a triangle */
567 char *v1, *v2, *v3;
568 {
569 char *mod;
570 VNDX v1i, v2i, v3i;
571 BARYCCM bvecs;
572 int texOK, patOK;
573
574 if ((mod = getmtl()) == NULL)
575 return(-1);
576
577 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
578 return(0);
579 /* compute barycentric coordinates */
580 texOK = !flatten && (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0);
581 #ifdef TEXMAPS
582 patOK = mapname[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0);
583 #else
584 patOK = 0;
585 #endif
586 if (texOK | patOK)
587 if (comp_baryc(bvecs, vlist[v1i[0]], vlist[v2i[0]],
588 vlist[v3i[0]]) < 0)
589 return(-1);
590 /* put out texture (if any) */
591 if (texOK) {
592 printf("\n%s texfunc %s\n", mod, TEXNAME);
593 mod = TEXNAME;
594 printf("4 dx dy dz %s\n", TCALNAME);
595 printf("0\n21\n");
596 put_baryc(bvecs);
597 printf("\t%14.12g %14.12g %14.12g\n",
598 vnlist[v1i[2]][0], vnlist[v2i[2]][0],
599 vnlist[v3i[2]][0]);
600 printf("\t%14.12g %14.12g %14.12g\n",
601 vnlist[v1i[2]][1], vnlist[v2i[2]][1],
602 vnlist[v3i[2]][1]);
603 printf("\t%14.12g %14.12g %14.12g\n",
604 vnlist[v1i[2]][2], vnlist[v2i[2]][2],
605 vnlist[v3i[2]][2]);
606 }
607 #ifdef TEXMAPS
608 /* put out pattern (if any) */
609 if (patOK) {
610 printf("\n%s colorpict %s\n", mod, PATNAME);
611 mod = PATNAME;
612 printf("7 noneg noneg noneg %s %s u v\n", mapname, TCALNAME);
613 printf("0\n18\n");
614 put_baryc(bvecs);
615 printf("\t%f %f %f\n", vtlist[v1i[1]][0],
616 vtlist[v2i[1]][0], vtlist[v3i[1]][0]);
617 printf("\t%f %f %f\n", vtlist[v1i[1]][1],
618 vtlist[v2i[1]][1], vtlist[v3i[1]][1]);
619 }
620 #endif
621 /* put out triangle */
622 printf("\n%s polygon %s.%d\n", mod, getonm(), faceno);
623 printf("0\n0\n9\n");
624 pvect(vlist[v1i[0]]);
625 pvect(vlist[v2i[0]]);
626 pvect(vlist[v3i[0]]);
627
628 return(1);
629 }
630
631
632 int
633 comp_baryc(bcm, v1, v2, v3) /* compute barycentric vectors */
634 register BARYCCM bcm;
635 FLOAT *v1, *v2, *v3;
636 {
637 FLOAT *vt;
638 FVECT va, vab, vcb;
639 double d;
640 register int i, j;
641
642 for (j = 0; j < 3; j++) {
643 for (i = 0; i < 3; i++) {
644 vab[i] = v1[i] - v2[i];
645 vcb[i] = v3[i] - v2[i];
646 }
647 d = DOT(vcb,vcb);
648 if (d <= FTINY)
649 return(-1);
650 d = DOT(vcb,vab)/d;
651 for (i = 0; i < 3; i++)
652 va[i] = vab[i] - vcb[i]*d;
653 d = DOT(va,va);
654 if (d <= FTINY)
655 return(-1);
656 for (i = 0; i < 3; i++) {
657 va[i] /= d;
658 bcm[j][i] = va[i];
659 }
660 bcm[j][3] = -DOT(v2,va);
661 /* rotate vertices */
662 vt = v1;
663 v1 = v2;
664 v2 = v3;
665 v3 = vt;
666 }
667 return(0);
668 }
669
670
671 put_baryc(bcm) /* put barycentric coord. vectors */
672 register BARYCCM bcm;
673 {
674 register int i;
675
676 for (i = 0; i < 3; i++)
677 printf("%14.8f %14.8f %14.8f %14.8f\n",
678 bcm[i][0], bcm[i][1], bcm[i][2], bcm[i][3]);
679 }
680
681
682 putquad(p0, p1, p3, p2) /* put out a quadrilateral */
683 char *p0, *p1, *p3, *p2; /* names correspond to binary pos. */
684 {
685 VNDX p0i, p1i, p2i, p3i;
686 FVECT norm[4];
687 char *mod, *name;
688 int axis;
689 FVECT v1, v2, vc1, vc2;
690 int ok1, ok2;
691
692 #ifdef TEXMAPS
693 /* also should output texture index coordinates,
694 * which will require new .cal file
695 */
696 #endif
697 if ((mod = getmtl()) == NULL)
698 return(-1);
699 name = getonm();
700 /* get actual indices */
701 if (!cvtndx(p0i,p0) || !cvtndx(p1i,p1) ||
702 !cvtndx(p2i,p2) || !cvtndx(p3i,p3))
703 return(0);
704 /* compute exact normals */
705 fvsum(v1, vlist[p1i[0]], vlist[p0i[0]], -1.0);
706 fvsum(v2, vlist[p2i[0]], vlist[p0i[0]], -1.0);
707 fcross(vc1, v1, v2);
708 ok1 = normalize(vc1) != 0.0;
709 fvsum(v1, vlist[p2i[0]], vlist[p3i[0]], -1.0);
710 fvsum(v2, vlist[p1i[0]], vlist[p3i[0]], -1.0);
711 fcross(vc2, v1, v2);
712 ok2 = normalize(vc2) != 0.0;
713 if (!(ok1 | ok2))
714 return(-1);
715 /* compute normal interpolation */
716 axis = norminterp(norm, p0i, p1i, p2i, p3i);
717
718 /* put out quadrilateral? */
719 if (ok1 & ok2 && fabs(fdot(vc1,vc2)) >= 1.0-FTINY) {
720 printf("\n%s ", mod);
721 if (axis != -1) {
722 printf("texfunc %s\n", TEXNAME);
723 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
724 printf("0\n13\t%d\n", axis);
725 pvect(norm[0]);
726 pvect(norm[1]);
727 pvect(norm[2]);
728 fvsum(v1, norm[3], vc1, -0.5);
729 fvsum(v1, v1, vc2, -0.5);
730 pvect(v1);
731 printf("\n%s ", TEXNAME);
732 }
733 printf("polygon %s.%d\n", name, faceno);
734 printf("0\n0\n12\n");
735 pvect(vlist[p0i[0]]);
736 pvect(vlist[p1i[0]]);
737 pvect(vlist[p3i[0]]);
738 pvect(vlist[p2i[0]]);
739 return(1);
740 }
741 /* put out triangles? */
742 if (ok1) {
743 printf("\n%s ", mod);
744 if (axis != -1) {
745 printf("texfunc %s\n", TEXNAME);
746 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
747 printf("0\n13\t%d\n", axis);
748 pvect(norm[0]);
749 pvect(norm[1]);
750 pvect(norm[2]);
751 fvsum(v1, norm[3], vc1, -1.0);
752 pvect(v1);
753 printf("\n%s ", TEXNAME);
754 }
755 printf("polygon %s.%da\n", name, faceno);
756 printf("0\n0\n9\n");
757 pvect(vlist[p0i[0]]);
758 pvect(vlist[p1i[0]]);
759 pvect(vlist[p2i[0]]);
760 }
761 if (ok2) {
762 printf("\n%s ", mod);
763 if (axis != -1) {
764 printf("texfunc %s\n", TEXNAME);
765 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
766 printf("0\n13\t%d\n", axis);
767 pvect(norm[0]);
768 pvect(norm[1]);
769 pvect(norm[2]);
770 fvsum(v2, norm[3], vc2, -1.0);
771 pvect(v2);
772 printf("\n%s ", TEXNAME);
773 }
774 printf("polygon %s.%db\n", name, faceno);
775 printf("0\n0\n9\n");
776 pvect(vlist[p2i[0]]);
777 pvect(vlist[p1i[0]]);
778 pvect(vlist[p3i[0]]);
779 }
780 return(1);
781 }
782
783
784 int
785 norminterp(resmat, p0i, p1i, p2i, p3i) /* compute normal interpolation */
786 register FVECT resmat[4];
787 register VNDX p0i, p1i, p2i, p3i;
788 {
789 #define u ((ax+1)%3)
790 #define v ((ax+2)%3)
791
792 register int ax;
793 MAT4 eqnmat;
794 FVECT v1;
795 register int i, j;
796
797 #ifdef TEXMAPS
798 /* also check for texture indices */
799 #endif
800 if (flatten || !(p0i[2]>=0 && p1i[2]>=0 && p2i[2]>=0 && p3i[2]>=0))
801 return(-1);
802 /* find dominant axis */
803 VCOPY(v1, vnlist[p0i[2]]);
804 fvsum(v1, v1, vnlist[p1i[2]], 1.0);
805 fvsum(v1, v1, vnlist[p2i[2]], 1.0);
806 fvsum(v1, v1, vnlist[p3i[2]], 1.0);
807 ax = ABS(v1[0]) > ABS(v1[1]) ? 0 : 1;
808 ax = ABS(v1[ax]) > ABS(v1[2]) ? ax : 2;
809 /* assign equation matrix */
810 eqnmat[0][0] = vlist[p0i[0]][u]*vlist[p0i[0]][v];
811 eqnmat[0][1] = vlist[p0i[0]][u];
812 eqnmat[0][2] = vlist[p0i[0]][v];
813 eqnmat[0][3] = 1.0;
814 eqnmat[1][0] = vlist[p1i[0]][u]*vlist[p1i[0]][v];
815 eqnmat[1][1] = vlist[p1i[0]][u];
816 eqnmat[1][2] = vlist[p1i[0]][v];
817 eqnmat[1][3] = 1.0;
818 eqnmat[2][0] = vlist[p2i[0]][u]*vlist[p2i[0]][v];
819 eqnmat[2][1] = vlist[p2i[0]][u];
820 eqnmat[2][2] = vlist[p2i[0]][v];
821 eqnmat[2][3] = 1.0;
822 eqnmat[3][0] = vlist[p3i[0]][u]*vlist[p3i[0]][v];
823 eqnmat[3][1] = vlist[p3i[0]][u];
824 eqnmat[3][2] = vlist[p3i[0]][v];
825 eqnmat[3][3] = 1.0;
826 /* invert matrix (solve system) */
827 if (!invmat4(eqnmat, eqnmat))
828 return(-1); /* no solution */
829 /* compute result matrix */
830 for (j = 0; j < 4; j++)
831 for (i = 0; i < 3; i++)
832 resmat[j][i] = eqnmat[j][0]*vnlist[p0i[2]][i] +
833 eqnmat[j][1]*vnlist[p1i[2]][i] +
834 eqnmat[j][2]*vnlist[p2i[2]][i] +
835 eqnmat[j][3]*vnlist[p3i[2]][i];
836 #ifdef TEXMAPS
837 /* compute result matrix for texture indices */
838 #endif
839 return(ax);
840
841 #undef u
842 #undef v
843 }
844
845
846 freeverts() /* free all vertices */
847 {
848 if (nvs) {
849 free((char *)vlist);
850 nvs = 0;
851 }
852 if (nvts) {
853 free((char *)vtlist);
854 nvts = 0;
855 }
856 if (nvns) {
857 free((char *)vnlist);
858 nvns = 0;
859 }
860 }
861
862
863 int
864 newv(x, y, z) /* create a new vertex */
865 double x, y, z;
866 {
867 if (!(nvs%CHUNKSIZ)) { /* allocate next block */
868 if (nvs == 0)
869 vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
870 else
871 vlist = (FVECT *)realloc((char *)vlist,
872 (nvs+CHUNKSIZ)*sizeof(FVECT));
873 if (vlist == NULL) {
874 fprintf(stderr,
875 "Out of memory while allocating vertex %d\n", nvs);
876 exit(1);
877 }
878 }
879 /* assign new vertex */
880 vlist[nvs][0] = x;
881 vlist[nvs][1] = y;
882 vlist[nvs][2] = z;
883 return(++nvs);
884 }
885
886
887 int
888 newvn(x, y, z) /* create a new vertex normal */
889 double x, y, z;
890 {
891 if (!(nvns%CHUNKSIZ)) { /* allocate next block */
892 if (nvns == 0)
893 vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
894 else
895 vnlist = (FVECT *)realloc((char *)vnlist,
896 (nvns+CHUNKSIZ)*sizeof(FVECT));
897 if (vnlist == NULL) {
898 fprintf(stderr,
899 "Out of memory while allocating normal %d\n", nvns);
900 exit(1);
901 }
902 }
903 /* assign new normal */
904 vnlist[nvns][0] = x;
905 vnlist[nvns][1] = y;
906 vnlist[nvns][2] = z;
907 if (normalize(vnlist[nvns]) == 0.0)
908 return(0);
909 return(++nvns);
910 }
911
912
913 int
914 newvt(x, y) /* create a new texture map vertex */
915 double x, y;
916 {
917 if (!(nvts%CHUNKSIZ)) { /* allocate next block */
918 if (nvts == 0)
919 vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
920 else
921 vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
922 (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
923 if (vtlist == NULL) {
924 fprintf(stderr,
925 "Out of memory while allocating texture vertex %d\n",
926 nvts);
927 exit(1);
928 }
929 }
930 /* assign new vertex */
931 vtlist[nvts][0] = x;
932 vtlist[nvts][1] = y;
933 return(++nvts);
934 }
935
936
937 syntax(er) /* report syntax error and exit */
938 char *er;
939 {
940 fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
941 inpfile, lineno, er);
942 exit(1);
943 }