llvosky.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LLVOSKY_H
00033 #define LL_LLVOSKY_H
00034 
00035 #include "stdtypes.h"
00036 #include "v3color.h"
00037 #include "v4coloru.h"
00038 #include "llviewerimage.h"
00039 #include "llviewerobject.h"
00040 #include "llframetimer.h"
00041 
00042 
00044 //
00045 // Lots of constants
00046 //
00047 // Will clean these up at some point...
00048 //
00049 
00050 const F32 HORIZON_DIST                  = 1024.0f;
00051 const F32 HEAVENLY_BODY_DIST            = HORIZON_DIST - 10.f;
00052 const F32 HEAVENLY_BODY_FACTOR  = 0.1f;
00053 const F32 HEAVENLY_BODY_SCALE   = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR;
00054 const F32 EARTH_RADIUS                  = 6.4e6f;       // exact radius = 6.37 x 10^6 m
00055 const F32 ATM_EXP_FALLOFF               = 0.000126f;
00056 const F32 ATM_SEA_LEVEL_NDENS   = 2.55e25f;
00057 // Somewhat arbitrary:
00058 const F32 ATM_HEIGHT                    = 100000.f;
00059 
00060 const F32 FIRST_STEP = 5000.f;
00061 const F32 INV_FIRST_STEP = 1.f/FIRST_STEP;
00062 const S32 NO_STEPS = 15;
00063 const F32 INV_NO_STEPS = 1.f/NO_STEPS;
00064 
00065 
00066 // constants used in calculation of scattering coeff of clear air
00067 const F32 sigma         = 0.035f;
00068 const F32 fsigma        = (6.f + 3.f * sigma) / (6.f-7.f*sigma);
00069 const F64 Ndens         = 2.55e25;
00070 const F64 Ndens2        = Ndens*Ndens;
00071 
00072 
00073 LL_FORCE_INLINE LLColor3 color_div(const LLColor3 &col1, const LLColor3 &col2)
00074 {
00075         return LLColor3( 
00076                 col1.mV[0] / col2.mV[0],
00077                 col1.mV[1] / col2.mV[1],
00078                 col1.mV[2] / col2.mV[2] );
00079 }
00080 
00081 LLColor3 color_norm(const LLColor3 &col);
00082 LLVector3 move_vec (const LLVector3& v, F32 cos_max_angle);
00083 BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
00084                                                   const LLVector3 v_corner[4], const F32 cos_max_angle);
00085 F32 clip_side_to_horizon(const LLVector3& v0, const LLVector3& v1, const F32 cos_max_angle);
00086 
00087 inline F32 color_intens ( const LLColor3 &col )
00088 {
00089         return col.mV[0] + col.mV[1] + col.mV[2];
00090 }
00091 
00092 inline F32 color_max(const LLColor3 &col)
00093 {
00094         return llmax(col.mV[0], col.mV[1], col.mV[2]);
00095 }
00096 
00097 inline F32 color_max(const LLColor4 &col)
00098 {
00099         return llmax(col.mV[0], col.mV[1], col.mV[2]);
00100 }
00101 
00102 
00103 inline F32 color_min(const LLColor3 &col)
00104 {
00105         return llmin(col.mV[0], col.mV[1], col.mV[2]);
00106 }
00107 
00108 inline LLColor3 color_norm_abs(const LLColor3 &col)
00109 {
00110         const F32 m = color_max(col);
00111         if (m > 1e-6)
00112         {
00113                 return 1.f/m * col;
00114         }
00115         else return col;
00116 }
00117 
00118 
00119 
00120 class LLFace;
00121 class LLHaze;
00122 
00123 
00124 class LLSkyTex
00125 {
00126         friend class LLVOSky;
00127 private:
00128         static S32              sResolution;
00129         static S32              sComponents;
00130         LLPointer<LLImageGL> mImageGL[2];
00131         LLPointer<LLImageRaw> mImageRaw[2];
00132         LLColor3                *mSkyData;
00133         LLVector3               *mSkyDirs;                      // Cache of sky direction vectors
00134         static S32              sCurrent;
00135         static F32              sInterpVal;
00136 
00137 public:
00138         static F32 getInterpVal()                                       { return sInterpVal; }
00139         static void setInterpVal(const F32 v)           { sInterpVal = v; }
00140         static BOOL doInterpolate()                                     { return sInterpVal > 0.001f; }
00141 
00142         void bindTexture(BOOL curr = TRUE);
00143         
00144 protected:
00145         LLSkyTex();
00146         void init();
00147         void cleanupGL();
00148         void restoreGL();
00149 
00150         ~LLSkyTex();
00151 
00152 
00153         static S32 getResolution()                                              { return sResolution; }
00154         static S32 getCurrent()                                         { return sCurrent; }
00155         static S32 stepCurrent()                                        { return (sCurrent = ++sCurrent % 2); }
00156         static S32 getNext()                                            { return ((sCurrent+1) % 2); }
00157         static S32 getWhich(const BOOL curr)            { return curr ? sCurrent : getNext(); }
00158 
00159         void initEmpty(const S32 tex);
00160         void create(F32 brightness_scale, const LLColor3& multiscatt);
00161 
00162         void setDir(const LLVector3 &dir, const S32 i, const S32 j)
00163         {
00164                 S32 offset = i * sResolution + j;
00165                 mSkyDirs[offset] = dir;
00166         }
00167 
00168         const LLVector3 &getDir(const S32 i, const S32 j) const
00169         {
00170                 S32 offset = i * sResolution + j;
00171                 return mSkyDirs[offset];
00172         }
00173 
00174         void setPixel(const LLColor3 &col, const S32 i, const S32 j)
00175         {
00176                 S32 offset = i * sResolution + j;
00177                 mSkyData[offset] = col;
00178         }
00179 
00180         void setPixel(const LLColor4U &col, const S32 i, const S32 j)
00181         {
00182                 S32 offset = (i * sResolution + j) * sComponents;
00183                 U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
00184                 *pix = col.mAll;
00185         }
00186 
00187         LLColor4U getPixel(const S32 i, const S32 j)
00188         {
00189                 LLColor4U col;
00190                 S32 offset = (i * sResolution + j) * sComponents;
00191                 U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
00192                 col.mAll = *pix;
00193                 return col;
00194         }
00195 
00196         LLImageRaw* getImageRaw(BOOL curr=TRUE)                 { return mImageRaw[getWhich(curr)]; }
00197         void createGLImage(BOOL curr=TRUE);
00198 };
00199 
00200 
00201 class LLHeavenBody
00202 {
00203 protected:
00204         LLVector3               mDirectionCached;               // hack for events that shouldn't happen every frame
00205 
00206         LLColor3                mColor;
00207         LLColor3                mColorCached;
00208         F32                             mIntensity;
00209         LLVector3               mDirection;                             // direction of the local heavenly body
00210         LLVector3               mAngularVelocity;               // velocity of the local heavenly body
00211 
00212         F32                             mDiskRadius;
00213         BOOL                    mDraw;                                  // FALSE - do not draw.
00214         F32                             mHorizonVisibility;             // number [0, 1] due to how horizon
00215         F32                             mVisibility;                    // same but due to other objects being in frong.
00216         BOOL                    mVisible;
00217         static F32              sInterpVal;
00218         LLVector3               mQuadCorner[4];
00219         LLVector3               mU;
00220         LLVector3               mV;
00221         LLVector3               mO;
00222 
00223 public:
00224         LLHeavenBody(const F32 rad) :
00225                         mDirectionCached(LLVector3(0,0,0)), mDirection(LLVector3(0,0,0)),
00226                         mDiskRadius(rad), mDraw(FALSE),
00227                         mHorizonVisibility(1), mVisibility(1)
00228 
00229         {
00230                 mColor.setToBlack();
00231                 mColorCached.setToBlack();
00232         }
00233         ~LLHeavenBody() {}
00234 
00235         const LLVector3& getDirection() const                           { return mDirection; }
00236         void setDirection(const LLVector3 &direction)           { mDirection = direction; }
00237         void setAngularVelocity(const LLVector3 &ang_vel)       { mAngularVelocity = ang_vel; }
00238         const LLVector3& getAngularVelocity() const                     { return mAngularVelocity; }
00239 
00240         const LLVector3& getDirectionCached() const                     { return mDirectionCached; }
00241         void renewDirection()                                                           { mDirectionCached = mDirection; }
00242 
00243         const LLColor3& getColorCached() const                          { return mColorCached; }
00244         void setColorCached(const LLColor3& c)                          { mColorCached = c; }
00245         const LLColor3& getColor() const                                        { return mColor; }
00246         void setColor(const LLColor3& c)                                        { mColor = c; }
00247 
00248         void renewColor()                                                                       { mColorCached = mColor; }
00249 
00250         static F32 interpVal()                                                          { return sInterpVal; }
00251         static void setInterpVal(const F32 v)                           { sInterpVal = v; }
00252 
00253         LLColor3 getInterpColor() const
00254         {
00255                 return sInterpVal * mColor + (1 - sInterpVal) * mColorCached;
00256         }
00257 
00258 //      LLColor3 getDiffuseColor() const
00259 //      {
00260 //              LLColor3 dif = mColorCached;
00261 //              dif.clamp();
00262 //              return 2 * dif;
00263 //      }
00264         
00265 //      LLColor4 getAmbientColor(const LLColor3& scatt, F32 scale) const
00266 //      {
00267 //              const F32 min_val = 0.05f;
00268 //              LLColor4 col = LLColor4(scale * (0.8f * color_norm_abs(getDiffuseColor()) + 0.2f * scatt));
00269 //              //F32 left = max(0, 1 - col.mV[0]);
00270 //              if (col.mV[0] >= 0.9)
00271 //              {
00272 //                      col.mV[1] = llmax(col.mV[1], 2.f * min_val);
00273 //                      col.mV[2] = llmax(col.mV[2], min_val);
00274 //              }
00275 //              col.setAlpha(1.f);
00276 //              return col;
00277 //      }
00278 
00279         const F32& getHorizonVisibility() const                         { return mHorizonVisibility; }
00280         void setHorizonVisibility(const F32 c = 1)                      { mHorizonVisibility = c; }
00281         const F32& getVisibility() const                                        { return mVisibility; }
00282         void setVisibility(const F32 c = 1)                                     { mVisibility = c; }
00283         F32 getHaloBrighness() const
00284         {
00285                 return llmax(0.f, llmin(0.9f, mHorizonVisibility)) * mVisibility;
00286         }
00287         BOOL isVisible() const                                                          { return mVisible; }
00288         void setVisible(const BOOL v)                                           { mVisible = v; }
00289 
00290 
00291         const F32& getIntensity() const                                         { return mIntensity; }
00292         void setIntensity(const F32 c)                                          { mIntensity = c; }
00293 
00294         void setDiskRadius(const F32 radius)                            { mDiskRadius = radius; }
00295         F32     getDiskRadius() const                                                   { return mDiskRadius; }
00296 
00297         void setDraw(const BOOL draw)                                           { mDraw = draw; }
00298         BOOL getDraw() const                                                            { return mDraw; }
00299 
00300         const LLVector3& corner(const S32 n) const                      { return mQuadCorner[n]; }
00301         LLVector3& corner(const S32 n)                                          { return mQuadCorner[n]; }
00302         const LLVector3* corners() const                                        { return mQuadCorner; }
00303 
00304         const LLVector3& getU() const                                           { return mU; }
00305         const LLVector3& getV() const                                           { return mV; }
00306         void setU(const LLVector3& u)                                           { mU = u; }
00307         void setV(const LLVector3& v)                                           { mV = v; }
00308 };
00309 
00310 
00311 LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length)
00312 {
00313         LLColor3 refr_ind;
00314         for (S32 i = 0; i < 3; ++i)
00315         {
00316                 const F32 wl2 = wave_length.mV[i] * wave_length.mV[i] * 1e-6f;
00317                 refr_ind.mV[i] = 6.43e3f + ( 2.95e6f / ( 146.0f - 1.f/wl2 ) ) + ( 2.55e4f / ( 41.0f - 1.f/wl2 ) );
00318                 refr_ind.mV[i] *= 1.0e-8f;
00319                 refr_ind.mV[i] += 1.f;
00320         }
00321         return refr_ind;
00322 }
00323 
00324 
00325 LL_FORCE_INLINE LLColor3 calc_air_sca_sea_level()
00326 {
00327         const static LLColor3 WAVE_LEN(675, 520, 445);
00328         const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
00329         const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
00330         const static LLColor3 n4 = n21 * n21;
00331         const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
00332         const static LLColor3 wl4 = wl2 * wl2;
00333         const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
00334         const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
00335         return dens_div_N * color_div ( mult_const, wl4 );
00336 }
00337 
00338 const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level();
00339 const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel);       
00340 const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3;     
00341 
00342 class LLHaze
00343 {
00344 public:
00345         LLHaze() : mG(0), mFalloff(1) {mSigSca.setToBlack();}
00346         LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2) : 
00347                         mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0)
00348         {
00349                 mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS;
00350         }
00351 
00352         LLHaze(const F32 g, const F32 sca, const F32 fo = 2) : mG(g),
00353                         mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
00354         {
00355                 mAbsCoef = 0.01f * sca / AIR_SCA_AVG;
00356         }
00357 
00358         static void initClass();
00359 
00360 
00361         F32 getG() const                                { return mG; }
00362 
00363         void setG(const F32 g)
00364         {
00365                 mG = g;
00366         }
00367 
00368         const LLColor3& getSigSca() const // sea level
00369         {
00370                 return mSigSca;
00371         } 
00372 
00373         void setSigSca(const LLColor3& s)
00374         {
00375                 mSigSca = s;
00376                 mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS;
00377         }
00378 
00379         void setSigSca(const F32 s0, const F32 s1, const F32 s2)
00380         {
00381                 mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2);
00382                 mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
00383         }
00384 
00385         F32 getFalloff() const
00386         {
00387                 return mFalloff;
00388         }
00389 
00390         void setFalloff(const F32 fo)
00391         {
00392                 mFalloff = fo;
00393         }
00394 
00395         F32 getAbsCoef() const
00396         {
00397                 return mAbsCoef;
00398         }
00399 
00400         inline static F32 calcFalloff(const F32 h)
00401         {
00402                 return (h <= 0) ? 1.0f : (F32)LL_FAST_EXP(-ATM_EXP_FALLOFF * h);
00403         }
00404 
00405         inline LLColor3 calcSigSca(const F32 h) const
00406         {
00407                 return calcFalloff(h * mFalloff) * mSigSca;
00408         }
00409 
00410         inline void calcSigSca(const F32 h, LLColor3 &result) const
00411         {
00412                 result = mSigSca;
00413                 result *= calcFalloff(h * mFalloff);
00414         }
00415 
00416         LLColor3 calcSigExt(const F32 h) const
00417         {
00418                 return calcFalloff(h * mFalloff) * (1 + mAbsCoef) * mSigSca;
00419         }
00420 
00421         F32 calcPhase(const F32 cos_theta) const;
00422 
00423         static inline LLColor3 calcAirSca(const F32 h);
00424         static inline void calcAirSca(const F32 h, LLColor3 &result);
00425         static LLColor3 calcAirScaSeaLevel()                    { return gAirScaSeaLevel; }
00426         static const LLColor3 &getAirScaSeaLevel()              { return sAirScaSeaLevel; }
00427 public:
00428         static LLColor3 sAirScaSeaLevel;
00429 
00430 protected:
00431         F32                     mG;
00432         LLColor3        mSigSca;
00433         F32                     mFalloff;       // 1 - slow, >1 - faster
00434         F32                     mAbsCoef;
00435 };
00436 
00437 class LLTranspMap
00438 {
00439 public:
00440         LLTranspMap() : mElevation(0), mMaxAngle(0), mStep(5), mHaze(NULL), mT(NULL) {}
00441         ~LLTranspMap()
00442         {
00443                 delete[] mT;
00444                 mT = NULL;
00445         }
00446 
00447         void init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze);
00448 
00449         F32 calcHeight(const LLVector3& pos) const
00450         {
00451                 return pos.magVec() - EARTH_RADIUS ;
00452         }
00453 
00454         BOOL hasHaze() const
00455         {
00456                 return mHaze != NULL;
00457         }
00458 
00459         LLColor3 calcSigExt(const F32 h) const
00460         {
00461                 return LLHaze::calcAirSca(h) + (hasHaze() ? mHaze->calcSigExt(h) : LLColor3(0, 0, 0));
00462         }
00463 
00464         inline void calcAirTransp(const F32 cos_angle, LLColor3 &result) const;
00465         LLColor3 calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const;
00466         LLColor3 getHorizonAirTransp () const                           { return mT[mMapSize-1]; }
00467         F32 hitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const;
00468 
00469 protected:
00470         F32                             mAtmHeight;
00471         F32                             mElevation;
00472         F32                             mMaxAngle;
00473         F32                             mCosMaxAngle;
00474         F32                             mStep;
00475         F32                             mStepInv;
00476         S32                             mMapSize;
00477         const LLHaze    *mHaze;
00478         LLColor3                *mT;    // transparency values in all directions
00479                                                         //starting with mAngleBelowHorz at mElevation
00480 };
00481 
00482 class LLTranspMapSet
00483 {
00484 protected:
00485         F32                                     *mHeights;
00486         LLTranspMap                     *mTransp;
00487         S32                                     mSize;
00488         F32                                     mMediaHeight;
00489         const LLHaze            *mHaze;
00490         S32 lerp(F32& dt, S32& indx, const F32 h) const;
00491 public:
00492         LLTranspMapSet() : mHeights(NULL), mTransp(NULL), mHaze(NULL) {}
00493         ~LLTranspMapSet();
00494 
00495         void init (S32 size, F32 first_step, F32 media_height, const LLHaze* const haze);
00496         S32 getSize() const                                                     { return mSize; }
00497         F32 getMediaHeight() const                                      { return mMediaHeight; }
00498         const LLTranspMap& getLastTransp() const        { return mTransp[mSize-1]; }
00499         F32 getLastHeight() const                                       { return mHeights[mSize-1]; }
00500         const LLTranspMap& getMap(const S32 n) const    { return mTransp[n]; }
00501         F32 getHeight(const S32 n) const                                { return mHeights[n]; }
00502         BOOL isReady() const                                            { return mTransp != NULL; }
00503 
00504         inline LLColor3 calcTransp(const F32 cos_angle, const F32 h) const;
00505         inline void calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const;
00506 };
00507 
00508 class LLCubeMap;
00509 
00510 
00511 class LLVOSky : public LLStaticViewerObject
00512 {
00513 public:
00514         enum
00515         {
00516                 FACE_SIDE0,
00517                 FACE_SIDE1,
00518                 FACE_SIDE2,
00519                 FACE_SIDE3,
00520                 FACE_SIDE4,
00521                 FACE_SIDE5,
00522                 FACE_SUN, // was 6
00523                 FACE_MOON, // was 7
00524                 FACE_BLOOM, // was 8
00525                 FACE_REFLECTION, // was 10
00526                 FACE_COUNT
00527         };
00528         
00529         LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
00530 
00531         // Initialize/delete data that's only inited once per class.
00532         static void initClass();
00533         void init();
00534         void initCubeMap();
00535         void initEmpty();
00536         BOOL isReady() const                                                                    { return mTransp.isReady(); }
00537         const LLTranspMapSet& getTransp() const                         { return mTransp; }
00538 
00539         void cleanupGL();
00540         void restoreGL();
00541 
00542         /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
00543         BOOL updateSky();
00544         
00545         // Graphical stuff for objects - maybe broken out into render class
00546         // later?
00547         /*virtual*/ void updateTextures(LLAgent &agent);
00548         /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
00549         /*virtual*/ BOOL                updateGeometry(LLDrawable *drawable);
00550 
00551         void initSkyTextureDirs(const S32 side, const S32 tile);
00552         void createSkyTexture(const S32 side, const S32 tile);
00553 
00554         void updateBrightestDir();
00555         void calcBrightnessScaleAndColors();
00556 
00557         LLColor3 calcSkyColorInDir(const LLVector3& dir);
00558         void calcSkyColorInDir(LLColor3& res, LLColor3& transp, 
00559                                                         const LLVector3& dir) const;
00560         LLColor4 calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exag) const;
00561         void calcInScatter( LLColor3& res, LLColor3& transp,
00562                                         const LLVector3& P, F32 exag) const;
00563 
00564         // Not currently used.
00565         //LLColor3 calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const;
00566         //void calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 dist) const;
00567 
00568         LLColor3 calcRadianceAtPoint(const LLVector3& pos) const
00569         {
00570                 const F32 cos_angle = calcUpVec(pos) * getToSunLast();
00571                 LLColor3 tr;
00572                 mTransp.calcTransp(cos_angle, calcHeight(pos), tr);
00573                 return mBrightnessScaleGuess * mSun.getIntensity() * tr;
00574         }
00575 
00576         const LLHeavenBody& getSun() const                                              { return mSun; }
00577         const LLHeavenBody& getMoon() const                                             { return mMoon; }
00578 
00579         const LLVector3& getToSunLast() const                                   { return mSun.getDirectionCached(); }
00580         const LLVector3& getToSun() const                                               { return mSun.getDirection(); }
00581         const LLVector3& getToMoon() const                                              { return mMoon.getDirection(); }
00582         const LLVector3& getToMoonLast() const                                  { return mMoon.getDirectionCached(); }
00583         BOOL isSunUp() const                                                                    { return mSun.getDirectionCached().mV[2] > -0.05f; }
00584         void calculateColors();
00585 
00586         LLColor3 getSunDiffuseColor() const                                             { return mSunDiffuse; }
00587         LLColor3 getMoonDiffuseColor() const                                    { return mMoonDiffuse; }
00588         LLColor4 getSunAmbientColor() const                                             { return mSunAmbient; }
00589         LLColor4 getMoonAmbientColor() const                                    { return mMoonAmbient; }
00590         const LLColor4& getTotalAmbientColor() const                    { return mTotalAmbient; }
00591         LLColor4 getFogColor() const                                                    { return mFogColor; }
00592         LLColor4 getGLFogColor() const                                                  { return mGLFogCol; }
00593         
00594         LLVector3 calcUpVec(const LLVector3 &pos) const
00595         {
00596                 LLVector3 v = pos - mEarthCenter;
00597                 v.normVec();
00598                 return v;
00599         }
00600 
00601         F32 calcHeight(const LLVector3& pos) const
00602         {
00603                 return dist_vec(pos, mEarthCenter) - EARTH_RADIUS;
00604         }
00605 
00606         // Phase function for atmospheric scattering.
00607         // co = cos ( theta )
00608         F32 calcAirPhaseFunc(const F32 co) const
00609         {
00610                 return (0.75f * (1.f + co*co));
00611         }
00612 
00613 
00614         BOOL isSameFace(S32 idx, const LLFace* face) const { return mFace[idx] == face; }
00615 
00616         void initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
00617         {
00618                 LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
00619                 sun_direction.normVec();
00620                 mSun.setDirection(sun_direction);
00621                 mSun.renewDirection();
00622                 mSun.setAngularVelocity(sun_ang_velocity);
00623                 mMoon.setDirection(-mSun.getDirection());
00624                 mMoon.renewDirection();
00625                 mLastLightingDirection = mSun.getDirection();
00626 
00627                 if ( !isReady() )
00628                 {
00629                         init();
00630                         LLSkyTex::stepCurrent();
00631                 }
00632         }
00633 
00634         void setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity);
00635 
00636         void updateHaze();
00637 
00638         BOOL updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 side, const BOOL is_sun,
00639                                                                         LLHeavenBody& hb, const F32 sin_max_angle,
00640                                                                         const LLVector3 &up, const LLVector3 &right);
00641 
00642         LLVector3 toHorizon(const LLVector3& dir, F32 delta = 0) const
00643         {
00644                 return move_vec(dir, cosHorizon(delta));
00645         }
00646         F32 cosHorizon(const F32 delta = 0) const
00647         {
00648                 const F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mCameraPosAgent.mV[2]);
00649                 return delta - (F32)sqrt(1.f - sin_angle * sin_angle);
00650         }
00651 
00652         void updateSunHaloGeometry(LLDrawable *drawable);
00653         void updateReflectionGeometry(LLDrawable *drawable, F32 H, const LLHeavenBody& HB);
00654 
00655         
00656         const LLHaze& getHaze() const                                           { return mHaze; }
00657         LLHaze& getHaze()                                                                       { return mHaze; }
00658         F32 getHazeConcentration() const                                        { return mHazeConcentration; }
00659         void setHaze(const LLHaze& h)                                           { mHaze = h; }
00660         F32 getWorldScale() const                                                       { return mWorldScale; }
00661         void setWorldScale(const F32 s)                                         { mWorldScale = s; }
00662         void updateFog(const F32 distance);
00663         void setFogRatio(const F32 fog_ratio)                           { mFogRatio = fog_ratio; }
00664         LLColor4U getFadeColor() const                                          { return mFadeColor; }
00665         F32 getFogRatio() const                                                         { return mFogRatio; }
00666         void setCloudDensity(F32 cloud_density)                         { mCloudDensity = cloud_density; }
00667         void setWind ( const LLVector3& wind )                          { mWind = wind.magVec(); }
00668 
00669         const LLVector3 &getCameraPosAgent() const                      { return mCameraPosAgent; }
00670         LLVector3 getEarthCenter() const                                        { return mEarthCenter; }
00671 
00672         LLCubeMap *getCubeMap() const                                           { return mCubeMap; }
00673         S32 getDrawRefl() const                                                         { return mDrawRefl; }
00674         void setDrawRefl(const S32 r)                                           { mDrawRefl = r; }
00675         BOOL isReflFace(const LLFace* face) const                       { return face == mFace[FACE_REFLECTION]; }
00676         LLFace* getReflFace() const                                                     { return mFace[FACE_REFLECTION]; }
00677 
00678         F32 calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const;
00679         F32 calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const;
00680         LLViewerImage*  getSunTex() const                                       { return mSunTexturep; }
00681         LLViewerImage*  getMoonTex() const                                      { return mMoonTexturep; }
00682         LLViewerImage*  getBloomTex() const                                     { return mBloomTexturep; }
00683 
00684         void                    generateScatterMap();
00685         LLImageGL*              getScatterMap()                                         { return mScatterMap; }
00686 
00687 public:
00688         static F32 sNighttimeBrightness; // [0,2] default = 1.0
00689         LLFace                          *mFace[FACE_COUNT];
00690 
00691 protected:
00692         ~LLVOSky();
00693 
00694         LLPointer<LLViewerImage> mSunTexturep;
00695         LLPointer<LLViewerImage> mMoonTexturep;
00696         LLPointer<LLViewerImage> mBloomTexturep;
00697 
00698         static S32                      sResolution;
00699         static S32                      sTileResX;
00700         static S32                      sTileResY;
00701         LLSkyTex                        mSkyTex[6];
00702         LLHeavenBody            mSun;
00703         LLHeavenBody            mMoon;
00704         LLVector3                       mSunDefaultPosition;
00705         LLVector3                       mSunAngVel;
00706         F32                                     mAtmHeight;
00707         LLVector3                       mEarthCenter;
00708         LLVector3                       mCameraPosAgent;
00709         F32                                     mBrightnessScale;
00710         LLColor3                        mBrightestPoint;
00711         F32                                     mBrightnessScaleNew;
00712         LLColor3                        mBrightestPointNew;
00713         F32                                     mBrightnessScaleGuess;
00714         LLColor3                        mBrightestPointGuess;
00715         LLTranspMapSet          mTransp;
00716         LLHaze                          mHaze;
00717         F32                                     mHazeConcentration;
00718         BOOL                            mWeatherChange;
00719         F32                                     mCloudDensity;
00720         F32                                     mWind;
00721         
00722         BOOL                            mInitialized;
00723         BOOL                            mForceUpdate;                           //flag to force instantaneous update of cubemap
00724         LLVector3                       mLastLightingDirection;
00725         LLColor3                        mLastTotalAmbient;
00726         F32                                     mAmbientScale;
00727         LLColor3                        mNightColorShift;
00728         F32                                     sInterpVal;
00729 
00730         LLColor4                        mFogColor;
00731         LLColor4                        mGLFogCol;
00732         
00733         F32                                     mFogRatio;
00734         F32                                     mWorldScale;
00735 
00736         LLColor4                        mSunAmbient;
00737         LLColor4                        mMoonAmbient;
00738         LLColor4                        mTotalAmbient;
00739         LLColor3                        mSunDiffuse;
00740         LLColor3                        mMoonDiffuse;
00741         LLColor4U                       mFadeColor;                                     // Color to fade in from        
00742 
00743         LLPointer<LLCubeMap>    mCubeMap;                                       // Cube map for the environment
00744         S32                                     mDrawRefl;
00745 
00746         LLFrameTimer            mUpdateTimer;
00747 
00748         LLPointer<LLImageGL>    mScatterMap;
00749         LLPointer<LLImageRaw>   mScatterMapRaw;
00750 };
00751 
00752 // Utility functions
00753 F32 azimuth(const LLVector3 &v);
00754 F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
00755 
00756 
00757 /* Proportion of light that is scattered into 'path' from 'in' over distance dt. */
00758 /* assumes that vectors 'path' and 'in' are normalized. Scattering coef / 2pi */
00759 
00760 inline LLColor3 LLHaze::calcAirSca(const F32 h)
00761 {
00762         static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
00763         return calcFalloff(h) * air_sca_sea_level;
00764 }
00765 
00766 inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result)
00767 {
00768         static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
00769         result = air_sca_sea_level;
00770         result *= calcFalloff(h);
00771 }
00772 
00773 // Given cos of the angle between direction of interest and zenith,
00774 // compute transparency by interpolation of known values.
00775 inline void LLTranspMap::calcAirTransp(const F32 cos_angle, LLColor3 &result) const
00776 {
00777         if (cos_angle > 1.f)
00778         {
00779                 result = mT[0];
00780                 return;
00781         }
00782         if (cos_angle < mCosMaxAngle - 0.1f)
00783         {
00784                 result.setVec(0.f, 0.f, 0.f);
00785                 return;
00786         }
00787         if (cos_angle < mCosMaxAngle)
00788         {
00789                 result = mT[mMapSize-1];
00790                 return;
00791         }
00792 
00793 
00794         const F32 relative = (1 - cos_angle)*mStepInv;
00795         const S32 index = llfloor(relative);
00796         const F32 dt = relative - index;
00797 
00798         if (index >= (mMapSize-1))
00799         {
00800                 result = mT[0];
00801                 return;
00802         }
00803 //      result = mT[index];
00804 //      LLColor3 res2(mT[index+1]);
00805 //      result *= 1 - dt;
00806 //      res2 *= dt;
00807 //      result += res2;
00808 
00809         const LLColor3& color1 = mT[index];
00810         const LLColor3& color2 = mT[index + 1];
00811 
00812         const F32 x1 = color1.mV[VX];
00813         const F32 x2 = color2.mV[VX];
00814         result.mV[VX] = x1 - dt * (x1 - x2);
00815 
00816         const F32 y1 = color1.mV[VY];
00817         const F32 y2 = color2.mV[VY];
00818         result.mV[VY] = y1 - dt * (y1 - y2);
00819 
00820         const F32 z1 = color1.mV[VZ];
00821         const F32 z2 = color2.mV[VZ];
00822         result.mV[VZ] = z1 - dt * (z1 - z2);
00823 }
00824 
00825 
00826 
00827 // Returns the translucency of the atmosphere along the ray in the sky.
00828 // dir is assumed to be normalized
00829 inline void LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const
00830 {
00831         S32 indx = 0;
00832         F32 dt = 0.f;
00833         const S32 status = lerp(dt, indx, h);
00834 
00835         if (status < 0)
00836         {
00837                 mTransp[0].calcAirTransp(cos_angle, result);
00838                 return;
00839         }
00840         if (status > 0)
00841         {
00842                 mTransp[NO_STEPS].calcAirTransp(cos_angle, result);
00843                 return;
00844         }
00845 
00846         mTransp[indx].calcAirTransp(cos_angle, result);
00847         result *= 1 - dt;
00848 
00849         LLColor3 transp_above;
00850 
00851         mTransp[indx + 1].calcAirTransp(cos_angle, transp_above);
00852         transp_above *= dt;
00853         result += transp_above;
00854 }
00855 
00856 
00857 inline LLColor3 LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h) const
00858 {
00859         LLColor3 result;
00860         S32 indx = 0;
00861         F32 dt = 0;
00862         const S32 status = lerp(dt, indx, h);
00863 
00864         if (status < 0)
00865         {
00866                 mTransp[0].calcAirTransp(cos_angle, result);
00867                 return result;
00868         }
00869         if (status > 0)
00870         {
00871                 mTransp[NO_STEPS].calcAirTransp(cos_angle, result);
00872                 return result;
00873         }
00874 
00875         mTransp[indx].calcAirTransp(cos_angle, result);
00876         result *= 1 - dt;
00877 
00878         LLColor3 transp_above;
00879 
00880         mTransp[indx + 1].calcAirTransp(cos_angle, transp_above);
00881         transp_above *= dt;
00882         result += transp_above;
00883         return result;
00884 }
00885 
00886 
00887 // Returns -1 if height < 0; +1 if height > max height; 0 if within range
00888 inline S32 LLTranspMapSet::lerp(F32& dt, S32& indx, const F32 h) const
00889 {
00890         static S32 last_indx = 0;
00891 
00892         if (h < 0)
00893         {
00894                 return -1;
00895         }
00896         if (h > getLastHeight())
00897         {
00898                 return 1;
00899         }
00900 
00901         if (h < mHeights[last_indx])
00902         {
00903                 indx = last_indx-1;
00904                 while (mHeights[indx] > h)
00905                 {
00906                         indx--;
00907                 }
00908                 last_indx = indx;
00909         }
00910         else if (h > mHeights[last_indx+1])
00911         {
00912                 indx = last_indx+1;
00913                 while (mHeights[indx+1] < h)
00914                 {
00915                         indx++;
00916                 }
00917                 last_indx = indx;
00918         }
00919         else
00920         {
00921                 indx = last_indx;
00922         }
00923 
00924         const F32 h_below = mHeights[indx];
00925         const F32 h_above = mHeights[indx+1];
00926         dt = (h - h_below) / (h_above - h_below);
00927         return 0;
00928 }
00929 
00930 #endif

Generated on Thu Jul 1 06:09:43 2010 for Second Life Viewer by  doxygen 1.4.7