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