ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/rad2mgf.c
Revision: 2.24
Committed: Wed Dec 28 18:35:42 2005 UTC (18 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.23: +49 -38 lines
Log Message:
Made scene i/o work for identifiers with spaces and quotes

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.24 static const char RCSid[] = "$Id: rad2mgf.c,v 2.23 2003/11/15 17:54:06 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Convert Radiance scene description to MGF
6     */
7    
8 greg 2.12 #include <ctype.h>
9 greg 2.1 #include <string.h>
10 schorsch 2.17 #include <stdio.h>
11    
12 schorsch 2.23 #include "platform.h"
13     #include "rtmath.h"
14     #include "rtio.h"
15 schorsch 2.21 #include "rtprocess.h"
16 greg 2.1 #include "object.h"
17     #include "color.h"
18     #include "lookup.h"
19    
20 greg 2.10 #define C_1SIDEDTHICK 0.005
21    
22 greg 2.1
23     LUTAB rmats = LU_SINIT(free,NULL); /* defined material table */
24    
25     LUTAB rdispatch = LU_SINIT(NULL,NULL); /* function dispatch table */
26    
27 greg 2.2 char curmat[80]; /* current material */
28     char curobj[128] = "Untitled"; /* current object name */
29 greg 2.1
30 greg 2.2 double unit_mult = 1.; /* units multiplier */
31 greg 2.1
32 greg 2.2 #define hasmult (unit_mult < .999 || unit_mult > 1.001)
33 greg 2.1
34 greg 2.4 /*
35     * Stuff for tracking and reusing vertices:
36     */
37 greg 2.2
38 greg 2.9 char VKFMT[] = "%+16.9e %+16.9e %+16.9e";
39 greg 2.4 #define VKLEN 64
40    
41     #define mkvkey(k,v) sprintf(k, VKFMT, (v)[0], (v)[1], (v)[2])
42    
43     #define NVERTS 256
44    
45 greg 2.8 long vclock; /* incremented at each vertex request */
46 greg 2.4
47     struct vert {
48     long lused; /* when last used (0 if unassigned) */
49     FVECT p; /* track point position only */
50     } vert[NVERTS]; /* our vertex cache */
51    
52     LUTAB vertab = LU_SINIT(free,NULL); /* our vertex lookup table */
53    
54 greg 2.24 void rad2mgf(char *inp);
55     void cvtprim(char *inp, char *mod, char *typ, char *id, FUNARGS *fa);
56     void newmat(char *id, char *alias);
57     void setmat(char *id);
58     void setobj(char *id);
59     void init(void);
60     void uninit(void);
61     void clrverts(void);
62     void unspace(char *s);
63     void add2dispatch(char *name, int (*func)());
64     char *getvertid(char *vname, FVECT vp);
65     int o_unsupported(char *mod, char *typ, char *id, FUNARGS *fa);
66     int o_face(char *mod, char *typ, char *id, FUNARGS *fa);
67     int o_cone(char *mod, char *typ, char *id, FUNARGS *fa);
68     int o_sphere(char *mod, char *typ, char *id, FUNARGS *fa);
69     int o_cylinder(char *mod, char *typ, char *id, FUNARGS *fa);
70     int o_ring(char *mod, char *typ, char *id, FUNARGS *fa);
71     int o_instance(char *mod, char *typ, char *id, FUNARGS *fa);
72     int o_illum(char *mod, char *typ, char *id, FUNARGS *fa);
73     int o_plastic(char *mod, char *typ, char *id, FUNARGS *fa);
74     int o_metal(char *mod, char *typ, char *id, FUNARGS *fa);
75     int o_glass(char *mod, char *typ, char *id, FUNARGS *fa);
76     int o_dielectric(char *mod, char *typ, char *id, FUNARGS *fa);
77     int o_mirror(char *mod, char *typ, char *id, FUNARGS *fa);
78     int o_trans(char *mod, char *typ, char *id, FUNARGS *fa);
79     int o_light(char *mod, char *typ, char *id, FUNARGS *fa);
80 greg 2.4
81 schorsch 2.22
82     int
83     main(
84     int argc,
85     char **argv
86     )
87 greg 2.1 {
88     int i;
89    
90     for (i = 1; i < argc && argv[i][0] == '-'; i++)
91     switch (argv[i][1]) {
92     case 'd': /* units */
93     switch (argv[i][2]) {
94     case 'm': /* meters */
95     unit_mult = 1.;
96     break;
97     case 'c': /* centimeters */
98     unit_mult = .01;
99     break;
100     case 'f': /* feet */
101     unit_mult = 12.*.0254;
102     break;
103     case 'i': /* inches */
104     unit_mult = .0254;
105     break;
106     default:
107     goto unkopt;
108     }
109     break;
110 greg 2.6 default:
111     goto unkopt;
112 greg 2.1 }
113     init();
114     if (i >= argc)
115     rad2mgf(NULL);
116     else
117     for ( ; i < argc; i++)
118     rad2mgf(argv[i]);
119     uninit();
120     exit(0);
121     unkopt:
122     fprintf(stderr, "Usage: %s [-d{m|c|f|i}] file ..\n", argv[0]);
123     exit(1);
124     }
125    
126    
127 schorsch 2.22 void
128     rad2mgf( /* convert a Radiance file to MGF */
129     char *inp
130     )
131 greg 2.1 {
132 greg 2.24 char mod[128], typ[32], id[128], alias[128];
133 greg 2.1 FUNARGS fa;
134     register FILE *fp;
135     register int c;
136    
137     if (inp == NULL) {
138 greg 2.2 inp = "standard input";
139 greg 2.1 fp = stdin;
140     } else if (inp[0] == '!') {
141     if ((fp = popen(inp+1, "r")) == NULL) {
142     fputs(inp, stderr);
143     fputs(": cannot execute\n", stderr);
144     exit(1);
145     }
146     } else if ((fp = fopen(inp, "r")) == NULL) {
147     fputs(inp, stderr);
148     fputs(": cannot open\n", stderr);
149     exit(1);
150     }
151     printf("# Begin conversion from: %s\n", inp);
152     while ((c = getc(fp)) != EOF)
153     switch (c) {
154     case ' ': /* white space */
155     case '\t':
156     case '\n':
157     case '\r':
158     case '\f':
159     break;
160     case '#': /* comment */
161     if (fgets(buf, sizeof(buf), fp) != NULL)
162     printf("# %s", buf);
163     break;
164     case '!': /* inline command */
165     ungetc(c, fp);
166     fgetline(buf, sizeof(buf), fp);
167     rad2mgf(buf);
168     break;
169     default: /* Radiance primitive */
170     ungetc(c, fp);
171 greg 2.24 if (fgetword(mod, sizeof(mod), fp) == NULL ||
172     fgetword(typ, sizeof(typ), fp) == NULL ||
173     fgetword(id, sizeof(id), fp) == NULL) {
174 greg 2.1 fputs(inp, stderr);
175     fputs(": unexpected EOF\n", stderr);
176     exit(1);
177     }
178 greg 2.24 unspace(mod);
179     unspace(id);
180 greg 2.1 if (!strcmp(typ, "alias")) {
181     strcpy(alias, "EOF");
182 greg 2.24 fgetword(alias, sizeof(alias), fp);
183     unspace(alias);
184 greg 2.1 newmat(id, alias);
185     } else {
186     if (!readfargs(&fa, fp)) {
187     fprintf(stderr,
188     "%s: bad argument syntax for %s \"%s\"\n",
189     inp, typ, id);
190     exit(1);
191     }
192     cvtprim(inp, mod, typ, id, &fa);
193     freefargs(&fa);
194     }
195     break;
196     }
197     printf("# End conversion from: %s\n", inp);
198     if (inp[0] == '!')
199     pclose(fp);
200     else
201     fclose(fp);
202 greg 2.24 }
203    
204    
205     void
206     unspace( /* replace spaces with underscores in s */
207     char *s
208     )
209     {
210     while (*s) {
211     if (isspace(*s))
212     *s = '_';
213     ++s;
214     }
215 greg 2.1 }
216    
217    
218 schorsch 2.22 void
219     cvtprim( /* process Radiance primitive */
220     char *inp,
221     char *mod,
222     char *typ,
223     char *id,
224     FUNARGS *fa
225     )
226 greg 2.1 {
227     int (*df)();
228    
229     df = (int (*)())lu_find(&rdispatch, typ)->data;
230     if (df != NULL) { /* convert */
231     if ((*df)(mod, typ, id, fa) < 0) {
232 greg 2.24 fprintf(stderr, "%s: bad %s \"%s\"\n", "rad2mgf", typ, id);
233 greg 2.1 exit(1);
234     }
235 greg 2.11 } else { /* unsupported */
236     o_unsupported(mod, typ, id, fa);
237     if (lu_find(&rmats, mod)->data != NULL) /* make alias */
238     newmat(id, mod);
239     }
240 greg 2.1 }
241    
242    
243 schorsch 2.22 void
244     newmat( /* add a modifier to the alias list */
245     char *id,
246     char *alias
247     )
248 greg 2.1 {
249     register LUENT *lp, *lpa;
250    
251     if (alias != NULL) { /* look up alias */
252     if ((lpa = lu_find(&rmats, alias)) == NULL)
253     goto memerr;
254     if (lpa->data == NULL)
255     alias = NULL; /* doesn't exist! */
256     }
257     if ((lp = lu_find(&rmats, id)) == NULL) /* look up material */
258     goto memerr;
259     if (alias != NULL && lp->data == lpa->key)
260     return; /* alias set already */
261     if (lp->data == NULL) { /* allocate material */
262     if ((lp->key = (char *)malloc(strlen(id)+1)) == NULL)
263     goto memerr;
264     strcpy(lp->key, id);
265     }
266     if (alias == NULL) { /* set this material */
267     lp->data = lp->key;
268     printf("m %s =\n", id);
269     } else { /* set this alias */
270     lp->data = lpa->key;
271     printf("m %s = %s\n", id, alias);
272     }
273     strcpy(curmat, id);
274     return;
275     memerr:
276     fputs("Out of memory in newmat!\n", stderr);
277     exit(1);
278     }
279    
280    
281 schorsch 2.22 void
282     setmat( /* set material to this one */
283     char *id
284     )
285 greg 2.1 {
286     if (!strcmp(id, curmat)) /* already set? */
287     return;
288 greg 2.2 if (!strcmp(id, VOIDID)) /* cannot set */
289     return;
290 greg 2.1 printf("m %s\n", id);
291     strcpy(curmat, id);
292     }
293    
294    
295 schorsch 2.22 void
296     setobj( /* set object name to this one */
297     char *id
298     )
299 greg 2.2 {
300     register char *cp, *cp2;
301     char *end = NULL;
302     int diff = 0;
303     /* use all but final suffix */
304     for (cp = id; *cp; cp++)
305     if (*cp == '.')
306     end = cp;
307     if (end == NULL)
308     end = cp;
309     /* copy to current object */
310 greg 2.12 cp2 = curobj;
311     if (!isalpha(*id)) { /* start with letter */
312     diff = *cp2 != 'O';
313     *cp2++ = 'O';
314     }
315     for (cp = id; cp < end; *cp2++ = *cp++) {
316 schorsch 2.18 if ((*cp < '!') | (*cp > '~')) /* limit to visible chars */
317 greg 2.12 *cp = '?';
318 greg 2.2 diff += *cp != *cp2;
319 greg 2.12 }
320 greg 2.2 if (!diff && !*cp2)
321     return;
322     *cp2 = '\0';
323     fputs("o\no ", stdout);
324     puts(curobj);
325     }
326    
327    
328 schorsch 2.22 void
329     init(void) /* initialize dispatch table and output */
330 greg 2.1 {
331 greg 2.4 lu_init(&vertab, NVERTS);
332 greg 2.1 lu_init(&rdispatch, 22);
333     add2dispatch("polygon", o_face);
334     add2dispatch("cone", o_cone);
335     add2dispatch("cup", o_cone);
336     add2dispatch("sphere", o_sphere);
337     add2dispatch("bubble", o_sphere);
338     add2dispatch("cylinder", o_cylinder);
339     add2dispatch("tube", o_cylinder);
340     add2dispatch("ring", o_ring);
341     add2dispatch("instance", o_instance);
342 greg 2.19 add2dispatch("mesh", o_instance);
343 greg 2.1 add2dispatch("plastic", o_plastic);
344     add2dispatch("plastic2", o_plastic);
345     add2dispatch("metal", o_metal);
346     add2dispatch("metal2", o_metal);
347     add2dispatch("glass", o_glass);
348 greg 2.10 add2dispatch("dielectric", o_dielectric);
349 greg 2.1 add2dispatch("trans", o_trans);
350     add2dispatch("trans2", o_trans);
351     add2dispatch("mirror", o_mirror);
352     add2dispatch("light", o_light);
353     add2dispatch("spotlight", o_light);
354     add2dispatch("glow", o_light);
355     add2dispatch("illum", o_illum);
356 greg 2.11 puts("# The following was converted from RADIANCE scene input");
357 greg 2.2 if (hasmult)
358 greg 2.1 printf("xf -s %.4e\n", unit_mult);
359 greg 2.2 printf("o %s\n", curobj);
360 greg 2.1 }
361    
362    
363 schorsch 2.22 void
364     uninit(void) /* mark end of MGF file */
365 greg 2.1 {
366 greg 2.2 puts("o");
367     if (hasmult)
368 greg 2.1 puts("xf");
369 greg 2.11 puts("# End of data converted from RADIANCE scene input");
370 greg 2.1 lu_done(&rdispatch);
371     lu_done(&rmats);
372 greg 2.4 lu_done(&vertab);
373 greg 2.1 }
374    
375    
376 schorsch 2.22 void
377     clrverts(void) /* clear vertex table */
378 greg 2.5 {
379     register int i;
380    
381     lu_done(&vertab);
382     for (i = 0; i < NVERTS; i++)
383     vert[i].lused = 0;
384     lu_init(&vertab, NVERTS);
385     }
386    
387    
388 schorsch 2.22 void
389     add2dispatch( /* add function to dispatch table */
390     char *name,
391     int (*func)()
392     )
393 greg 2.1 {
394     register LUENT *lp;
395    
396     lp = lu_find(&rdispatch, name);
397     if (lp->key != NULL) {
398     fputs(name, stderr);
399     fputs(": duplicate dispatch entry!\n", stderr);
400     exit(1);
401     }
402     lp->key = name;
403     lp->data = (char *)func;
404     }
405    
406    
407     char *
408 schorsch 2.22 getvertid( /* get/set vertex ID for this point */
409     char *vname,
410     FVECT vp
411     )
412 greg 2.1 {
413 greg 2.9 static char vkey[VKLEN];
414 greg 2.1 register LUENT *lp;
415     register int i, vndx;
416    
417 greg 2.8 vclock++; /* increment counter */
418 greg 2.1 mkvkey(vkey, vp);
419     if ((lp = lu_find(&vertab, vkey)) == NULL)
420     goto memerr;
421     if (lp->data == NULL) { /* allocate new vertex entry */
422     if (lp->key != NULL) /* reclaim deleted entry */
423     vertab.ndel--;
424     else {
425     if ((lp->key = (char *)malloc(VKLEN)) == NULL)
426     goto memerr;
427     strcpy(lp->key, vkey);
428     }
429     vndx = 0; /* find oldest vertex */
430     for (i = 1; i < NVERTS; i++)
431     if (vert[i].lused < vert[vndx].lused)
432     vndx = i;
433     if (vert[vndx].lused) { /* free old entry first */
434     mkvkey(vkey, vert[vndx].p);
435     lu_delete(&vertab, vkey);
436     }
437 greg 2.3 VCOPY(vert[vndx].p, vp); /* assign it */
438 greg 2.2 printf("v v%d =\n\tp %.15g %.15g %.15g\n", /* print it */
439 greg 2.1 vndx, vp[0], vp[1], vp[2]);
440     lp->data = (char *)&vert[vndx]; /* set it */
441     } else
442     vndx = (struct vert *)lp->data - vert;
443 greg 2.8 vert[vndx].lused = vclock; /* record this use */
444 greg 2.1 sprintf(vname, "v%d", vndx);
445     return(vname);
446     memerr:
447     fputs("Out of memory in getvertid!\n", stderr);
448     exit(1);
449     }
450    
451    
452     int
453 schorsch 2.22 o_unsupported( /* mark unsupported primitive */
454     char *mod,
455     char *typ,
456     char *id,
457     FUNARGS *fa
458     )
459 greg 2.11 {
460     register int i;
461    
462     fputs("\n# Unsupported RADIANCE primitive:\n", stdout);
463     printf("# %s %s %s", mod, typ, id);
464     printf("\n# %d", fa->nsargs);
465     for (i = 0; i < fa->nsargs; i++)
466     printf(" %s", fa->sarg[i]);
467     #ifdef IARGS
468     printf("\n# %d", fa->niargs);
469     for (i = 0; i < fa->niargs; i++)
470     printf(" %ld", fa->iarg[i]);
471     #else
472     fputs("\n# 0", stdout);
473     #endif
474     printf("\n# %d", fa->nfargs);
475     for (i = 0; i < fa->nfargs; i++)
476     printf(" %g", fa->farg[i]);
477     fputs("\n\n", stdout);
478     return(0);
479     }
480    
481    
482     int
483 schorsch 2.22 o_face( /* print out a polygon */
484     char *mod,
485     char *typ,
486     char *id,
487     FUNARGS *fa
488     )
489 greg 2.1 {
490 gwlarson 2.15 char entbuf[2048], *linestart;
491 greg 2.2 register char *cp;
492 greg 2.1 register int i;
493    
494 schorsch 2.18 if ((fa->nfargs < 9) | (fa->nfargs % 3))
495 greg 2.1 return(-1);
496     setmat(mod);
497 greg 2.2 setobj(id);
498 gwlarson 2.15 cp = linestart = entbuf;
499 greg 2.2 *cp++ = 'f';
500 greg 2.1 for (i = 0; i < fa->nfargs; i += 3) {
501 greg 2.2 *cp++ = ' ';
502 gwlarson 2.15 if (cp - linestart > 72) {
503     *cp++ = '\\'; *cp++ = '\n';
504     linestart = cp;
505     *cp++ = ' '; *cp++ = ' ';
506     }
507 greg 2.2 getvertid(cp, fa->farg + i);
508     while (*cp)
509     cp++;
510 greg 2.1 }
511     puts(entbuf);
512     return(0);
513     }
514    
515    
516     int
517 schorsch 2.22 o_cone( /* print out a cone */
518     char *mod,
519     char *typ,
520     char *id,
521     register FUNARGS *fa
522     )
523 greg 2.1 {
524 greg 2.2 char v1[6], v2[6];
525    
526 greg 2.1 if (fa->nfargs != 8)
527     return(-1);
528     setmat(mod);
529 greg 2.2 setobj(id);
530     getvertid(v1, fa->farg);
531     getvertid(v2, fa->farg + 3);
532 greg 2.1 if (typ[1] == 'u') /* cup -> inverted cone */
533 greg 2.2 printf("cone %s %.12g %s %.12g\n",
534     v1, -fa->farg[6], v2, -fa->farg[7]);
535 greg 2.1 else
536 greg 2.2 printf("cone %s %.12g %s %.12g\n",
537     v1, fa->farg[6], v2, fa->farg[7]);
538 greg 2.1 return(0);
539     }
540    
541    
542     int
543 schorsch 2.22 o_sphere( /* print out a sphere */
544     char *mod,
545     char *typ,
546     char *id,
547     register FUNARGS *fa
548     )
549 greg 2.1 {
550 greg 2.2 char cent[6];
551    
552 greg 2.1 if (fa->nfargs != 4)
553     return(-1);
554     setmat(mod);
555 greg 2.2 setobj(id);
556     printf("sph %s %.12g\n", getvertid(cent, fa->farg),
557     typ[0]=='b' ? -fa->farg[3] : fa->farg[3]);
558 greg 2.1 return(0);
559     }
560    
561    
562     int
563 schorsch 2.22 o_cylinder( /* print out a cylinder */
564     char *mod,
565     char *typ,
566     char *id,
567     register FUNARGS *fa
568     )
569 greg 2.1 {
570 greg 2.2 char v1[6], v2[6];
571    
572 greg 2.1 if (fa->nfargs != 7)
573     return(-1);
574     setmat(mod);
575 greg 2.2 setobj(id);
576     getvertid(v1, fa->farg);
577     getvertid(v2, fa->farg + 3);
578     printf("cyl %s %.12g %s\n", v1,
579     typ[0]=='t' ? -fa->farg[6] : fa->farg[6], v2);
580 greg 2.1 return(0);
581     }
582    
583    
584     int
585 schorsch 2.22 o_ring( /* print out a ring */
586     char *mod,
587     char *typ,
588     char *id,
589     register FUNARGS *fa
590     )
591 greg 2.1 {
592     if (fa->nfargs != 8)
593     return(-1);
594     setmat(mod);
595 greg 2.2 setobj(id);
596     printf("v cent =\n\tp %.12g %.12g %.12g\n",
597 greg 2.1 fa->farg[0], fa->farg[1], fa->farg[2]);
598 greg 2.2 printf("\tn %.12g %.12g %.12g\n",
599 greg 2.1 fa->farg[3], fa->farg[4], fa->farg[5]);
600     if (fa->farg[6] < fa->farg[7])
601     printf("ring cent %.12g %.12g\n",
602     fa->farg[6], fa->farg[7]);
603     else
604     printf("ring cent %.12g %.12g\n",
605     fa->farg[7], fa->farg[6]);
606     return(0);
607     }
608    
609    
610     int
611 schorsch 2.22 o_instance( /* convert an instance (or mesh) */
612     char *mod,
613     char *typ,
614     char *id,
615     FUNARGS *fa
616     )
617 greg 2.1 {
618 greg 2.2 register int i;
619     register char *cp;
620     char *start = NULL, *end = NULL;
621     /*
622     * We don't really know how to do this, so we just create
623     * a reference to an undefined MGF file and it's the user's
624     * responsibility to create this file and put the appropriate
625     * stuff into it.
626     */
627     if (fa->nsargs < 1)
628     return(-1);
629     setmat(mod); /* only works if surfaces are void */
630     setobj(id);
631     for (cp = fa->sarg[0]; *cp; cp++) /* construct MGF file name */
632     if (*cp == '/')
633     start = cp+1;
634     else if (*cp == '.')
635     end = cp;
636     if (start == NULL)
637     start = fa->sarg[0];
638     if (end == NULL || start >= end)
639     end = cp;
640     fputs("i ", stdout); /* print include entity */
641     for (cp = start; cp < end; cp++)
642     putchar(*cp);
643     fputs(".mgf", stdout); /* add MGF suffix */
644     for (i = 1; i < fa->nsargs; i++) { /* add transform */
645     putchar(' ');
646     fputs(fa->sarg[i], stdout);
647     }
648     putchar('\n');
649 greg 2.5 clrverts(); /* vertex id's no longer reliable */
650 greg 2.2 return(0);
651 greg 2.1 }
652    
653    
654     int
655 schorsch 2.22 o_illum( /* convert an illum material */
656     char *mod,
657     char *typ,
658     char *id,
659     FUNARGS *fa
660     )
661 greg 2.1 {
662     if (fa->nsargs == 1 && strcmp(fa->sarg[0], VOIDID)) {
663     newmat(id, fa->sarg[0]); /* just create alias */
664     return(0);
665     }
666     /* else create invisible material */
667     newmat(id, NULL);
668 greg 2.2 puts("\tts 1 0");
669 greg 2.1 return(0);
670     }
671    
672    
673     int
674 schorsch 2.22 o_plastic( /* convert a plastic material */
675     char *mod,
676     char *typ,
677     char *id,
678     register FUNARGS *fa
679     )
680 greg 2.1 {
681     COLOR cxyz, rrgb;
682     double d;
683    
684     if (fa->nfargs != (typ[7]=='2' ? 6 : 5))
685     return(-1);
686     newmat(id, NULL);
687     rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
688     rgb_cie(cxyz, rrgb);
689 greg 2.2 puts("\tc"); /* put diffuse component */
690 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
691     if (d > FTINY)
692 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
693     printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3]));
694     if (fa->farg[3] > FTINY) { /* put specular component */
695     puts("\tc");
696     printf("\trs %.4f %.4f\n", fa->farg[3],
697     typ[7]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
698     fa->farg[4]);
699     }
700 greg 2.1 return(0);
701     }
702    
703    
704     int
705 schorsch 2.22 o_metal( /* convert a metal material */
706     char *mod,
707     char *typ,
708     char *id,
709     register FUNARGS *fa
710     )
711 greg 2.1 {
712     COLOR cxyz, rrgb;
713     double d;
714    
715     if (fa->nfargs != (typ[5]=='2' ? 6 : 5))
716     return(-1);
717     newmat(id, NULL);
718     rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
719     rgb_cie(cxyz, rrgb);
720 greg 2.2 puts("\tc"); /* put diffuse component */
721 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
722     if (d > FTINY)
723 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
724     printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3]));
725 greg 2.1 /* put specular component */
726 greg 2.2 printf("\trs %.4f %.4f\n", cxyz[1]*fa->farg[3],
727 greg 2.1 typ[5]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
728     fa->farg[4]);
729     return(0);
730     }
731    
732    
733     int
734 schorsch 2.22 o_glass( /* convert a glass material */
735     char *mod,
736     char *typ,
737     char *id,
738     register FUNARGS *fa
739     )
740 greg 2.1 {
741     COLOR cxyz, rrgb, trgb;
742     double nrfr = 1.52, F, d;
743     register int i;
744    
745     if (fa->nfargs != 3 && fa->nfargs != 4)
746     return(-1);
747     newmat(id, NULL);
748     if (fa->nfargs == 4)
749     nrfr = fa->farg[3];
750 greg 2.10 printf("\tir %f 0\n", nrfr);
751 greg 2.1 F = (1. - nrfr)/(1. + nrfr); /* use normal incidence */
752     F *= F;
753     for (i = 0; i < 3; i++) {
754 greg 2.2 trgb[i] = fa->farg[i] * (1. - F)*(1. - F) /
755 greg 2.1 (1. - F*F*fa->farg[i]*fa->farg[i]);
756 greg 2.2 rrgb[i] = F * (1. + (1. - 2.*F)*fa->farg[i]) /
757     (1. - F*F*fa->farg[i]*fa->farg[i]);
758 greg 2.1 }
759     rgb_cie(cxyz, rrgb); /* put reflected component */
760 greg 2.2 puts("\tc");
761 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
762     if (d > FTINY)
763 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
764     printf("\trs %.4f 0\n", cxyz[1]);
765 greg 2.10 rgb_cie(cxyz, trgb); /* put transmitted component */
766     puts("\tc");
767     d = cxyz[0] + cxyz[1] + cxyz[2];
768     if (d > FTINY)
769     printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
770     printf("\tts %.4f 0\n", cxyz[1]);
771     return(0);
772     }
773    
774    
775     int
776 schorsch 2.22 o_dielectric( /* convert a dielectric material */
777     char *mod,
778     char *typ,
779     char *id,
780     register FUNARGS *fa
781     )
782 greg 2.10 {
783     COLOR cxyz, trgb;
784     double F, d;
785     register int i;
786    
787     if (fa->nfargs != 5)
788     return(-1);
789     newmat(id, NULL);
790     F = (1. - fa->farg[3])/(1. + fa->farg[3]); /* normal incidence */
791     F *= F;
792     for (i = 0; i < 3; i++)
793     trgb[i] = (1. - F)*pow(fa->farg[i], C_1SIDEDTHICK/unit_mult);
794     printf("\tir %f 0\n", fa->farg[3]); /* put index of refraction */
795     printf("\tsides 1\n");
796     puts("\tc"); /* put reflected component */
797     printf("\trs %.4f 0\n", F);
798 greg 2.1 rgb_cie(cxyz, trgb); /* put transmitted component */
799 greg 2.2 puts("\tc");
800 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
801     if (d > FTINY)
802 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
803     printf("\tts %.4f 0\n", cxyz[1]);
804 greg 2.1 return(0);
805     }
806    
807    
808     int
809 schorsch 2.22 o_mirror( /* convert a mirror material */
810     char *mod,
811     char *typ,
812     char *id,
813     register FUNARGS *fa
814     )
815 greg 2.1 {
816     COLOR cxyz, rrgb;
817     double d;
818    
819     if (fa->nsargs == 1) { /* use alternate material */
820     newmat(id, fa->sarg[0]);
821     return(0);
822     }
823     if (fa->nfargs != 3)
824     return(-1);
825     newmat(id, NULL);
826     rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
827     rgb_cie(cxyz, rrgb);
828 greg 2.2 puts("\tc"); /* put specular component */
829 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
830     if (d > FTINY)
831 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
832     printf("\trs %.4f 0\n", cxyz[1]);
833 greg 2.1 return(0);
834     }
835    
836    
837     int
838 schorsch 2.22 o_trans( /* convert a trans material */
839     char *mod,
840     char *typ,
841     char *id,
842     register FUNARGS *fa
843     )
844 greg 2.1 {
845     COLOR cxyz, rrgb;
846     double rough, trans, tspec, d;
847    
848     if (typ[4] == '2') { /* trans2 */
849     if (fa->nfargs != 8)
850     return(-1);
851     rough = .5*(fa->farg[4] + fa->farg[5]);
852     trans = fa->farg[6];
853     tspec = fa->farg[7];
854     } else { /* trans */
855     if (fa->nfargs != 7)
856     return(-1);
857     rough = fa->farg[4];
858     trans = fa->farg[5];
859     tspec = fa->farg[6];
860     }
861     newmat(id, NULL);
862     rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
863     rgb_cie(cxyz, rrgb);
864 greg 2.2 puts("\tc"); /* put transmitted diffuse */
865 greg 2.1 d = cxyz[0] + cxyz[1] + cxyz[2];
866     if (d > FTINY)
867 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
868     printf("\ttd %.4f\n", cxyz[1]*trans*(1. - fa->farg[3])*(1. - tspec));
869 greg 2.1 /* put transmitted specular */
870 greg 2.2 printf("\tts %.4f %.4f\n", cxyz[1]*trans*tspec*(1. - fa->farg[3]), rough);
871 greg 2.1 /* put reflected diffuse */
872 greg 2.2 printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3])*(1. - trans));
873     puts("\tc"); /* put reflected specular */
874     printf("\trs %.4f %.4f\n", fa->farg[3], rough);
875 greg 2.1 return(0);
876     }
877    
878    
879     int
880 schorsch 2.22 o_light( /* convert a light type */
881     char *mod,
882     char *typ,
883     char *id,
884     register FUNARGS *fa
885     )
886 greg 2.1 {
887     COLOR cxyz, rrgb;
888     double d;
889    
890     if (fa->nfargs < 3)
891     return(-1);
892     newmat(id, NULL);
893     rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
894     rgb_cie(cxyz, rrgb);
895     d = cxyz[0] + cxyz[1] + cxyz[2];
896 greg 2.2 puts("\tc");
897 greg 2.1 if (d > FTINY)
898 greg 2.2 printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
899 greg 2.7 printf("\ted %.4g\n", cxyz[1]*(PI*WHTEFFICACY));
900 greg 2.1 return(0);
901     }