00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _SKYLIGHT_HPP_
00024 #define _SKYLIGHT_HPP_
00025
00026 #include <cmath>
00027 #include <QDebug>
00028
00029 typedef struct {
00030 float zenithAngle;
00031 float distSun;
00032 float color[3];
00033 } skylightStruct;
00034
00035 typedef struct {
00036 float pos[3];
00037 float color[3];
00038 } skylightStruct2;
00039
00040 class Skylight
00041 {
00042 public:
00043 Skylight();
00044 virtual ~Skylight();
00045
00046
00047 void setParams(float sunZenithAngle, float turbidity);
00048
00049
00050
00051 inline void getZenithColor(float * v) const;
00052
00053
00054
00055 void setParamsv(const float * sunPos, float turbidity);
00056
00057
00058
00059
00060
00061 void getxyYValuev(skylightStruct2& p) const
00062 {
00063 const float cosDistSun = sunPos[0]*p.pos[0] + sunPos[1]*p.pos[1] + sunPos[2]*p.pos[2];
00064 const float distSun = fastAcos(cosDistSun);
00065 const float cosDistSun_q = cosDistSun*cosDistSun;
00066
00067 Q_ASSERT(p.pos[2] >= 0.f);
00068 const float oneOverCosZenithAngle = (p.pos[2]==0.) ? 1e99 : 1.f / p.pos[2];
00069 p.color[0] = term_x * (1.f + Ax * std::exp(Bx*oneOverCosZenithAngle))
00070 * (1.f + Cx * std::exp(Dx*distSun) + Ex * cosDistSun_q);
00071
00072 p.color[1] = term_y * (1.f + Ay * std::exp(By*oneOverCosZenithAngle))
00073 * (1.f + Cy * std::exp(Dy*distSun) + Ey * cosDistSun_q);
00074
00075 p.color[2] = term_Y * (1.f + AY * std::exp(BY*oneOverCosZenithAngle))
00076 * (1.f + CY * std::exp(DY*distSun) + EY * cosDistSun_q);
00077
00078
00079 if (p.color[2] < 0. || p.color[0] < 0. || p.color[1] < 0.)
00080 {
00081 p.color[0] = 0.25;
00082 p.color[1] = 0.25;
00083 p.color[2] = 0.;
00084 }
00085 }
00086
00087 private:
00088 float thetas;
00089 float T;
00090
00091
00092
00093
00094
00095
00096
00097
00098 float zenithLuminance;
00099 float zenithColorX;
00100 float zenithColorY;
00101
00102 float eyeLumConversion;
00103
00104
00105 float AY, BY, CY, DY, EY;
00106 float Ax, Bx, Cx, Dx, Ex;
00107 float Ay, By, Cy, Dy, Ey;
00108
00109 float term_x;
00110 float term_y;
00111 float term_Y;
00112
00113 float sunPos[3];
00114
00115
00116 inline void computeZenithLuminance(void);
00117
00118 inline void computeZenithColor(void);
00119
00120 inline void computeLuminanceDistributionCoefs(void);
00121
00122 inline void computeColorDistributionCoefs(void);
00123
00126 static inline float fastAcos(float x)
00127 {
00128 return M_PI_2 - (x + x*x*x * (1.f/6.f + x*x * (3.f/40.f + 5.f/112.f * x*x)) );
00129 }
00130 };
00131
00132
00133 inline void Skylight::getZenithColor(float * v) const
00134 {
00135 v[0] = zenithColorX;
00136 v[1] = zenithColorY;
00137 v[2] = zenithLuminance;
00138 }
00139
00140
00141 inline void Skylight::computeZenithLuminance(void)
00142 {
00143 zenithLuminance = 1000.f * ((4.0453f*T - 4.9710f) * std::tan( (0.4444f - T/120.f) * (M_PI-2.f*thetas) ) -
00144 0.2155f*T + 2.4192f);
00145 if (zenithLuminance<=0.f) zenithLuminance=0.00000000001;
00146 }
00147
00148
00149
00150 inline void Skylight::computeZenithColor(void)
00151 {
00152 static float thetas2;
00153 static float thetas3;
00154 static float T2;
00155
00156 thetas2 = thetas * thetas;
00157 thetas3 = thetas2 * thetas;
00158 T2 = T * T;
00159
00160 zenithColorX = ( 0.00216f*thetas3 - 0.00375f*thetas2 + 0.00209f*thetas) * T2 +
00161 (-0.02903f*thetas3 + 0.06377f*thetas2 - 0.03202f*thetas + 0.00394f) * T +
00162 ( 0.10169f*thetas3 - 0.21196f*thetas2 + 0.06052f*thetas + 0.25886f);
00163
00164 zenithColorY = ( 0.00275f*thetas3 - 0.00610f*thetas2 + 0.00317f*thetas) * T2 +
00165 (-0.04214f*thetas3 + 0.08970f*thetas2 - 0.04153f*thetas + 0.00516f) * T +
00166 ( 0.14535f*thetas3 - 0.26756f*thetas2 + 0.06670f*thetas + 0.26688f);
00167
00168 }
00169
00170
00171
00172 inline void Skylight::computeLuminanceDistributionCoefs(void)
00173 {
00174 AY = 0.2787f*T - 1.0630f;
00175 BY =-0.3554f*T + 0.4275f;
00176 CY =-0.0227f*T + 6.3251f;
00177 DY = 0.1206f*T - 2.5771f;
00178 EY =-0.0670f*T + 0.3703f;
00179
00180 Q_ASSERT(BY <= 0.0);
00181 }
00182
00183
00184
00185 inline void Skylight::computeColorDistributionCoefs(void)
00186 {
00187 Ax =-0.0148f*T - 0.1703f;
00188 Bx =-0.0664f*T + 0.0011f;
00189 Cx =-0.0005f*T + 0.2127f;
00190 Dx =-0.0641f*T - 0.8992f;
00191 Ex =-0.0035f*T + 0.0453f;
00192
00193 Ay =-0.0131f*T - 0.2498f;
00194 By =-0.0951f*T + 0.0092f;
00195 Cy =-0.0082f*T + 0.2404f;
00196 Dy =-0.0438f*T - 1.0539f;
00197 Ey =-0.0109f*T + 0.0531f;
00198
00199 Q_ASSERT(Bx <= 0.0);
00200 Q_ASSERT(By <= 0.0);
00201 }
00202
00203
00204 #endif // _SKYLIGHT_H_
00205