| 1 |
gwlarson |
3.1 |
/* Copyright (c) 1998 Silicon Graphics, Inc. */ |
| 2 |
|
|
|
| 3 |
|
|
#ifndef lint |
| 4 |
|
|
static char SCCSid[] = "$SunId$ SGI"; |
| 5 |
|
|
#endif |
| 6 |
|
|
|
| 7 |
|
|
/* |
| 8 |
|
|
* Routines for handling OpenGL light sources |
| 9 |
|
|
*/ |
| 10 |
|
|
|
| 11 |
|
|
#include "radogl.h" |
| 12 |
|
|
|
| 13 |
|
|
double expval = 0.; /* global exposure value */ |
| 14 |
|
|
|
| 15 |
|
|
COLOR ambval = {0.2, 0.2, 0.2}; /* global ambient value */ |
| 16 |
|
|
|
| 17 |
|
|
int dolights = MAXLIGHTS; /* do how many more light sources? */ |
| 18 |
|
|
|
| 19 |
gwlarson |
3.2 |
int glightid[MAXLIGHTS] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, |
| 20 |
gwlarson |
3.1 |
GL_LIGHT3, GL_LIGHT4, GL_LIGHT5, GL_LIGHT6, GL_LIGHT7}; |
| 21 |
|
|
|
| 22 |
|
|
static int lightlist; /* light list id */ |
| 23 |
|
|
|
| 24 |
|
|
/* source types */ |
| 25 |
|
|
#define L_NONE 0 |
| 26 |
|
|
#define L_SOURCE 1 |
| 27 |
|
|
#define L_FLAT 2 |
| 28 |
|
|
#define L_SPHERE 3 |
| 29 |
|
|
|
| 30 |
|
|
static struct { |
| 31 |
|
|
int type; /* light type (0 if none) */ |
| 32 |
|
|
MATREC *m; /* light material */ |
| 33 |
|
|
FVECT pos; /* light position (or direction) */ |
| 34 |
|
|
FVECT norm; /* flat source normal */ |
| 35 |
|
|
double area; /* source area (or solid angle) */ |
| 36 |
|
|
} lightrec[MAXLIGHTS]; /* light source list */ |
| 37 |
|
|
|
| 38 |
|
|
static int nlights; /* number of defined lights */ |
| 39 |
|
|
|
| 40 |
|
|
static int l_flatsrc(), l_spheresrc(), l_source(); |
| 41 |
|
|
|
| 42 |
|
|
|
| 43 |
|
|
lightinit() /* initialize lighting */ |
| 44 |
|
|
{ |
| 45 |
|
|
GLfloat ambv[4]; |
| 46 |
|
|
register int i; |
| 47 |
|
|
|
| 48 |
|
|
if (!dolights) |
| 49 |
|
|
return; |
| 50 |
|
|
glPushAttrib(GL_LIGHTING_BIT); |
| 51 |
|
|
if (expval <= FTINY && bright(ambval) > FTINY) |
| 52 |
|
|
expval = 0.2/bright(ambval); |
| 53 |
|
|
ambv[0] = expval*colval(ambval,RED); |
| 54 |
|
|
ambv[1] = expval*colval(ambval,GRN); |
| 55 |
|
|
ambv[2] = expval*colval(ambval,BLU); |
| 56 |
|
|
ambv[3] = 1.; |
| 57 |
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambv); |
| 58 |
|
|
glCallList(lightlist = newglist()); |
| 59 |
|
|
rgl_checkerr("in lightinit"); |
| 60 |
|
|
nlights = 0; |
| 61 |
|
|
} |
| 62 |
|
|
|
| 63 |
|
|
|
| 64 |
|
|
lightclean() /* clean up light source commands */ |
| 65 |
|
|
{ |
| 66 |
|
|
if ((dolights += nlights) <= 0) |
| 67 |
|
|
return; |
| 68 |
|
|
glPopAttrib(); |
| 69 |
|
|
} |
| 70 |
|
|
|
| 71 |
|
|
|
| 72 |
|
|
lightdefs() /* define light source list */ |
| 73 |
|
|
{ |
| 74 |
|
|
register int i; |
| 75 |
|
|
|
| 76 |
|
|
if (!nlights) |
| 77 |
|
|
return; |
| 78 |
|
|
glNewList(lightlist, GL_COMPILE); |
| 79 |
|
|
while (nlights--) { |
| 80 |
|
|
switch (lightrec[nlights].type) { |
| 81 |
|
|
case L_FLAT: |
| 82 |
|
|
l_flatsrc(nlights); |
| 83 |
|
|
break; |
| 84 |
|
|
case L_SPHERE: |
| 85 |
|
|
l_sphsrc(nlights); |
| 86 |
|
|
break; |
| 87 |
|
|
case L_SOURCE: |
| 88 |
|
|
l_source(nlights); |
| 89 |
|
|
break; |
| 90 |
|
|
default: |
| 91 |
|
|
error(CONSISTENCY, "botched light type in lightdefs"); |
| 92 |
|
|
} |
| 93 |
|
|
freemtl(lightrec[nlights].m); |
| 94 |
|
|
lightrec[nlights].type = L_NONE; |
| 95 |
|
|
} |
| 96 |
|
|
glEndList(); |
| 97 |
|
|
rgl_checkerr("defining lights"); |
| 98 |
|
|
} |
| 99 |
|
|
|
| 100 |
|
|
|
| 101 |
|
|
o_source(o) /* record a distant source */ |
| 102 |
|
|
register OBJREC *o; |
| 103 |
|
|
{ |
| 104 |
|
|
if (!dolights || !issrcmat((MATREC *)o->os)) |
| 105 |
|
|
return(0); |
| 106 |
|
|
if (o->oargs.nfargs != 4) |
| 107 |
|
|
objerror(o, USER, "bad # real arguments"); |
| 108 |
|
|
/* record type & material */ |
| 109 |
|
|
lightrec[nlights].type = L_SOURCE; |
| 110 |
|
|
(lightrec[nlights].m = (MATREC *)o->os)->nlinks++; |
| 111 |
|
|
/* assign direction */ |
| 112 |
|
|
VCOPY(lightrec[nlights].pos, o->oargs.farg); |
| 113 |
|
|
/* compute solid angle */ |
| 114 |
|
|
if (o->oargs.farg[3] <= FTINY) |
| 115 |
|
|
objerror(o, USER, "zero size"); |
| 116 |
|
|
lightrec[nlights].area = 2.*PI*(1. - cos(PI/180./2.*o->oargs.farg[3])); |
| 117 |
|
|
nlights++; dolights--; |
| 118 |
|
|
return(1); |
| 119 |
|
|
} |
| 120 |
|
|
|
| 121 |
|
|
|
| 122 |
|
|
int |
| 123 |
|
|
doflatsrc(m, pos, norm, area) /* record a flat source */ |
| 124 |
|
|
MATREC *m; |
| 125 |
|
|
FVECT pos, norm; |
| 126 |
|
|
double area; |
| 127 |
|
|
{ |
| 128 |
|
|
if (!dolights || !issrcmat(m) || area <= FTINY) |
| 129 |
|
|
return(0); |
| 130 |
|
|
/* record type & material */ |
| 131 |
|
|
lightrec[nlights].type = L_FLAT; |
| 132 |
|
|
(lightrec[nlights].m = m)->nlinks++; |
| 133 |
|
|
/* assign geometry */ |
| 134 |
|
|
VCOPY(lightrec[nlights].pos, pos); |
| 135 |
|
|
VCOPY(lightrec[nlights].norm, norm); |
| 136 |
|
|
lightrec[nlights].area = area; |
| 137 |
|
|
nlights++; dolights--; |
| 138 |
|
|
return(1); |
| 139 |
|
|
} |
| 140 |
|
|
|
| 141 |
|
|
|
| 142 |
|
|
int |
| 143 |
|
|
dosphsrc(m, pos, area) /* record a spherical source */ |
| 144 |
|
|
register MATREC *m; |
| 145 |
|
|
FVECT pos; |
| 146 |
|
|
double area; |
| 147 |
|
|
{ |
| 148 |
|
|
if (!dolights || !issrcmat(m) || area <= FTINY) |
| 149 |
|
|
return(0); |
| 150 |
|
|
/* record type & material */ |
| 151 |
|
|
lightrec[nlights].type = L_SPHERE; |
| 152 |
|
|
(lightrec[nlights].m = m)->nlinks++; |
| 153 |
|
|
/* assign geometry */ |
| 154 |
|
|
VCOPY(lightrec[nlights].pos, pos); |
| 155 |
|
|
lightrec[nlights].area = area; |
| 156 |
|
|
nlights++; dolights--; |
| 157 |
|
|
return(1); |
| 158 |
|
|
} |
| 159 |
|
|
|
| 160 |
|
|
|
| 161 |
|
|
static |
| 162 |
|
|
l_source(n) /* convert a distant source */ |
| 163 |
|
|
register int n; |
| 164 |
|
|
{ |
| 165 |
|
|
register MATREC *m = lightrec[n].m; |
| 166 |
gwlarson |
3.2 |
int thislight = glightid[n]; |
| 167 |
gwlarson |
3.1 |
GLfloat vec[4]; |
| 168 |
|
|
/* assign direction */ |
| 169 |
|
|
VCOPY(vec, lightrec[n].pos); |
| 170 |
|
|
vec[3] = 0.; |
| 171 |
|
|
glLightfv(thislight, GL_POSITION, vec); |
| 172 |
|
|
/* assign color */ |
| 173 |
|
|
vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED); |
| 174 |
|
|
vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN); |
| 175 |
|
|
vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU); |
| 176 |
|
|
vec[3] = 1.; |
| 177 |
|
|
glLightfv(thislight, GL_SPECULAR, vec); |
| 178 |
|
|
glLightfv(thislight, GL_DIFFUSE, vec); |
| 179 |
|
|
vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.; |
| 180 |
|
|
glLightfv(thislight, GL_AMBIENT, vec); |
| 181 |
|
|
glEnable(thislight); |
| 182 |
|
|
} |
| 183 |
|
|
|
| 184 |
|
|
|
| 185 |
|
|
static |
| 186 |
|
|
l_flatsrc(n) /* convert a flat source */ |
| 187 |
|
|
register int n; |
| 188 |
|
|
{ |
| 189 |
|
|
GLfloat vec[4]; |
| 190 |
|
|
register MATREC *m = lightrec[n].m; |
| 191 |
gwlarson |
3.2 |
int thislight = glightid[n]; |
| 192 |
gwlarson |
3.1 |
/* assign position */ |
| 193 |
|
|
VCOPY(vec, lightrec[n].pos); vec[3] = 1.; |
| 194 |
|
|
glLightfv(thislight, GL_POSITION, vec); |
| 195 |
|
|
/* assign color */ |
| 196 |
|
|
vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED); |
| 197 |
|
|
vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN); |
| 198 |
|
|
vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU); |
| 199 |
|
|
vec[3] = 1.; |
| 200 |
|
|
glLightfv(thislight, GL_SPECULAR, vec); |
| 201 |
|
|
glLightfv(thislight, GL_DIFFUSE, vec); |
| 202 |
|
|
vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.; |
| 203 |
|
|
glLightfv(thislight, GL_AMBIENT, vec); |
| 204 |
|
|
glLightf(thislight, GL_SPOT_EXPONENT, 1.); |
| 205 |
|
|
glLightf(thislight, GL_CONSTANT_ATTENUATION, 0.); |
| 206 |
|
|
glLightf(thislight, GL_LINEAR_ATTENUATION, 0.); |
| 207 |
|
|
glLightf(thislight, GL_QUADRATIC_ATTENUATION, 1.); |
| 208 |
|
|
if (m->type == MAT_SPOT && m->u.l.spotang < 90.) { |
| 209 |
|
|
glLightf(thislight, GL_SPOT_CUTOFF, m->u.l.spotang); |
| 210 |
|
|
glLightfv(thislight, GL_SPOT_DIRECTION, m->u.l.spotdir); |
| 211 |
|
|
} else { |
| 212 |
|
|
glLightf(thislight, GL_SPOT_CUTOFF, 90.); |
| 213 |
|
|
VCOPY(vec, lightrec[n].norm); |
| 214 |
|
|
glLightfv(thislight, GL_SPOT_DIRECTION, vec); |
| 215 |
|
|
} |
| 216 |
|
|
glEnable(thislight); |
| 217 |
|
|
} |
| 218 |
|
|
|
| 219 |
|
|
|
| 220 |
|
|
static |
| 221 |
|
|
l_sphsrc(n) /* convert a spherical source */ |
| 222 |
|
|
register int n; |
| 223 |
|
|
{ |
| 224 |
|
|
GLfloat vec[4]; |
| 225 |
|
|
register MATREC *m = lightrec[n].m; |
| 226 |
gwlarson |
3.2 |
int thislight = glightid[n]; |
| 227 |
gwlarson |
3.1 |
/* assign position */ |
| 228 |
|
|
VCOPY(vec, lightrec[n].pos); vec[3] = 1.; |
| 229 |
|
|
glLightfv(thislight, GL_POSITION, vec); |
| 230 |
|
|
/* assign color */ |
| 231 |
|
|
vec[0] = expval*lightrec[n].area*colval(m->u.l.emission,RED); |
| 232 |
|
|
vec[1] = expval*lightrec[n].area*colval(m->u.l.emission,GRN); |
| 233 |
|
|
vec[2] = expval*lightrec[n].area*colval(m->u.l.emission,BLU); |
| 234 |
|
|
vec[3] = 1.; |
| 235 |
|
|
glLightfv(thislight, GL_SPECULAR, vec); |
| 236 |
|
|
glLightfv(thislight, GL_DIFFUSE, vec); |
| 237 |
|
|
vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.; |
| 238 |
|
|
glLightfv(thislight, GL_AMBIENT, vec); |
| 239 |
|
|
glLightf(thislight, GL_SPOT_EXPONENT, 0.); |
| 240 |
|
|
glLightf(thislight, GL_CONSTANT_ATTENUATION, 0.); |
| 241 |
|
|
glLightf(thislight, GL_LINEAR_ATTENUATION, 0.); |
| 242 |
|
|
glLightf(thislight, GL_QUADRATIC_ATTENUATION, 1.); |
| 243 |
|
|
if (m->type == MAT_SPOT && m->u.l.spotang <= 90.) { |
| 244 |
|
|
glLightf(thislight, GL_SPOT_CUTOFF, m->u.l.spotang); |
| 245 |
|
|
glLightfv(thislight, GL_SPOT_DIRECTION, m->u.l.spotdir); |
| 246 |
|
|
} else |
| 247 |
|
|
glLightf(thislight, GL_SPOT_CUTOFF, 180.); |
| 248 |
|
|
glEnable(thislight); |
| 249 |
|
|
} |