ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/obj2rad.c
Revision: 2.1
Committed: Tue Apr 12 17:12:42 1994 UTC (30 years ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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("# 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
322 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
323 return(0);
324 /* compute barycentric coordinates */
325 if ((v1i[2]>=0&&v2i[2]>=0&&v3i[2]>=0) ||
326 (v1i[1]>=0&&v2i[1]>=0&&v3i[1]>=0))
327 if (comp_baryc(bvecs, vlist[v1i[0]], vlist[v2i[0]],
328 vlist[v3i[0]]) < 0)
329 return(0);
330 /* put out texture (if any) */
331 if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) {
332 printf("\n%s texfunc %s\n", mod, TEXNAME);
333 mod = TEXNAME;
334 printf("4 dx dy dz %s\n", TCALNAME);
335 printf("0\n21\n");
336 put_baryc(bvecs);
337 printf("\t%14.12g %14.12g %14.12g\n",
338 vnlist[v1i[2]][0], vnlist[v2i[2]][0],
339 vnlist[v3i[2]][0]);
340 printf("\t%14.12g %14.12g %14.12g\n",
341 vnlist[v1i[2]][1], vnlist[v2i[2]][1],
342 vnlist[v3i[2]][1]);
343 printf("\t%14.12g %14.12g %14.12g\n",
344 vnlist[v1i[2]][2], vnlist[v2i[2]][2],
345 vnlist[v3i[2]][2]);
346 }
347 /* put out pattern (if any) */
348 if (picfile[0] && v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
349 printf("\n%s colorpict %s\n", mod, PATNAME);
350 mod = PATNAME;
351 printf("7 noneg noneg noneg %s %s u v\n", picfile, TCALNAME);
352 printf("0\n18\n");
353 put_baryc(bvecs);
354 printf("\t%f %f %f\n", vtlist[v1i[1]][0],
355 vtlist[v2i[1]][0], vtlist[v3i[1]][0]);
356 printf("\t%f %f %f\n", vtlist[v1i[1]][1],
357 vtlist[v2i[1]][1], vtlist[v3i[1]][1]);
358 }
359 /* put out triangle */
360 printf("\n%s polygon %s.%d\n", matname, objname, ++nfaces);
361 printf("0\n0\n9\n");
362 pvect(vlist[v1i[0]]);
363 pvect(vlist[v2i[0]]);
364 pvect(vlist[v3i[0]]);
365
366 return(1);
367 }
368
369
370 int
371 comp_baryc(bcm, v1, v2, v3) /* compute barycentric vectors */
372 register BARYCCM bcm;
373 FLOAT *v1, *v2, *v3;
374 {
375 FLOAT *vt;
376 FVECT va, vab, vcb;
377 double d;
378 register int i, j;
379
380 for (j = 0; j < 3; j++) {
381 for (i = 0; i < 3; i++) {
382 vab[i] = v1[i] - v2[i];
383 vcb[i] = v3[i] - v2[i];
384 }
385 d = DOT(vcb,vcb);
386 if (d <= FTINY)
387 return(-1);
388 d = DOT(vcb,vab)/d;
389 for (i = 0; i < 3; i++)
390 va[i] = vab[i] - vcb[i]*d;
391 d = DOT(va,va);
392 if (d <= FTINY)
393 return(-1);
394 for (i = 0; i < 3; i++) {
395 va[i] /= d;
396 bcm[j][i] = va[i];
397 }
398 bcm[j][3] = -DOT(v2,va);
399 /* rotate vertices */
400 vt = v1;
401 v1 = v2;
402 v2 = v3;
403 v3 = vt;
404 }
405 return(0);
406 }
407
408
409 put_baryc(bcm) /* put barycentric coord. vectors */
410 register BARYCCM bcm;
411 {
412 register int i;
413
414 for (i = 0; i < 3; i++)
415 printf("%14.8f %14.8f %14.8f %14.8f\n",
416 bcm[i][0], bcm[i][1], bcm[i][2], bcm[i][3]);
417 }
418
419
420 putquad(p0, p1, p2, p3) /* put out a quadrilateral */
421 char *p0, *p1, *p2, *p3;
422 {
423 VNDX p0i, p1i, p2i, p3i;
424 FVECT norm[4];
425 int axis;
426 FVECT v1, v2, vc1, vc2;
427 int ok1, ok2;
428 /* get actual indices */
429 if (!cvtndx(p0i,p0) || !cvtndx(p1i,p1) ||
430 !cvtndx(p2i,p2) || !cvtndx(p3i,p3))
431 return(0);
432 /* compute exact normals */
433 fvsum(v1, vlist[p1i[0]], vlist[p0i[0]], -1.0);
434 fvsum(v2, vlist[p2i[0]], vlist[p0i[0]], -1.0);
435 fcross(vc1, v1, v2);
436 ok1 = normalize(vc1) != 0.0;
437 fvsum(v1, vlist[p2i[0]], vlist[p3i[0]], -1.0);
438 fvsum(v2, vlist[p1i[0]], vlist[p3i[0]], -1.0);
439 fcross(vc2, v1, v2);
440 ok2 = normalize(vc2) != 0.0;
441 if (!(ok1 | ok2))
442 return(0);
443 /* compute normal interpolation */
444 axis = norminterp(norm, p0i, p1i, p2i, p3i);
445
446 /* put out quadrilateral? */
447 if (ok1 & ok2 && fdot(vc1,vc2) >= 1.0-FTINY*FTINY) {
448 printf("\n%s ", matname);
449 if (axis != -1) {
450 printf("texfunc %s\n", TEXNAME);
451 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
452 printf("0\n13\t%d\n", axis);
453 pvect(norm[0]);
454 pvect(norm[1]);
455 pvect(norm[2]);
456 fvsum(v1, norm[3], vc1, -0.5);
457 fvsum(v1, v1, vc2, -0.5);
458 pvect(v1);
459 printf("\n%s ", TEXNAME);
460 }
461 printf("polygon %s.%d\n", objname, ++nfaces);
462 printf("0\n0\n12\n");
463 pvect(vlist[p0i[0]]);
464 pvect(vlist[p1i[0]]);
465 pvect(vlist[p3i[0]]);
466 pvect(vlist[p2i[0]]);
467 return(1);
468 }
469 /* put out triangles? */
470 if (ok1) {
471 printf("\n%s ", matname);
472 if (axis != -1) {
473 printf("texfunc %s\n", TEXNAME);
474 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
475 printf("0\n13\t%d\n", axis);
476 pvect(norm[0]);
477 pvect(norm[1]);
478 pvect(norm[2]);
479 fvsum(v1, norm[3], vc1, -1.0);
480 pvect(v1);
481 printf("\n%s ", TEXNAME);
482 }
483 printf("polygon %s.%d\n", objname, ++nfaces);
484 printf("0\n0\n9\n");
485 pvect(vlist[p0i[0]]);
486 pvect(vlist[p1i[0]]);
487 pvect(vlist[p2i[0]]);
488 }
489 if (ok2) {
490 printf("\n%s ", matname);
491 if (axis != -1) {
492 printf("texfunc %s\n", TEXNAME);
493 printf("4 surf_dx surf_dy surf_dz %s\n", QCALNAME);
494 printf("0\n13\t%d\n", axis);
495 pvect(norm[0]);
496 pvect(norm[1]);
497 pvect(norm[2]);
498 fvsum(v2, norm[3], vc2, -1.0);
499 pvect(v2);
500 printf("\n%s ", TEXNAME);
501 }
502 printf("polygon %s.%d\n", objname, ++nfaces);
503 printf("0\n0\n9\n");
504 pvect(vlist[p2i[0]]);
505 pvect(vlist[p1i[0]]);
506 pvect(vlist[p3i[0]]);
507 }
508 return(1);
509 }
510
511
512 int
513 norminterp(resmat, p0i, p1i, p2i, p3i) /* compute normal interpolation */
514 register FVECT resmat[4];
515 register VNDX p0i, p1i, p2i, p3i;
516 {
517 #define u ((ax+1)%3)
518 #define v ((ax+2)%3)
519
520 register int ax;
521 MAT4 eqnmat;
522 FVECT v1;
523 register int i, j;
524
525 if (!(p0i[2]>=0 && p1i[2]>=0 && p2i[2]>=0 && p3i[2]>=0))
526 return(-1);
527 /* find dominant axis */
528 VCOPY(v1, vnlist[p0i[2]]);
529 fvsum(v1, v1, vnlist[p1i[2]], 1.0);
530 fvsum(v1, v1, vnlist[p2i[2]], 1.0);
531 fvsum(v1, v1, vnlist[p3i[2]], 1.0);
532 ax = ABS(v1[0]) > ABS(v1[1]) ? 0 : 1;
533 ax = ABS(v1[ax]) > ABS(v1[2]) ? ax : 2;
534 /* assign equation matrix */
535 eqnmat[0][0] = vlist[p0i[0]][u]*vlist[p0i[0]][v];
536 eqnmat[0][1] = vlist[p0i[0]][u];
537 eqnmat[0][2] = vlist[p0i[0]][v];
538 eqnmat[0][3] = 1.0;
539 eqnmat[1][0] = vlist[p1i[0]][u]*vlist[p1i[0]][v];
540 eqnmat[1][1] = vlist[p1i[0]][u];
541 eqnmat[1][2] = vlist[p1i[0]][v];
542 eqnmat[1][3] = 1.0;
543 eqnmat[2][0] = vlist[p2i[0]][u]*vlist[p2i[0]][v];
544 eqnmat[2][1] = vlist[p2i[0]][u];
545 eqnmat[2][2] = vlist[p2i[0]][v];
546 eqnmat[2][3] = 1.0;
547 eqnmat[3][0] = vlist[p3i[0]][u]*vlist[p3i[0]][v];
548 eqnmat[3][1] = vlist[p3i[0]][u];
549 eqnmat[3][2] = vlist[p3i[0]][v];
550 eqnmat[3][3] = 1.0;
551 /* invert matrix (solve system) */
552 if (!invmat4(eqnmat, eqnmat))
553 return(-1); /* no solution */
554 /* compute result matrix */
555 for (j = 0; j < 4; j++)
556 for (i = 0; i < 3; i++)
557 resmat[j][i] = eqnmat[j][0]*vnlist[p0i[2]][i] +
558 eqnmat[j][1]*vnlist[p1i[2]][i] +
559 eqnmat[j][2]*vnlist[p2i[2]][i] +
560 eqnmat[j][3]*vnlist[p3i[2]][i];
561 return(ax);
562
563 #undef u
564 #undef v
565 }
566
567
568 freeverts() /* free all vertices */
569 {
570 if (nvs) {
571 free((char *)vlist);
572 nvs = 0;
573 }
574 if (nvts) {
575 free((char *)vtlist);
576 nvts = 0;
577 }
578 if (nvns) {
579 free((char *)vnlist);
580 nvns = 0;
581 }
582 }
583
584
585 int
586 newv(x, y, z) /* create a new vertex */
587 double x, y, z;
588 {
589 if (!(nvs%CHUNKSIZ)) { /* allocate next block */
590 if (nvs == 0)
591 vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
592 else
593 vlist = (FVECT *)realloc((char *)vlist,
594 (nvs+CHUNKSIZ)*sizeof(FVECT));
595 if (vlist == NULL) {
596 fprintf(stderr,
597 "Out of memory while allocating vertex %d\n", nvs);
598 exit(1);
599 }
600 }
601 /* assign new vertex */
602 vlist[nvs][0] = x;
603 vlist[nvs][1] = y;
604 vlist[nvs][2] = z;
605 return(++nvs);
606 }
607
608
609 int
610 newvn(x, y, z) /* create a new vertex normal */
611 double x, y, z;
612 {
613 if (!(nvns%CHUNKSIZ)) { /* allocate next block */
614 if (nvns == 0)
615 vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
616 else
617 vnlist = (FVECT *)realloc((char *)vnlist,
618 (nvns+CHUNKSIZ)*sizeof(FVECT));
619 if (vnlist == NULL) {
620 fprintf(stderr,
621 "Out of memory while allocating normal %d\n", nvns);
622 exit(1);
623 }
624 }
625 /* assign new normal */
626 vnlist[nvns][0] = x;
627 vnlist[nvns][1] = y;
628 vnlist[nvns][2] = z;
629 if (normalize(vnlist[nvns]) == 0.0)
630 return(0);
631 return(++nvns);
632 }
633
634
635 int
636 newvt(x, y) /* create a new texture vertex */
637 double x, y;
638 {
639 if (!(nvts%CHUNKSIZ)) { /* allocate next block */
640 if (nvts == 0)
641 vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
642 else
643 vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
644 (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
645 if (vtlist == NULL) {
646 fprintf(stderr,
647 "Out of memory while allocating texture vertex %d\n",
648 nvts);
649 exit(1);
650 }
651 }
652 /* assign new texture vertex */
653 vtlist[nvts][0] = x;
654 vtlist[nvts][1] = y;
655 return(++nvts);
656 }
657
658
659 syntax(fn, ln, er) /* report syntax error and exit */
660 char *fn;
661 int ln;
662 char *er;
663 {
664 fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
665 fn, ln, er);
666 exit(1);
667 }