/* NIGHTFALL OpenGL Interface */ /* Copyright (C) 2001 Rainer Wichmann & Markus Kuster */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ANSI C forbids an empty source file, so put this outside */ /* do nothing here if we don't have OpenGL */ #include #include #include #include #include "Light.h" #ifdef _WITH_OPENGL /* CIE Color Matching Functions xb,yb,zb * conversion table in 5 nm steps from 380 nm to 780 nm */ static double cie_cmf[81][3] = { {0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201}, {0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102}, {0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456}, {0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230}, {0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721}, {0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281}, {0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130}, {0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533}, {0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582}, {0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573}, {0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203}, {0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057}, {0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021}, {0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014}, {1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008}, {1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002}, {0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000}, {0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000}, {0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000}, {0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000}, {0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000}, {0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000}, {0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000}, {0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000}, {0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000} }; /**************************************************************************** @package nightfall @author Markus Kuster (kuster@astro.uni-tuebingen.de) @version 0.6 @short Calculate relative color cromaticities x,y,z based on CIE color matching functions for a given Black Body temperature @param (double) temperature Black Body temperature (double) *x CIE x value (double) *y CIE y value (double) *z CIE z value @return (void) @heading Open GL Animation ****************************************************************************/ void GLBBtoxyz(double temperature, double *x, double *y,double *z) { register int i; double lambda, X=0, Y=0, Z=0, norm; double Flambda; for (i=0, lambda=380.0; lambda<=780.0; i++,lambda+=5) { /* get black body flux for a given temperature and wave length */ Flambda = GLbbflux(lambda, temperature); /* intergrate cie_cmf contributions over all lambda */ X += Flambda*cie_cmf[i][0]; Y += Flambda*cie_cmf[i][1]; Z += Flambda*cie_cmf[i][2]; /* normalize XYZ values, to get relative cromaticities */ /* we do not need absolute values here */ norm = X+Y+Z; *x = X/norm; *y = Y/norm; *z = Z/norm; } } /**************************************************************************** @package nightfall @author Markus Kuster (kuster@astro.uni-tuebingen.de) @version 0.6 @short Transform CIE x,y,z to RGB @param (double) x CIE x value (double) y CIE y value (double) z CIE z value (double) *R RGB R value (double) *G RGB G value (double) *B RGB B value @return (void) @heading Open GL Animation ****************************************************************************/ void GLxyztoRGB(struct GLColorSystem *csyst, double x, double y,double z, double *R, double *G, double *B) { double denom; double zr, zg, zb; zr = 1.0 - (csyst->xr + csyst->yr); zg = 1.0 - (csyst->xg + csyst->yg); zb = 1.0 - (csyst->xb + csyst->yb); denom = (csyst->xr*csyst->yg - csyst->xg*csyst->yr) * zb + (csyst->xb*csyst->yr - csyst->xr*csyst->yb) * zg + (csyst->xg*csyst->yb - csyst->xb*csyst->yg) * zr; /* Get R, G, B values depending on color system we use */ *R = ( (x * csyst->yg - csyst->xg * y ) * zb + (csyst->xg * csyst->yb - csyst->xb * csyst->yg) * z + (csyst->xb * y - x * csyst->yb) * zg ) / denom; *G = ( (y * csyst->xr - csyst->yr * x ) * zb + (csyst->xb * csyst->yr - csyst->xr * csyst->yb) * z + (csyst->yb * x - y * csyst->xb) * zr ) / denom; *B = ( (csyst->xr * csyst->yg - csyst->xg * csyst->yr) * z + (x * csyst->yr - csyst->xr * y ) * zg + (csyst->xg * y - x * csyst->yg) * zr ) / denom; if (*R < 0.0) *R = 0.0; if (*R > 1.0) *R = 1.0; if (*G < 0.0) *G = 0.0; if (*G > 1.0) *G = 1.0; if (*B < 0.0) *B = 0.0; if (*B > 1.0) *B = 1.0; } /**************************************************************************** @package nightfall @author Markus Kuster (kuster@astro.uni-tuebingen.de) @version 1.0 @short Calculate flux from a black body spectal distribution @param (double) lambda wavelength in meters (double) temp temperature in K @return (void) @heading Open GL Animation ****************************************************************************/ double GLbbflux(double lambda, double temp) { double flux; lambda = lambda * 1e-9; /* convert from nm to meters */ flux = (3.74183e-16 * pow(lambda, -5.0)) / ( exp(1.4388e-2 / (lambda * temp)) - 1.0 ); return(flux); } #endif /* OpenGL end */