ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/rad2mgf.c
Revision: 2.31
Committed: Wed Apr 23 01:57:04 2025 UTC (4 weeks, 1 day ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.30: +37 -45 lines
Log Message:
fix: Functio prototypes and other fixes to reduce compiler warnings

File Contents

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