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 (9 days, 6 hours 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rad2mgf.c,v 2.30 2025/04/22 14:51:29 greg Exp $";
3 #endif
4 /*
5 * Convert Radiance scene description to MGF
6 */
7
8 #include <ctype.h>
9
10 #include "platform.h"
11 #include "rtmath.h"
12 #include "rtio.h"
13 #include "rtprocess.h"
14 #include "object.h"
15 #include "color.h"
16 #include "lookup.h"
17
18 #define C_1SIDEDTHICK 0.005
19
20
21 LUTAB rmats = LU_SINIT(free,NULL); /* defined material table */
22
23 LUTAB rdispatch = LU_SINIT(NULL,NULL); /* function dispatch table */
24
25 char curmat[80]; /* current material */
26 char curobj[128] = "Untitled"; /* current object name */
27
28 double unit_mult = 1.; /* units multiplier */
29
30 #define hasmult (unit_mult < .999 || unit_mult > 1.001)
31
32 /*
33 * Stuff for tracking and reusing vertices:
34 */
35
36 char VKFMT[] = "%+16.9e %+16.9e %+16.9e";
37 #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 long vclock; /* incremented at each vertex request */
44
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 typedef int dispatchf(char *mod, char *typ, char *id, FUNARGS *fa);
53
54 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, dispatchf *func);
64 char *getvertid(char *vname, FVECT vp);
65
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
71
72 int
73 main(
74 int argc,
75 char **argv
76 )
77 {
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 default:
101 goto unkopt;
102 }
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 void
118 rad2mgf( /* convert a Radiance file to MGF */
119 char *inp
120 )
121 {
122 char buf[512];
123 char mod[128], typ[32], id[128], alias[128];
124 FUNARGS fa;
125 FILE *fp;
126 int c;
127
128 if (inp == NULL) {
129 inp = "standard input";
130 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 if (fgetword(mod, sizeof(mod), fp) == NULL ||
163 fgetword(typ, sizeof(typ), fp) == NULL ||
164 fgetword(id, sizeof(id), fp) == NULL) {
165 fputs(inp, stderr);
166 fputs(": unexpected EOF\n", stderr);
167 exit(1);
168 }
169 unspace(mod);
170 unspace(id);
171 if (!strcmp(typ, "alias")) {
172 strcpy(alias, "EOF");
173 fgetword(alias, sizeof(alias), fp);
174 unspace(alias);
175 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 if (inp[0] == '!') {
189 if (pclose(fp) != 0)
190 fprintf(stderr, "%s: warning - bad exit status\n", inp);
191 } else
192 fclose(fp);
193 printf("# End conversion from: %s\n", inp);
194 }
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 }
208
209
210 void
211 cvtprim( /* process Radiance primitive */
212 char *inp,
213 char *mod,
214 char *typ,
215 char *id,
216 FUNARGS *fa
217 )
218 {
219 dispatchf *df;
220
221 df = (dispatchf *)lu_find(&rdispatch, typ)->data;
222 if (df != NULL) { /* convert */
223 if ((*df)(mod, typ, id, fa) < 0) {
224 fprintf(stderr, "%s: bad %s \"%s\"\n", "rad2mgf", typ, id);
225 exit(1);
226 }
227 } 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 }
233
234
235 void
236 newmat( /* add a modifier to the alias list */
237 char *id,
238 char *alias
239 )
240 {
241 LUENT *lp, *lpa;
242
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 void
274 setmat( /* set material to this one */
275 char *id
276 )
277 {
278 if (!strcmp(id, curmat)) /* already set? */
279 return;
280 if (!strcmp(id, VOIDID)) /* cannot set */
281 return;
282 printf("m %s\n", id);
283 strcpy(curmat, id);
284 }
285
286
287 void
288 setobj( /* set object name to this one */
289 char *id
290 )
291 {
292 char *cp, *cp2;
293 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 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 if ((*cp < '!') | (*cp > '~')) /* limit to visible chars */
309 *cp = '?';
310 diff += *cp != *cp2;
311 }
312 if (!diff && !*cp2)
313 return;
314 *cp2 = '\0';
315 fputs("o\no ", stdout);
316 puts(curobj);
317 }
318
319
320 void
321 init(void) /* initialize dispatch table and output */
322 {
323 lu_init(&vertab, NVERTS);
324 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 add2dispatch("mesh", o_instance);
335 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 add2dispatch("dielectric", o_dielectric);
341 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 puts("# The following was converted from RADIANCE scene input");
349 if (hasmult)
350 printf("xf -s %.4e\n", unit_mult);
351 printf("o %s\n", curobj);
352 }
353
354
355 void
356 uninit(void) /* mark end of MGF file */
357 {
358 puts("o");
359 if (hasmult)
360 puts("xf");
361 puts("# End of data converted from RADIANCE scene input");
362 lu_done(&rdispatch);
363 lu_done(&rmats);
364 lu_done(&vertab);
365 }
366
367
368 void
369 clrverts(void) /* clear vertex table */
370 {
371 int i;
372
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 void
381 add2dispatch( /* add function to dispatch table */
382 char *name,
383 int (*func)()
384 )
385 {
386 LUENT *lp;
387
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 getvertid( /* get/set vertex ID for this point */
401 char *vname,
402 FVECT vp
403 )
404 {
405 static char vkey[VKLEN];
406 LUENT *lp;
407 int i, vndx;
408
409 vclock++; /* increment counter */
410 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 VCOPY(vert[vndx].p, vp); /* assign it */
430 printf("v v%d =\n\tp %.15g %.15g %.15g\n", /* print it */
431 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 vert[vndx].lused = vclock; /* record this use */
436 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 o_unsupported( /* mark unsupported primitive */
446 char *mod,
447 char *typ,
448 char *id,
449 FUNARGS *fa
450 )
451 {
452 int i;
453
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 o_face( /* print out a polygon */
476 char *mod,
477 char *typ,
478 char *id,
479 FUNARGS *fa
480 )
481 {
482 char entbuf[2048], *linestart;
483 char *cp;
484 int i;
485
486 if ((fa->nfargs < 9) | (fa->nfargs % 3))
487 return(-1);
488 setmat(mod);
489 setobj(id);
490 cp = linestart = entbuf;
491 *cp++ = 'f';
492 for (i = 0; i < fa->nfargs; i += 3) {
493 *cp++ = ' ';
494 if (cp - linestart > 72) {
495 *cp++ = '\\'; *cp++ = '\n';
496 linestart = cp;
497 *cp++ = ' '; *cp++ = ' ';
498 }
499 getvertid(cp, fa->farg + i);
500 while (*cp)
501 cp++;
502 }
503 puts(entbuf);
504 return(0);
505 }
506
507
508 int
509 o_cone( /* print out a cone */
510 char *mod,
511 char *typ,
512 char *id,
513 FUNARGS *fa
514 )
515 {
516 char v1[6], v2[6];
517
518 if (fa->nfargs != 8)
519 return(-1);
520 setmat(mod);
521 setobj(id);
522 getvertid(v1, fa->farg);
523 getvertid(v2, fa->farg + 3);
524 if (typ[1] == 'u') /* cup -> inverted cone */
525 printf("cone %s %.12g %s %.12g\n",
526 v1, -fa->farg[6], v2, -fa->farg[7]);
527 else
528 printf("cone %s %.12g %s %.12g\n",
529 v1, fa->farg[6], v2, fa->farg[7]);
530 return(0);
531 }
532
533
534 int
535 o_sphere( /* print out a sphere */
536 char *mod,
537 char *typ,
538 char *id,
539 FUNARGS *fa
540 )
541 {
542 char cent[6];
543
544 if (fa->nfargs != 4)
545 return(-1);
546 setmat(mod);
547 setobj(id);
548 printf("sph %s %.12g\n", getvertid(cent, fa->farg),
549 typ[0]=='b' ? -fa->farg[3] : fa->farg[3]);
550 return(0);
551 }
552
553
554 int
555 o_cylinder( /* print out a cylinder */
556 char *mod,
557 char *typ,
558 char *id,
559 FUNARGS *fa
560 )
561 {
562 char v1[6], v2[6];
563
564 if (fa->nfargs != 7)
565 return(-1);
566 setmat(mod);
567 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 return(0);
573 }
574
575
576 int
577 o_ring( /* print out a ring */
578 char *mod,
579 char *typ,
580 char *id,
581 FUNARGS *fa
582 )
583 {
584 if (fa->nfargs != 8)
585 return(-1);
586 setmat(mod);
587 setobj(id);
588 printf("v cent =\n\tp %.12g %.12g %.12g\n",
589 fa->farg[0], fa->farg[1], fa->farg[2]);
590 printf("\tn %.12g %.12g %.12g\n",
591 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 o_instance( /* convert an instance (or mesh) */
604 char *mod,
605 char *typ,
606 char *id,
607 FUNARGS *fa
608 )
609 {
610 int i;
611 char *cp;
612 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 clrverts(); /* vertex id's no longer reliable */
642 return(0);
643 }
644
645
646 int
647 o_illum( /* convert an illum material */
648 char *mod,
649 char *typ,
650 char *id,
651 FUNARGS *fa
652 )
653 {
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 puts("\tts 1 0");
661 return(0);
662 }
663
664
665 int
666 o_plastic( /* convert a plastic material */
667 char *mod,
668 char *typ,
669 char *id,
670 FUNARGS *fa
671 )
672 {
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 puts("\tc"); /* put diffuse component */
682 d = cxyz[0] + cxyz[1] + cxyz[2];
683 if (d > FTINY)
684 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
685 printf("\trd %.6f\n", cxyz[1]*(1. - fa->farg[3]));
686 if (fa->farg[3] > FTINY) { /* put specular component */
687 puts("\tc");
688 printf("\trs %.6f %.6f\n", fa->farg[3],
689 typ[7]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
690 fa->farg[4]);
691 }
692 return(0);
693 }
694
695
696 int
697 o_metal( /* convert a metal material */
698 char *mod,
699 char *typ,
700 char *id,
701 FUNARGS *fa
702 )
703 {
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 puts("\tc"); /* put diffuse component */
713 d = cxyz[0] + cxyz[1] + cxyz[2];
714 if (d > FTINY)
715 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
716 printf("\trd %.6f\n", cxyz[1]*(1. - fa->farg[3]));
717 /* put specular component */
718 printf("\trs %.6f %.6f\n", cxyz[1]*fa->farg[3],
719 typ[5]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
720 fa->farg[4]);
721 return(0);
722 }
723
724
725 int
726 o_glass( /* convert a glass material */
727 char *mod,
728 char *typ,
729 char *id,
730 FUNARGS *fa
731 )
732 {
733 COLOR cxyz, rrgb, trgb;
734 double nrfr = 1.52, F, d;
735 int i;
736
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 printf("\tir %f 0\n", nrfr);
743 F = (1. - nrfr)/(1. + nrfr); /* use normal incidence */
744 F *= F;
745 for (i = 0; i < 3; i++) {
746 trgb[i] = fa->farg[i] * (1. - F)*(1. - F) /
747 (1. - F*F*fa->farg[i]*fa->farg[i]);
748 rrgb[i] = F * (1. + (1. - 2.*F)*fa->farg[i]) /
749 (1. - F*F*fa->farg[i]*fa->farg[i]);
750 }
751 rgb_cie(cxyz, rrgb); /* put reflected component */
752 puts("\tc");
753 d = cxyz[0] + cxyz[1] + cxyz[2];
754 if (d > FTINY)
755 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
756 printf("\trs %.6f 0\n", cxyz[1]);
757 rgb_cie(cxyz, trgb); /* put transmitted component */
758 puts("\tc");
759 d = cxyz[0] + cxyz[1] + cxyz[2];
760 if (d > FTINY)
761 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
762 printf("\tts %.6f 0\n", cxyz[1]);
763 return(0);
764 }
765
766
767 int
768 o_dielectric( /* convert a dielectric material */
769 char *mod,
770 char *typ,
771 char *id,
772 FUNARGS *fa
773 )
774 {
775 COLOR cxyz, trgb;
776 double F, d;
777 int i;
778
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 printf("\trs %.6f 0\n", F);
790 rgb_cie(cxyz, trgb); /* put transmitted component */
791 puts("\tc");
792 d = cxyz[0] + cxyz[1] + cxyz[2];
793 if (d > FTINY)
794 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
795 printf("\tts %.6f 0\n", cxyz[1]);
796 return(0);
797 }
798
799
800 int
801 o_mirror( /* convert a mirror material */
802 char *mod,
803 char *typ,
804 char *id,
805 FUNARGS *fa
806 )
807 {
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 puts("\tc"); /* put specular component */
821 d = cxyz[0] + cxyz[1] + cxyz[2];
822 if (d > FTINY)
823 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
824 printf("\trs %.6f 0\n", cxyz[1]);
825 return(0);
826 }
827
828
829 int
830 o_trans( /* convert a trans material */
831 char *mod,
832 char *typ,
833 char *id,
834 FUNARGS *fa
835 )
836 {
837 COLOR cxyz, rrgb;
838 double rough, trans, tspec, d;
839
840 if (typ[5] == '2') { /* trans2 */
841 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 puts("\tc"); /* put transmitted diffuse */
857 d = cxyz[0] + cxyz[1] + cxyz[2];
858 if (d > FTINY)
859 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 /* put transmitted specular */
862 printf("\tts %.6f %.6f\n", cxyz[1]*trans*tspec*(1. - fa->farg[3]), rough);
863 /* put reflected diffuse */
864 printf("\trd %.6f\n", cxyz[1]*(1. - fa->farg[3])*(1. - trans));
865 puts("\tc"); /* put reflected specular */
866 printf("\trs %.6f %.6f\n", fa->farg[3], rough);
867 return(0);
868 }
869
870
871 int
872 o_light( /* convert a light type */
873 char *mod,
874 char *typ,
875 char *id,
876 FUNARGS *fa
877 )
878 {
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 puts("\tc");
889 if (d > FTINY)
890 printf("\t\tcxy %.6f %.6f\n", cxyz[0]/d, cxyz[1]/d);
891 printf("\ted %.4g\n", cxyz[1]*(PI*WHTEFFICACY));
892 return(0);
893 }