ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.10
Committed: Wed Jun 15 12:29:55 1994 UTC (29 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.9: +40 -29 lines
Log Message:
changed to more compact barycentric coordinate calculation

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