ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.7
Committed: Thu Apr 14 13:36:18 1994 UTC (30 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +28 -9 lines
Log Message:
took out use of Wavefront texture maps and indices
fixed bug introduced last time in conversion of non-planar polygons

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