Back to index

radiance  4R0+20100331
rad2mgf.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rad2mgf.c,v 2.25 2005/12/28 18:39:07 greg Exp $";
00003 #endif
00004 /*
00005  * Convert Radiance scene description to MGF
00006  */
00007 
00008 #include <ctype.h>
00009 #include <string.h>
00010 #include <stdio.h>
00011 
00012 #include "platform.h"
00013 #include "rtmath.h"
00014 #include "rtio.h"
00015 #include "rtprocess.h"
00016 #include "object.h"
00017 #include "color.h"
00018 #include "lookup.h"
00019 
00020 #define C_1SIDEDTHICK       0.005
00021 
00022 
00023 LUTAB  rmats = LU_SINIT(free,NULL);              /* defined material table */
00024 
00025 LUTAB  rdispatch = LU_SINIT(NULL,NULL);   /* function dispatch table */
00026 
00027 char   curmat[80];                        /* current material */
00028 char   curobj[128] = "Untitled";          /* current object name */
00029 
00030 double unit_mult = 1.;                           /* units multiplier */
00031 
00032 #define hasmult             (unit_mult < .999 || unit_mult > 1.001)
00033 
00034 /*
00035  * Stuff for tracking and reusing vertices:
00036  */
00037 
00038 char   VKFMT[] = "%+16.9e %+16.9e %+16.9e";
00039 #define VKLEN        64
00040 
00041 #define mkvkey(k,v)  sprintf(k, VKFMT, (v)[0], (v)[1], (v)[2])
00042 
00043 #define NVERTS              256
00044 
00045 long   vclock;              /* incremented at each vertex request */
00046 
00047 struct vert {
00048        long   lused;        /* when last used (0 if unassigned) */
00049        FVECT  p;            /* track point position only */
00050 } vert[NVERTS];             /* our vertex cache */
00051 
00052 LUTAB  vertab = LU_SINIT(free,NULL);      /* our vertex lookup table */
00053 
00054 void rad2mgf(char *inp);
00055 void cvtprim(char *inp, char *mod, char *typ, char *id, FUNARGS *fa);
00056 void newmat(char *id, char *alias);
00057 void setmat(char *id);
00058 void setobj(char *id);
00059 void init(void);
00060 void uninit(void);
00061 void clrverts(void);
00062 void unspace(char *s);
00063 void add2dispatch(char *name, int (*func)());
00064 char *getvertid(char *vname, FVECT vp);
00065 int o_unsupported(char *mod, char *typ, char *id, FUNARGS *fa);
00066 int o_face(char *mod, char *typ, char *id, FUNARGS *fa);
00067 int o_cone(char *mod, char *typ, char *id, FUNARGS *fa);
00068 int o_sphere(char *mod, char *typ, char *id, FUNARGS *fa);
00069 int o_cylinder(char *mod, char *typ, char *id, FUNARGS *fa);
00070 int o_ring(char *mod, char *typ, char *id, FUNARGS *fa);
00071 int o_instance(char *mod, char *typ, char *id, FUNARGS *fa);
00072 int o_illum(char *mod, char *typ, char *id, FUNARGS *fa);
00073 int o_plastic(char *mod, char *typ, char *id, FUNARGS *fa);
00074 int o_metal(char *mod, char *typ, char *id, FUNARGS *fa);
00075 int o_glass(char *mod, char *typ, char *id, FUNARGS *fa);
00076 int o_dielectric(char *mod, char *typ, char *id, FUNARGS *fa);
00077 int o_mirror(char *mod, char *typ, char *id, FUNARGS *fa);
00078 int o_trans(char *mod, char *typ, char *id, FUNARGS *fa);
00079 int o_light(char *mod, char *typ, char *id, FUNARGS *fa);
00080 
00081 
00082 int
00083 main(
00084        int    argc,
00085        char   **argv
00086 )
00087 {
00088        int    i;
00089 
00090        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00091               switch (argv[i][1]) {
00092               case 'd':                   /* units */
00093                      switch (argv[i][2]) {
00094                      case 'm':                   /* meters */
00095                             unit_mult = 1.;
00096                             break;
00097                      case 'c':                   /* centimeters */
00098                             unit_mult = .01;
00099                             break;
00100                      case 'f':                   /* feet */
00101                             unit_mult = 12.*.0254;
00102                             break;
00103                      case 'i':                   /* inches */
00104                             unit_mult = .0254;
00105                             break;
00106                      default:
00107                             goto unkopt;
00108                      }
00109                      break;
00110               default:
00111                      goto unkopt;
00112               }
00113        init();
00114        if (i >= argc)
00115               rad2mgf(NULL);
00116        else
00117               for ( ; i < argc; i++)
00118                      rad2mgf(argv[i]);
00119        uninit();
00120        exit(0);
00121 unkopt:
00122        fprintf(stderr, "Usage: %s [-d{m|c|f|i}] file ..\n", argv[0]);
00123        exit(1);
00124 }
00125 
00126 
00127 void
00128 rad2mgf(             /* convert a Radiance file to MGF */
00129        char   *inp
00130 )
00131 {
00132        char  buf[512];
00133        char  mod[128], typ[32], id[128], alias[128];
00134        FUNARGS       fa;
00135        register FILE *fp;
00136        register int  c;
00137 
00138        if (inp == NULL) {
00139               inp = "standard input";
00140               fp = stdin;
00141        } else if (inp[0] == '!') {
00142               if ((fp = popen(inp+1, "r")) == NULL) {
00143                      fputs(inp, stderr);
00144                      fputs(": cannot execute\n", stderr);
00145                      exit(1);
00146               }
00147        } else if ((fp = fopen(inp, "r")) == NULL) {
00148               fputs(inp, stderr);
00149               fputs(": cannot open\n", stderr);
00150               exit(1);
00151        }
00152        printf("# Begin conversion from: %s\n", inp);
00153        while ((c = getc(fp)) != EOF)
00154               switch (c) {
00155               case ' ':            /* white space */
00156               case '\t':
00157               case '\n':
00158               case '\r':
00159               case '\f':
00160                      break;
00161               case '#':            /* comment */
00162                      if (fgets(buf, sizeof(buf), fp) != NULL)
00163                             printf("# %s", buf);
00164                      break;
00165               case '!':            /* inline command */
00166                      ungetc(c, fp);
00167                      fgetline(buf, sizeof(buf), fp);
00168                      rad2mgf(buf);
00169                      break;
00170               default:             /* Radiance primitive */
00171                      ungetc(c, fp);
00172                      if (fgetword(mod, sizeof(mod), fp) == NULL ||
00173                                    fgetword(typ, sizeof(typ), fp) == NULL ||
00174                                    fgetword(id, sizeof(id), fp) == NULL) {
00175                             fputs(inp, stderr);
00176                             fputs(": unexpected EOF\n", stderr);
00177                             exit(1);
00178                      }
00179                      unspace(mod);
00180                      unspace(id);
00181                      if (!strcmp(typ, "alias")) {
00182                             strcpy(alias, "EOF");
00183                             fgetword(alias, sizeof(alias), fp);
00184                             unspace(alias);
00185                             newmat(id, alias);
00186                      } else {
00187                             if (!readfargs(&fa, fp)) {
00188                                    fprintf(stderr,
00189                             "%s: bad argument syntax for %s \"%s\"\n",
00190                                                  inp, typ, id);
00191                                    exit(1);
00192                             }
00193                             cvtprim(inp, mod, typ, id, &fa);
00194                             freefargs(&fa);
00195                      }
00196                      break;
00197               }
00198        printf("# End conversion from: %s\n", inp);
00199        if (inp[0] == '!')
00200               pclose(fp);
00201        else
00202               fclose(fp);
00203 }
00204 
00205 
00206 void
00207 unspace(      /* replace spaces with underscores in s */
00208        char *s
00209 )
00210 {
00211        while (*s) {
00212               if (isspace(*s))
00213                      *s = '_';
00214               ++s;
00215        }
00216 }
00217 
00218 
00219 void
00220 cvtprim(      /* process Radiance primitive */
00221        char   *inp,
00222        char   *mod,
00223        char   *typ,
00224        char   *id,
00225        FUNARGS       *fa
00226 )
00227 {
00228        int    (*df)();
00229 
00230        df = (int (*)())lu_find(&rdispatch, typ)->data;
00231        if (df != NULL) {                         /* convert */
00232               if ((*df)(mod, typ, id, fa) < 0) {
00233                      fprintf(stderr, "%s: bad %s \"%s\"\n", "rad2mgf", typ, id);
00234                      exit(1);
00235               }
00236        } else {                                  /* unsupported */
00237               o_unsupported(mod, typ, id, fa);
00238               if (lu_find(&rmats, mod)->data != NULL)   /* make alias */
00239                      newmat(id, mod);
00240        }
00241 }
00242 
00243 
00244 void
00245 newmat(              /* add a modifier to the alias list */
00246        char   *id,
00247        char   *alias
00248 )
00249 {
00250        register LUENT       *lp, *lpa;
00251 
00252        if (alias != NULL) {               /* look up alias */
00253               if ((lpa = lu_find(&rmats, alias)) == NULL)
00254                      goto memerr;
00255               if (lpa->data == NULL)
00256                      alias = NULL;        /* doesn't exist! */
00257        }
00258        if ((lp = lu_find(&rmats, id)) == NULL)   /* look up material */
00259               goto memerr;
00260        if (alias != NULL && lp->data == lpa->key)
00261               return;                     /* alias set already */
00262        if (lp->data == NULL) {                   /* allocate material */
00263               if ((lp->key = (char *)malloc(strlen(id)+1)) == NULL)
00264                      goto memerr;
00265               strcpy(lp->key, id);
00266        }
00267        if (alias == NULL) {               /* set this material */
00268               lp->data = lp->key;
00269               printf("m %s =\n", id);
00270        } else {                           /* set this alias */
00271               lp->data = lpa->key;
00272               printf("m %s = %s\n", id, alias);
00273        }
00274        strcpy(curmat, id);
00275        return;
00276 memerr:
00277        fputs("Out of memory in newmat!\n", stderr);
00278        exit(1);
00279 }
00280 
00281 
00282 void
00283 setmat(                     /* set material to this one */
00284        char   *id
00285 )
00286 {
00287        if (!strcmp(id, curmat))    /* already set? */
00288               return;
00289        if (!strcmp(id, VOIDID))    /* cannot set */
00290               return;
00291        printf("m %s\n", id);
00292        strcpy(curmat, id);
00293 }
00294 
00295 
00296 void
00297 setobj(                     /* set object name to this one */
00298        char   *id
00299 )
00300 {
00301        register char *cp, *cp2;
00302        char   *end = NULL;
00303        int    diff = 0;
00304                             /* use all but final suffix */
00305        for (cp = id; *cp; cp++)
00306               if (*cp == '.')
00307                      end = cp;
00308        if (end == NULL)
00309               end = cp;
00310                             /* copy to current object */
00311        cp2 = curobj;
00312        if (!isalpha(*id)) { /* start with letter */
00313               diff = *cp2 != 'O';
00314               *cp2++ = 'O';
00315        }
00316        for (cp = id; cp < end; *cp2++ = *cp++) {
00317               if ((*cp < '!') | (*cp > '~'))     /* limit to visible chars */
00318                      *cp = '?';
00319               diff += *cp != *cp2;
00320        }
00321        if (!diff && !*cp2)
00322               return;
00323        *cp2 = '\0';
00324        fputs("o\no ", stdout);
00325        puts(curobj);
00326 }
00327 
00328 
00329 void
00330 init(void)                  /* initialize dispatch table and output */
00331 {
00332        lu_init(&vertab, NVERTS);
00333        lu_init(&rdispatch, 22);
00334        add2dispatch("polygon", o_face);
00335        add2dispatch("cone", o_cone);
00336        add2dispatch("cup", o_cone);
00337        add2dispatch("sphere", o_sphere);
00338        add2dispatch("bubble", o_sphere);
00339        add2dispatch("cylinder", o_cylinder);
00340        add2dispatch("tube", o_cylinder);
00341        add2dispatch("ring", o_ring);
00342        add2dispatch("instance", o_instance);
00343        add2dispatch("mesh", o_instance);
00344        add2dispatch("plastic", o_plastic);
00345        add2dispatch("plastic2", o_plastic);
00346        add2dispatch("metal", o_metal);
00347        add2dispatch("metal2", o_metal);
00348        add2dispatch("glass", o_glass);
00349        add2dispatch("dielectric", o_dielectric);
00350        add2dispatch("trans", o_trans);
00351        add2dispatch("trans2", o_trans);
00352        add2dispatch("mirror", o_mirror);
00353        add2dispatch("light", o_light);
00354        add2dispatch("spotlight", o_light);
00355        add2dispatch("glow", o_light);
00356        add2dispatch("illum", o_illum);
00357        puts("# The following was converted from RADIANCE scene input");
00358        if (hasmult)
00359               printf("xf -s %.4e\n", unit_mult);
00360        printf("o %s\n", curobj);
00361 }
00362 
00363 
00364 void
00365 uninit(void)                /* mark end of MGF file */
00366 {
00367        puts("o");
00368        if (hasmult)
00369               puts("xf");
00370        puts("# End of data converted from RADIANCE scene input");
00371        lu_done(&rdispatch);
00372        lu_done(&rmats);
00373        lu_done(&vertab);
00374 }
00375 
00376 
00377 void
00378 clrverts(void)                     /* clear vertex table */
00379 {
00380        register int  i;
00381 
00382        lu_done(&vertab);
00383        for (i = 0; i < NVERTS; i++)
00384               vert[i].lused = 0;
00385        lu_init(&vertab, NVERTS);
00386 }
00387 
00388 
00389 void
00390 add2dispatch( /* add function to dispatch table */
00391        char   *name,
00392        int    (*func)()
00393 )
00394 {
00395        register LUENT       *lp;
00396 
00397        lp = lu_find(&rdispatch, name);
00398        if (lp->key != NULL) {
00399               fputs(name, stderr);
00400               fputs(": duplicate dispatch entry!\n", stderr);
00401               exit(1);
00402        }
00403        lp->key = name;
00404        lp->data = (char *)func;
00405 }
00406 
00407 
00408 char *
00409 getvertid(           /* get/set vertex ID for this point */
00410        char   *vname,
00411        FVECT  vp
00412 )
00413 {
00414        static char   vkey[VKLEN];
00415        register LUENT       *lp;
00416        register int  i, vndx;
00417 
00418        vclock++;                   /* increment counter */
00419        mkvkey(vkey, vp);
00420        if ((lp = lu_find(&vertab, vkey)) == NULL)
00421               goto memerr;
00422        if (lp->data == NULL) {            /* allocate new vertex entry */
00423               if (lp->key != NULL)        /* reclaim deleted entry */
00424                      vertab.ndel--;
00425               else {
00426                      if ((lp->key = (char *)malloc(VKLEN)) == NULL)
00427                             goto memerr;
00428                      strcpy(lp->key, vkey);
00429               }
00430               vndx = 0;                   /* find oldest vertex */
00431               for (i = 1; i < NVERTS; i++)
00432                      if (vert[i].lused < vert[vndx].lused)
00433                             vndx = i;
00434               if (vert[vndx].lused) {            /* free old entry first */
00435                      mkvkey(vkey, vert[vndx].p);
00436                      lu_delete(&vertab, vkey);
00437               }
00438               VCOPY(vert[vndx].p, vp);                  /* assign it */
00439               printf("v v%d =\n\tp %.15g %.15g %.15g\n",       /* print it */
00440                             vndx, vp[0], vp[1], vp[2]);
00441               lp->data = (char *)&vert[vndx];                  /* set it */
00442        } else
00443               vndx = (struct vert *)lp->data - vert;
00444        vert[vndx].lused = vclock;         /* record this use */
00445        sprintf(vname, "v%d", vndx);
00446        return(vname);
00447 memerr:
00448        fputs("Out of memory in getvertid!\n", stderr);
00449        exit(1);
00450 }
00451 
00452 
00453 int
00454 o_unsupported(              /* mark unsupported primitive */
00455        char   *mod,
00456        char   *typ,
00457        char   *id,
00458        FUNARGS       *fa
00459 )
00460 {
00461        register int  i;
00462 
00463        fputs("\n# Unsupported RADIANCE primitive:\n", stdout);
00464        printf("# %s %s %s", mod, typ, id);
00465        printf("\n# %d", fa->nsargs);
00466        for (i = 0; i < fa->nsargs; i++)
00467               printf(" %s", fa->sarg[i]);
00468 #ifdef IARGS
00469        printf("\n# %d", fa->niargs);
00470        for (i = 0; i < fa->niargs; i++)
00471               printf(" %ld", fa->iarg[i]);
00472 #else
00473        fputs("\n# 0", stdout);
00474 #endif
00475        printf("\n# %d", fa->nfargs);
00476        for (i = 0; i < fa->nfargs; i++)
00477               printf(" %g", fa->farg[i]);
00478        fputs("\n\n", stdout);
00479        return(0);
00480 }
00481 
00482 
00483 int
00484 o_face(              /* print out a polygon */
00485        char   *mod,
00486        char   *typ,
00487        char   *id,
00488        FUNARGS       *fa
00489 )
00490 {
00491        char   entbuf[2048], *linestart;
00492        register char *cp;
00493        register int  i;
00494 
00495        if ((fa->nfargs < 9) | (fa->nfargs % 3))
00496               return(-1);
00497        setmat(mod);
00498        setobj(id);
00499        cp = linestart = entbuf;
00500        *cp++ = 'f';
00501        for (i = 0; i < fa->nfargs; i += 3) {
00502               *cp++ = ' ';
00503               if (cp - linestart > 72) {
00504                      *cp++ = '\\'; *cp++ = '\n';
00505                      linestart = cp;
00506                      *cp++ = ' '; *cp++ = ' ';
00507               }
00508               getvertid(cp, fa->farg + i);
00509               while (*cp)
00510                      cp++;
00511        }
00512        puts(entbuf);
00513        return(0);
00514 }
00515 
00516 
00517 int
00518 o_cone(       /* print out a cone */
00519        char   *mod,
00520        char   *typ,
00521        char   *id,
00522        register FUNARGS     *fa
00523 )
00524 {
00525        char   v1[6], v2[6];
00526 
00527        if (fa->nfargs != 8)
00528               return(-1);
00529        setmat(mod);
00530        setobj(id);
00531        getvertid(v1, fa->farg);
00532        getvertid(v2, fa->farg + 3);
00533        if (typ[1] == 'u')                 /* cup -> inverted cone */
00534               printf("cone %s %.12g %s %.12g\n",
00535                             v1, -fa->farg[6], v2, -fa->farg[7]);
00536        else
00537               printf("cone %s %.12g %s %.12g\n",
00538                             v1, fa->farg[6], v2, fa->farg[7]);
00539        return(0);
00540 }
00541 
00542 
00543 int
00544 o_sphere(     /* print out a sphere */
00545        char   *mod,
00546        char   *typ,
00547        char   *id,
00548        register FUNARGS     *fa
00549 )
00550 {
00551        char   cent[6];
00552 
00553        if (fa->nfargs != 4)
00554               return(-1);
00555        setmat(mod);
00556        setobj(id);
00557        printf("sph %s %.12g\n", getvertid(cent, fa->farg),
00558                      typ[0]=='b' ? -fa->farg[3] : fa->farg[3]);
00559        return(0);
00560 }
00561 
00562 
00563 int
00564 o_cylinder(   /* print out a cylinder */
00565        char   *mod,
00566        char   *typ,
00567        char   *id,
00568        register FUNARGS     *fa
00569 )
00570 {
00571        char   v1[6], v2[6];
00572 
00573        if (fa->nfargs != 7)
00574               return(-1);
00575        setmat(mod);
00576        setobj(id);
00577        getvertid(v1, fa->farg);
00578        getvertid(v2, fa->farg + 3);
00579        printf("cyl %s %.12g %s\n", v1,
00580                      typ[0]=='t' ? -fa->farg[6] : fa->farg[6], v2);
00581        return(0);
00582 }
00583 
00584 
00585 int
00586 o_ring(       /* print out a ring */
00587        char   *mod,
00588        char   *typ,
00589        char   *id,
00590        register FUNARGS     *fa
00591 )
00592 {
00593        if (fa->nfargs != 8)
00594               return(-1);
00595        setmat(mod);
00596        setobj(id);
00597        printf("v cent =\n\tp %.12g %.12g %.12g\n",
00598                      fa->farg[0], fa->farg[1], fa->farg[2]);
00599        printf("\tn %.12g %.12g %.12g\n",
00600                      fa->farg[3], fa->farg[4], fa->farg[5]);
00601        if (fa->farg[6] < fa->farg[7])
00602               printf("ring cent %.12g %.12g\n",
00603                             fa->farg[6], fa->farg[7]);
00604        else
00605               printf("ring cent %.12g %.12g\n",
00606                             fa->farg[7], fa->farg[6]);
00607        return(0);
00608 }
00609 
00610 
00611 int
00612 o_instance(   /* convert an instance (or mesh) */
00613        char   *mod,
00614        char   *typ,
00615        char   *id,
00616        FUNARGS       *fa
00617 )
00618 {
00619        register int  i;
00620        register char *cp;
00621        char   *start = NULL, *end = NULL;
00622        /*
00623         * We don't really know how to do this, so we just create
00624         * a reference to an undefined MGF file and it's the user's
00625         * responsibility to create this file and put the appropriate
00626         * stuff into it.
00627         */
00628        if (fa->nsargs < 1)
00629               return(-1);
00630        setmat(mod);                /* only works if surfaces are void */
00631        setobj(id);
00632        for (cp = fa->sarg[0]; *cp; cp++)  /* construct MGF file name */
00633               if (*cp == '/')
00634                      start = cp+1;
00635               else if (*cp == '.')
00636                      end = cp;
00637        if (start == NULL)
00638               start = fa->sarg[0];
00639        if (end == NULL || start >= end)
00640               end = cp;
00641        fputs("i ", stdout);               /* print include entity */
00642        for (cp = start; cp < end; cp++)
00643               putchar(*cp);
00644        fputs(".mgf", stdout);                    /* add MGF suffix */
00645        for (i = 1; i < fa->nsargs; i++) { /* add transform */
00646               putchar(' ');
00647               fputs(fa->sarg[i], stdout);
00648        }
00649        putchar('\n');
00650        clrverts();                 /* vertex id's no longer reliable */
00651        return(0);
00652 }
00653 
00654 
00655 int
00656 o_illum(      /* convert an illum material */
00657        char   *mod,
00658        char   *typ,
00659        char   *id,
00660        FUNARGS       *fa
00661 )
00662 {
00663        if (fa->nsargs == 1 && strcmp(fa->sarg[0], VOIDID)) {
00664               newmat(id, fa->sarg[0]);    /* just create alias */
00665               return(0);
00666        }
00667                                    /* else create invisible material */
00668        newmat(id, NULL);
00669        puts("\tts 1 0");
00670        return(0);
00671 }
00672 
00673 
00674 int
00675 o_plastic(    /* convert a plastic material */
00676        char   *mod,
00677        char   *typ,
00678        char   *id,
00679        register FUNARGS     *fa
00680 )
00681 {
00682        COLOR  cxyz, rrgb;
00683        double d;
00684 
00685        if (fa->nfargs != (typ[7]=='2' ? 6 : 5))
00686               return(-1);
00687        newmat(id, NULL);
00688        rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
00689        rgb_cie(cxyz, rrgb);
00690        puts("\tc");                       /* put diffuse component */
00691        d = cxyz[0] + cxyz[1] + cxyz[2];
00692        if (d > FTINY)
00693               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00694        printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3]));
00695        if (fa->farg[3] > FTINY) {         /* put specular component */
00696               puts("\tc");
00697               printf("\trs %.4f %.4f\n", fa->farg[3],
00698                             typ[7]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
00699                                           fa->farg[4]);
00700        }
00701        return(0);
00702 }
00703 
00704 
00705 int
00706 o_metal(      /* convert a metal material */
00707        char   *mod,
00708        char   *typ,
00709        char   *id,
00710        register FUNARGS     *fa
00711 )
00712 {
00713        COLOR  cxyz, rrgb;
00714        double d;
00715 
00716        if (fa->nfargs != (typ[5]=='2' ? 6 : 5))
00717               return(-1);
00718        newmat(id, NULL);
00719        rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
00720        rgb_cie(cxyz, rrgb);
00721        puts("\tc");                       /* put diffuse component */
00722        d = cxyz[0] + cxyz[1] + cxyz[2];
00723        if (d > FTINY)
00724               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00725        printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3]));
00726                                           /* put specular component */
00727        printf("\trs %.4f %.4f\n", cxyz[1]*fa->farg[3],
00728                      typ[5]=='2' ? .5*(fa->farg[4] + fa->farg[5]) :
00729                                    fa->farg[4]);
00730        return(0);
00731 }
00732 
00733 
00734 int
00735 o_glass(      /* convert a glass material */
00736        char   *mod,
00737        char   *typ,
00738        char   *id,
00739        register FUNARGS     *fa
00740 )
00741 {
00742        COLOR  cxyz, rrgb, trgb;
00743        double nrfr = 1.52, F, d;
00744        register int  i;
00745 
00746        if (fa->nfargs != 3 && fa->nfargs != 4)
00747               return(-1);
00748        newmat(id, NULL);
00749        if (fa->nfargs == 4)
00750               nrfr = fa->farg[3];
00751        printf("\tir %f 0\n", nrfr);
00752        F = (1. - nrfr)/(1. + nrfr);              /* use normal incidence */
00753        F *= F;
00754        for (i = 0; i < 3; i++) {
00755               trgb[i] = fa->farg[i] * (1. - F)*(1. - F) /
00756                             (1. - F*F*fa->farg[i]*fa->farg[i]);
00757               rrgb[i] = F * (1. + (1. - 2.*F)*fa->farg[i]) /
00758                             (1. - F*F*fa->farg[i]*fa->farg[i]);
00759        }
00760        rgb_cie(cxyz, rrgb);               /* put reflected component */
00761        puts("\tc");
00762        d = cxyz[0] + cxyz[1] + cxyz[2];
00763        if (d > FTINY)
00764               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00765        printf("\trs %.4f 0\n", cxyz[1]);
00766        rgb_cie(cxyz, trgb);               /* put transmitted component */
00767        puts("\tc");
00768        d = cxyz[0] + cxyz[1] + cxyz[2];
00769        if (d > FTINY)
00770               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00771        printf("\tts %.4f 0\n", cxyz[1]);
00772        return(0);
00773 }
00774 
00775 
00776 int
00777 o_dielectric( /* convert a dielectric material */
00778        char   *mod,
00779        char   *typ,
00780        char   *id,
00781        register FUNARGS     *fa
00782 )
00783 {
00784        COLOR  cxyz, trgb;
00785        double F, d;
00786        register int  i;
00787 
00788        if (fa->nfargs != 5)
00789               return(-1);
00790        newmat(id, NULL);
00791        F = (1. - fa->farg[3])/(1. + fa->farg[3]);       /* normal incidence */
00792        F *= F;
00793        for (i = 0; i < 3; i++)
00794               trgb[i] = (1. - F)*pow(fa->farg[i], C_1SIDEDTHICK/unit_mult);
00795        printf("\tir %f 0\n", fa->farg[3]);       /* put index of refraction */
00796        printf("\tsides 1\n");
00797        puts("\tc");                       /* put reflected component */
00798        printf("\trs %.4f 0\n", F);
00799        rgb_cie(cxyz, trgb);               /* put transmitted component */
00800        puts("\tc");
00801        d = cxyz[0] + cxyz[1] + cxyz[2];
00802        if (d > FTINY)
00803               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00804        printf("\tts %.4f 0\n", cxyz[1]);
00805        return(0);
00806 }
00807 
00808 
00809 int
00810 o_mirror(     /* convert a mirror material */
00811        char   *mod,
00812        char   *typ,
00813        char   *id,
00814        register FUNARGS     *fa
00815 )
00816 {
00817        COLOR  cxyz, rrgb;
00818        double d;
00819 
00820        if (fa->nsargs == 1) {                    /* use alternate material */
00821               newmat(id, fa->sarg[0]);
00822               return(0);
00823        }
00824        if (fa->nfargs != 3)
00825               return(-1);
00826        newmat(id, NULL);
00827        rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
00828        rgb_cie(cxyz, rrgb);
00829        puts("\tc");                       /* put specular component */
00830        d = cxyz[0] + cxyz[1] + cxyz[2];
00831        if (d > FTINY)
00832               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00833        printf("\trs %.4f 0\n", cxyz[1]);
00834        return(0);
00835 }
00836 
00837 
00838 int
00839 o_trans(      /* convert a trans material */
00840        char   *mod,
00841        char   *typ,
00842        char   *id,
00843        register FUNARGS     *fa
00844 )
00845 {
00846        COLOR  cxyz, rrgb;
00847        double rough, trans, tspec, d;
00848 
00849        if (typ[4] == '2') {        /* trans2 */
00850               if (fa->nfargs != 8)
00851                      return(-1);
00852               rough = .5*(fa->farg[4] + fa->farg[5]);
00853               trans = fa->farg[6];
00854               tspec = fa->farg[7];
00855        } else {                    /* trans */
00856               if (fa->nfargs != 7)
00857                      return(-1);
00858               rough = fa->farg[4];
00859               trans = fa->farg[5];
00860               tspec = fa->farg[6];
00861        }
00862        newmat(id, NULL);
00863        rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
00864        rgb_cie(cxyz, rrgb);
00865        puts("\tc");                       /* put transmitted diffuse */
00866        d = cxyz[0] + cxyz[1] + cxyz[2];
00867        if (d > FTINY)
00868               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00869        printf("\ttd %.4f\n", cxyz[1]*trans*(1. - fa->farg[3])*(1. - tspec));
00870                                           /* put transmitted specular */
00871        printf("\tts %.4f %.4f\n", cxyz[1]*trans*tspec*(1. - fa->farg[3]), rough);
00872                                           /* put reflected diffuse */
00873        printf("\trd %.4f\n", cxyz[1]*(1. - fa->farg[3])*(1. - trans));
00874        puts("\tc");                       /* put reflected specular */
00875        printf("\trs %.4f %.4f\n", fa->farg[3], rough);
00876        return(0);
00877 }
00878 
00879 
00880 int
00881 o_light(             /* convert a light type */
00882        char   *mod,
00883        char   *typ,
00884        char   *id,
00885        register FUNARGS     *fa
00886 )
00887 {
00888        COLOR  cxyz, rrgb;
00889        double d;
00890 
00891        if (fa->nfargs < 3)
00892               return(-1);
00893        newmat(id, NULL);
00894        rrgb[0] = fa->farg[0]; rrgb[1] = fa->farg[1]; rrgb[2] = fa->farg[2];
00895        rgb_cie(cxyz, rrgb);
00896        d = cxyz[0] + cxyz[1] + cxyz[2];
00897        puts("\tc");
00898        if (d > FTINY)
00899               printf("\t\tcxy %.4f %.4f\n", cxyz[0]/d, cxyz[1]/d);
00900        printf("\ted %.4g\n", cxyz[1]*(PI*WHTEFFICACY));
00901        return(0);
00902 }