Back to index

radiance  4R0+20100331
rglsrc.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rglsrc.c,v 3.6 2003/11/14 17:22:06 schorsch Exp $";
00003 #endif
00004 /*
00005  * Routines for handling OpenGL light sources
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include "radogl.h"
00011 
00012 double expval = 0.;                /* global exposure value */
00013 
00014 COLOR  ambval = {0.2, 0.2, 0.2};   /* global ambient value */
00015 
00016 int    dolights = MAXLIGHTS;              /* do how many more light sources? */
00017 
00018 int    glightid[MAXLIGHTS] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2,
00019                      GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7};
00020 
00021 static int    lightlist;           /* light list id */
00022 
00023                             /* source types */
00024 #define L_NONE              0
00025 #define L_SOURCE     1
00026 #define L_FLAT              2
00027 #define L_SPHERE     3
00028 
00029 static struct {
00030        int    type;         /* light type (0 if none) */
00031        MATREC *m;           /* light material */
00032        FVECT  pos;          /* light position (or direction) */
00033        FVECT  norm;         /* flat source normal */
00034        double area;         /* source area (or solid angle) */
00035 } lightrec[MAXLIGHTS];      /* light source list */
00036 
00037 static int    nlights;             /* number of defined lights */
00038 
00039 static void   l_flatsrc(int), l_sphsrc(int), l_source(int);
00040 
00041 
00042 void
00043 lightinit()                 /* initialize lighting */
00044 {
00045        GLfloat       ambv[4];
00046 
00047        if (!dolights)
00048               return;
00049        glPushAttrib(GL_LIGHTING_BIT);
00050        if (expval <= FTINY && bright(ambval) > FTINY)
00051               expval = 0.2/bright(ambval);
00052        ambv[0] = expval*colval(ambval,RED);
00053        ambv[1] = expval*colval(ambval,GRN);
00054        ambv[2] = expval*colval(ambval,BLU);
00055        ambv[3] = 1.;
00056        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambv);
00057        glCallList(lightlist = newglist());
00058        rgl_checkerr("in lightinit");
00059        nlights = 0;
00060 }
00061 
00062 
00063 void
00064 lightclean()                /* clean up light source commands */
00065 {
00066        if ((dolights += nlights) <= 0)
00067               return;
00068        glPopAttrib();
00069 }
00070 
00071 
00072 void
00073 lightdefs()                 /* define light source list */
00074 {
00075        if (!nlights)
00076               return;
00077        glNewList(lightlist, GL_COMPILE);
00078        while (nlights--) {
00079               switch (lightrec[nlights].type) {
00080               case L_FLAT:
00081                      l_flatsrc(nlights);
00082                      break;
00083               case L_SPHERE:
00084                      l_sphsrc(nlights);
00085                      break;
00086               case L_SOURCE:
00087                      l_source(nlights);
00088                      break;
00089               default:
00090                      error(CONSISTENCY, "botched light type in lightdefs");
00091               }
00092               freemtl(lightrec[nlights].m);
00093               lightrec[nlights].type = L_NONE;
00094        }
00095        glEndList();
00096        rgl_checkerr("defining lights");
00097 }
00098 
00099 
00100 int
00101 o_source(o)                 /* record a distant source */
00102 register OBJREC      *o;
00103 {
00104        if (!dolights || !issrcmat((MATREC *)o->os))
00105               return(0);
00106        if (o->oargs.nfargs != 4)
00107               objerror(o, USER, "bad # real arguments");
00108                                           /* record type & material */
00109        lightrec[nlights].type = L_SOURCE;
00110        (lightrec[nlights].m = (MATREC *)o->os)->nlinks++;
00111                                           /* assign direction */
00112        VCOPY(lightrec[nlights].pos, o->oargs.farg);
00113                                           /* compute solid angle */
00114        if (o->oargs.farg[3] <= FTINY)
00115               objerror(o, USER, "zero size");
00116        lightrec[nlights].area = 2.*PI*(1. - cos(PI/180./2.*o->oargs.farg[3]));
00117        nlights++; dolights--;
00118        return(1);
00119 }
00120 
00121 
00122 int
00123 doflatsrc(m, pos, norm, area)      /* record a flat source */
00124 MATREC *m;
00125 FVECT  pos, norm;
00126 double area;
00127 {
00128        if (!dolights || !issrcmat(m) || area <= FTINY)
00129               return(0);
00130                                           /* record type & material */
00131        lightrec[nlights].type = L_FLAT;
00132        (lightrec[nlights].m = m)->nlinks++;
00133                                           /* assign geometry */
00134        VCOPY(lightrec[nlights].pos, pos);
00135        VCOPY(lightrec[nlights].norm, norm);
00136        lightrec[nlights].area = area;
00137        nlights++; dolights--;
00138        return(1);
00139 }
00140 
00141 
00142 int
00143 dosphsrc(m, pos, area)             /* record a spherical source */
00144 register MATREC      *m;
00145 FVECT  pos;
00146 double area;
00147 {
00148        if (!dolights || !issrcmat(m) || area <= FTINY)
00149               return(0);
00150                                           /* record type & material */
00151        lightrec[nlights].type = L_SPHERE;
00152        (lightrec[nlights].m = m)->nlinks++;
00153                                           /* assign geometry */
00154        VCOPY(lightrec[nlights].pos, pos);
00155        lightrec[nlights].area = area;
00156        nlights++; dolights--;
00157        return(1);
00158 }
00159 
00160 
00161 static void
00162 l_source(n)                 /* convert a distant source */
00163 register int  n;
00164 {
00165        register MATREC      *m = lightrec[n].m;
00166        int    thislight = glightid[n];
00167        GLfloat       vec[4];
00168                                           /* assign direction */
00169        VCOPY(vec, lightrec[n].pos);
00170        vec[3] = 0.;
00171        glLightfv(thislight, GL_POSITION, vec);
00172                                           /* assign color */
00173        vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED);
00174        vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN);
00175        vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU);
00176        vec[3] = 1.;
00177        glLightfv(thislight, GL_SPECULAR, vec);
00178        glLightfv(thislight, GL_DIFFUSE, vec);
00179        vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.;
00180        glLightfv(thislight, GL_AMBIENT, vec);
00181        glEnable(thislight);
00182 }
00183 
00184 
00185 static void
00186 l_flatsrc(n)                /* convert a flat source */
00187 register int  n;
00188 {
00189        GLfloat       vec[4];
00190        register MATREC      *m = lightrec[n].m;
00191        int    thislight = glightid[n];
00192                                           /* assign position */
00193        VCOPY(vec, lightrec[n].pos); vec[3] = 1.;
00194        glLightfv(thislight, GL_POSITION, vec);
00195                                           /* assign color */
00196        vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED);
00197        vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN);
00198        vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU);
00199        vec[3] = 1.;
00200        glLightfv(thislight, GL_SPECULAR, vec);
00201        glLightfv(thislight, GL_DIFFUSE, vec);
00202        vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.;
00203        glLightfv(thislight, GL_AMBIENT, vec);
00204        glLightf(thislight, GL_SPOT_EXPONENT, 1.);
00205        glLightf(thislight, GL_CONSTANT_ATTENUATION, 0.);
00206        glLightf(thislight, GL_LINEAR_ATTENUATION, 0.);
00207        glLightf(thislight, GL_QUADRATIC_ATTENUATION, 1.);
00208        if (m->type == MAT_SPOT && m->u.l.spotang < 90.) {
00209               glLightf(thislight, GL_SPOT_CUTOFF, m->u.l.spotang);
00210               glLightfv(thislight, GL_SPOT_DIRECTION, m->u.l.spotdir);
00211        } else {
00212               glLightf(thislight, GL_SPOT_CUTOFF, 90.);
00213               VCOPY(vec, lightrec[n].norm);
00214               glLightfv(thislight, GL_SPOT_DIRECTION, vec);
00215        }
00216        glEnable(thislight);
00217 }
00218 
00219 
00220 static void
00221 l_sphsrc(n)                 /* convert a spherical source */
00222 register int  n;
00223 {
00224        GLfloat       vec[4];
00225        register MATREC      *m = lightrec[n].m;
00226        int    thislight = glightid[n];
00227                                           /* assign position */
00228        VCOPY(vec, lightrec[n].pos); vec[3] = 1.;
00229        glLightfv(thislight, GL_POSITION, vec);
00230                                           /* assign color */
00231        vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED);
00232        vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN);
00233        vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU);
00234        vec[3] = 1.;
00235        glLightfv(thislight, GL_SPECULAR, vec);
00236        glLightfv(thislight, GL_DIFFUSE, vec);
00237        vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.;
00238        glLightfv(thislight, GL_AMBIENT, vec);
00239        glLightf(thislight, GL_SPOT_EXPONENT, 0.);
00240        glLightf(thislight, GL_CONSTANT_ATTENUATION, 0.);
00241        glLightf(thislight, GL_LINEAR_ATTENUATION, 0.);
00242        glLightf(thislight, GL_QUADRATIC_ATTENUATION, 1.);
00243        if (m->type == MAT_SPOT && m->u.l.spotang <= 90.) {
00244               glLightf(thislight, GL_SPOT_CUTOFF, m->u.l.spotang);
00245               glLightfv(thislight, GL_SPOT_DIRECTION, m->u.l.spotdir);
00246        } else
00247               glLightf(thislight, GL_SPOT_CUTOFF, 180.);
00248        glEnable(thislight);
00249 }