Back to index

radiance  4R0+20100331
rglmat.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rglmat.c,v 3.6 2003/11/14 17:22:06 schorsch Exp $";
00003 #endif
00004 /*
00005  * Routines for Radiance -> OpenGL materials.
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include "radogl.h"
00011 
00012 int    domats = 1;                 /* are we doing materials? */
00013 
00014 LUTAB  mtab = LU_SINIT(free,freemtl);
00015 
00016 
00017 void
00018 rgl_matclear()                     /* clean up materials */
00019 {
00020        lu_done(&mtab);
00021        domats = 1;
00022 }
00023 
00024 
00025 MATREC *
00026 getmatp(nam)                /* find material record for modifier name */
00027 char   *nam;
00028 {
00029        register LUENT       *lup;
00030 
00031        if (nam == NULL)
00032               return(NULL);
00033        if ((lup = lu_find(&mtab, nam)) == NULL)
00034               return(NULL);
00035        return((MATREC *)lup->data);
00036 }
00037 
00038 
00039 int
00040 o_default(o)                /* default object is non-material modifier */
00041 register OBJREC      *o;
00042 {
00043        register LUENT       *lup;
00044 #ifdef DEBUG
00045        if (o->otype >= 0 && !ismodifier(o->otype))
00046               error(CONSISTENCY, "o_default handed non-modifier");
00047 #endif
00048                                    /* find name in lookup table */
00049        if ((lup = lu_find(&mtab, o->oname)) == NULL)
00050               goto memerr;
00051        if (lup->key == NULL) {            /* new entry? */
00052               lup->key = (char *)malloc(strlen(o->oname)+1);
00053               if (lup->key == NULL)
00054                      goto memerr;
00055               strcpy(lup->key, o->oname);
00056        } else if (lup->data != NULL)
00057               freemtl(lup->data);
00058        if ((lup->data = o->os) != NULL)   /* make material reference */
00059               ((MATREC *)lup->data)->nlinks++;
00060        return(0);
00061 memerr:
00062        error(SYSTEM, "out of memory in o_default");
00063        return(0);
00064 }
00065 
00066 
00067 int
00068 o_unsupported(o)            /* unsupported object primitive */
00069 OBJREC *o;
00070 {
00071        objerror(o, WARNING, "unsupported type");
00072        return(0);
00073 }
00074 
00075 
00076 MATREC *
00077 newmaterial(nam)            /* get an entry for a new material */
00078 char   *nam;
00079 {
00080        register LUENT       *lup;
00081                                    /* look it up (assign entry) */
00082        if ((lup = lu_find(&mtab, nam)) == NULL)
00083               goto memerr;
00084        if (lup->key == NULL) {            /* new entry? */
00085               lup->key = (char *)malloc(strlen(nam)+1);
00086               if (lup->key == NULL)
00087                      goto memerr;
00088               strcpy(lup->key, nam);
00089        } else if (lup->data != NULL)
00090               freemtl(lup->data);
00091        lup->data = (char *)malloc(sizeof(MATREC));
00092        if (lup->data == NULL)
00093               goto memerr;
00094        ((MATREC *)lup->data)->nlinks = 1;
00095        return((MATREC *)lup->data);
00096 memerr:
00097        error(SYSTEM, "out of memory in newmaterial");
00098        return NULL; /* pro forma return */
00099 }
00100 
00101 
00102 void
00103 freemtl(p)                  /* free a material */
00104 void   *p;
00105 {
00106        register MATREC      *mp = (MATREC *)p;
00107 
00108        if (!--mp->nlinks)
00109               free((void *)mp);
00110 }
00111 
00112 
00113 int
00114 m_normal(o)                 /* compute normal material parameters */
00115 register OBJREC      *o;
00116 {
00117        register MATREC      *m;
00118                                    /* check arguments */
00119        if (o->oargs.nfargs != (o->otype == MAT_TRANS ? 7 : 5))
00120               objerror(o, USER, "bad # of real arguments");
00121                                    /* allocate/insert material */
00122        m = newmaterial(o->oname);
00123                                    /* assign parameters */
00124        setcolor(m->u.m.ambdiff, o->oargs.farg[0],
00125                      o->oargs.farg[1], o->oargs.farg[2]);
00126        if ((m->type = o->otype) == MAT_METAL)
00127               copycolor(m->u.m.specular, m->u.m.ambdiff);
00128        else
00129               setcolor(m->u.m.specular, 1., 1., 1.);
00130        scalecolor(m->u.m.specular, o->oargs.farg[3]);
00131        scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]);
00132        if (m->type == MAT_TRANS) {
00133               scalecolor(m->u.m.specular, 1.-o->oargs.farg[5]);
00134               scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[5]);
00135        }
00136        if (o->oargs.farg[4] <= FTINY)
00137               m->u.m.specexp = MAXSPECEXP;
00138        else
00139               m->u.m.specexp = 2./(o->oargs.farg[4]*o->oargs.farg[4]);
00140        if (m->u.m.specexp > MAXSPECEXP)
00141               m->u.m.specexp = MAXSPECEXP;
00142        return(0);
00143 }
00144 
00145 
00146 int
00147 m_aniso(o)                  /* anisotropic material */
00148 register OBJREC      *o;
00149 {
00150        register MATREC      *m;
00151                                    /* check arguments */
00152        if (o->oargs.nfargs < (o->otype == MAT_TRANS2 ? 8 : 6))
00153               objerror(o, USER, "bad # of real arguments");
00154                                    /* allocate/insert material */
00155        m = newmaterial(o->oname);
00156                                    /* assign parameters */
00157        setcolor(m->u.m.ambdiff, o->oargs.farg[0],
00158                      o->oargs.farg[1], o->oargs.farg[2]);
00159        if ((m->type = o->otype) == MAT_METAL2)
00160               copycolor(m->u.m.specular, m->u.m.ambdiff);
00161        else
00162               setcolor(m->u.m.specular, 1., 1., 1.);
00163        scalecolor(m->u.m.specular, o->oargs.farg[3]);
00164        scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]);
00165        if (m->type == MAT_TRANS2) {
00166               scalecolor(m->u.m.specular, 1.-o->oargs.farg[6]);
00167               scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[6]);
00168        }
00169        if (o->oargs.farg[4]*o->oargs.farg[5] <= FTINY*FTINY)
00170               m->u.m.specexp = MAXSPECEXP;
00171        else
00172               m->u.m.specexp = 2./(o->oargs.farg[4]*o->oargs.farg[5]);
00173        if (m->u.m.specexp > MAXSPECEXP)
00174               m->u.m.specexp = MAXSPECEXP;
00175        return(0);
00176 }
00177 
00178 
00179 int
00180 m_glass(o)                  /* glass material (hopeless) */
00181 OBJREC *o;
00182 {
00183        register MATREC      *m;
00184 
00185        m = newmaterial(o->oname);
00186        m->type = o->otype;
00187        setcolor(m->u.m.ambdiff, 0., 0., 0.);
00188        setcolor(m->u.m.specular, .08, .08, .08);
00189        m->u.m.specexp = MAXSPECEXP;
00190        return(0);
00191 }
00192 
00193 
00194 int
00195 m_brdf(o)                   /* convert functional material */
00196 register OBJREC      *o;
00197 {
00198        register MATREC      *m;
00199                                    /* check arguments */
00200        if (o->oargs.nfargs < (o->otype == MAT_TFUNC ? 6 : 4))
00201               objerror(o, USER, "bad # of real arguments");
00202                                    /* allocate/insert material */
00203        m = newmaterial(o->oname);
00204                                    /* assign parameters */
00205        setcolor(m->u.m.ambdiff, o->oargs.farg[0],
00206                      o->oargs.farg[1], o->oargs.farg[2]);
00207        if ((m->type = o->otype) == MAT_MFUNC)
00208               copycolor(m->u.m.specular, m->u.m.ambdiff);
00209        else
00210               setcolor(m->u.m.specular, 1., 1., 1.);
00211        scalecolor(m->u.m.specular, o->oargs.farg[3]);
00212        scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[3]);
00213        if (m->type == MAT_TFUNC) {
00214               scalecolor(m->u.m.specular, 1.-o->oargs.farg[4]);
00215               scalecolor(m->u.m.ambdiff, 1.-o->oargs.farg[4]);
00216        }
00217        m->u.m.specexp = UNKSPECEXP;
00218        return(0);
00219 }
00220 
00221 
00222 int
00223 m_brdf2(o)                  /* convert advanced functional material */
00224 register OBJREC      *o;
00225 {
00226        register MATREC      *m;
00227 
00228        if (o->oargs.nfargs < 9)
00229               objerror(o, USER, "bad # of real arguments");
00230        m = newmaterial(o->oname);
00231        m->type = o->otype;
00232                                    /* assign average diffuse front+back */
00233        setcolor(m->u.m.ambdiff, (o->oargs.farg[0]+o->oargs.farg[3])*.5,
00234                              (o->oargs.farg[1]+o->oargs.farg[4])*.5,
00235                              (o->oargs.farg[2]+o->oargs.farg[5])*.5);
00236                                    /* guess the rest */
00237        setcolor(m->u.m.specular, .1, .1, .1);
00238        m->u.m.specexp = UNKSPECEXP;
00239        return(0);
00240 }
00241 
00242 
00243 int
00244 m_light(o)                  /* convert light type */
00245 register OBJREC      *o;
00246 {
00247        FVECT  v;
00248        register MATREC      *m;
00249 
00250        if (o->oargs.nfargs < (o->otype == MAT_SPOT ? 7 : 3))
00251               objerror(o, USER, "bad # of real arguments");
00252        m = newmaterial(o->oname);
00253        setcolor(m->u.l.emission, o->oargs.farg[0],
00254                      o->oargs.farg[1], o->oargs.farg[2]);
00255        if ((m->type = o->otype) == MAT_SPOT) {
00256               if ((m->u.l.spotang = o->oargs.farg[3]/2.) > 90.)
00257                      m->u.l.spotang = 180.;
00258               v[0] = o->oargs.farg[4];
00259               v[1] = o->oargs.farg[5];
00260               v[2] = o->oargs.farg[6];
00261               if (normalize(v) == 0.)
00262                      objerror(o, USER, "illegal direction");
00263               VCOPY(m->u.l.spotdir, v);
00264        } else {
00265               m->u.l.spotang = 180.;
00266               m->u.l.spotdir[0] = m->u.l.spotdir[1] = 0.;
00267               m->u.l.spotdir[2] = -1.;
00268        }
00269        return(0);
00270 }
00271 
00272 
00273 int
00274 m_mirror(o)                 /* convert mirror type */
00275 register OBJREC      *o;
00276 {
00277        register MATREC      *m;
00278 
00279        if (o->oargs.nfargs != 3)
00280               objerror(o, USER, "bad # real arguments");
00281        m = newmaterial(o->oname);
00282        m->type = o->otype;
00283        setcolor(m->u.m.ambdiff, 0., 0., 0.);
00284        setcolor(m->u.m.specular, o->oargs.farg[0],
00285                      o->oargs.farg[1], o->oargs.farg[2]);
00286        m->u.m.specexp = MAXSPECEXP;
00287        return(0);
00288 }
00289 
00290 
00291 int
00292 m_prism(o)                  /* convert prism type */
00293 register OBJREC      *o;
00294 {
00295        register MATREC      *m;
00296                                    /* can't really deal with this type */
00297        m = newmaterial(o->oname);
00298        m->type = o->otype;
00299        setcolor(m->u.m.ambdiff, 0.2, 0.2, 0.2);
00300        setcolor(m->u.m.specular, 0.1, 0.1, 0.1);
00301        m->u.m.specexp = UNKSPECEXP;
00302        return(0);
00303 }