ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/rad2mgf.c
Revision: 2.29
Committed: Tue Apr 22 04:45:25 2025 UTC (10 days, 13 hours ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.28: +8 -5 lines
Log Message:
fix: Added check to return value of pclose() in several tools

File Contents

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