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

# User Rev Content
1 greg 2.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     }