llvosky.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llvosky.h"
00035 
00036 #include "imageids.h"
00037 #include "llfeaturemanager.h"
00038 #include "llviewercontrol.h"
00039 #include "llframetimer.h"
00040 #include "timing.h"
00041 
00042 #include "llagent.h"
00043 #include "lldrawable.h"
00044 #include "llface.h"
00045 #include "llcubemap.h"
00046 #include "lldrawpoolsky.h"
00047 #include "lldrawpoolwater.h"
00048 #include "llglheaders.h"
00049 #include "llsky.h"
00050 #include "llviewercamera.h"
00051 #include "llviewerimagelist.h"
00052 #include "llviewerobjectlist.h"
00053 #include "llviewerregion.h"
00054 #include "llworld.h"
00055 #include "pipeline.h"
00056 #include "viewer.h"             // for gSunTextureID
00057 
00058 const S32 NUM_TILES_X = 8;
00059 const S32 NUM_TILES_Y = 4;
00060 const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
00061 
00062 // Heavenly body constants
00063 const F32 SUN_DISK_RADIUS       = 0.5f;
00064 const F32 MOON_DISK_RADIUS      = SUN_DISK_RADIUS * 0.9f;
00065 const F32 SUN_INTENSITY = 1e5;
00066 const F32 SUN_DISK_INTENSITY = 24.f;
00067 
00068 
00069 // Texture coordinates:
00070 const LLVector2 TEX00 = LLVector2(0.f, 0.f);
00071 const LLVector2 TEX01 = LLVector2(0.f, 1.f);
00072 const LLVector2 TEX10 = LLVector2(1.f, 0.f);
00073 const LLVector2 TEX11 = LLVector2(1.f, 1.f);
00074 
00075 //static 
00076 LLColor3 LLHaze::sAirScaSeaLevel;
00077 
00078 class LLFastLn
00079 {
00080 public:
00081         LLFastLn() 
00082         {
00083                 mTable[0] = 0;
00084                 for( S32 i = 1; i < 257; i++ )
00085                 {
00086                         mTable[i] = log((F32)i);
00087                 }
00088         }
00089 
00090         F32 ln( F32 x )
00091         {
00092                 const F32 OO_255 = 0.003921568627450980392156862745098f;
00093                 const F32 LN_255 = 5.5412635451584261462455391880218f;
00094 
00095                 if( x < OO_255 )
00096                 {
00097                         return log(x);
00098                 }
00099                 else
00100                 if( x < 1 )
00101                 {
00102                         x *= 255.f;
00103                         S32 index = llfloor(x);
00104                         F32 t = x - index;
00105                         F32 low = mTable[index];
00106                         F32 high = mTable[index + 1];
00107                         return low + t * (high - low) - LN_255;
00108                 }
00109                 else
00110                 if( x <= 255 )
00111                 {
00112                         S32 index = llfloor(x);
00113                         F32 t = x - index;
00114                         F32 low = mTable[index];
00115                         F32 high = mTable[index + 1];
00116                         return low + t * (high - low);
00117                 }
00118                 else
00119                 {
00120                         return log( x );
00121                 }
00122         }
00123 
00124         F32 pow( F32 x, F32 y )
00125         {
00126                 return (F32)LL_FAST_EXP(y * ln(x));
00127         }
00128 
00129 
00130 private:
00131         F32 mTable[257]; // index 0 is unused
00132 };
00133 
00134 LLFastLn gFastLn;
00135 
00136 
00137 // Functions used a lot.
00138 
00139 inline F32 LLHaze::calcPhase(const F32 cos_theta) const
00140 {
00141         const F32 g2 = mG * mG;
00142         const F32 den = 1 + g2 - 2 * mG * cos_theta;
00143         return (1 - g2) * gFastLn.pow(den, -1.5);
00144 }
00145 
00146 inline void color_pow(LLColor3 &col, const F32 e)
00147 {
00148         col.mV[0] = gFastLn.pow(col.mV[0], e);
00149         col.mV[1] = gFastLn.pow(col.mV[1], e);
00150         col.mV[2] = gFastLn.pow(col.mV[2], e);
00151 }
00152 
00153 inline LLColor3 color_norm(const LLColor3 &col)
00154 {
00155         const F32 m = color_max(col);
00156         if (m > 1.f)
00157         {
00158                 return 1.f/m * col;
00159         }
00160         else return col;
00161 }
00162 
00163 inline LLColor3 color_norm_fog(const LLColor3 &col)
00164 {
00165         const F32 m = color_max(col);
00166         if (m > 0.75f)
00167         {
00168                 return 0.75f/m * col;
00169         }
00170         else return col;
00171 }
00172 
00173 
00174 inline LLColor4 color_norm_abs(const LLColor4 &col)
00175 {
00176         const F32 m = color_max(col);
00177         if (m > 1e-6)
00178         {
00179                 return 1.f/m * col;
00180         }
00181         else
00182         {
00183                 return col;
00184         }
00185 }
00186 
00187 
00188 inline F32 color_intens ( const LLColor4 &col )
00189 {
00190         return col.mV[0] + col.mV[1] + col.mV[2];
00191 }
00192 
00193 
00194 inline F32 color_avg ( const LLColor3 &col )
00195 {
00196         return color_intens(col) / 3.f;
00197 }
00198 
00199 inline void color_gamma_correct(LLColor3 &col)
00200 {
00201         const F32 gamma_inv = 1.f/1.2f;
00202         if (col.mV[0] != 0.f)
00203         {
00204                 col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
00205         }
00206         if (col.mV[1] != 0.f)
00207         {
00208                 col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
00209         }
00210         if (col.mV[2] != 0.f)
00211         {
00212                 col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
00213         }
00214 }
00215 
00216 inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply = FALSE);
00217 inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply)
00218 { 
00219         const F32 intens = color_intens(col);
00220         F32 factor = 1;
00221         if (0 == intens)
00222         {
00223                 return 0;
00224         }
00225 
00226         if (intens < min_intens)
00227         {
00228                 factor = min_intens / intens;
00229                 if (postmultiply)
00230                         col *= factor;
00231         }
00232         return factor;
00233 }
00234 
00235 inline LLVector3 move_vec(const LLVector3& v, const F32 cos_max_angle)
00236 {
00237         LLVector3 v_norm = v;
00238         v_norm.normVec();
00239 
00240         LLVector2 v_norm_proj(v_norm.mV[0], v_norm.mV[1]);
00241         const F32 projection2 = v_norm_proj.magVecSquared();
00242         const F32 scale = sqrt((1 - cos_max_angle * cos_max_angle) / projection2);
00243         return LLVector3(scale * v_norm_proj.mV[0], scale * v_norm_proj.mV[1], cos_max_angle);
00244 }
00245 
00246 
00247 /***************************************
00248                 Transparency Map
00249 ***************************************/
00250 
00251 void LLTranspMap::init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze)
00252 {
00253         mHaze = haze;
00254         mAtmHeight = h;
00255         mElevation = elev;
00256         mStep = step;
00257         mStepInv = 1.f / step;
00258         F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mElevation);
00259         mCosMaxAngle = -sqrt(1 - sin_angle * sin_angle);
00260         mMapSize = S32(ceil((1 - mCosMaxAngle) * mStepInv + 1) + 0.5);
00261         delete mT;
00262         mT = new LLColor3[mMapSize];
00263 
00264         for (S32 i = 0; i < mMapSize; ++i)
00265         {
00266                 const F32 cos_a = 1 - i*mStep;
00267                 const LLVector3 dir(0, sqrt(1-cos_a*cos_a), cos_a);
00268                 mT[i] = calcAirTranspDir(mElevation, dir);
00269         }
00270 }
00271 
00272 
00273 
00274 LLColor3 LLTranspMap::calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const
00275 {
00276         LLColor3 opt_depth(0, 0, 0);
00277         const LLVector3 point(0, 0, EARTH_RADIUS + elevation);
00278         F32 dist = -dir * point;
00279         LLVector3 cur_point;
00280         S32 s;
00281 
00282         if (dist > 0)
00283         {
00284                 cur_point = point + dist * dir;
00285 //              const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS;
00286 //              const F32 e_pow_k = LL_FAST_EXP(K);
00287                 const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS );
00288                 F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
00289 
00290                 for (s = 0; s < NO_STEPS; ++s)
00291                 {
00292                         const F32 h = cur_point.magVec() - EARTH_RADIUS;
00293                         step *= e_pow_k;
00294                         opt_depth += calcSigExt(h) * step;
00295                         cur_point -= dir * step;
00296                 }
00297                 opt_depth *= 2;
00298                 cur_point = point + 2 * dist * dir;
00299         }
00300         else
00301         {
00302                 cur_point = point;
00303         }
00304 
00305         dist = hitsAtmEdge(cur_point, dir);
00306 //      const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS;
00307 //      const F32 e_pow_k = LL_FAST_EXP(K);
00308         const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS );
00309         F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
00310 
00311         for (s = 0; s < NO_STEPS; ++s)
00312         {
00313                 const F32 h = cur_point.magVec() - EARTH_RADIUS;
00314                 step *= e_pow_k;
00315                 opt_depth += calcSigExt(h) * step;
00316                 cur_point += dir * step;
00317         }
00318 
00319         opt_depth *= -4.0f*F_PI;
00320         opt_depth.exp();
00321         return opt_depth;
00322 }
00323 
00324 
00325 
00326 F32 LLTranspMap::hitsAtmEdge(const LLVector3& X, const LLVector3& dir) const
00327 {
00328         const F32 tca = -dir * X;
00329         const F32 R = EARTH_RADIUS + mAtmHeight;
00330         const F32 thc2 = R * R - X.magVecSquared() + tca * tca;
00331         return tca + sqrt ( thc2 );
00332 }
00333 
00334 
00335 
00336 
00337 
00338 void LLTranspMapSet::init(const S32 size, const F32 first_step, const F32 media_height, const LLHaze* const haze)
00339 {
00340         const F32 angle_step = 0.005f;
00341         mSize = size;
00342         mMediaHeight = media_height;
00343 
00344         delete[] mTransp;
00345         mTransp = new LLTranspMap[mSize];
00346 
00347         delete[] mHeights;
00348         mHeights = new F32[mSize];
00349 
00350         F32 h = 0;
00351         mHeights[0] = h;
00352         mTransp[0].init(h, angle_step, mMediaHeight, haze);     
00353         const F32 K = log(mMediaHeight / first_step + 1) / (mSize - 1);
00354         const F32 e_pow_k = exp(K);
00355         F32 step = first_step * (e_pow_k - 1);
00356 
00357         for (S32 s = 1; s < mSize; ++s)
00358         {
00359                 h += step;
00360                 mHeights[s] = h;
00361                 mTransp[s].init(h, angle_step, mMediaHeight, haze);
00362                 step *= e_pow_k;
00363         }
00364 }
00365 
00366 LLTranspMapSet::~LLTranspMapSet()
00367 {
00368         delete[] mTransp;
00369         mTransp = NULL;
00370         delete[] mHeights;
00371         mHeights = NULL;
00372 }
00373 
00374 
00375 
00376 /***************************************
00377                 SkyTex
00378 ***************************************/
00379 
00380 S32 LLSkyTex::sComponents = 4;
00381 S32 LLSkyTex::sResolution = 64;
00382 F32     LLSkyTex::sInterpVal = 0.f;
00383 S32 LLSkyTex::sCurrent = 0;
00384 
00385 
00386 LLSkyTex::LLSkyTex()
00387 {
00388 }
00389 
00390 void LLSkyTex::init()
00391 {
00392         mSkyData = new LLColor3[sResolution * sResolution];
00393         mSkyDirs = new LLVector3[sResolution * sResolution];
00394 
00395         for (S32 i = 0; i < 2; ++i)
00396         {
00397                 mImageGL[i] = new LLImageGL(FALSE);
00398                 mImageGL[i]->setClamp(TRUE, TRUE);
00399                 mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents);
00400                 
00401                 initEmpty(i);
00402         }
00403 }
00404 
00405 void LLSkyTex::cleanupGL()
00406 {
00407         mImageGL[0] = NULL;
00408         mImageGL[1] = NULL;
00409 }
00410 
00411 void LLSkyTex::restoreGL()
00412 {
00413         for (S32 i = 0; i < 2; i++)
00414         {
00415                 mImageGL[i] = new LLImageGL(FALSE);
00416                 mImageGL[i]->setClamp(TRUE, TRUE);
00417         }
00418 }
00419 
00420 LLSkyTex::~LLSkyTex()
00421 {
00422         delete[] mSkyData;
00423         mSkyData = NULL;
00424 
00425         delete[] mSkyDirs;
00426         mSkyDirs = NULL;
00427 }
00428 
00429 
00430 void LLSkyTex::initEmpty(const S32 tex)
00431 {
00432         U8* data = mImageRaw[tex]->getData();
00433         for (S32 i = 0; i < sResolution; ++i)
00434         {
00435                 for (S32 j = 0; j < sResolution; ++j)
00436                 {
00437                         const S32 basic_offset = (i * sResolution + j);
00438                         S32 offset = basic_offset * sComponents;
00439                         data[offset] = 0;
00440                         data[offset+1] = 0;
00441                         data[offset+2] = 0;
00442                         data[offset+3] = 255;
00443 
00444                         mSkyData[basic_offset].setToBlack();
00445                 }
00446         }
00447 
00448         createGLImage(tex);
00449 }
00450 
00451 
00452 void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt)
00453 {
00454         U8* data = mImageRaw[sCurrent]->getData();
00455         for (S32 i = 0; i < sResolution; ++i)
00456         {
00457                 for (S32 j = 0; j < sResolution; ++j)
00458                 {
00459                         const S32 basic_offset = (i * sResolution + j);
00460                         S32 offset = basic_offset * sComponents;
00461                         LLColor3 col(mSkyData[basic_offset]);
00462                         if (getDir(i, j).mV[VZ] >= -0.02f) {
00463                                 col += 0.1f * multiscatt;
00464                                 col *= brightness_scale;
00465                                 col.clamp();
00466                                 color_gamma_correct(col);
00467                         }
00468                         
00469                         U32* pix = (U32*)(data + offset);
00470                         LLColor4 temp = LLColor4(col, 0);
00471                         LLColor4U temp1 = LLColor4U(temp);
00472                         *pix = temp1.mAll;
00473                 }
00474         }
00475         createGLImage(sCurrent);
00476 }
00477 
00478 void LLSkyTex::createGLImage(S32 which)
00479 {       
00480         mImageGL[which]->createGLTexture(0, mImageRaw[which]);
00481         mImageGL[which]->setClamp(TRUE, TRUE);
00482 }
00483 
00484 void LLSkyTex::bindTexture(BOOL curr)
00485 {
00486         mImageGL[getWhich(curr)]->bind();
00487 }
00488 
00489 /***************************************
00490                 Sky
00491 ***************************************/
00492 
00493 F32     LLHeavenBody::sInterpVal = 0;
00494 
00495 F32 LLVOSky::sNighttimeBrightness = 1.5f;
00496 
00497 S32 LLVOSky::sResolution = LLSkyTex::getResolution();
00498 S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
00499 S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
00500 
00501 LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00502 :       LLStaticViewerObject(id, pcode, regionp),
00503         mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
00504         mBrightnessScale(1.f),
00505         mBrightnessScaleNew(0.f),
00506         mBrightnessScaleGuess(1.f),
00507         mWeatherChange(FALSE),
00508         mCloudDensity(0.2f),
00509         mWind(0.f),
00510         mForceUpdate(FALSE),
00511         mWorldScale(1.f)
00512 {
00513         mInitialized = FALSE;
00514         mbCanSelect = FALSE;
00515         mUpdateTimer.reset();
00516 
00517         for (S32 i = 0; i < 6; i++)
00518         {
00519                 mSkyTex[i].init();
00520         }
00521         for (S32 i=0; i<FACE_COUNT; i++)
00522         {
00523                 mFace[i] = NULL;
00524         }
00525         
00526         mCameraPosAgent = gAgent.getCameraPositionAgent();
00527         mAtmHeight = ATM_HEIGHT;
00528         mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
00529         updateHaze();
00530 
00531         mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition");
00532         if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
00533         {
00534                 initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
00535         }
00536         mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
00537         mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
00538         mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
00539         mFogColor.mV[VALPHA] = 0.0f;
00540         mFogRatio = 1.2f;
00541 
00542         mSun.setIntensity(SUN_INTENSITY);
00543         mMoon.setIntensity(0.1f * SUN_INTENSITY);
00544 
00545         mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
00546         mSunTexturep->setClamp(TRUE, TRUE);
00547         mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
00548         mMoonTexturep->setClamp(TRUE, TRUE);
00549         mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
00550         mBloomTexturep->setClamp(TRUE, TRUE);
00551 }
00552 
00553 
00554 LLVOSky::~LLVOSky()
00555 {
00556         // Don't delete images - it'll get deleted by gImageList on shutdown
00557         // This needs to be done for each texture
00558 
00559         mCubeMap = NULL;
00560 }
00561 
00562 void LLVOSky::initClass()
00563 {
00564         LLHaze::initClass();
00565 }
00566 
00567 
00568 void LLVOSky::init()
00569 {
00570     // index of refraction calculation.
00571         mTransp.init(NO_STEPS+1+4, FIRST_STEP, mAtmHeight, &mHaze);
00572 
00573         const F32 haze_int = color_intens(mHaze.calcSigSca(0));
00574         mHazeConcentration = haze_int /
00575                 (color_intens(LLHaze::calcAirSca(0)) + haze_int);
00576 
00577         mBrightnessScaleNew = 0;
00578 
00579         // Initialize the cached normalized direction vectors
00580         for (S32 side = 0; side < 6; ++side)
00581         {
00582                 for (S32 tile = 0; tile < NUM_TILES; ++tile)
00583                 {
00584                         initSkyTextureDirs(side, tile);
00585                         createSkyTexture(side, tile);
00586                 }
00587         }
00588 
00589         calcBrightnessScaleAndColors();
00590         initCubeMap();
00591 }
00592 
00593 void LLVOSky::initCubeMap() 
00594 {
00595         std::vector<LLPointer<LLImageRaw> > images;
00596         for (S32 side = 0; side < 6; side++)
00597         {
00598                 images.push_back(mSkyTex[side].getImageRaw());
00599         }
00600         if (mCubeMap)
00601         {
00602                 mCubeMap->init(images);
00603         }
00604         else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && gFeatureManagerp->isFeatureAvailable("RenderCubeMap"))
00605         {
00606                 mCubeMap = new LLCubeMap();
00607                 mCubeMap->init(images);
00608         }
00609 }
00610 
00611 
00612 void LLVOSky::cleanupGL()
00613 {
00614         S32 i;
00615         for (i = 0; i < 6; i++)
00616         {
00617                 mSkyTex[i].cleanupGL();
00618         }
00619         if (getCubeMap())
00620         {
00621                 getCubeMap()->destroyGL();
00622         }
00623 }
00624 
00625 void LLVOSky::restoreGL()
00626 {
00627         S32 i;
00628         for (i = 0; i < 6; i++)
00629         {
00630                 mSkyTex[i].restoreGL();
00631         }
00632         mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
00633         mSunTexturep->setClamp(TRUE, TRUE);
00634         mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
00635         mMoonTexturep->setClamp(TRUE, TRUE);
00636         mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
00637         mBloomTexturep->setClamp(TRUE, TRUE);
00638 
00639         calcBrightnessScaleAndColors();
00640 
00641         if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
00642             && gFeatureManagerp->isFeatureAvailable("RenderCubeMap"))
00643         {
00644                 LLCubeMap* cube_map = getCubeMap();
00645 
00646                 std::vector<LLPointer<LLImageRaw> > images;
00647                 for (S32 side = 0; side < 6; side++)
00648                 {
00649                         images.push_back(mSkyTex[side].getImageRaw());
00650                 }
00651 
00652                 if(cube_map)
00653                 {
00654                         cube_map->init(images);
00655                         mForceUpdate = TRUE;
00656                 }
00657         }
00658 
00659         if (mDrawable)
00660         {
00661                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00662         }
00663 
00664 }
00665 
00666 
00667 void LLVOSky::updateHaze()
00668 {
00669         static LLRandLagFib607 weather_generator(LLUUID::getRandomSeed());
00670         if (gSavedSettings.getBOOL("FixedWeather"))
00671         {
00672                 weather_generator.seed(8008135);
00673         }
00674 
00675         const F32 fo_upper_bound = 5;
00676         const F32 sca_upper_bound = 6;
00677         const F32 fo = 1 + (F32)weather_generator() *(fo_upper_bound - 1);
00678         const static F32 upper = 0.5f / gFastLn.ln(fo_upper_bound);
00679         mHaze.setFalloff(fo);
00680         mHaze.setG((F32)weather_generator() * (0.0f + upper * gFastLn.ln(fo)));
00681         LLColor3 sca;
00682         const F32 cd = mCloudDensity * 3;
00683         F32 min_r = cd - 1;
00684         if (min_r < 0)
00685         {
00686                 min_r = 0;
00687         }
00688         F32 max_r = cd + 1;
00689         if (max_r > sca_upper_bound)
00690         {
00691                 max_r = sca_upper_bound;
00692         }
00693 
00694         sca.mV[0] = min_r + (F32)weather_generator() * (max_r - min_r);
00695 
00696         min_r = sca.mV[0] - 0.1f;
00697         if (min_r < 0)
00698         {
00699                 min_r = 0;
00700         }
00701         max_r = sca.mV[0] + 0.5f;
00702         if (max_r > sca_upper_bound)
00703         {
00704                 max_r = sca_upper_bound;
00705         }
00706 
00707         sca.mV[1] = min_r + (F32)weather_generator() * (max_r - min_r);
00708 
00709         min_r = sca.mV[1];
00710         if (min_r < 0)
00711         {
00712                 min_r = 0;
00713         }
00714         max_r = sca.mV[1] + 1;
00715         if (max_r > sca_upper_bound)
00716         {
00717                 max_r = sca_upper_bound;
00718         }
00719 
00720         sca.mV[2] = min_r + (F32)weather_generator() * (max_r - min_r);
00721 
00722         sca = AIR_SCA_AVG * sca;
00723 
00724         mHaze.setSigSca(sca);
00725 }
00726 
00727 void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
00728 {
00729         S32 tile_x = tile % NUM_TILES_X;
00730         S32 tile_y = tile / NUM_TILES_X;
00731 
00732         S32 tile_x_pos = tile_x * sTileResX;
00733         S32 tile_y_pos = tile_y * sTileResY;
00734 
00735         F32 coeff[3] = {0, 0, 0};
00736         const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
00737         const S32 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
00738         const S32 x_coef = (curr_coef + 1) % 3;
00739         const S32 y_coef = (x_coef + 1) % 3;
00740 
00741         coeff[curr_coef] = (F32)side_dir;
00742 
00743         F32 inv_res = 1.f/sResolution;
00744         S32 x, y;
00745         for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
00746         {
00747                 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
00748                 {
00749                         coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f;
00750                         coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f;
00751                         LLVector3 dir(coeff[0], coeff[1], coeff[2]);
00752                         dir.normVec();
00753                         mSkyTex[side].setDir(dir, x, y);
00754                 }
00755         }
00756 }
00757 
00758 void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
00759 {
00760         S32 tile_x = tile % NUM_TILES_X;
00761         S32 tile_y = tile / NUM_TILES_X;
00762 
00763         S32 tile_x_pos = tile_x * sTileResX;
00764         S32 tile_y_pos = tile_y * sTileResY;
00765 
00766         S32 x, y;
00767         for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
00768         {
00769                 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
00770                 {
00771                         mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y);
00772                 }
00773         }
00774 }
00775 
00776 
00777 LLColor3 LLVOSky::calcSkyColorInDir(const LLVector3 &dir)
00778 {
00779         LLColor3 col, transp;
00780 
00781         if (dir.mV[VZ] < -0.02f)
00782         {
00783                 col = LLColor3(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.27f));
00784                 float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
00785                 x *= x;
00786                 col.mV[0] *= x*x;
00787                 col.mV[1] *= powf(x, 2.5f);
00788                 col.mV[2] *= x*x*x;
00789                 return col;
00790         }
00791 
00792 
00793         calcSkyColorInDir(col, transp, dir);
00794         F32 br = color_max(col);
00795         if (br > mBrightnessScaleNew)
00796         {
00797                 mBrightnessScaleNew = br;
00798                 mBrightestPointNew = col;
00799         }
00800         return col;
00801 }
00802 
00803 
00804 LLColor4 LLVOSky::calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exager = 1) const
00805 {
00806         LLColor3 col, tr;
00807         calcInScatter(col, tr, point, exager);
00808         col *= mBrightnessScaleGuess;
00809         transp = LLColor4(tr);
00810         return LLColor4(col);
00811 }
00812 
00813 
00814 
00815 void LLVOSky::calcSkyColorInDir(LLColor3& res, LLColor3& transp, const LLVector3& dir) const
00816 {
00817         const LLVector3& tosun = getToSunLast();
00818         res.setToBlack();
00819         LLColor3 haze_res(0.f, 0.f, 0.f);
00820         transp.setToWhite();
00821         LLVector3 step_v ;
00822         LLVector3 cur_pos = mCameraPosAgent;
00823         F32 h;
00824 
00825         F32 dist = calcHitsAtmEdge(mCameraPosAgent, dir);
00826 //      const F32 K = log(dist / FIRST_STEP + 1) / NO_STEPS;
00827         const F32 K = gFastLn.ln(dist / FIRST_STEP + 1) / NO_STEPS;
00828         const F32 e_pow_k = (F32)LL_FAST_EXP(K);
00829         F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
00830 
00831         // Initialize outside the loop because we write into them every iteration. JC
00832         LLColor3 air_sca_opt_depth;
00833         LLColor3 haze_sca_opt_depth;
00834         LLColor3 air_transp;
00835 
00836         for (S32 s = 0; s < NO_STEPS; ++s)
00837         {
00838                 h = calcHeight(cur_pos);
00839                 step *= e_pow_k;
00840                 LLHaze::calcAirSca(h, air_sca_opt_depth);
00841                 air_sca_opt_depth *= step;
00842 
00843                 mHaze.calcSigSca(h, haze_sca_opt_depth);
00844                 haze_sca_opt_depth *= step;
00845 
00846                 LLColor3 haze_ext_opt_depth = haze_sca_opt_depth;
00847                 haze_ext_opt_depth *= (1.f + mHaze.getAbsCoef());
00848 
00849                 if (calcHitsEarth(cur_pos, tosun) < 0) // calculates amount of in-scattered light from the sun
00850                 {
00851                         //visibility check is too expensive
00852                         mTransp.calcTransp(calcUpVec(cur_pos) * tosun, h, air_transp);
00853                         air_transp *= transp;
00854                         res += air_sca_opt_depth * air_transp;
00855                         haze_res += haze_sca_opt_depth * air_transp;
00856                 }
00857                 LLColor3 temp(-4.f * F_PI * (air_sca_opt_depth + haze_ext_opt_depth));
00858                 temp.exp();
00859                 transp *= temp;
00860                 step_v = dir * step;
00861                 cur_pos += step_v;
00862         }
00863         const F32 cos_dir = dir * tosun;
00864         res *= calcAirPhaseFunc(cos_dir);
00865         res += haze_res * mHaze.calcPhase(cos_dir);
00866         res *= mSun.getIntensity();
00867 }
00868 
00869 
00870 
00871 
00872 void LLVOSky::calcInScatter(LLColor3& res, LLColor3& transp, 
00873                                         const LLVector3& P, const F32 exaggeration) const
00874 {
00875         const LLVector3& tosun = getToSunLast();
00876         res.setToBlack();
00877         transp.setToWhite();
00878 
00879         LLVector3 lower, upper;
00880         LLVector3 dir = P - mCameraPosAgent;
00881 
00882         F32 dist = exaggeration * dir.normVec();
00883 
00884         const F32 cos_dir = dir * tosun;
00885 
00886         if (dir.mV[VZ] > 0)
00887         {
00888                 lower = mCameraPosAgent;
00889                 upper = P;
00890         }
00891         else
00892         {
00893                 lower = P;
00894                 upper = mCameraPosAgent;
00895                 dir = -dir;
00896         }
00897 
00898         const F32 lower_h = calcHeight(lower);
00899         const F32 upper_h = calcHeight(upper);
00900         const LLVector3 up_upper = calcUpVec(upper);
00901         const LLVector3 up_lower = calcUpVec(lower);
00902 
00903         transp = color_div(mTransp.calcTransp(up_lower * dir, lower_h),
00904                                         mTransp.calcTransp(up_upper * dir, upper_h));
00905         color_pow(transp, exaggeration);
00906 
00907         if (calcHitsEarth(upper, tosun) > 0)
00908         {
00909                 const F32 avg = color_avg(transp);
00910                 //const F32 avg = llmin(1.f, 1.2f * color_avg(transp));
00911                 transp.setVec(avg, avg, avg);
00912                 return;
00913         }
00914 
00915         LLColor3 air_sca_opt_depth = LLHaze::calcAirSca(upper_h);
00916         LLColor3 haze_sca_opt_depth = mHaze.calcSigSca(upper_h);
00917         LLColor3 sun_transp;
00918         mTransp.calcTransp(up_upper * tosun, upper_h, sun_transp);
00919 
00920         if (calcHitsEarth(lower, tosun) < 0)
00921         {
00922                 air_sca_opt_depth += LLHaze::calcAirSca(lower_h);
00923                 air_sca_opt_depth *= 0.5;
00924                 haze_sca_opt_depth += mHaze.calcSigSca(lower_h);
00925                 haze_sca_opt_depth *= 0.5;
00926                 sun_transp += mTransp.calcTransp(up_lower * tosun, lower_h);
00927                 sun_transp *= 0.5;
00928         }
00929 
00930         res = calcAirPhaseFunc(cos_dir) * air_sca_opt_depth;
00931         res += mHaze.calcPhase(cos_dir) * haze_sca_opt_depth;
00932         res = mSun.getIntensity() * dist * sun_transp * res;
00933 }
00934 
00935 
00936 
00937 
00938 
00939 
00940 F32 LLVOSky::calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const
00941 {
00942         const LLVector3 from_earth_center = mEarthCenter - orig;
00943         const F32 tca = dir * from_earth_center;
00944         if ( tca < 0 )
00945         {
00946                 return -1;
00947         }
00948 
00949         const F32 thc2 = EARTH_RADIUS * EARTH_RADIUS -
00950                         from_earth_center.magVecSquared() + tca * tca;
00951         if (thc2 < 0 )
00952         {
00953                 return -1;
00954         }
00955 
00956         return tca - sqrt ( thc2 );
00957 }
00958 
00959 F32 LLVOSky::calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const
00960 {
00961         const LLVector3 from_earth_center = mEarthCenter - orig;
00962         const F32 tca = dir * from_earth_center;
00963 
00964         const F32 thc2 = (EARTH_RADIUS + mAtmHeight) * (EARTH_RADIUS + mAtmHeight) -
00965                         from_earth_center.magVecSquared() + tca * tca;
00966         return tca + sqrt(thc2);
00967 }
00968 
00969 
00970 void LLVOSky::updateBrightestDir()
00971 {
00972         LLColor3 br_pt, transp;
00973         const S32 test_no = 5;
00974         const F32 step = F_PI_BY_TWO / (test_no + 1);
00975         for (S32 i = 0; i < test_no; ++i)
00976         {
00977                 F32 cos_dir = cos ((i + 1) * step);
00978                 calcSkyColorInDir(br_pt, transp, move_vec(getToSunLast(), cos_dir));
00979                 const F32 br = color_max(br_pt);
00980                 if (br > mBrightnessScaleGuess)
00981                 {
00982                         mBrightnessScaleGuess = br;
00983                         mBrightestPointGuess = br_pt;
00984                 }
00985         }
00986 }
00987 
00988 
00989 void LLVOSky::calcBrightnessScaleAndColors()
00990 {
00991         // new correct normalization.
00992         if (mBrightnessScaleNew < 1e-7)
00993         {
00994                 mBrightnessScale = 1;
00995                 mBrightestPoint.setToBlack();
00996         }
00997         else
00998         {
00999                 mBrightnessScale = 1.f/mBrightnessScaleNew;
01000                 mBrightestPoint = mBrightestPointNew;
01001         }
01002 
01003         mBrightnessScaleNew = 0;
01004         // and addition
01005 
01006         // Calculate Sun and Moon color
01007         const F32 h = llmax(0.0f, mCameraPosAgent.mV[2]);
01008         const LLColor3 sun_color = mSun.getIntensity() * mTransp.calcTransp(getToSunLast().mV[2], h);
01009         const LLColor3 moon_color = mNightColorShift * 
01010                                 mMoon.getIntensity() * mTransp.calcTransp(getToMoonLast().mV[2], h);
01011 
01012         F32 intens = color_intens(sun_color);
01013         F32 increase_sun_br = (intens > 0) ? 1.2f * color_intens(mBrightestPoint) / intens : 1;
01014 
01015         intens = color_intens(moon_color);
01016         F32 increase_moon_br = (intens > 0) ? 1.2f * llmax(1.0f, color_intens(mBrightestPoint) / intens) : 1;
01017 
01018         mSun.setColor(mBrightnessScale * increase_sun_br * sun_color);
01019         mMoon.setColor(mBrightnessScale * increase_moon_br * moon_color);
01020 
01021         const LLColor3 haze_col = color_norm_abs(mHaze.getSigSca());
01022         for (S32 i = 0; i < 6; ++i)
01023         {
01024                 mSkyTex[i].create(mBrightnessScale, mHazeConcentration * mBrightestPoint * haze_col);
01025         }
01026 
01027         mBrightnessScaleGuess = mBrightnessScale;
01028         mBrightestPointGuess = mBrightestPoint;
01029 
01030 //      calculateColors(); // MSMSM Moving this down to before generateScatterMap(), per Milo Lindens suggestion, to fix orange flashing bug.
01031 
01032         mSun.renewDirection();
01033         mSun.renewColor();
01034         mMoon.renewDirection();
01035         mMoon.renewColor();
01036 
01037         LLColor3 transp;
01038 
01039         if (calcHitsEarth(mCameraPosAgent, getToSunLast()) < 0)
01040         {
01041                 calcSkyColorInDir(mBrightestPointGuess, transp, getToSunLast());
01042                 mBrightnessScaleGuess = color_max(mBrightestPointGuess);
01043                 updateBrightestDir();
01044                 mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess);
01045         }
01046         else if (getToSunLast().mV[2] > -0.5)
01047         {
01048                 const LLVector3 almost_to_sun = toHorizon(getToSunLast());
01049                 calcSkyColorInDir(mBrightestPointGuess, transp, almost_to_sun);
01050                 mBrightnessScaleGuess = color_max(mBrightestPointGuess);
01051                 updateBrightestDir();
01052                 mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess);
01053         }
01054         else
01055         {
01056                 mBrightestPointGuess.setToBlack();
01057                 mBrightnessScaleGuess = 1;
01058         }
01059 
01060         calculateColors(); // MSMSM Moved this down here per Milo Lindens suggestion, to fix orange flashing bug at sunset.
01061 }
01062 
01063 
01064 void LLVOSky::calculateColors()
01065 {
01066         const F32 h = -0.1f;
01067         const LLVector3& tosun = getToSunLast();
01068 
01069         F32 full_on, full_off, on, on_cl;
01070         F32 sun_factor = 1;
01071         
01072         // Sun Diffuse
01073         F32 sun_height = tosun.mV[2];
01074 
01075         if (sun_height <= 0.0)
01076                 sun_height = 0.0;
01077         
01078         mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(sun_height, h);
01079 
01080         mSunDiffuse = 1.0f * color_norm(mSunDiffuse);
01081 
01082         // Sun Ambient
01083         full_off = -0.3f;
01084         full_on = -0.03f;
01085         if (tosun.mV[2] < full_off)
01086         {
01087                 mSunAmbient.setToBlack();
01088         }
01089         else
01090         {
01091                 on = (tosun.mV[2] - full_off) / (full_on - full_off);
01092                 sun_factor = llmax(0.0f, llmin(on, 1.0f));
01093 
01094                 LLColor3 sun_amb = mAmbientScale * (0.8f * mSunDiffuse + 
01095                                         0.2f * mBrightnessScaleGuess * mBrightestPointGuess);
01096 
01097                 color_norm_pow(sun_amb, 0.1f, TRUE);
01098                 sun_factor *= min_intens_factor(sun_amb, 1.9f);
01099                 mSunAmbient = LLColor4(sun_factor * sun_amb);
01100         }
01101 
01102 
01103         // Moon Diffuse
01104         full_on = 0.3f;
01105         full_off = 0.01f;
01106         if (getToMoonLast().mV[2] < full_off)
01107         {
01108                 mMoonDiffuse.setToBlack();
01109         }
01110         else
01111         {
01112                 // Steve: Added moonlight diffuse factor scalar (was constant .3)
01113                 F32 diffuse_factor = .1f + sNighttimeBrightness * .2f; // [.1, .5] default = .3
01114                 on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off);
01115                 on_cl = llmin(on, 1.0f);
01116                 mMoonDiffuse = on_cl * mNightColorShift * diffuse_factor;
01117         }
01118 
01119         // Moon Ambient
01120 
01121         F32 moon_amb_factor = 1.f;
01122 
01123         if (gAgent.inPrelude())
01124         {
01125                 moon_amb_factor *= 2.0f;
01126         }
01127 
01128         full_on = 0.30f;
01129         full_off = 0.01f;
01130         if (getToMoonLast().mV[2] < full_off)
01131         {
01132                 mMoonAmbient.setToBlack();
01133         }
01134         else
01135         {
01136                 on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off);
01137                 on_cl = llmax(0.0f, llmin(on, 1.0f));
01138                 mMoonAmbient = on_cl * moon_amb_factor * mMoonDiffuse;
01139         }
01140 
01141 
01142         // Sun Diffuse
01143         full_off = -0.05f;
01144         full_on = -0.00f;
01145         if (tosun.mV[2] < full_off)
01146         {
01147                 mSunDiffuse.setToBlack();
01148         }
01149         else
01150         {
01151                 on = (getToSunLast().mV[2] - full_off) / (full_on - full_off);
01152                 sun_factor = llmax(0.0f, llmin(on, 1.0f));
01153 
01154                 color_norm_pow(mSunDiffuse, 0.12f, TRUE);
01155                 sun_factor *= min_intens_factor(mSunDiffuse, 2.1f);
01156                 mSunDiffuse *= sun_factor;
01157         }
01158 
01159 
01160         mTotalAmbient = mSunAmbient + mMoonAmbient;
01161         mTotalAmbient.setAlpha(1);
01162         //llinfos << "MoonDiffuse: " << mMoonDiffuse << llendl;
01163         //llinfos << "TotalAmbient: " << mTotalAmbient << llendl;
01164 
01165         mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
01166         mFadeColor.setAlpha(0);
01167 }
01168 
01169 
01170 BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
01171 {
01172         return TRUE;
01173 }
01174 
01175 BOOL LLVOSky::updateSky()
01176 {
01177         if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
01178         {
01179                 return TRUE;
01180         }
01181         
01182         if (mDead)
01183         {
01184                 // It's dead.  Don't update it.
01185                 return TRUE;
01186         }
01187         if (gGLManager.mIsDisabled)
01188         {
01189                 return TRUE;
01190         }
01191 
01192         static S32 next_frame = 0;
01193         const S32 total_no_tiles = 6 * NUM_TILES;
01194         const S32 cycle_frame_no = total_no_tiles + 1;
01195 
01196 //      if (mUpdateTimer.getElapsedTimeF32() > 0.1f)
01197         {
01198                 mUpdateTimer.reset();
01199                 const S32 frame = next_frame;
01200 
01201                 ++next_frame;
01202                 next_frame = next_frame % cycle_frame_no;
01203 
01204                 sInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
01205                 LLSkyTex::setInterpVal( sInterpVal );
01206                 LLHeavenBody::setInterpVal( sInterpVal );
01207                 calculateColors();
01208                 if (mForceUpdate || total_no_tiles == frame)
01209                 {
01210                         calcBrightnessScaleAndColors();
01211                         LLSkyTex::stepCurrent();
01212                         
01213                         const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f);
01214                         const static F32 COLOR_CHANGE_THRESHOLD = 0.01f;
01215 
01216                         LLVector3 direction = mSun.getDirection();
01217                         direction.normVec();
01218                         const F32 dot_lighting = direction * mLastLightingDirection;
01219 
01220                         LLColor3 delta_color;
01221                         delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0],
01222                                                            mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1],
01223                                                            mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
01224 
01225                         if ( mForceUpdate 
01226                                  || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
01227                                  || (delta_color.magVec() > COLOR_CHANGE_THRESHOLD)
01228                                  || !mInitialized)
01229                                 && !direction.isExactlyZero())
01230                         {
01231                                 mLastLightingDirection = direction;
01232                                 mLastTotalAmbient = mTotalAmbient;
01233                                 mInitialized = TRUE;
01234 
01235                                 if (mCubeMap)
01236                                 {
01237                     if (mForceUpdate)
01238                                         {
01239                                                 updateFog(gCamera->getFar());
01240                                                 for (int side = 0; side < 6; side++) 
01241                                                 {
01242                                                         for (int tile = 0; tile < NUM_TILES; tile++) 
01243                                                         {
01244                                                                 createSkyTexture(side, tile);
01245                                                         }
01246                                                 }
01247 
01248                                                 calcBrightnessScaleAndColors();
01249 
01250                                                 for (int side = 0; side < 6; side++) 
01251                                                 {
01252                                                         LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
01253                                                         LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
01254                                                         raw2->copy(raw1);
01255                                                         mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE));
01256                                                 }
01257                                                 next_frame = 0; 
01258                                         }
01259 
01260                                         std::vector<LLPointer<LLImageRaw> > images;
01261                                         for (S32 side = 0; side < 6; side++)
01262                                         {
01263                                                 images.push_back(mSkyTex[side].getImageRaw(FALSE));
01264                                         }
01265                                         mCubeMap->init(images);
01266                                 }
01267                         }
01268 
01269                         gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
01270                         gPipeline.markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
01271 
01272                         mForceUpdate = FALSE;
01273                 }
01274                 else
01275                 {
01276                         const S32 side = frame / NUM_TILES;
01277                         const S32 tile = frame % NUM_TILES;
01278                         createSkyTexture(side, tile);
01279                 }
01280         }
01281 
01282 
01283         if (mDrawable)
01284         {
01285                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
01286         }
01287         return TRUE;
01288 }
01289 
01290 
01291 void LLVOSky::updateTextures(LLAgent &agent)
01292 {
01293         if (mSunTexturep)
01294         {
01295                 mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01296                 mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01297                 mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
01298         }
01299 }
01300 
01301 LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
01302 {
01303         pipeline->allocDrawable(this);
01304         mDrawable->setLit(FALSE);
01305 
01306         LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
01307         poolp->setSkyTex(mSkyTex);
01308         poolp->setSun(&mSun);
01309         poolp->setMoon(&mMoon);
01310         mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
01311         
01312         for (S32 i = 0; i < 6; ++i)
01313         {
01314                 mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
01315         }
01316 
01317         mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
01318         mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
01319         mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
01320 
01321         return mDrawable;
01322 }
01323 
01324 BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
01325 {
01326         if (mFace[FACE_REFLECTION] == NULL)
01327         {
01328                 LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
01329                 mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
01330         }
01331 
01332         mCameraPosAgent = drawable->getPositionAgent();
01333         mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
01334         mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
01335 
01336         LLVector3 v_agent[8];
01337         for (S32 i = 0; i < 8; ++i)
01338         {
01339                 F32 x_sgn = (i&1) ? 1.f : -1.f;
01340                 F32 y_sgn = (i&2) ? 1.f : -1.f;
01341                 F32 z_sgn = (i&4) ? 1.f : -1.f;
01342                 v_agent[i] = HORIZON_DIST*0.25f * LLVector3(x_sgn, y_sgn, z_sgn);
01343         }
01344 
01345         LLStrider<LLVector3> verticesp;
01346         LLStrider<LLVector3> normalsp;
01347         LLStrider<LLVector2> texCoordsp;
01348         LLStrider<U32> indicesp;
01349         S32 index_offset;
01350         LLFace *face;   
01351 
01352         for (S32 side = 0; side < 6; ++side)
01353         {
01354                 face = mFace[FACE_SIDE0 + side]; 
01355 
01356                 if (face->mVertexBuffer.isNull())
01357                 {
01358                         face->setSize(4, 6);
01359                         face->setGeomIndex(0);
01360                         face->setIndicesIndex(0);
01361                         face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01362                         face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
01363                         
01364                         index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01365                         
01366                         S32 vtx = 0;
01367                         S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
01368                         S32 side_dir = side & 1;  // even - 0, odd - 1
01369                         S32 i_bit = (curr_bit + 2) % 3;
01370                         S32 j_bit = (i_bit + 2) % 3;
01371 
01372                         LLVector3 axis;
01373                         axis.mV[curr_bit] = 1;
01374                         face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
01375 
01376                         vtx = side_dir << curr_bit;
01377                         *(verticesp++)  = v_agent[vtx];
01378                         *(verticesp++)  = v_agent[vtx | 1 << j_bit];
01379                         *(verticesp++)  = v_agent[vtx | 1 << i_bit];
01380                         *(verticesp++)  = v_agent[vtx | 1 << i_bit | 1 << j_bit];
01381 
01382                         *(texCoordsp++) = TEX00;
01383                         *(texCoordsp++) = TEX01;
01384                         *(texCoordsp++) = TEX10;
01385                         *(texCoordsp++) = TEX11;
01386 
01387                         // Triangles for each side
01388                         *indicesp++ = index_offset + 0;
01389                         *indicesp++ = index_offset + 1;
01390                         *indicesp++ = index_offset + 3;
01391 
01392                         *indicesp++ = index_offset + 0;
01393                         *indicesp++ = index_offset + 3;
01394                         *indicesp++ = index_offset + 2;
01395                 }
01396         }
01397 
01398         const LLVector3 &look_at = gCamera->getAtAxis();
01399         LLVector3 right = look_at % LLVector3::z_axis;
01400         LLVector3 up = right % look_at;
01401         right.normVec();
01402         up.normVec();
01403 
01404         const static F32 elevation_factor = 0.0f/sResolution;
01405         const F32 cos_max_angle = cosHorizon(elevation_factor);
01406         mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right));
01407         mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right));
01408 
01409         const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
01410                 // gWorldPointer->getWaterHeight() + 0.01f;
01411         const F32 camera_height = mCameraPosAgent.mV[2];
01412         const F32 height_above_water = camera_height - water_height;
01413 
01414         BOOL sun_flag = FALSE;
01415 
01416         if (mSun.isVisible())
01417         {
01418                 if (mMoon.isVisible())
01419                 {
01420                         sun_flag = look_at * mSun.getDirection() > 0;
01421                 }
01422                 else
01423                 {
01424                         sun_flag = TRUE;
01425                 }
01426         }
01427         
01428         if (height_above_water > 0)
01429         {
01430 #if 1 //1.9.1
01431                 BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
01432 #else
01433                 BOOL render_ref = !(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= LLDrawPoolWater::SHADER_LEVEL_RIPPLE);
01434 #endif
01435                 if (sun_flag)
01436                 {
01437                         setDrawRefl(0);
01438                         if (render_ref)
01439                         {
01440                                 updateReflectionGeometry(drawable, height_above_water, mSun);
01441                         }
01442                 }
01443                 else
01444                 {
01445                         setDrawRefl(1);
01446                         if (render_ref)
01447                         {
01448                                 updateReflectionGeometry(drawable, height_above_water, mMoon);
01449                         }
01450                 }
01451         }
01452         else
01453         {
01454                 setDrawRefl(-1);
01455         }
01456 
01457 
01458         LLPipeline::sCompiles++;
01459         return TRUE;
01460 }
01461 
01462 
01463 BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun,
01464                                                                                  LLHeavenBody& hb, const F32 cos_max_angle,
01465                                                                                  const LLVector3 &up, const LLVector3 &right)
01466 {
01467         LLStrider<LLVector3> verticesp;
01468         LLStrider<LLVector3> normalsp;
01469         LLStrider<LLVector2> texCoordsp;
01470         LLStrider<U32> indicesp;
01471         S32 index_offset;
01472         LLFace *facep;
01473 
01474         LLVector3 to_dir = hb.getDirection();
01475         LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
01476 
01477 
01478         LLVector3 hb_right = to_dir % LLVector3::z_axis;
01479         LLVector3 hb_up = hb_right % to_dir;
01480         hb_right.normVec();
01481         hb_up.normVec();
01482 
01483         //const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees
01484         //const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right));
01485         //const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up);
01486 
01487         const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
01488         F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
01489         F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
01490 
01491         // Parameters for the water reflection
01492         hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right);
01493         hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up);
01494         // End of parameters for the water reflection
01495 
01496         const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
01497         const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
01498 
01499         //const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right;
01500         //const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//up;
01501         LLVector3 v_clipped[4];
01502 
01503         hb.corner(0) = draw_pos - scaled_right + scaled_up;
01504         hb.corner(1) = draw_pos - scaled_right - scaled_up;
01505         hb.corner(2) = draw_pos + scaled_right + scaled_up;
01506         hb.corner(3) = draw_pos + scaled_right - scaled_up;
01507 
01508 
01509         F32 t_left, t_right;
01510         if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle))
01511         {
01512                 hb.setVisible(FALSE);
01513                 return FALSE;
01514         }
01515         hb.setVisible(TRUE);
01516 
01517         facep = mFace[f]; 
01518 
01519         if (facep->mVertexBuffer.isNull())
01520         {
01521                 facep->setSize(4, 6);
01522                 facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01523                 facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
01524                 facep->setGeomIndex(0);
01525                 facep->setIndicesIndex(0);
01526         }
01527 
01528         index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01529         if (-1 == index_offset)
01530         {
01531                 return TRUE;
01532         }
01533 
01534         for (S32 vtx = 0; vtx < 4; ++vtx)
01535         {
01536                 hb.corner(vtx) = v_clipped[vtx];
01537                 *(verticesp++)  = hb.corner(vtx) + mCameraPosAgent;
01538         }
01539 
01540         *(texCoordsp++) = TEX01;
01541         *(texCoordsp++) = TEX00;
01542         //*(texCoordsp++) = (t_left > 0) ? LLVector2(0, t_left) : TEX00;
01543         *(texCoordsp++) = TEX11;
01544         *(texCoordsp++) = TEX10;
01545         //*(texCoordsp++) = (t_right > 0) ? LLVector2(1, t_right) : TEX10;
01546 
01547         *indicesp++ = index_offset + 0;
01548         *indicesp++ = index_offset + 2;
01549         *indicesp++ = index_offset + 1;
01550 
01551         *indicesp++ = index_offset + 1;
01552         *indicesp++ = index_offset + 2;
01553         *indicesp++ = index_offset + 3;
01554 
01555         if (is_sun)
01556         {
01557                 if ((t_left > 0) && (t_right > 0))
01558                 {
01559                         F32 t = (t_left + t_right) * 0.5f;
01560                         mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI)));
01561                 }
01562                 else
01563                 {
01564                         mSun.setHorizonVisibility();
01565                 }
01566                 updateSunHaloGeometry(drawable);
01567         }
01568 
01569         return TRUE;
01570 }
01571 
01572 
01573 
01574 
01575 // Clips quads with top and bottom sides parallel to horizon.
01576 
01577 BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
01578                                                   const LLVector3 v_corner[4], const F32 cos_max_angle)
01579 {
01580         t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle);
01581         t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle);
01582 
01583         if ((t_left >= 1) || (t_right >= 1))
01584         {
01585                 return FALSE;
01586         }
01587 
01588         //const BOOL left_clip = (t_left > 0);
01589         //const BOOL right_clip = (t_right > 0);
01590 
01591         //if (!left_clip && !right_clip)
01592         {
01593                 for (S32 vtx = 0; vtx < 4; ++vtx)
01594                 {
01595                         v_clipped[vtx]  = v_corner[vtx];
01596                 }
01597         }
01598 /*      else
01599         {
01600                 v_clipped[0] = v_corner[0];
01601                 v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0])
01602                                                                         : v_corner[1];
01603                 v_clipped[2] = v_corner[2];
01604                 v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2])
01605                                                                         : v_corner[3];
01606         }*/
01607 
01608         return TRUE;
01609 }
01610 
01611 
01612 F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle)
01613 {
01614         const LLVector3 V = V1 - V0;
01615         const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1;
01616         const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2];
01617         const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2];
01618         const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2];
01619 
01620         if (fabs(A) < 1e-7)
01621         {
01622                 return -0.1f;   // v0 is cone origin and v1 is on the surface of the cone.
01623         }
01624 
01625         const F32 det = sqrt(B*B - A*C);
01626         const F32 t1 = (-B - det) / A;
01627         const F32 t2 = (-B + det) / A;
01628         const F32 z1 = V0.mV[2] + t1 * V.mV[2];
01629         const F32 z2 = V0.mV[2] + t2 * V.mV[2];
01630         if (z1 * cos_max_angle < 0)
01631         {
01632                 return t2;
01633         }
01634         else if (z2 * cos_max_angle < 0)
01635         {
01636                 return t1;
01637         }
01638         else if ((t1 < 0) || (t1 > 1))
01639         {
01640                 return t2;
01641         }
01642         else
01643         {
01644                 return t1;
01645         }
01646 }
01647 
01648 
01649 void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
01650 {
01651         const LLVector3* v_corner = mSun.corners();
01652 
01653         LLStrider<LLVector3> verticesp;
01654         LLStrider<LLVector3> normalsp;
01655         LLStrider<LLVector2> texCoordsp;
01656         LLStrider<U32> indicesp;
01657         S32 index_offset;
01658         LLFace *face;
01659 
01660         const LLVector3 right = 2 * (v_corner[2] - v_corner[0]);
01661         LLVector3 up = 2 * (v_corner[2] - v_corner[3]);
01662         up.normVec();
01663         F32 size = right.magVec();
01664         up = size * up;
01665         const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]);
01666         
01667         LLVector3 v_glow_corner[4];
01668 
01669         v_glow_corner[0] = draw_pos - right + up;
01670         v_glow_corner[1] = draw_pos - right - up;
01671         v_glow_corner[2] = draw_pos + right + up;
01672         v_glow_corner[3] = draw_pos + right - up;
01673 
01674         face = mFace[FACE_BLOOM]; 
01675 
01676         if (face->mVertexBuffer.isNull())
01677         {
01678                 face->setSize(4, 6);
01679                 face->setGeomIndex(0);
01680                 face->setIndicesIndex(0);
01681                 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01682                 face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
01683         }
01684 
01685         index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01686         if (-1 == index_offset)
01687         {
01688                 return;
01689         }
01690 
01691         for (S32 vtx = 0; vtx < 4; ++vtx)
01692         {
01693                 *(verticesp++)  = v_glow_corner[vtx] + mCameraPosAgent;
01694         }
01695 
01696         *(texCoordsp++) = TEX01;
01697         *(texCoordsp++) = TEX00;
01698         *(texCoordsp++) = TEX11;
01699         *(texCoordsp++) = TEX10;
01700 
01701         *indicesp++ = index_offset + 0;
01702         *indicesp++ = index_offset + 2;
01703         *indicesp++ = index_offset + 1;
01704 
01705         *indicesp++ = index_offset + 1;
01706         *indicesp++ = index_offset + 2;
01707         *indicesp++ = index_offset + 3;
01708 }
01709 
01710 
01711 F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
01712 {
01713         LLVector3 P = p;
01714         P.normVec();
01715 
01716         const F32 cos_dir_angle = -P.mV[VZ];
01717         const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle);
01718 
01719         F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top
01720                                                                         + sin_dir_angle * sin_dir_from_top;
01721 
01722         F32 diff_angles;
01723         if (cos_diff_angles > (1 - 1e-7))
01724                 diff_angles = 0;
01725         else
01726                 diff_angles = acos(cos_diff_angles);
01727 
01728         const F32 rel_diff_angles = diff_angles / diff_angl_dir;
01729         const F32 dt = 1 - rel_diff_angles;
01730 
01731         return (dt < 0) ? 0 : dt;
01732 }
01733 
01734 
01735 F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2)
01736 {
01737         F32 dt_clip;
01738         const LLVector3 otrezok = v1 - v0;
01739         const F32 A = otrezok.magVecSquared();
01740         const F32 B = v0 * otrezok;
01741         const F32 C = v0.magVecSquared() - far_clip2;
01742         const F32 det = sqrt(B*B - A*C);
01743         dt_clip = (-B - det) / A;
01744         if ((dt_clip < 0) || (dt_clip > 1))
01745                 dt_clip = (-B + det) / A;
01746         return dt_clip;
01747 }
01748 
01749 
01750 void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
01751                                                                                  const LLHeavenBody& HB)
01752 {
01753         const LLVector3 &look_at = gCamera->getAtAxis();
01754         // const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f;
01755         // gWorldPointer->getWaterHeight() + 0.001f;
01756 
01757         LLVector3 to_dir = HB.getDirection();
01758         LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10);
01759         LLVector3 to_dir_proj = to_dir;
01760         to_dir_proj.mV[VZ] = 0;
01761         to_dir_proj.normVec();
01762 
01763         LLVector3 Right = to_dir % LLVector3::z_axis;
01764         LLVector3 Up = Right % to_dir;
01765         Right.normVec();
01766         Up.normVec();
01767 
01768         // finding angle between  look direction and sprite.
01769         LLVector3 look_at_right = look_at % LLVector3::z_axis;
01770         look_at_right.normVec();
01771 
01772         const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution);
01773         //const static F32 horizon_angle = acos(cos_horizon_angle);
01774 
01775         const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
01776         F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
01777         F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
01778 
01779         F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
01780         Right *= /*cos_lookAt_toDir */ horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
01781         Up *= vert_size;
01782 
01783         LLVector3 v_corner[2];
01784         LLVector3 stretch_corner[2];
01785 
01786         LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
01787         v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
01788 
01789         F32 dt_hor, dt;
01790         dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle);
01791 
01792         LLVector2 TEX0t = TEX00;
01793         LLVector2 TEX1t = TEX10;
01794         LLVector3 lower_corner = v_corner[1];
01795 
01796         if ((dt_hor > 0) && (dt_hor < 1))
01797         {
01798                 TEX0t = LLVector2(0, dt_hor);
01799                 TEX1t = LLVector2(1, dt_hor);
01800                 lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0];
01801         }
01802         else
01803                 dt_hor = llmax(0.0f, llmin(1.0f, dt_hor));
01804 
01805         top_hb.normVec();
01806         const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
01807         const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
01808 
01809         const S32 cols = 1;
01810         const S32 raws = lltrunc(16 * extension);
01811         S32 quads = cols * raws;
01812 
01813         stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
01814         stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
01815 
01816         dt = dt_hor;
01817 
01818 
01819         F32 cos_dir_from_top[2];
01820 
01821         LLVector3 dir = stretch_corner[0];
01822         dir.normVec();
01823         cos_dir_from_top[0] = dir.mV[VZ];
01824 
01825         dir = stretch_corner[1];
01826         dir.normVec();
01827         cos_dir_from_top[1] = dir.mV[VZ];
01828 
01829         const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]);
01830         const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]);
01831         const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1]
01832                                                         + sin_dir_from_top * sin_dir_from_top2;
01833         const F32 diff_angl_dir = acos(cos_diff_dir);
01834 
01835         v_corner[0] = stretch_corner[0];
01836         v_corner[1] = lower_corner;
01837 
01838 
01839         LLVector2 TEX0tt = TEX01;
01840         LLVector2 TEX1tt = TEX11;
01841 
01842         LLVector3 v_refl_corner[4];
01843         LLVector3 v_sprite_corner[4];
01844 
01845         S32 vtx;
01846         for (vtx = 0; vtx < 2; ++vtx)
01847         {
01848                 LLVector3 light_proj = v_corner[vtx];
01849                 light_proj.normVec();
01850 
01851                 const F32 z = light_proj.mV[VZ];
01852                 const F32 sin_angle = sqrt(1 - z * z);
01853                 light_proj *= 1.f / sin_angle;
01854                 light_proj.mV[VZ] = 0;
01855                 const F32 to_refl_point = H * sin_angle / fabs(z);
01856 
01857                 v_refl_corner[vtx] = to_refl_point * light_proj;
01858         }
01859 
01860 
01861         for (vtx = 2; vtx < 4; ++vtx)
01862         {
01863                 const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj;
01864                 v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]);
01865         }
01866 
01867         for (vtx = 0; vtx < 4; ++vtx)
01868                 v_refl_corner[vtx].mV[VZ] -= H;
01869 
01870         S32 side = 0;
01871         LLVector3 refl_corn_norm[2];
01872         refl_corn_norm[0] = v_refl_corner[1];
01873         refl_corn_norm[0].normVec();
01874         refl_corn_norm[1] = v_refl_corner[3];
01875         refl_corn_norm[1].normVec();
01876 
01877         F32 cos_refl_look_at[2];
01878         cos_refl_look_at[0] = refl_corn_norm[0] * look_at;
01879         cos_refl_look_at[1] = refl_corn_norm[1] * look_at;
01880 
01881         if (cos_refl_look_at[1] > cos_refl_look_at[0])
01882         {
01883                 side = 2;
01884         }
01885 
01886         //const F32 far_clip = (gCamera->getFar() - 0.01) / far_clip_factor;
01887         const F32 far_clip = 512;
01888         const F32 far_clip2 = far_clip*far_clip;
01889 
01890         F32 dt_clip;
01891         F32 vtx_near2, vtx_far2;
01892 
01893         if ((vtx_far2 = v_refl_corner[side].magVecSquared()) > far_clip2)
01894         {
01895                 // whole thing is sprite: reflection is beyond far clip plane.
01896                 dt_clip = 1.1f;
01897                 quads = 1;
01898         }
01899         else if ((vtx_near2 = v_refl_corner[side+1].magVecSquared()) > far_clip2)
01900         {
01901                 // part is reflection, the rest is sprite.
01902                 dt_clip = dtClip(v_refl_corner[side + 1], v_refl_corner[side], far_clip2);
01903                 const LLVector3 P = (1 - dt_clip) * v_refl_corner[side + 1] + dt_clip * v_refl_corner[side];
01904 
01905                 F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
01906 
01907                 dt = dt_tex;
01908                 TEX0tt = LLVector2(0, dt);
01909                 TEX1tt = LLVector2(1, dt);
01910                 quads++;
01911         }
01912         else
01913         {
01914                 // whole thing is correct reflection.
01915                 dt_clip = -0.1f;
01916         }
01917 
01918         LLFace *face = mFace[FACE_REFLECTION]; 
01919 
01920         if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount())
01921         {
01922                 face->setSize(quads * 4, quads * 6);
01923                 face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
01924                 face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
01925                 face->setIndicesIndex(0);
01926                 face->setGeomIndex(0);
01927         }
01928         
01929         LLStrider<LLVector3> verticesp;
01930         LLStrider<LLVector3> normalsp;
01931         LLStrider<LLVector2> texCoordsp;
01932         LLStrider<U32> indicesp;
01933         S32 index_offset;
01934         
01935         index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
01936         if (-1 == index_offset)
01937         {
01938                 return;
01939         }
01940 
01941         LLColor3 hb_col3 = HB.getInterpColor();
01942         hb_col3.clamp();
01943         const LLColor4 hb_col = LLColor4(hb_col3);
01944 
01945         const F32 min_attenuation = 0.4f;
01946         const F32 max_attenuation = 0.7f;
01947         const F32 attenuation = min_attenuation
01948                 + cos_angle_of_view * (max_attenuation - min_attenuation);
01949 
01950         LLColor4 hb_refl_col = (1-attenuation) * hb_col + attenuation * mFogColor;
01951         face->setFaceColor(hb_refl_col);
01952         
01953         LLVector3 v_far[2];
01954         v_far[0] = v_refl_corner[1];
01955         v_far[1] = v_refl_corner[3];
01956 
01957         if(dt_clip > 0)
01958         {
01959                 if (dt_clip >= 1)
01960                 {
01961                         for (S32 vtx = 0; vtx < 4; ++vtx)
01962                         {
01963                                 F32 ratio = far_clip / v_refl_corner[vtx].magVec();
01964                                 *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
01965                         }
01966                         const LLVector3 draw_pos = 0.25 *
01967                                 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
01968                         face->mCenterAgent = draw_pos;
01969                 }
01970                 else
01971                 {
01972                         F32 ratio = far_clip / v_refl_corner[1].magVec();
01973                         v_sprite_corner[1] = v_refl_corner[1] * ratio;
01974 
01975                         ratio = far_clip / v_refl_corner[3].magVec();
01976                         v_sprite_corner[3] = v_refl_corner[3] * ratio;
01977 
01978                         v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
01979                         v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
01980                         v_sprite_corner[0] = v_refl_corner[1];
01981                         v_sprite_corner[2] = v_refl_corner[3];
01982 
01983                         for (S32 vtx = 0; vtx < 4; ++vtx)
01984                         {
01985                                 *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
01986                         }
01987 
01988                         const LLVector3 draw_pos = 0.25 *
01989                                 (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
01990                         face->mCenterAgent = draw_pos;
01991                 }
01992 
01993                 *(texCoordsp++) = TEX0tt;
01994                 *(texCoordsp++) = TEX0t;
01995                 *(texCoordsp++) = TEX1tt;
01996                 *(texCoordsp++) = TEX1t;
01997 
01998                 *indicesp++ = index_offset + 0;
01999                 *indicesp++ = index_offset + 2;
02000                 *indicesp++ = index_offset + 1;
02001 
02002                 *indicesp++ = index_offset + 1;
02003                 *indicesp++ = index_offset + 2;
02004                 *indicesp++ = index_offset + 3;
02005 
02006                 index_offset += 4;
02007         }
02008 
02009         if (dt_clip < 1)
02010         {
02011                 if (dt_clip <= 0)
02012                 {
02013                         const LLVector3 draw_pos = 0.25 *
02014                                 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
02015                         face->mCenterAgent = draw_pos;
02016                 }
02017 
02018                 const F32 raws_inv = 1.f/raws;
02019                 const F32 cols_inv = 1.f/cols;
02020                 LLVector3 left  = v_refl_corner[0] - v_refl_corner[1];
02021                 LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
02022                 left *= raws_inv;
02023                 right *= raws_inv;
02024 
02025                 F32 dt_raw = dt;
02026 
02027                 for (S32 raw = 0; raw < raws; ++raw)
02028                 {
02029                         F32 dt_v0 = raw * raws_inv;
02030                         F32 dt_v1 = (raw + 1) * raws_inv;
02031                         const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
02032                         const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
02033                         const LLVector3 EL = BL + left;
02034                         const LLVector3 ER = BR + right;
02035                         dt_v0 = dt_raw;
02036                         dt_raw = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
02037                         for (S32 col = 0; col < cols; ++col)
02038                         {
02039                                 F32 dt_h0 = col * cols_inv;
02040                                 *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
02041                                 *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
02042                                 F32 dt_h1 = (col + 1) * cols_inv;
02043                                 *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
02044                                 *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
02045 
02046                                 *(texCoordsp++) = LLVector2(dt_h0, dt_v1);
02047                                 *(texCoordsp++) = LLVector2(dt_h0, dt_v0);
02048                                 *(texCoordsp++) = LLVector2(dt_h1, dt_v1);
02049                                 *(texCoordsp++) = LLVector2(dt_h1, dt_v0);
02050 
02051                                 *indicesp++ = index_offset + 0;
02052                                 *indicesp++ = index_offset + 2;
02053                                 *indicesp++ = index_offset + 1;
02054 
02055                                 *indicesp++ = index_offset + 1;
02056                                 *indicesp++ = index_offset + 2;
02057                                 *indicesp++ = index_offset + 3;
02058 
02059                                 index_offset += 4;
02060                         }
02061                 }
02062         }
02063 }
02064 
02065 
02066 
02067 
02068 void LLVOSky::updateFog(const F32 distance)
02069 {
02070         if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG))
02071         {
02072                 /*gGLSFog.addCap(GL_FOG, FALSE);
02073                 gGLSPipeline.addCap(GL_FOG, FALSE);
02074                 gGLSPipelineAlpha.addCap(GL_FOG, FALSE);
02075                 gGLSPipelinePixieDust.addCap(GL_FOG, FALSE);
02076                 gGLSPipelineSelection.addCap(GL_FOG, FALSE);
02077                 gGLSPipelineAvatar.addCap(GL_FOG, FALSE);
02078                 gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, FALSE);
02079                 gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, FALSE);
02080                 gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, FALSE);
02081                 gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, FALSE);*/
02082                 glFogf(GL_FOG_DENSITY, 0);
02083                 glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV);
02084                 glFogf(GL_FOG_END, 1000000.f);
02085                 return;
02086         }
02087         else
02088         {
02089                 /*gGLSFog.addCap(GL_FOG, TRUE);
02090                 gGLSPipeline.addCap(GL_FOG, TRUE);
02091                 gGLSPipelineAlpha.addCap(GL_FOG, TRUE);
02092                 gGLSPipelinePixieDust.addCap(GL_FOG, TRUE);
02093                 gGLSPipelineSelection.addCap(GL_FOG, TRUE);
02094                 if (!gGLManager.mIsATI)
02095                 {
02096                         gGLSPipelineAvatar.addCap(GL_FOG, TRUE);
02097                         gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, TRUE);
02098                         gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, TRUE);
02099                         gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, TRUE);
02100                         gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, TRUE);
02101                 }*/
02102         }
02103 
02104         const BOOL hide_clip_plane = TRUE;
02105         LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f);
02106 
02107         const F32 water_height = gAgent.getRegion()->getWaterHeight();
02108         // gWorldPointer->getWaterHeight();
02109         F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
02110 
02111         F32 near_clip_height = gCamera->getAtAxis().mV[VZ] * gCamera->getNear();
02112         camera_height += near_clip_height;
02113 
02114         F32 fog_distance = 0.f;
02115         LLColor3 res_color[3];
02116 
02117         LLColor3 sky_fog_color = LLColor3::white;
02118         LLColor3 render_fog_color = LLColor3::white;
02119 
02120         LLColor3 transp;
02121         LLVector3 tosun = getToSunLast();
02122         const F32 tosun_z = tosun.mV[VZ];
02123         tosun.mV[VZ] = 0.f;
02124         tosun.normVec();
02125         LLVector3 perp_tosun;
02126         perp_tosun.mV[VX] = -tosun.mV[VY];
02127         perp_tosun.mV[VY] = tosun.mV[VX];
02128         LLVector3 tosun_45 = tosun + perp_tosun;
02129         tosun_45.normVec();
02130 
02131         F32 delta = 0.06f;
02132         tosun.mV[VZ] = delta;
02133         perp_tosun.mV[VZ] = delta;
02134         tosun_45.mV[VZ] = delta;
02135         tosun.normVec();
02136         perp_tosun.normVec();
02137         tosun_45.normVec();
02138 
02139         // Sky colors, just slightly above the horizon in the direction of the sun, perpendicular to the sun, and at a 45 degree angle to the sun.
02140         calcSkyColorInDir(res_color[0],transp, tosun);
02141         calcSkyColorInDir(res_color[1],transp, perp_tosun);
02142         calcSkyColorInDir(res_color[2],transp, tosun_45);
02143 
02144         sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]);
02145 
02146         F32 full_off = -0.25f;
02147         F32 full_on = 0.00f;
02148         F32 on = (tosun_z - full_off) / (full_on - full_off);
02149         on = llclamp(on, 0.01f, 1.f);
02150         sky_fog_color *= 0.5f * on;
02151 
02152 
02153         // We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ???
02154         S32 i;
02155         for (i = 0; i < 3; i++)
02156         {
02157                 sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]);
02158         }
02159 
02160         color_gamma_correct(sky_fog_color);
02161 
02162         render_fog_color = sky_fog_color;
02163         
02164         if (camera_height > water_height)
02165         {
02166                 fog_distance = mFogRatio * distance;
02167                 LLColor4 fog(render_fog_color);
02168                 glFogfv(GL_FOG_COLOR, fog.mV);
02169                 mGLFogCol = fog;
02170         }
02171         else
02172         {
02173                 // Interpolate between sky fog and water fog...
02174                 F32 depth = water_height - camera_height;
02175                 F32 depth_frac = 1.f/(1.f + 200.f*depth);
02176                 F32 color_frac = 1.f/(1.f + 0.5f* depth)* 0.2f;
02177                 fog_distance = (mFogRatio * distance) * depth_frac + 30.f * (1.f-depth_frac);
02178                 fog_distance = llmin(75.f, fog_distance);
02179 
02180                 F32 brightness = 1.f/(1.f + 0.05f*depth);
02181                 F32 sun_brightness = getSunDiffuseColor().magVec() * 0.3f;
02182                 brightness = llmin(1.f, brightness);
02183                 brightness = llmin(brightness, sun_brightness);
02184                 color_frac = llmin(0.7f, color_frac);
02185 
02186                 LLColor4 fogCol = brightness * (color_frac * render_fog_color + (1.f - color_frac) * LLColor4(0.f, 0.2f, 0.3f, 1.f));
02187                 fogCol.setAlpha(1);
02188                 glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
02189                 mGLFogCol = fogCol;
02190         }
02191 
02192         mFogColor = sky_fog_color;
02193         mFogColor.setAlpha(1);
02194         LLGLSFog gls_fog;
02195 
02196         F32 fog_density;
02197         if (hide_clip_plane)
02198         {
02199                 // For now, set the density to extend to the cull distance.
02200                 const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f)))
02201                 fog_density = f_log/fog_distance;
02202                 glFogi(GL_FOG_MODE, GL_EXP2);
02203         }
02204         else
02205         {
02206                 const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f))
02207                 fog_density = (f_log)/fog_distance;
02208                 glFogi(GL_FOG_MODE, GL_EXP);
02209         }
02210 
02211         glFogf(GL_FOG_END, fog_distance*2.2f);
02212 
02213         glFogf(GL_FOG_DENSITY, fog_density);
02214 
02215         glHint(GL_FOG_HINT, GL_NICEST);
02216         stop_glerror();
02217 }
02218 
02219 // static
02220 void LLHaze::initClass()
02221 {
02222         sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
02223 }
02224 
02225 
02226 
02227 // Functions used a lot.
02228 
02229 
02230 F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
02231 {
02232         F32 mv = color_max(col);
02233         if (0 == mv)
02234         {
02235                 return 0;
02236         }
02237 
02238         col *= 1.f / mv;
02239         color_pow(col, e);
02240         if (postmultiply)
02241         {
02242                 col *= mv;
02243         }
02244         return mv;
02245 }
02246 
02247 // Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis.
02248 // Range of output is 0.0f to 2pi //359.99999...f
02249 // Returns 0.0f when "v" = +/- z_axis.
02250 F32 azimuth(const LLVector3 &v)
02251 {
02252         F32 azimuth = 0.0f;
02253         if (v.mV[VX] == 0.0f)
02254         {
02255                 if (v.mV[VY] > 0.0f)
02256                 {
02257                         azimuth = F_PI * 0.5f;
02258                 }
02259                 else if (v.mV[VY] < 0.0f)
02260                 {
02261                         azimuth = F_PI * 1.5f;// 270.f;
02262                 }
02263         }
02264         else
02265         {
02266                 azimuth = (F32) atan(v.mV[VY] / v.mV[VX]);
02267                 if (v.mV[VX] < 0.0f)
02268                 {
02269                         azimuth += F_PI;
02270                 }
02271                 else if (v.mV[VY] < 0.0f)
02272                 {
02273                         azimuth += F_PI * 2;
02274                 }
02275         }       
02276         return azimuth;
02277 }
02278 
02279 
02280 #if 0
02281 // Not currently used
02282 LLColor3 LLVOSky::calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const
02283 {
02284         LLColor3 col;
02285         calcGroundFog(col, transp, view_dir, obj_dist);
02286         col *= mBrightnessScaleGuess;
02287         return col;
02288 }
02289 #endif
02290 
02291 void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
02292 {
02293         LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
02294         sun_direction.normVec();
02295         F32 dp = mSun.getDirection() * sun_direction;
02296         mSun.setDirection(sun_direction);
02297         mSun.setAngularVelocity(sun_ang_velocity);
02298         mMoon.setDirection(-sun_direction);
02299         if (dp < 0.995f) { //the sun jumped a great deal, update immediately
02300                 updateHaze();
02301                 mWeatherChange = FALSE;
02302                 mForceUpdate = TRUE;
02303         }
02304         else if (mWeatherChange && (mSun.getDirection().mV[VZ] > -0.5) )
02305         {
02306                 updateHaze();
02307                 init();
02308                 mWeatherChange = FALSE;
02309         }
02310         else if (mSun.getDirection().mV[VZ] < -0.5)
02311         {
02312                 mWeatherChange = TRUE;
02313         }
02314 }
02315 
02316 #define INV_WAVELENGTH_R_POW4 (1.f/0.2401f)                     // = 1/0.7^4
02317 #define INV_WAVELENGTH_G_POW4 (1.f/0.0789f)                     // = 1/0.53^4
02318 #define INV_WAVELENGTH_B_POW4 (1.f/0.03748f)            // = 1/0.44^4
02319 
02320 // Dummy class for globals used below. Replace when KILLERSKY is merged in.
02321 class LLKillerSky
02322 {
02323 public:
02324         static F32 sRaleighGroundDensity;
02325         static F32 sMieFactor;
02326         static F32 sNearFalloffFactor;
02327         static F32 sSkyContrib;
02328 
02329         static void getRaleighCoefficients(float eye_sun_dp, float density, float *coefficients)
02330         {
02331                 float dp = eye_sun_dp;
02332                 float angle_dep = density*(1 + dp*dp);
02333                 coefficients[0] = angle_dep * INV_WAVELENGTH_R_POW4;
02334                 coefficients[1] = angle_dep * INV_WAVELENGTH_G_POW4;
02335                 coefficients[2] = angle_dep * INV_WAVELENGTH_B_POW4;
02336         }
02337 
02338         static void getMieCoefficients(float eye_sun_dp, float density, float *coefficient)
02339         {
02340                 // TOTALLY ARBITRARY FUNCTION. Seems to work though
02341                 // If anyone can replace this with some *actual* mie function, that'd be great
02342                 float dp = eye_sun_dp;
02343                 float dp_highpower = dp*dp;
02344                 float angle_dep = density * (llclamp(dp_highpower*dp, 0.f, 1.f) + 0.4f);
02345                 *coefficient = angle_dep;
02346         }
02347 };
02348 
02349 F32 LLKillerSky::sRaleighGroundDensity = 0.013f;
02350 F32 LLKillerSky::sMieFactor = 50;
02351 F32 LLKillerSky::sNearFalloffFactor = 1.5f;
02352 F32 LLKillerSky::sSkyContrib = 0.06f;
02353 
02354 void LLVOSky::generateScatterMap()
02355 {
02356         float raleigh[3], mie;
02357 
02358         mScatterMap = new LLImageGL(FALSE);
02359         mScatterMapRaw = new LLImageRaw(256, 256, 4);
02360         U8 *data = mScatterMapRaw->getData();
02361 
02362         F32 light_brightness = gSky.getSunDirection().mV[VZ]+0.1f;
02363         LLColor4 light_color;
02364         LLColor4 sky_color;
02365         if (light_brightness > 0)
02366         {
02367                 F32 interp = sqrtf(light_brightness);
02368                 light_brightness = sqrt(sqrtf(interp));
02369                 light_color = lerp(gSky.getSunDiffuseColor(), LLColor4(1,1,1,1), interp) * light_brightness;
02370                 sky_color = lerp(LLColor4(0,0,0,0), LLColor4(0.4f, 0.6f, 1.f, 1.f), light_brightness)*LLKillerSky::sSkyContrib;
02371         }
02372         else
02373         {
02374                 light_brightness = /*0.3f*/sqrt(-light_brightness);
02375                 light_color = gSky.getMoonDiffuseColor() * light_brightness;
02376                 sky_color = LLColor4(0,0,0,1);
02377         }
02378 
02379         // x = distance [0..1024m]
02380         // y = dot product [-1,1]
02381         for (int y=0;y<256;y++)
02382         {
02383                 // Accumulate outward
02384                 float accum_r = 0, accum_g = 0, accum_b = 0;
02385 
02386                 float dp = (((float)y)/255.f)*1.95f - 0.975f;
02387                 U8 *scanline = &data[y*256*4];
02388                 for (int x=0;x<256;x++)
02389                 {
02390                         float dist = ((float)x+1)*4; // x -> 2048
02391 
02392                         float raleigh_density = LLKillerSky::sRaleighGroundDensity * 0.05f; // Arbitrary? Perhaps...
02393                         float mie_density = raleigh_density*LLKillerSky::sMieFactor;
02394 
02395                         float extinction_factor = dist/LLKillerSky::sNearFalloffFactor;
02396 
02397                         LLKillerSky::getRaleighCoefficients(dp, raleigh_density, raleigh);
02398                         LLKillerSky::getMieCoefficients(dp, mie_density, &mie);
02399 
02400                         float falloff_r = pow(llclamp(0.985f-raleigh[0],0.f,1.f), extinction_factor);
02401                         float falloff_g = pow(llclamp(0.985f-raleigh[1],0.f,1.f), extinction_factor);
02402                         float falloff_b = pow(llclamp(0.985f-raleigh[2],0.f,1.f), extinction_factor);
02403 
02404                         float light_r = light_color.mV[0] * (raleigh[0]+mie+sky_color.mV[0]) * falloff_r;
02405                         float light_g = light_color.mV[1] * (raleigh[1]+mie+sky_color.mV[1]) * falloff_g;
02406                         float light_b = light_color.mV[2] * (raleigh[2]+mie+sky_color.mV[2]) * falloff_b;
02407 
02408                         accum_r += light_r;
02409                         accum_g += light_g;
02410                         accum_b += light_b;
02411 
02412                         scanline[x*4] = (U8)llclamp(accum_r*255.f, 0.f, 255.f);
02413                         scanline[x*4+1] = (U8)llclamp(accum_g*255.f, 0.f, 255.f);
02414                         scanline[x*4+2] = (U8)llclamp(accum_b*255.f, 0.f, 255.f);
02415                         float alpha = ((falloff_r+falloff_g+falloff_b)*0.33f);
02416                         scanline[x*4+3] = (U8)llclamp(alpha*255.f, 0.f, 255.f); // Avg falloff
02417 
02418                         // Output color Co, Input color Ci, Map channels Mrgb, Ma:
02419                         // Co = (Ci * Ma) + Mrgb
02420                 }
02421         }
02422 
02423         mScatterMap->createGLTexture(0, mScatterMapRaw);
02424         mScatterMap->bind(0);
02425         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02426         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02427 }
02428 
02429 #if 0
02430 // Not currently used
02431 void LLVOSky::calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 obj_dist) const
02432 {
02433         const LLVector3& tosun = getToSunLast();//use_old_value ? sunDir() : toSunLast();
02434         res.setToBlack();
02435         transp.setToWhite();
02436         const F32 dist = obj_dist * mWorldScale;
02437 
02438         //LLVector3 view_dir = gCamera->getAtAxis();
02439 
02440         const F32 cos_dir = view_dir * tosun;
02441         LLVector3 dir = view_dir;
02442         LLVector3 virtual_P = mCameraPosAgent + dist * dir;
02443 
02444         if (dir.mV[VZ] < 0)
02445         {
02446                 dir = -dir;
02447         }
02448 
02449         const F32 z_dir = dir.mV[2];
02450 
02451         const F32 h = mCameraPosAgent.mV[2];
02452 
02453         transp = color_div(mTransp.calcTransp(dir * calcUpVec(virtual_P), 0),
02454                 mTransp.calcTransp(z_dir, h));
02455 
02456         if (calcHitsEarth(mCameraPosAgent, tosun) > 0)
02457         {
02458                 const F32 avg = llmin(1.f, 1.2f * color_avg(transp));
02459                 transp = LLColor3(avg, avg, avg);
02460                 return;
02461         }
02462 
02463         LLColor3 haze_sca_opt_depth = mHaze.getSigSca();
02464         LLColor3 sun_transp;
02465         mTransp.calcTransp(tosun.mV[2], -0.1f, sun_transp);
02466 
02467         res = calcAirPhaseFunc(cos_dir) * LLHaze::getAirScaSeaLevel();
02468         res += mHaze.calcPhase(cos_dir) * mHaze.getSigSca();
02469         res = mSun.getIntensity() * dist * sun_transp * res;
02470 }
02471 
02472 #endif

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