ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/rad2mgf.c
Revision: 2.22
Committed: Sat Nov 15 16:29:11 2003 UTC (20 years, 5 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.21: +163 -75 lines
Log Message:
ANSIfication, and fixed bad fprintf() call.

File Contents

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