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
00046
00047
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;
00055 const F32 ATM_EXP_FALLOFF = 0.000126f;
00056 const F32 ATM_SEA_LEVEL_NDENS = 2.55e25f;
00057
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
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;
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;
00205
00206 LLColor3 mColor;
00207 LLColor3 mColorCached;
00208 F32 mIntensity;
00209 LLVector3 mDirection;
00210 LLVector3 mAngularVelocity;
00211
00212 F32 mDiskRadius;
00213 BOOL mDraw;
00214 F32 mHorizonVisibility;
00215 F32 mVisibility;
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
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
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
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;
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;
00479
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,
00523 FACE_MOON,
00524 FACE_BLOOM,
00525 FACE_REFLECTION,
00526 FACE_COUNT
00527 };
00528
00529 LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
00530
00531
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 BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
00543 BOOL updateSky();
00544
00545
00546
00547 void updateTextures(LLAgent &agent);
00548 LLDrawable* createDrawable(LLPipeline *pipeline);
00549 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
00565
00566
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
00607
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;
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;
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;
00742
00743 LLPointer<LLCubeMap> mCubeMap;
00744 S32 mDrawRefl;
00745
00746 LLFrameTimer mUpdateTimer;
00747
00748 LLPointer<LLImageGL> mScatterMap;
00749 LLPointer<LLImageRaw> mScatterMapRaw;
00750 };
00751
00752
00753 F32 azimuth(const LLVector3 &v);
00754 F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
00755
00756
00757
00758
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
00774
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
00804
00805
00806
00807
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
00828
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
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