Home · All Namespaces · All Classes · Functions · Coding Style · Scripting · Plugins · File Structure

core/modules/Skylight.hpp

00001 /*
00002  * Copyright (C) 2003 Fabien Chereau
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017  */
00018 
00019 // Class which computes the daylight sky color
00020 // Fast implementation of the algorithm from the article
00021 // "A Practical Analytic Model for Daylight" by A. J. Preetham, Peter Shirley and Brian Smits.
00022 
00023 #ifndef _SKYLIGHT_HPP_
00024 #define _SKYLIGHT_HPP_
00025 
00026 #include <cmath>
00027 #include <QDebug>
00028 #include "StelUtils.hpp"
00029 
00030 typedef struct {
00031     float zenithAngle;  // zenithAngle : angular distance to the zenith in radian
00032     float distSun;      // distSun     : angular distance to the sun in radian
00033     float color[3];     // 3 component color, can be RGB or CIE color system
00034 } skylightStruct;
00035 
00036 typedef struct {
00037     float pos[3];       // Vector to the position (vertical = pos[2])
00038     float color[3];     // 3 component color, can be RGB or CIE color system
00039 } skylightStruct2;
00040 
00041 class Skylight
00042 {
00043 public:
00044     Skylight();
00045     virtual ~Skylight();
00046     // Set the fixed parameters and precompute what can be
00047     // This function has to be called once before any call to get_*_value()
00048     void setParams(float sunZenithAngle, float turbidity);
00049     // Compute the sky color at the given position in the xyY color system and store it in position.color
00050     // void getxyYValue(skylightStruct * position);
00051     // Return the current zenith color
00052     inline void getZenithColor(float * v) const;
00053 
00054     // Same functions but in vector mode : faster because prevents extra cosine calculations
00055     // The position vectors MUST be normalized, and the vertical z component is the third one
00056     void setParamsv(const float * sunPos, float turbidity);
00057     
00058     // Compute the sky color at the given position in the CIE color system and store it in p.color
00059     // p.color[0] is CIE x color component
00060     // p.color[1] is CIE y color component
00061     // p.color[2] is undefined (CIE Y color component (luminance) if uncommented)
00062     void getxyYValuev(skylightStruct2& p) const
00063     {
00064         const float cosDistSun = sunPos[0]*p.pos[0] + sunPos[1]*p.pos[1] + sunPos[2]*p.pos[2];
00065         const float distSun = StelUtils::fastAcos(cosDistSun);
00066         const float cosDistSun_q = cosDistSun*cosDistSun;
00067 
00068         Q_ASSERT(p.pos[2] >= 0.f);
00069         const float oneOverCosZenithAngle = (p.pos[2]==0.) ? 1e99 : 1.f / p.pos[2];
00070         p.color[0] = term_x * (1.f + Ax * std::exp(Bx*oneOverCosZenithAngle))
00071                 * (1.f + Cx * std::exp(Dx*distSun) + Ex * cosDistSun_q);
00072 
00073         p.color[1] = term_y * (1.f + Ay * std::exp(By*oneOverCosZenithAngle))
00074                 * (1.f + Cy * std::exp(Dy*distSun) + Ey * cosDistSun_q);
00075 
00076 //      p.color[2] = term_Y * (1.f + AY * std::exp(BY*oneOverCosZenithAngle))
00077 //              * (1.f + CY * std::exp(DY*distSun) + EY * cosDistSun_q);
00078 
00079 
00080         if (/*p.color[2] < 0. || */p.color[0] < 0. || p.color[1] < 0.)
00081         {
00082             p.color[0] = 0.25;
00083             p.color[1] = 0.25;
00084             p.color[2] = 0.;
00085         }
00086     }
00087 
00088     void getShadersParams(Vec3f& asunPos, float& aterm_x, float& aAx, float& aBx, float& aCx, float& aDx, float& aEx,
00089         float& aterm_y, float& aAy, float& aBy, float& aCy, float& aDy, float& aEy) const
00090     {
00091         asunPos=sunPos;
00092         aterm_x=term_x;aAx=Ax;aBx=Bx;aCx=Cx;aDx=Dx;aEx=Ex;
00093         aterm_y=term_y;aAy=Ay;aBy=By;aCy=Cy;aDy=Dy;aEy=Ey;
00094     }
00095     
00096     
00097     
00098 private:
00099     float thetas;  // angular distance between the zenith and the sun in radian
00100     float T;       // Turbidity : i.e. sky "clarity"
00101                    //  1 : pure air
00102                    //  2 : exceptionnally clear
00103                    //  4 : clear
00104                    //  8 : light haze
00105                    // 25 : haze
00106                    // 64 : thin fog
00107 
00108     // Computed variables depending on the 2 above
00109     float zenithLuminance;     // Y color component of the CIE color at zenith (luminance)
00110     float zenithColorX;        // x color component of the CIE color at zenith
00111     float zenithColorY;        // y color component of the CIE color at zenith
00112 
00113     float eyeLumConversion;    // luminance conversion for an eye adapted to screen luminance 
00114                                // (around 40 cd/m^2)
00115 
00116     float AY, BY, CY, DY, EY;  // Distribution coefficients for the luminance distribution function
00117     float Ax, Bx, Cx, Dx, Ex;  // Distribution coefficients for x distribution function
00118     float Ay, By, Cy, Dy, Ey;  // Distribution coefficients for y distribution function
00119 
00120     float term_x;              // Precomputed term for x calculation
00121     float term_y;              // Precomputed term for y calculation
00122     float term_Y;              // Precomputed term for luminance calculation
00123 
00124     float sunPos[3];
00125 
00126     // Compute CIE Y (luminance) for zenith in cd/m^2
00127     inline void computeZenithLuminance(void);
00128     // Compute CIE x and y color components
00129     inline void computeZenithColor(void);
00130     // Compute the luminance distribution coefficients
00131     inline void computeLuminanceDistributionCoefs(void);
00132     // Compute the color distribution coefficients
00133     inline void computeColorDistributionCoefs(void);
00134 };
00135 
00136 // Return the current zenith color in xyY color system
00137 inline void Skylight::getZenithColor(float * v) const
00138 {
00139     v[0] = zenithColorX;
00140     v[1] = zenithColorY;
00141     v[2] = zenithLuminance;
00142 }
00143 
00144 // Compute CIE luminance for zenith in cd/m^2
00145 inline void Skylight::computeZenithLuminance(void)
00146 {
00147     zenithLuminance = 1000.f * ((4.0453f*T - 4.9710f) * std::tan( (0.4444f - T/120.f) * (M_PI-2.f*thetas) ) -
00148         0.2155f*T + 2.4192f);
00149     if (zenithLuminance<=0.f) zenithLuminance=0.00000000001;
00150 }
00151 
00152 // Compute CIE x and y color components
00153 // Edit: changed some coefficients to get new sky color
00154 inline void Skylight::computeZenithColor(void)
00155 {
00156     static float thetas2;
00157     static float thetas3;
00158     static float T2;
00159 
00160     thetas2 = thetas * thetas;
00161     thetas3 = thetas2 * thetas;
00162     T2 = T * T;
00163 
00164     zenithColorX = ( 0.00216f*thetas3 - 0.00375f*thetas2 + 0.00209f*thetas) * T2 +
00165                    (-0.02903f*thetas3 + 0.06377f*thetas2 - 0.03202f*thetas + 0.00394f) * T +
00166                    ( 0.10169f*thetas3 - 0.21196f*thetas2 + 0.06052f*thetas + 0.25886f);
00167 
00168     zenithColorY = ( 0.00275f*thetas3 - 0.00610f*thetas2 + 0.00317f*thetas) * T2 +
00169                    (-0.04214f*thetas3 + 0.08970f*thetas2 - 0.04153f*thetas + 0.00516f) * T +
00170                    ( 0.14535f*thetas3 - 0.26756f*thetas2 + 0.06670f*thetas + 0.26688f);
00171 
00172 }
00173 
00174 // Compute the luminance distribution coefficients
00175 // Edit: changed some coefficients to get new sky color
00176 inline void Skylight::computeLuminanceDistributionCoefs(void)
00177 {
00178     AY = 0.2787f*T - 1.0630f;
00179     BY =-0.3554f*T + 0.4275f;
00180     CY =-0.0227f*T + 6.3251f;
00181     DY = 0.1206f*T - 2.5771f;
00182     EY =-0.0670f*T + 0.3703f;
00183     // with BY>0 the formulas in getxyYValuev make no sense
00184     Q_ASSERT(BY <= 0.0);
00185 }
00186 
00187 // Compute the color distribution coefficients
00188 // Edit: changed some coefficients to get new sky color
00189 inline void Skylight::computeColorDistributionCoefs(void)
00190 {
00191     Ax =-0.0148f*T - 0.1703f;
00192     Bx =-0.0664f*T + 0.0011f;
00193     Cx =-0.0005f*T + 0.2127f;
00194     Dx =-0.0641f*T - 0.8992f;
00195     Ex =-0.0035f*T + 0.0453f;
00196 
00197     Ay =-0.0131f*T - 0.2498f;
00198     By =-0.0951f*T + 0.0092f;
00199     Cy =-0.0082f*T + 0.2404f;
00200     Dy =-0.0438f*T - 1.0539f;
00201     Ey =-0.0109f*T + 0.0531f;
00202     // with Bx,By>0 the formulas in getxyYValuev make no sense
00203     Q_ASSERT(Bx <= 0.0);
00204     Q_ASSERT(By <= 0.0);
00205 }
00206 
00207 
00208 #endif // _SKYLIGHT_H_
00209 

Generated on Wed Jun 2 13:11:13 2010 for Stellarium by  doxygen 1.5.5