Back to index

radiance  4R0+20100331
mgf2rad.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: mgf2rad.c,v 1.3 2003/06/26 00:58:09 schorsch Exp $";
00003 #endif
00004 /*
00005  * Convert MGF (Materials and Geometry Format) to Radiance
00006  */
00007 
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <math.h>
00011 #include <string.h>
00012 #include "mgflib/parser.h"
00013 #include "color.h"
00014 #include "tmesh.h"
00015 
00016 #define putv(v)             printf("%18.12g %18.12g %18.12g\n",(v)[0],(v)[1],(v)[2])
00017 
00018 #define invert              (xf_context != NULL && xf_context->rev)
00019 
00020 double glowdist = FHUGE;           /* glow test distance */
00021 
00022 double  emult = 1.;                /* emitter multiplier */
00023 
00024 FILE   *matfp;                            /* material output file */
00025 
00026 int    r_comment(), r_cone(), r_cyl(), r_face(), r_ies(), r_ring(), r_sph();
00027 char   *material(), *object(), *addarg();
00028 
00029 
00030 main(argc, argv)            /* convert files to stdout */
00031 int    argc;
00032 char   *argv[];
00033 {
00034        int    i;
00035 
00036        matfp = stdout;
00037                             /* print out parser version */
00038        printf("## Translated from MGF Version %d.%d\n", MG_VMAJOR, MG_VMINOR);
00039                             /* initialize dispatch table */
00040        mg_ehand[MG_E_COMMENT] = r_comment;       /* we pass comments */
00041        mg_ehand[MG_E_COLOR] = c_hcolor;   /* they get color */
00042        mg_ehand[MG_E_CONE] = r_cone;             /* we do cones */
00043        mg_ehand[MG_E_CMIX] = c_hcolor;           /* they mix colors */
00044        mg_ehand[MG_E_CSPEC] = c_hcolor;   /* they get spectra */
00045        mg_ehand[MG_E_CXY] = c_hcolor;            /* they get chromaticities */
00046        mg_ehand[MG_E_CCT] = c_hcolor;            /* they get color temp's */
00047        mg_ehand[MG_E_CYL] = r_cyl;        /* we do cylinders */
00048        mg_ehand[MG_E_ED] = c_hmaterial;   /* they get emission */
00049        mg_ehand[MG_E_FACE] = r_face;             /* we do faces */
00050        mg_ehand[MG_E_IES] = r_ies;        /* we do IES files */
00051        mg_ehand[MG_E_IR] = c_hmaterial;   /* they get refractive index */
00052        mg_ehand[MG_E_MATERIAL] = c_hmaterial;    /* they get materials */
00053        mg_ehand[MG_E_NORMAL] = c_hvertex; /* they get normals */
00054        mg_ehand[MG_E_OBJECT] = obj_handler;      /* they track object names */
00055        mg_ehand[MG_E_POINT] = c_hvertex;  /* they get points */
00056        mg_ehand[MG_E_RD] = c_hmaterial;   /* they get diffuse refl. */
00057        mg_ehand[MG_E_RING] = r_ring;             /* we do rings */
00058        mg_ehand[MG_E_RS] = c_hmaterial;   /* they get specular refl. */
00059        mg_ehand[MG_E_SIDES] = c_hmaterial;       /* they get # sides */
00060        mg_ehand[MG_E_SPH] = r_sph;        /* we do spheres */
00061        mg_ehand[MG_E_TD] = c_hmaterial;   /* they get diffuse trans. */
00062        mg_ehand[MG_E_TS] = c_hmaterial;   /* they get specular trans. */
00063        mg_ehand[MG_E_VERTEX] = c_hvertex; /* they get vertices */
00064        mg_ehand[MG_E_XF] = xf_handler;           /* they track transforms */
00065        mg_init();           /* initialize the parser */
00066                                    /* get our options & print header */
00067        printf("## %s", argv[0]);
00068        for (i = 1; i < argc && argv[i][0] == '-'; i++) {
00069               printf(" %s", argv[i]);
00070               switch (argv[i][1]) {
00071               case 'g':                   /* glow distance (meters) */
00072                      if (argv[i][2] || badarg(argc-i-1, argv+i+1, "f"))
00073                             goto userr;
00074                      glowdist = atof(argv[++i]);
00075                      printf(" %s", argv[i]);
00076                      break;
00077               case 'e':                   /* emitter multiplier */
00078                      if (argv[i][2] || badarg(argc-i-1, argv+i+1, "f"))
00079                             goto userr;
00080                      emult = atof(argv[++i]);
00081                      printf(" %s", argv[i]);
00082                      break;
00083               case 'm':                   /* materials file */
00084                      matfp = fopen(argv[++i], "a");
00085                      if (matfp == NULL) {
00086                             fprintf(stderr, "%s: cannot append\n", argv[i]);
00087                             exit(1);
00088                      }
00089                      printf(" %s", argv[i]);
00090                      break;
00091               default:
00092                      goto userr;
00093               }
00094        }
00095        putchar('\n');
00096        if (i == argc) {            /* convert stdin */
00097               if (mg_load(NULL) != MG_OK)
00098                      exit(1);
00099               if (mg_nunknown)
00100                      printf("## %s: %u unknown entities\n",
00101                                    argv[0], mg_nunknown);
00102        } else                      /* convert each file */
00103               for ( ; i < argc; i++) {
00104                      printf("## %s %s ##############################\n",
00105                                    argv[0], argv[i]);
00106                      if (mg_load(argv[i]) != MG_OK)
00107                             exit(1);
00108                      if (mg_nunknown) {
00109                             printf("## %s %s: %u unknown entities\n",
00110                                           argv[0], argv[i], mg_nunknown);
00111                             mg_nunknown = 0;
00112                      }
00113               }
00114        exit(0);
00115 userr:
00116        fprintf(stderr, "Usage: %s [-g dist][-e mult][-m matf] [file.mgf] ..\n",
00117                      argv[0]);
00118        exit(1);
00119 }
00120 
00121 
00122 int
00123 r_comment(ac, av)           /* repeat a comment verbatim */
00124 register int  ac;
00125 register char **av;
00126 {
00127        putchar('#');        /* use Radiance comment character */
00128        while (--ac) {                     /* pass through verbatim */
00129               putchar(' ');
00130               fputs(*++av, stdout);
00131        }
00132        putchar('\n');
00133        return(MG_OK);
00134 }
00135 
00136 
00137 int
00138 r_cone(ac, av)                     /* put out a cone */
00139 int    ac;
00140 char   **av;
00141 {
00142        static int    ncones;
00143        char   *mat;
00144        double r1, r2;
00145        C_VERTEX      *cv1, *cv2;
00146        FVECT  p1, p2;
00147        int    inv;
00148                                    /* check argument count and type */
00149        if (ac != 5)
00150               return(MG_EARGC);
00151        if (!isflt(av[2]) || !isflt(av[4]))
00152               return(MG_ETYPE);
00153                                    /* get the endpoint vertices */
00154        if ((cv1 = c_getvert(av[1])) == NULL ||
00155                      (cv2 = c_getvert(av[3])) == NULL)
00156               return(MG_EUNDEF);
00157        xf_xfmpoint(p1, cv1->p);    /* transform endpoints */
00158        xf_xfmpoint(p2, cv2->p);
00159        r1 = xf_scale(atof(av[2])); /* scale radii */
00160        r2 = xf_scale(atof(av[4]));
00161        inv = r1 < 0.;                     /* check for inverted cone */
00162        if (r1 == 0.) {                    /* check for illegal radii */
00163               if (r2 == 0.)
00164                      return(MG_EILL);
00165               inv = r2 < 0.;
00166        } else if (r2 != 0. && inv ^ r2 < 0.)
00167               return(MG_EILL);
00168        if (inv) {
00169               r1 = -r1;
00170               r2 = -r2;
00171        }
00172        if ((mat = material()) == NULL)    /* get material */
00173               return(MG_EBADMAT);
00174                                    /* spit the sucker out */
00175        printf("\n%s %s %sc%d\n", mat, inv ? "cup" : "cone",
00176                      object(), ++ncones);
00177        printf("0\n0\n8\n");
00178        putv(p1);
00179        putv(p2);
00180        printf("%18.12g %18.12g\n", r1, r2);
00181        return(MG_OK);
00182 }
00183 
00184 
00185 int
00186 r_cyl(ac, av)               /* put out a cylinder */
00187 int    ac;
00188 char   **av;
00189 {
00190        static int    ncyls;
00191        char   *mat;
00192        double rad;
00193        C_VERTEX      *cv1, *cv2;
00194        FVECT  p1, p2;
00195        int    inv;
00196                                    /* check argument count and type */
00197        if (ac != 4)
00198               return(MG_EARGC);
00199        if (!isflt(av[2]))
00200               return(MG_ETYPE);
00201                                    /* get the endpoint vertices */
00202        if ((cv1 = c_getvert(av[1])) == NULL ||
00203                      (cv2 = c_getvert(av[3])) == NULL)
00204               return(MG_EUNDEF);
00205        xf_xfmpoint(p1, cv1->p);    /* transform endpoints */
00206        xf_xfmpoint(p2, cv2->p);
00207        rad = xf_scale(atof(av[2]));       /* scale radius */
00208        if ((inv = rad < 0.))              /* check for inverted cylinder */
00209               rad = -rad;
00210        if ((mat = material()) == NULL)    /* get material */
00211               return(MG_EBADMAT);
00212                                    /* spit out the primitive */
00213        printf("\n%s %s %scy%d\n", mat, inv ? "tube" : "cylinder",
00214                      object(), ++ncyls);
00215        printf("0\n0\n7\n");
00216        putv(p1);
00217        putv(p2);
00218        printf("%18.12g\n", rad);
00219        return(MG_OK);
00220 }
00221 
00222 
00223 int
00224 r_sph(ac, av)               /* put out a sphere */
00225 int    ac;
00226 char   **av;
00227 {
00228        static int    nsphs;
00229        char   *mat;
00230        double rad;
00231        C_VERTEX      *cv;
00232        FVECT  cent;
00233        int    inv;
00234                                    /* check argument count and type */
00235        if (ac != 3)
00236               return(MG_EARGC);
00237        if (!isflt(av[2]))
00238               return(MG_ETYPE);
00239        if ((cv = c_getvert(av[1])) == NULL)      /* get center vertex */
00240               return(MG_EUNDEF);
00241        xf_xfmpoint(cent, cv->p);          /* transform center */
00242        rad = xf_scale(atof(av[2]));              /* scale radius */
00243        if ((inv = rad < 0.))                     /* check for inversion */
00244               rad = -rad;
00245        if ((mat = material()) == NULL)           /* get material */
00246               return(MG_EBADMAT);
00247                                           /* spit out primitive */
00248        printf("\n%s %s %ss%d\n", mat, inv ? "bubble" : "sphere",
00249                      object(), ++nsphs);
00250        printf("0\n0\n4 %18.12g %18.12g %18.12g %18.12g\n",
00251                      cent[0], cent[1], cent[2], rad);
00252        return(MG_OK);
00253 }
00254 
00255 
00256 int
00257 r_ring(ac, av)                     /* put out a ring */
00258 int    ac;
00259 char   **av;
00260 {
00261        static int    nrings;
00262        char   *mat;
00263        double r1, r2;
00264        C_VERTEX      *cv;
00265        FVECT  cent, norm;
00266                                    /* check argument count and type */
00267        if (ac != 4)
00268               return(MG_EARGC);
00269        if (!isflt(av[2]) || !isflt(av[3]))
00270               return(MG_ETYPE);
00271        if ((cv = c_getvert(av[1])) == NULL)      /* get center vertex */
00272               return(MG_EUNDEF);
00273        if (is0vect(cv->n))                /* make sure we have normal */
00274               return(MG_EILL);
00275        xf_xfmpoint(cent, cv->p);          /* transform center */
00276        xf_rotvect(norm, cv->n);           /* rotate normal */
00277        r1 = xf_scale(atof(av[2]));        /* scale radii */
00278        r2 = xf_scale(atof(av[3]));
00279        if (r1 < 0. | r2 <= r1)
00280               return(MG_EILL);
00281        if ((mat = material()) == NULL)           /* get material */
00282               return(MG_EBADMAT);
00283                                           /* spit out primitive */
00284        printf("\n%s ring %sr%d\n", mat, object(), ++nrings);
00285        printf("0\n0\n8\n");
00286        putv(cent);
00287        putv(norm);
00288        printf("%18.12g %18.12g\n", r1, r2);
00289        return(MG_OK);
00290 }
00291 
00292 
00293 int
00294 r_face(ac, av)                     /* convert a face */
00295 int    ac;
00296 char   **av;
00297 {
00298        static int    nfaces;
00299        int           myi = invert;
00300        char   *mat;
00301        register int  i;
00302        register C_VERTEX    *cv;
00303        FVECT  v;
00304        int    rv;
00305                                    /* check argument count and type */
00306        if (ac < 4)
00307               return(MG_EARGC);
00308        if ((mat = material()) == NULL)    /* get material */
00309               return(MG_EBADMAT);
00310        if (ac <= 5) {                            /* check for smoothing */
00311               C_VERTEX      *cva[5];
00312               for (i = 1; i < ac; i++) {
00313                      if ((cva[i-1] = c_getvert(av[i])) == NULL)
00314                             return(MG_EUNDEF);
00315                      if (is0vect(cva[i-1]->n))
00316                             break;
00317               }
00318               if (i < ac)
00319                      i = ISFLAT;
00320               else
00321                      i = flat_tri(cva[0]->p, cva[1]->p, cva[2]->p,
00322                                    cva[0]->n, cva[1]->n, cva[2]->n);
00323               if (i == DEGEN)
00324                      return(MG_OK);              /* degenerate (error?) */
00325               if (i == RVBENT) {
00326                      myi = !myi;
00327                      i = ISBENT;
00328               } else if (i == RVFLAT) {
00329                      myi = !myi;
00330                      i = ISFLAT;
00331               }
00332               if (i == ISBENT) {          /* smoothed triangles */
00333                      do_tri(mat, cva[0], cva[1], cva[2], myi);
00334                      if (ac == 5)
00335                             do_tri(mat, cva[2], cva[3], cva[0], myi);
00336                      return(MG_OK);
00337               }
00338        }
00339                                    /* spit out unsmoothed primitive */
00340        printf("\n%s polygon %sf%d\n", mat, object(), ++nfaces);
00341        printf("0\n0\n%d\n", 3*(ac-1));
00342        for (i = 1; i < ac; i++) {  /* get, transform, print each vertex */
00343               if ((cv = c_getvert(av[myi ? ac-i : i])) == NULL)
00344                      return(MG_EUNDEF);
00345               xf_xfmpoint(v, cv->p);
00346               putv(v);
00347        }
00348        return(MG_OK);
00349 }
00350 
00351 
00352 int
00353 r_ies(ac, av)                      /* convert an IES luminaire file */
00354 int    ac;
00355 char   **av;
00356 {
00357        int    xa0 = 2;
00358        char   combuf[128];
00359        char   fname[48];
00360        char   *oname;
00361        register char *op;
00362        register int  i;
00363                                    /* check argument count */
00364        if (ac < 2)
00365               return(MG_EARGC);
00366                                    /* construct output file name */
00367        if ((op = strrchr(av[1], '/')) != NULL)
00368               op++;
00369        else
00370               op = av[1];
00371        (void)strcpy(fname, op);
00372        if ((op = strrchr(fname, '.')) == NULL)
00373               op = fname + strlen(fname);
00374        (void)strcpy(op, ".rad");
00375                                    /* see if we need to run ies2rad */
00376        if (access(fname, 0) == -1) {
00377               (void)strcpy(combuf, "ies2rad");/* build ies2rad command */
00378               op = combuf + 7;            /* get -m option (first) */
00379               if (ac-xa0 >= 2 && !strcmp(av[xa0], "-m")) {
00380                      if (!isflt(av[xa0+1]))
00381                             return(MG_ETYPE);
00382                      op = addarg(addarg(op, "-m"), av[xa0+1]);
00383                      xa0 += 2;
00384               }
00385               *op++ = ' ';                /* build IES filename */
00386               i = 0;
00387               if (mg_file != NULL &&
00388                             (oname = strrchr(mg_file->fname,'/')) != NULL) {
00389                      i = oname - mg_file->fname + 1;
00390                      (void)strcpy(op, mg_file->fname);
00391               }
00392               (void)strcpy(op+i, av[1]);
00393               if (access(op, 0) == -1)    /* check for file existence */
00394                      return(MG_ENOFILE);
00395               system(combuf);                    /* run ies2rad */
00396               if (access(fname, 0) == -1) /* check success */
00397                      return(MG_EINCL);
00398        }
00399        printf("\n!xform");                /* put out xform command */
00400        oname = object();
00401        if (*oname) {
00402               printf(" -n ");
00403               for (op = oname; op[1]; op++)      /* remove trailing separator */
00404                      putchar(*op);
00405        }
00406        for (i = xa0; i < ac; i++)
00407               printf(" %s", av[i]);
00408        if (ac > xa0 && xf_argc > 0)
00409               printf(" -i 1");
00410        for (i = 0; i < xf_argc; i++)
00411               printf(" %s", xf_argv[i]);
00412        printf(" %s\n", fname);
00413        return(MG_OK);
00414 }
00415 
00416 
00417 do_tri(mat, cv1, cv2, cv3, iv)            /* put out smoothed triangle */
00418 char   *mat;
00419 C_VERTEX      *cv1, *cv2, *cv3;
00420 int    iv;
00421 {
00422        static int    ntris;
00423        BARYCCM       bvecs;
00424        RREAL  bcoor[3][3];
00425        C_VERTEX      *cvt;
00426        FVECT  v1, v2, v3;
00427        FVECT  n1, n2, n3;
00428        register int  i;
00429 
00430        if (iv) {                   /* swap vertex order if inverted */
00431               cvt = cv1;
00432               cv1 = cv3;
00433               cv3 = cvt;
00434        }
00435        xf_xfmpoint(v1, cv1->p);
00436        xf_xfmpoint(v2, cv2->p);
00437        xf_xfmpoint(v3, cv3->p);
00438                                    /* compute barycentric coords. */
00439        if (comp_baryc(&bvecs, v1, v2, v3) < 0)
00440               return;                            /* degenerate triangle! */
00441        printf("\n%s texfunc T-nor\n", mat);      /* put out texture */
00442        printf("4 dx dy dz %s\n0\n", TCALNAME);
00443        xf_rotvect(n1, cv1->n);
00444        xf_rotvect(n2, cv2->n);
00445        xf_rotvect(n3, cv3->n);
00446        for (i = 0; i < 3; i++) {
00447               bcoor[i][0] = n1[i];
00448               bcoor[i][1] = n2[i];
00449               bcoor[i][2] = n3[i];
00450        }
00451        put_baryc(&bvecs, bcoor, 3);
00452                                           /* put out triangle */
00453        printf("\nT-nor polygon %st%d\n", object(), ++ntris);
00454        printf("0\n0\n9\n");
00455        putv(v1);
00456        putv(v2);
00457        putv(v3);
00458 }
00459 
00460 
00461 char *
00462 material()                  /* get (and print) current material */
00463 {
00464        char   *mname = "mat";
00465        COLOR  radrgb, c2;
00466        double d;
00467        register int  i;
00468 
00469        if (c_cmname != NULL)
00470               mname = c_cmname;
00471        if (!c_cmaterial->clock)
00472               return(mname);              /* already current */
00473                             /* else update output */
00474        c_cmaterial->clock = 0;
00475        if (c_cmaterial->ed > .1) { /* emitter */
00476               cvtcolor(radrgb, &c_cmaterial->ed_c,
00477                             emult*c_cmaterial->ed/(PI*WHTEFFICACY));
00478               if (glowdist < FHUGE) {            /* do a glow */
00479                      fprintf(matfp, "\nvoid glow %s\n0\n0\n", mname);
00480                      fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
00481                                    colval(radrgb,GRN),
00482                                    colval(radrgb,BLU), glowdist);
00483               } else {
00484                      fprintf(matfp, "\nvoid light %s\n0\n0\n", mname);
00485                      fprintf(matfp, "3 %f %f %f\n", colval(radrgb,RED),
00486                                    colval(radrgb,GRN),
00487                                    colval(radrgb,BLU));
00488               }
00489               return(mname);
00490        }
00491        d = c_cmaterial->rd + c_cmaterial->td +
00492                      c_cmaterial->rs + c_cmaterial->ts;
00493        if (d < 0. | d > 1.)
00494               return(NULL);
00495                                    /* check for glass/dielectric */
00496        if (c_cmaterial->nr > 1.1 &&
00497                      c_cmaterial->ts > .25 && c_cmaterial->rs <= .125 &&
00498                      c_cmaterial->td <= .01 && c_cmaterial->rd <= .01 &&
00499                      c_cmaterial->rs_a <= .01 && c_cmaterial->ts_a <= .01) {
00500               cvtcolor(radrgb, &c_cmaterial->ts_c,
00501                             c_cmaterial->ts + c_cmaterial->rs);
00502               if (c_cmaterial->sided) {          /* dielectric */
00503                      colval(radrgb,RED) = pow(colval(radrgb,RED),
00504                                                  1./C_1SIDEDTHICK);
00505                      colval(radrgb,GRN) = pow(colval(radrgb,GRN),
00506                                                  1./C_1SIDEDTHICK);
00507                      colval(radrgb,BLU) = pow(colval(radrgb,BLU),
00508                                                  1./C_1SIDEDTHICK);
00509                      fprintf(matfp, "\nvoid dielectric %s\n0\n0\n", mname);
00510                      fprintf(matfp, "5 %g %g %g %f 0\n", colval(radrgb,RED),
00511                                    colval(radrgb,GRN), colval(radrgb,BLU),
00512                                    c_cmaterial->nr);
00513                      return(mname);
00514               }
00515                                                  /* glass */
00516               fprintf(matfp, "\nvoid glass %s\n0\n0\n", mname);
00517               fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
00518                             colval(radrgb,GRN), colval(radrgb,BLU),
00519                             c_cmaterial->nr);
00520               return(mname);
00521               }
00522                                    /* check for trans */
00523        if (c_cmaterial->td > .01 || c_cmaterial->ts > .01) {
00524               double ts, a5, a6;
00525 
00526               if (c_cmaterial->sided) {
00527                      ts = sqrt(c_cmaterial->ts); /* approximate */
00528                      a5 = .5;
00529               } else {
00530                      ts = c_cmaterial->ts;
00531                      a5 = 1.;
00532               }
00533                                           /* average colors */
00534               d = c_cmaterial->rd + c_cmaterial->td + ts;
00535               cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/d);
00536               cvtcolor(c2, &c_cmaterial->td_c, c_cmaterial->td/d);
00537               addcolor(radrgb, c2);
00538               cvtcolor(c2, &c_cmaterial->ts_c, ts/d);
00539               addcolor(radrgb, c2);
00540               if (c_cmaterial->rs + ts > .0001)
00541                      a5 = (c_cmaterial->rs*c_cmaterial->rs_a +
00542                                    ts*a5*c_cmaterial->ts_a) /
00543                                    (c_cmaterial->rs + ts);
00544               a6 = (c_cmaterial->td + ts) /
00545                             (c_cmaterial->rd + c_cmaterial->td + ts);
00546               if (a6 < .999)
00547                      d = c_cmaterial->rd/(1. - c_cmaterial->rs)/(1. - a6);
00548               else
00549                      d = c_cmaterial->td + ts;
00550               scalecolor(radrgb, d);
00551               fprintf(matfp, "\nvoid trans %s\n0\n0\n", mname);
00552               fprintf(matfp, "7 %f %f %f\n", colval(radrgb,RED),
00553                             colval(radrgb,GRN), colval(radrgb,BLU));
00554               fprintf(matfp, "\t%f %f %f %f\n", c_cmaterial->rs, a5, a6,
00555                             ts/(ts + c_cmaterial->td));
00556               return(mname);
00557        }
00558                                    /* check for plastic */
00559        if (c_cmaterial->rs < .1) {
00560               cvtcolor(radrgb, &c_cmaterial->rd_c,
00561                                    c_cmaterial->rd/(1.-c_cmaterial->rs));
00562               fprintf(matfp, "\nvoid plastic %s\n0\n0\n", mname);
00563               fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
00564                             colval(radrgb,GRN), colval(radrgb,BLU),
00565                             c_cmaterial->rs, c_cmaterial->rs_a);
00566               return(mname);
00567        }
00568                                    /* else it's metal */
00569                                           /* average colors */
00570        cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd);
00571        cvtcolor(c2, &c_cmaterial->rs_c, c_cmaterial->rs);
00572        addcolor(radrgb, c2);
00573        fprintf(matfp, "\nvoid metal %s\n0\n0\n", mname);
00574        fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
00575                      colval(radrgb,GRN), colval(radrgb,BLU),
00576                      c_cmaterial->rs/(c_cmaterial->rd + c_cmaterial->rs),
00577                      c_cmaterial->rs_a);
00578        return(mname);
00579 }
00580 
00581 
00582 cvtcolor(radrgb, ciec, intensity)  /* convert a CIE XYZ color to RGB */
00583 COLOR  radrgb;
00584 register C_COLOR     *ciec;
00585 double intensity;
00586 {
00587        static COLOR  ciexyz;
00588 
00589        c_ccvt(ciec, C_CSXY);              /* get xy representation */
00590        ciexyz[1] = intensity;
00591        ciexyz[0] = ciec->cx/ciec->cy*ciexyz[1];
00592        ciexyz[2] = ciexyz[1]*(1./ciec->cy - 1.) - ciexyz[0];
00593        cie_rgb(radrgb, ciexyz);
00594 }
00595 
00596 
00597 char *
00598 object()                    /* return current object name */
00599 {
00600        static char   objbuf[64];
00601        register int  i;
00602        register char *cp;
00603        int    len;
00604                                           /* tracked by obj_handler */
00605        i = obj_nnames - sizeof(objbuf)/16;
00606        if (i < 0)
00607               i = 0;
00608        for (cp = objbuf; i < obj_nnames &&
00609               cp + (len=strlen(obj_name[i])) < objbuf+sizeof(objbuf)-1;
00610                      i++, *cp++ = '.') {
00611               strcpy(cp, obj_name[i]);
00612               cp += len;
00613        }
00614        *cp = '\0';
00615        return(objbuf);
00616 }
00617 
00618 
00619 char *
00620 addarg(op, arg)                           /* add argument and advance pointer */
00621 register char *op, *arg;
00622 {
00623        *op = ' ';
00624        while (*++op = *arg++)
00625               ;
00626        return(op);
00627 }