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

# 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 greg 2.2 printf("\n# Done processing file: %s\n", fname);
212 greg 2.1 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 greg 2.2 int texOK, patOK;
322 greg 2.1
323     if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
324     return(0);
325     /* compute barycentric coordinates */
326 greg 2.2 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 greg 2.1 if (comp_baryc(bvecs, vlist[v1i[0]], vlist[v2i[0]],
330     vlist[v3i[0]]) < 0)
331 greg 2.2 return(-1);
332 greg 2.1 /* put out texture (if any) */
333 greg 2.2 if (texOK) {
334 greg 2.1 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 greg 2.2 if (patOK) {
351 greg 2.1 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 greg 2.2 printf("\n%s polygon %s.%d\n", mod, objname, ++nfaces);
363 greg 2.1 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 greg 2.2 return(-1);
445 greg 2.1 /* 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     }