ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.2
Committed: Tue Apr 12 17:28:52 1994 UTC (29 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +10 -8 lines
Log Message:
made zero-area faces non-fatal

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, and faces
11 * must be either quads or triangles for smoothing to work.
12 * Also, texture indices only work for triangles, though
13 * I'm not sure they work correctly.
14 */
15
16 #include "standard.h"
17
18 #include <ctype.h>
19
20 #define VOIDID "void" /* this is defined in object.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
27 #define ABS(x) ((x)>=0 ? (x) : -(x))
28
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 FLOAT (*vtlist)[2]; /* texture vertex list */
36 int nvts;
37
38 typedef FLOAT BARYCCM[3][4]; /* barycentric coordinate system */
39
40 typedef int VNDX[3]; /* vertex index (point,texture,normal) */
41
42 #define CHUNKSIZ 128 /* vertex allocation chunk size */
43
44 #define MAXARG 64 /* maximum # arguments in a statement */
45
46 char *defmat = VOIDID; /* default (starting) material name */
47 char *defpat = ""; /* default (starting) picture name */
48 char *defobj = "F"; /* default (starting) object name */
49
50 char picfile[128]; /* current picture file */
51 char matname[64]; /* current material name */
52 char objname[128]; /* current object name */
53 int lineno; /* current line number */
54
55 int nfaces; /* total number of faces output */
56
57
58 main(argc, argv) /* read in T-mesh files and convert */
59 int argc;
60 char *argv[];
61 {
62 FILE *fp;
63 int i;
64
65 for (i = 1; i < argc && argv[i][0] == '-'; i++)
66 switch (argv[i][1]) {
67 case 'o': /* object name */
68 defobj = argv[++i];
69 break;
70 case 'm': /* default material */
71 defmat = argv[++i];
72 break;
73 case 'p': /* default picture */
74 defpat = argv[++i];
75 break;
76 default:
77 fprintf(stderr,
78 "Usage: %s [-o obj][-m mat][-p pic] [file ..]\n",
79 argv[0]);
80 exit(1);
81 }
82 if (i >= argc)
83 convert("<stdin>", stdin);
84 else
85 for ( ; i < argc; i++) {
86 if ((fp = fopen(argv[i], "r")) == NULL) {
87 perror(argv[i]);
88 exit(1);
89 }
90 convert(argv[i], fp);
91 fclose(fp);
92 }
93 exit(0);
94 }
95
96
97 convert(fname, fp) /* convert a T-mesh */
98 char *fname;
99 FILE *fp;
100 {
101 char *argv[MAXARG];
102 int argc;
103 int nstats, nunknown;
104 register int i;
105 /* start fresh */
106 freeverts();
107 strcpy(picfile, defpat);
108 strcpy(matname, defmat);
109 strcpy(objname, defobj);
110 lineno = 0;
111 nstats = nunknown = 0;
112
113 printf("\n# Wavefront file read from: %s\n", fname);
114 /* scan until EOF */
115 while (argc = getstmt(argv, fp)) {
116 switch (argv[0][0]) {
117 case 'v': /* vertex */
118 switch (argv[0][1]) {
119 case '\0': /* point */
120 if (badarg(argc-1,argv+1,"fff"))
121 syntax(fname, lineno, "Bad vertex");
122 newv(atof(argv[1]), atof(argv[2]),
123 atof(argv[3]));
124 break;
125 case 'n': /* normal */
126 if (argv[0][2])
127 goto unknown;
128 if (badarg(argc-1,argv+1,"fff"))
129 syntax(fname, lineno, "Bad normal");
130 if (!newvn(atof(argv[1]), atof(argv[2]),
131 atof(argv[3])))
132 syntax(fname, lineno, "Zero normal");
133 break;
134 case 't': /* texture */
135 if (argv[0][2])
136 goto unknown;
137 if (badarg(argc-1,argv+1,"ff"))
138 goto unknown;
139 newvt(atof(argv[1]), atof(argv[2]));
140 break;
141 default:
142 goto unknown;
143 }
144 break;
145 case 'f': /* face */
146 if (argv[0][1])
147 goto unknown;
148 switch (argc-1) {
149 case 0: case 1: case 2:
150 syntax(fname, lineno, "Too few vertices");
151 break;
152 case 3:
153 if (!puttri(argv[1], argv[2], argv[3]))
154 syntax(fname, lineno, "Bad triangle");
155 break;
156 case 4:
157 if (!putquad(argv[1], argv[2],
158 argv[3], argv[4]))
159 syntax(fname, lineno, "Bad quad");
160 break;
161 default:
162 if (!putface(argc-1, argv+1))
163 syntax(fname, lineno, "Bad face");
164 break;
165 }
166 break;
167 case 'u':
168 if (!strcmp(argv[0], "usemtl")) { /* material */
169 if (argc < 2)
170 break; /* not fatal */
171 strcpy(matname, argv[1]);
172 } else if (!strcmp(argv[0], "usemap")) {/* map */
173 if (argc < 2)
174 break; /* not fatal */
175 if (!strcmp(argv[1], "off"))
176 picfile[0] = '\0';
177 else
178 strcpy(picfile, argv[1]);
179 } else
180 goto unknown;
181 break;
182 case 'o': /* object name */
183 if (argv[0][1])
184 goto unknown;
185 if (argc < 2)
186 break; /* not fatal */
187 strcpy(objname, argv[1]);
188 break;
189 case 'g': /* group name(s) */
190 if (argv[0][1])
191 goto unknown;
192 if (argc < 2)
193 break; /* not fatal */
194 objname[0] = '\0';
195 for (i = 1; i < argc; i++)
196 if (objname[0])
197 sprintf(objname+strlen(objname),
198 ".%s", argv[i]);
199 else
200 strcpy(objname, argv[i]);
201 break;
202 case '#': /* comment */
203 break;
204 default:; /* something we don't deal with */
205 unknown:
206 nunknown++;
207 break;
208 }
209 nstats++;
210 }
211 printf("\n# Done processing file: %s\n", fname);
212 printf("# %d lines, %d statements, %d unrecognized\n",
213 lineno, nstats, nunknown);
214 }
215
216
217 int
218 getstmt(av, fp) /* read the next statement from fp */
219 register char *av[MAXARG];
220 FILE *fp;
221 {
222 extern char *fgetline();
223 static char sbuf[MAXARG*10];
224 register char *cp;
225 register int i;
226
227 do {
228 if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
229 return(0);
230 i = 0;
231 for ( ; ; ) {
232 while (isspace(*cp) || *cp == '\\') {
233 if (*cp == '\n')
234 lineno++;
235 *cp++ = '\0';
236 }
237 if (!*cp || i >= MAXARG-1)
238 break;
239 av[i++] = cp;
240 while (*++cp && !isspace(*cp))
241 ;
242 }
243 av[i] = NULL;
244 lineno++;
245 } while (!i);
246
247 return(i);
248 }
249
250
251 cvtndx(vi, vs) /* convert vertex string to index */
252 register VNDX vi;
253 register char *vs;
254 {
255 /* get point */
256 vi[0] = atoi(vs);
257 if (vi[0] > 0) {
258 if (vi[0]-- > nvs)
259 return(0);
260 } else if (vi[0] < 0) {
261 vi[0] = nvs + vi[0];
262 if (vi[0] < 0)
263 return(0);
264 } else
265 return(0);
266 /* get texture */
267 while (*vs)
268 if (*vs++ == '/')
269 break;
270 vi[1] = atoi(vs);
271 if (vi[1] > 0) {
272 if (vi[1]-- > nvts)
273 return(0);
274 } else if (vi[1] < 0) {
275 vi[1] = nvts + vi[1];
276 if (vi[1] < 0)
277 return(0);
278 } else
279 vi[1] = -1;
280 /* get normal */
281 while (*vs)
282 if (*vs++ == '/')
283 break;
284 vi[2] = atoi(vs);
285 if (vi[2] > 0) {
286 if (vi[2]-- > nvns)
287 return(0);
288 } else if (vi[2] < 0) {
289 vi[2] = nvns + vi[2];
290 if (vi[2] < 0)
291 return(0);
292 } else
293 vi[2] = -1;
294 return(1);
295 }
296
297
298 putface(ac, av) /* put out an N-sided polygon */
299 register int ac;
300 register char **av;
301 {
302 VNDX vi;
303
304 printf("\n%s polygon %s.%d\n", matname, objname, ++nfaces);
305 printf("0\n0\n%d\n", 3*ac);
306 while (ac--) {
307 if (!cvtndx(vi, *av++))
308 return(0);
309 pvect(vlist[vi[0]]);
310 }
311 return(1);
312 }
313
314
315 puttri(v1, v2, v3) /* put out a triangle */
316 char *v1, *v2, *v3;
317 {
318 char *mod = matname;
319 VNDX v1i, v2i, v3i;
320 BARYCCM bvecs;
321 int texOK, patOK;
322
323 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
324 return(0);
325 /* compute barycentric coordinates */
326 texOK = (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0);
327 patOK = picfile[0] && (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0);
328 if (texOK | patOK)
329 if (comp_baryc(bvecs, vlist[v1i[0]], vlist[v2i[0]],
330 vlist[v3i[0]]) < 0)
331 return(-1);
332 /* put out texture (if any) */
333 if (texOK) {
334 printf("\n%s texfunc %s\n", mod, TEXNAME);
335 mod = TEXNAME;
336 printf("4 dx dy dz %s\n", TCALNAME);
337 printf("0\n21\n");
338 put_baryc(bvecs);
339 printf("\t%14.12g %14.12g %14.12g\n",
340 vnlist[v1i[2]][0], vnlist[v2i[2]][0],
341 vnlist[v3i[2]][0]);
342 printf("\t%14.12g %14.12g %14.12g\n",
343 vnlist[v1i[2]][1], vnlist[v2i[2]][1],
344 vnlist[v3i[2]][1]);
345 printf("\t%14.12g %14.12g %14.12g\n",
346 vnlist[v1i[2]][2], vnlist[v2i[2]][2],
347 vnlist[v3i[2]][2]);
348 }
349 /* put out pattern (if any) */
350 if (patOK) {
351 printf("\n%s colorpict %s\n", mod, PATNAME);
352 mod = PATNAME;
353 printf("7 noneg noneg noneg %s %s u v\n", picfile, TCALNAME);
354 printf("0\n18\n");
355 put_baryc(bvecs);
356 printf("\t%f %f %f\n", vtlist[v1i[1]][0],
357 vtlist[v2i[1]][0], vtlist[v3i[1]][0]);
358 printf("\t%f %f %f\n", vtlist[v1i[1]][1],
359 vtlist[v2i[1]][1], vtlist[v3i[1]][1]);
360 }
361 /* put out triangle */
362 printf("\n%s polygon %s.%d\n", mod, objname, ++nfaces);
363 printf("0\n0\n9\n");
364 pvect(vlist[v1i[0]]);
365 pvect(vlist[v2i[0]]);
366 pvect(vlist[v3i[0]]);
367
368 return(1);
369 }
370
371
372 int
373 comp_baryc(bcm, v1, v2, v3) /* compute barycentric vectors */
374 register BARYCCM bcm;
375 FLOAT *v1, *v2, *v3;
376 {
377 FLOAT *vt;
378 FVECT va, vab, vcb;
379 double d;
380 register int i, j;
381
382 for (j = 0; j < 3; j++) {
383 for (i = 0; i < 3; i++) {
384 vab[i] = v1[i] - v2[i];
385 vcb[i] = v3[i] - v2[i];
386 }
387 d = DOT(vcb,vcb);
388 if (d <= FTINY)
389 return(-1);
390 d = DOT(vcb,vab)/d;
391 for (i = 0; i < 3; i++)
392 va[i] = vab[i] - vcb[i]*d;
393 d = DOT(va,va);
394 if (d <= FTINY)
395 return(-1);
396 for (i = 0; i < 3; i++) {
397 va[i] /= d;
398 bcm[j][i] = va[i];
399 }
400 bcm[j][3] = -DOT(v2,va);
401 /* rotate vertices */
402 vt = v1;
403 v1 = v2;
404 v2 = v3;
405 v3 = vt;
406 }
407 return(0);
408 }
409
410
411 put_baryc(bcm) /* put barycentric coord. vectors */
412 register BARYCCM bcm;
413 {
414 register int i;
415
416 for (i = 0; i < 3; i++)
417 printf("%14.8f %14.8f %14.8f %14.8f\n",
418 bcm[i][0], bcm[i][1], bcm[i][2], bcm[i][3]);
419 }
420
421
422 putquad(p0, p1, p2, p3) /* put out a quadrilateral */
423 char *p0, *p1, *p2, *p3;
424 {
425 VNDX p0i, p1i, p2i, p3i;
426 FVECT norm[4];
427 int axis;
428 FVECT v1, v2, vc1, vc2;
429 int ok1, ok2;
430 /* get actual indices */
431 if (!cvtndx(p0i,p0) || !cvtndx(p1i,p1) ||
432 !cvtndx(p2i,p2) || !cvtndx(p3i,p3))
433 return(0);
434 /* compute exact normals */
435 fvsum(v1, vlist[p1i[0]], vlist[p0i[0]], -1.0);
436 fvsum(v2, vlist[p2i[0]], vlist[p0i[0]], -1.0);
437 fcross(vc1, v1, v2);
438 ok1 = normalize(vc1) != 0.0;
439 fvsum(v1, vlist[p2i[0]], vlist[p3i[0]], -1.0);
440 fvsum(v2, vlist[p1i[0]], vlist[p3i[0]], -1.0);
441 fcross(vc2, v1, v2);
442 ok2 = normalize(vc2) != 0.0;
443 if (!(ok1 | ok2))
444 return(-1);
445 /* compute normal interpolation */
446 axis = norminterp(norm, p0i, p1i, p2i, p3i);
447
448 /* put out quadrilateral? */
449 if (ok1 & ok2 && fdot(vc1,vc2) >= 1.0-FTINY*FTINY) {
450 printf("\n%s ", matname);
451 if (axis != -1) {
452 printf("texfunc %s\n", TEXNAME);
453 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
454 printf("0\n13\t%d\n", axis);
455 pvect(norm[0]);
456 pvect(norm[1]);
457 pvect(norm[2]);
458 fvsum(v1, norm[3], vc1, -0.5);
459 fvsum(v1, v1, vc2, -0.5);
460 pvect(v1);
461 printf("\n%s ", TEXNAME);
462 }
463 printf("polygon %s.%d\n", objname, ++nfaces);
464 printf("0\n0\n12\n");
465 pvect(vlist[p0i[0]]);
466 pvect(vlist[p1i[0]]);
467 pvect(vlist[p3i[0]]);
468 pvect(vlist[p2i[0]]);
469 return(1);
470 }
471 /* put out triangles? */
472 if (ok1) {
473 printf("\n%s ", matname);
474 if (axis != -1) {
475 printf("texfunc %s\n", TEXNAME);
476 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
477 printf("0\n13\t%d\n", axis);
478 pvect(norm[0]);
479 pvect(norm[1]);
480 pvect(norm[2]);
481 fvsum(v1, norm[3], vc1, -1.0);
482 pvect(v1);
483 printf("\n%s ", TEXNAME);
484 }
485 printf("polygon %s.%d\n", objname, ++nfaces);
486 printf("0\n0\n9\n");
487 pvect(vlist[p0i[0]]);
488 pvect(vlist[p1i[0]]);
489 pvect(vlist[p2i[0]]);
490 }
491 if (ok2) {
492 printf("\n%s ", matname);
493 if (axis != -1) {
494 printf("texfunc %s\n", TEXNAME);
495 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
496 printf("0\n13\t%d\n", axis);
497 pvect(norm[0]);
498 pvect(norm[1]);
499 pvect(norm[2]);
500 fvsum(v2, norm[3], vc2, -1.0);
501 pvect(v2);
502 printf("\n%s ", TEXNAME);
503 }
504 printf("polygon %s.%d\n", objname, ++nfaces);
505 printf("0\n0\n9\n");
506 pvect(vlist[p2i[0]]);
507 pvect(vlist[p1i[0]]);
508 pvect(vlist[p3i[0]]);
509 }
510 return(1);
511 }
512
513
514 int
515 norminterp(resmat, p0i, p1i, p2i, p3i) /* compute normal interpolation */
516 register FVECT resmat[4];
517 register VNDX p0i, p1i, p2i, p3i;
518 {
519 #define u ((ax+1)%3)
520 #define v ((ax+2)%3)
521
522 register int ax;
523 MAT4 eqnmat;
524 FVECT v1;
525 register int i, j;
526
527 if (!(p0i[2]>=0 && p1i[2]>=0 && p2i[2]>=0 && p3i[2]>=0))
528 return(-1);
529 /* find dominant axis */
530 VCOPY(v1, vnlist[p0i[2]]);
531 fvsum(v1, v1, vnlist[p1i[2]], 1.0);
532 fvsum(v1, v1, vnlist[p2i[2]], 1.0);
533 fvsum(v1, v1, vnlist[p3i[2]], 1.0);
534 ax = ABS(v1[0]) > ABS(v1[1]) ? 0 : 1;
535 ax = ABS(v1[ax]) > ABS(v1[2]) ? ax : 2;
536 /* assign equation matrix */
537 eqnmat[0][0] = vlist[p0i[0]][u]*vlist[p0i[0]][v];
538 eqnmat[0][1] = vlist[p0i[0]][u];
539 eqnmat[0][2] = vlist[p0i[0]][v];
540 eqnmat[0][3] = 1.0;
541 eqnmat[1][0] = vlist[p1i[0]][u]*vlist[p1i[0]][v];
542 eqnmat[1][1] = vlist[p1i[0]][u];
543 eqnmat[1][2] = vlist[p1i[0]][v];
544 eqnmat[1][3] = 1.0;
545 eqnmat[2][0] = vlist[p2i[0]][u]*vlist[p2i[0]][v];
546 eqnmat[2][1] = vlist[p2i[0]][u];
547 eqnmat[2][2] = vlist[p2i[0]][v];
548 eqnmat[2][3] = 1.0;
549 eqnmat[3][0] = vlist[p3i[0]][u]*vlist[p3i[0]][v];
550 eqnmat[3][1] = vlist[p3i[0]][u];
551 eqnmat[3][2] = vlist[p3i[0]][v];
552 eqnmat[3][3] = 1.0;
553 /* invert matrix (solve system) */
554 if (!invmat4(eqnmat, eqnmat))
555 return(-1); /* no solution */
556 /* compute result matrix */
557 for (j = 0; j < 4; j++)
558 for (i = 0; i < 3; i++)
559 resmat[j][i] = eqnmat[j][0]*vnlist[p0i[2]][i] +
560 eqnmat[j][1]*vnlist[p1i[2]][i] +
561 eqnmat[j][2]*vnlist[p2i[2]][i] +
562 eqnmat[j][3]*vnlist[p3i[2]][i];
563 return(ax);
564
565 #undef u
566 #undef v
567 }
568
569
570 freeverts() /* free all vertices */
571 {
572 if (nvs) {
573 free((char *)vlist);
574 nvs = 0;
575 }
576 if (nvts) {
577 free((char *)vtlist);
578 nvts = 0;
579 }
580 if (nvns) {
581 free((char *)vnlist);
582 nvns = 0;
583 }
584 }
585
586
587 int
588 newv(x, y, z) /* create a new vertex */
589 double x, y, z;
590 {
591 if (!(nvs%CHUNKSIZ)) { /* allocate next block */
592 if (nvs == 0)
593 vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
594 else
595 vlist = (FVECT *)realloc((char *)vlist,
596 (nvs+CHUNKSIZ)*sizeof(FVECT));
597 if (vlist == NULL) {
598 fprintf(stderr,
599 "Out of memory while allocating vertex %d\n", nvs);
600 exit(1);
601 }
602 }
603 /* assign new vertex */
604 vlist[nvs][0] = x;
605 vlist[nvs][1] = y;
606 vlist[nvs][2] = z;
607 return(++nvs);
608 }
609
610
611 int
612 newvn(x, y, z) /* create a new vertex normal */
613 double x, y, z;
614 {
615 if (!(nvns%CHUNKSIZ)) { /* allocate next block */
616 if (nvns == 0)
617 vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
618 else
619 vnlist = (FVECT *)realloc((char *)vnlist,
620 (nvns+CHUNKSIZ)*sizeof(FVECT));
621 if (vnlist == NULL) {
622 fprintf(stderr,
623 "Out of memory while allocating normal %d\n", nvns);
624 exit(1);
625 }
626 }
627 /* assign new normal */
628 vnlist[nvns][0] = x;
629 vnlist[nvns][1] = y;
630 vnlist[nvns][2] = z;
631 if (normalize(vnlist[nvns]) == 0.0)
632 return(0);
633 return(++nvns);
634 }
635
636
637 int
638 newvt(x, y) /* create a new texture vertex */
639 double x, y;
640 {
641 if (!(nvts%CHUNKSIZ)) { /* allocate next block */
642 if (nvts == 0)
643 vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
644 else
645 vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
646 (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
647 if (vtlist == NULL) {
648 fprintf(stderr,
649 "Out of memory while allocating texture vertex %d\n",
650 nvts);
651 exit(1);
652 }
653 }
654 /* assign new texture vertex */
655 vtlist[nvts][0] = x;
656 vtlist[nvts][1] = y;
657 return(++nvts);
658 }
659
660
661 syntax(fn, ln, er) /* report syntax error and exit */
662 char *fn;
663 int ln;
664 char *er;
665 {
666 fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
667 fn, ln, er);
668 exit(1);
669 }