/* 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 <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 */









syntax highlighted by Code2HTML, v. 0.9.1