aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvosky.h
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvosky.h
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llvosky.h')
-rw-r--r--linden/indra/newview/llvosky.h929
1 files changed, 929 insertions, 0 deletions
diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h
new file mode 100644
index 0000000..1617c2a
--- /dev/null
+++ b/linden/indra/newview/llvosky.h
@@ -0,0 +1,929 @@
1/**
2 * @file llvosky.h
3 * @brief LLVOSky class header file
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#ifndef LL_LLVOSKY_H
29#define LL_LLVOSKY_H
30
31#include "stdtypes.h"
32#include "v3color.h"
33#include "v4coloru.h"
34#include "llviewerimage.h"
35#include "llviewerobject.h"
36#include "llframetimer.h"
37
38
39//////////////////////////////////
40//
41// Lots of constants
42//
43// Will clean these up at some point...
44//
45
46const F32 HORIZON_DIST = 1024.0f;
47const F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 10.f;
48const F32 HEAVENLY_BODY_FACTOR = 0.1f;
49const F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR;
50const F32 EARTH_RADIUS = 6.4e6f; // exact radius = 6.37 x 10^6 m
51const F32 ATM_EXP_FALLOFF = 0.000126f;
52const F32 ATM_SEA_LEVEL_NDENS = 2.55e25f;
53// Somewhat arbitrary:
54const F32 ATM_HEIGHT = 100000.f;
55
56const F32 FIRST_STEP = 5000.f;
57const F32 INV_FIRST_STEP = 1.f/FIRST_STEP;
58const S32 NO_STEPS = 15;
59const F32 INV_NO_STEPS = 1.f/NO_STEPS;
60
61
62// constants used in calculation of scattering coeff of clear air
63const F32 sigma = 0.035f;
64const F32 fsigma = (6+3*sigma)/(6.f-7.f*sigma);
65const F64 Ndens = 2.55e25;
66const F64 Ndens2 = Ndens*Ndens;
67
68// !!! *FIX: This #define should be in llcommon somewhere...
69// We should not be #defining anything with leading underscores and
70// much less double leading underscores since that is always vendor
71// specific. Change this to something like LL_FORCE_INLINE.
72#ifdef __GNUC__
73#define __forceinline inline __attribute__((always_inline))
74#endif
75
76__forceinline LLColor3 color_div(const LLColor3 &col1, const LLColor3 &col2)
77{
78 return LLColor3(
79 col1.mV[0] / col2.mV[0],
80 col1.mV[1] / col2.mV[1],
81 col1.mV[2] / col2.mV[2] );
82}
83
84LLColor3 color_norm(const LLColor3 &col);
85LLVector3 move_vec (const LLVector3& v, F32 cos_max_angle);
86BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
87 const LLVector3 v_corner[4], const F32 cos_max_angle);
88F32 clip_side_to_horizon(const LLVector3& v0, const LLVector3& v1, const F32 cos_max_angle);
89
90inline F32 color_intens ( const LLColor3 &col )
91{
92 return col.mV[0] + col.mV[1] + col.mV[2];
93}
94
95inline F32 color_max(const LLColor3 &col)
96{
97 return llmax(col.mV[0], col.mV[1], col.mV[2]);
98}
99
100inline F32 color_max(const LLColor4 &col)
101{
102 return llmax(col.mV[0], col.mV[1], col.mV[2]);
103}
104
105
106inline F32 color_min(const LLColor3 &col)
107{
108 return llmin(col.mV[0], col.mV[1], col.mV[2]);
109}
110
111inline LLColor3 color_norm_abs(const LLColor3 &col)
112{
113 const F32 m = color_max(col);
114 if (m > 1e-6)
115 {
116 return 1.f/m * col;
117 }
118 else return col;
119}
120
121
122
123class LLFace;
124class LLHaze;
125
126
127class LLSkyTex
128{
129 friend class LLVOSky;
130private:
131 static S32 sResolution;
132 static S32 sComponents;
133 LLPointer<LLImageGL> mImageGL[2];
134 LLPointer<LLImageRaw> mImageRaw[2];
135 LLColor3 *mSkyData;
136 LLVector3 *mSkyDirs; // Cache of sky direction vectors
137 static S32 sCurrent;
138 static F32 sInterpVal;
139
140public:
141 static F32 getInterpVal() { return sInterpVal; }
142 static void setInterpVal(const F32 v) { sInterpVal = v; }
143 static BOOL doInterpolate() { return sInterpVal > 0.001; }
144
145 void bindTexture(BOOL curr = TRUE);
146
147protected:
148 LLSkyTex();
149 void init();
150 void cleanupGL();
151 void restoreGL();
152
153 ~LLSkyTex();
154
155
156 static S32 getResolution() { return sResolution; }
157 static S32 getCurrent() { return sCurrent; }
158 static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); }
159 static S32 getNext() { return ((sCurrent+1) % 2); }
160 static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); }
161
162 void initEmpty(const S32 tex);
163 void create(F32 brightness_scale, const LLColor3& multiscatt);
164
165 void setDir(const LLVector3 &dir, const S32 i, const S32 j)
166 {
167 S32 offset = i * sResolution + j;
168 mSkyDirs[offset] = dir;
169 }
170
171 const LLVector3 &getDir(const S32 i, const S32 j) const
172 {
173 S32 offset = i * sResolution + j;
174 return mSkyDirs[offset];
175 }
176
177 void setPixel(const LLColor3 &col, const S32 i, const S32 j)
178 {
179 S32 offset = i * sResolution + j;
180 mSkyData[offset] = col;
181 }
182
183 void setPixel(const LLColor4U &col, const S32 i, const S32 j)
184 {
185 S32 offset = (i * sResolution + j) * sComponents;
186 U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
187 *pix = col.mAll;
188 }
189
190 LLColor4U getPixel(const S32 i, const S32 j)
191 {
192 LLColor4U col;
193 S32 offset = (i * sResolution + j) * sComponents;
194 U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
195 col.mAll = *pix;
196 return col;
197 }
198
199 LLImageRaw* getImageRaw(BOOL curr=TRUE) { return mImageRaw[getWhich(curr)]; }
200 void createTexture(BOOL curr=TRUE);
201};
202
203
204class LLHeavenBody
205{
206protected:
207 LLVector3 mDirectionCached; // hack for events that shouldn't happen every frame
208
209 LLColor3 mColor;
210 LLColor3 mColorCached;
211 F32 mIntensity;
212 LLVector3 mDirection; // direction of the local heavenly body
213 LLVector3 mAngularVelocity; // velocity of the local heavenly body
214
215 F32 mDiskRadius;
216 BOOL mDraw; // FALSE - do not draw.
217 F32 mHorizonVisibility; // number [0, 1] due to how horizon
218 F32 mVisibility; // same but due to other objects being in frong.
219 BOOL mVisible;
220 static F32 sInterpVal;
221 LLVector3 mQuadCorner[4];
222 LLVector3 mU;
223 LLVector3 mV;
224 LLVector3 mO;
225
226public:
227 LLHeavenBody(const F32 rad) :
228 mDirectionCached(LLVector3(0,0,0)), mDirection(LLVector3(0,0,0)),
229 mDiskRadius(rad), mDraw(FALSE),
230 mHorizonVisibility(1), mVisibility(1)
231
232 {
233 mColor.setToBlack();
234 mColorCached.setToBlack();
235 }
236 ~LLHeavenBody() {}
237
238 const LLVector3& getDirection() const { return mDirection; }
239 void setDirection(const LLVector3 &direction) { mDirection = direction; }
240 void setAngularVelocity(const LLVector3 &ang_vel) { mAngularVelocity = ang_vel; }
241 const LLVector3& getAngularVelocity() const { return mAngularVelocity; }
242
243 const LLVector3& getDirectionCached() const { return mDirectionCached; }
244 void renewDirection() { mDirectionCached = mDirection; }
245
246 const LLColor3& getColorCached() const { return mColorCached; }
247 void setColorCached(const LLColor3& c) { mColorCached = c; }
248 const LLColor3& getColor() const { return mColor; }
249 void setColor(const LLColor3& c) { mColor = c; }
250
251 void renewColor() { mColorCached = mColor; }
252
253 static F32 interpVal() { return sInterpVal; }
254 static void setInterpVal(const F32 v) { sInterpVal = v; }
255
256 LLColor3 getInterpColor() const
257 {
258 return sInterpVal * mColor + (1 - sInterpVal) * mColorCached;
259 }
260
261// LLColor3 getDiffuseColor() const
262// {
263// LLColor3 dif = mColorCached;
264// dif.clamp();
265// return 2 * dif;
266// }
267
268// LLColor4 getAmbientColor(const LLColor3& scatt, F32 scale) const
269// {
270// const F32 min_val = 0.05f;
271// LLColor4 col = LLColor4(scale * (0.8f * color_norm_abs(getDiffuseColor()) + 0.2f * scatt));
272// //F32 left = max(0, 1 - col.mV[0]);
273// if (col.mV[0] >= 0.9)
274// {
275// col.mV[1] = llmax(col.mV[1], 2.f * min_val);
276// col.mV[2] = llmax(col.mV[2], min_val);
277// }
278// col.setAlpha(1.f);
279// return col;
280// }
281
282 const F32& getHorizonVisibility() const { return mHorizonVisibility; }
283 void setHorizonVisibility(const F32 c = 1) { mHorizonVisibility = c; }
284 const F32& getVisibility() const { return mVisibility; }
285 void setVisibility(const F32 c = 1) { mVisibility = c; }
286 const F32 getHaloBrighness() const
287 {
288 return llmax(0.f, llmin(0.9f, mHorizonVisibility)) * mVisibility;
289 }
290 BOOL isVisible() const { return mVisible; }
291 void setVisible(const BOOL v) { mVisible = v; }
292
293
294 const F32& getIntensity() const { return mIntensity; }
295 void setIntensity(const F32 c) { mIntensity = c; }
296
297 void setDiskRadius(const F32 radius) { mDiskRadius = radius; }
298 F32 getDiskRadius() const { return mDiskRadius; }
299
300 void setDraw(const BOOL draw) { mDraw = draw; }
301 BOOL getDraw() const { return mDraw; }
302
303 const LLVector3& corner(const S32 n) const { return mQuadCorner[n]; }
304 LLVector3& corner(const S32 n) { return mQuadCorner[n]; }
305 const LLVector3* corners() const { return mQuadCorner; }
306
307 const LLVector3& getU() const { return mU; }
308 const LLVector3& getV() const { return mV; }
309 void setU(const LLVector3& u) { mU = u; }
310 void setV(const LLVector3& v) { mV = v; }
311};
312
313
314__forceinline LLColor3 refr_ind_calc(const LLColor3 &wave_length)
315{
316 LLColor3 refr_ind;
317 for (S32 i = 0; i < 3; ++i)
318 {
319 const F32 wl2 = wave_length.mV[i] * wave_length.mV[i] * 1e-6f;
320 refr_ind.mV[i] = 6.43e3f + ( 2.95e6f / ( 146.0f - 1.f/wl2 ) ) + ( 2.55e4f / ( 41.0f - 1.f/wl2 ) );
321 refr_ind.mV[i] *= 1.0e-8f;
322 refr_ind.mV[i] += 1.f;
323 }
324 return refr_ind;
325}
326
327
328__forceinline LLColor3 calc_air_sca_sea_level()
329{
330 const static LLColor3 WAVE_LEN(675, 520, 445);
331 const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
332 const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
333 const static LLColor3 n4 = n21 * n21;
334 const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
335 const static LLColor3 wl4 = wl2 * wl2;
336 const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
337 const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
338 return dens_div_N * color_div ( mult_const, wl4 );
339}
340
341const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level();
342const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel);
343const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3;
344
345class LLHaze
346{
347public:
348 LLHaze() : mG(0), mFalloff(1) {mSigSca.setToBlack();}
349 LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2) :
350 mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0)
351 {
352 mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS;
353 }
354
355 LLHaze(const F32 g, const F32 sca, const F32 fo = 2) : mG(g),
356 mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
357 {
358 mAbsCoef = 0.01f * sca / AIR_SCA_AVG;
359 }
360
361 static void initClass();
362
363
364 F32 getG() const { return mG; }
365
366 void setG(const F32 g)
367 {
368 mG = g;
369 }
370
371 const LLColor3& getSigSca() const // sea level
372 {
373 return mSigSca;
374 }
375
376 void setSigSca(const LLColor3& s)
377 {
378 mSigSca = s;
379 mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS;
380 }
381
382 void setSigSca(const F32 s0, const F32 s1, const F32 s2)
383 {
384 mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2);
385 mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
386 }
387
388 F32 getFalloff() const
389 {
390 return mFalloff;
391 }
392
393 void setFalloff(const F32 fo)
394 {
395 mFalloff = fo;
396 }
397
398 F32 getAbsCoef() const
399 {
400 return mAbsCoef;
401 }
402
403 inline static F32 calcFalloff(const F32 h)
404 {
405 return (h <= 0) ? 1.0f : (F32)LL_FAST_EXP(-ATM_EXP_FALLOFF * h);
406 }
407
408 inline LLColor3 calcSigSca(const F32 h) const
409 {
410 return calcFalloff(h * mFalloff) * mSigSca;
411 }
412
413 inline void calcSigSca(const F32 h, LLColor3 &result) const
414 {
415 result = mSigSca;
416 result *= calcFalloff(h * mFalloff);
417 }
418
419 LLColor3 calcSigExt(const F32 h) const
420 {
421 return calcFalloff(h * mFalloff) * (1 + mAbsCoef) * mSigSca;
422 }
423
424 F32 calcPhase(const F32 cos_theta) const;
425
426 static inline LLColor3 calcAirSca(const F32 h);
427 static inline void calcAirSca(const F32 h, LLColor3 &result);
428 static LLColor3 calcAirScaSeaLevel() { return gAirScaSeaLevel; }
429 static const LLColor3 &getAirScaSeaLevel() { return sAirScaSeaLevel; }
430public:
431 static LLColor3 sAirScaSeaLevel;
432
433protected:
434 F32 mG;
435 LLColor3 mSigSca;
436 F32 mFalloff; // 1 - slow, >1 - faster
437 F32 mAbsCoef;
438};
439
440class LLTranspMap
441{
442public:
443 LLTranspMap() : mElevation(0), mMaxAngle(0), mStep(5), mHaze(NULL), mT(NULL) {}
444 ~LLTranspMap()
445 {
446 delete[] mT;
447 mT = NULL;
448 }
449
450 void init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze);
451
452 F32 calcHeight(const LLVector3& pos) const
453 {
454 return pos.magVec() - EARTH_RADIUS ;
455 }
456
457 BOOL hasHaze() const
458 {
459 return mHaze != NULL;
460 }
461
462 LLColor3 calcSigExt(const F32 h) const
463 {
464 return LLHaze::calcAirSca(h) + (hasHaze() ? mHaze->calcSigExt(h) : LLColor3(0, 0, 0));
465 }
466
467 inline void calcAirTransp(const F32 cos_angle, LLColor3 &result) const;
468 LLColor3 calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const;
469 LLColor3 getHorizonAirTransp () const { return mT[mMapSize-1]; }
470 F32 hitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const;
471
472protected:
473 F32 mAtmHeight;
474 F32 mElevation;
475 F32 mMaxAngle;
476 F32 mCosMaxAngle;
477 F32 mStep;
478 F32 mStepInv;
479 S32 mMapSize;
480 const LLHaze *mHaze;
481 LLColor3 *mT; // transparency values in all directions
482 //starting with mAngleBelowHorz at mElevation
483};
484
485class LLTranspMapSet
486{
487protected:
488 F32 *mHeights;
489 LLTranspMap *mTransp;
490 S32 mSize;
491 F32 mMediaHeight;
492 const LLHaze *mHaze;
493 S32 lerp(F32& dt, S32& indx, const F32 h) const;
494public:
495 LLTranspMapSet() : mHeights(NULL), mTransp(NULL), mHaze(NULL) {}
496 ~LLTranspMapSet();
497
498 void init (S32 size, F32 first_step, F32 media_height, const LLHaze* const haze);
499 S32 getSize() const { return mSize; }
500 F32 getMediaHeight() const { return mMediaHeight; }
501 const LLTranspMap& getLastTransp() const { return mTransp[mSize-1]; }
502 F32 getLastHeight() const { return mHeights[mSize-1]; }
503 const LLTranspMap& getMap(const S32 n) const { return mTransp[n]; }
504 F32 getHeight(const S32 n) const { return mHeights[n]; }
505 BOOL isReady() const { return mTransp != NULL; }
506
507 inline LLColor3 calcTransp(const F32 cos_angle, const F32 h) const;
508 inline void calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const;
509};
510
511class LLCubeMap;
512
513
514class LLVOSky : public LLViewerObject
515{
516public:
517 enum
518 {
519 FACE_SIDE0,
520 FACE_SIDE1,
521 FACE_SIDE2,
522 FACE_SIDE3,
523 FACE_SIDE4,
524 FACE_SIDE5,
525 FACE_SUN, // was 6
526 FACE_MOON, // was 7
527 FACE_BLOOM, // was 8
528 FACE_REFLECTION, // was 10
529 FACE_COUNT
530 };
531
532 LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
533 virtual ~LLVOSky();
534
535 // Initialize/delete data that's only inited once per class.
536 static void initClass();
537 void init();
538 void initCubeMap();
539 void initEmpty();
540 BOOL isReady() const { return mTransp.isReady(); }
541 const LLTranspMapSet& getTransp() const { return mTransp; }
542
543 void cleanupGL();
544 void restoreGL();
545
546 /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
547 BOOL updateSky();
548
549 // Graphical stuff for objects - maybe broken out into render class
550 // later?
551 /*virtual*/ void updateTextures(LLAgent &agent);
552 /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
553 /*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
554
555 void initSkyTextureDirs(const S32 side, const S32 tile);
556 void createSkyTexture(const S32 side, const S32 tile);
557
558 void updateBrightestDir();
559 void calcBrightnessScaleAndColors();
560
561 LLColor3 calcSkyColorInDir(const LLVector3& dir);
562 void calcSkyColorInDir(LLColor3& res, LLColor3& transp,
563 const LLVector3& dir) const;
564 LLColor4 calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exag) const;
565 void calcInScatter( LLColor3& res, LLColor3& transp,
566 const LLVector3& P, F32 exag) const;
567
568 // Not currently used.
569 //LLColor3 calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const;
570 //void calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 dist) const;
571
572 LLColor3 calcRadianceAtPoint(const LLVector3& pos) const
573 {
574 const F32 cos_angle = calcUpVec(pos) * getToSunLast();
575 LLColor3 tr;
576 mTransp.calcTransp(cos_angle, calcHeight(pos), tr);
577 return mBrightnessScaleGuess * mSun.getIntensity() * tr;
578 }
579
580 const LLHeavenBody& getSun() const { return mSun; }
581 const LLHeavenBody& getMoon() const { return mMoon; }
582
583 const LLVector3& getToSunLast() const { return mSun.getDirectionCached(); }
584 const LLVector3& getToSun() const { return mSun.getDirection(); }
585 const LLVector3& getToMoon() const { return mMoon.getDirection(); }
586 const LLVector3& getToMoonLast() const { return mMoon.getDirectionCached(); }
587 BOOL isSunUp() const { return mSun.getDirectionCached().mV[2] > -0.05f; }
588 void calculateColors();
589
590 LLColor3 getSunDiffuseColor() const { return mSunDiffuse; }
591 LLColor3 getMoonDiffuseColor() const { return mMoonDiffuse; }
592 LLColor4 getSunAmbientColor() const { return mSunAmbient; }
593 LLColor4 getMoonAmbientColor() const { return mMoonAmbient; }
594 const LLColor4& getTotalAmbientColor() const { return mTotalAmbient; }
595 LLColor4 getFogColor() const { return mFogColor; }
596
597 LLVector3 calcUpVec(const LLVector3 &pos) const
598 {
599 LLVector3 v = pos - mEarthCenter;
600 v.normVec();
601 return v;
602 }
603
604 F32 calcHeight(const LLVector3& pos) const
605 {
606 return dist_vec(pos, mEarthCenter) - EARTH_RADIUS;
607 }
608
609 // Phase function for atmospheric scattering.
610 // co = cos ( theta )
611 F32 calcAirPhaseFunc(const F32 co) const
612 {
613 return (0.75f * (1.f + co*co));
614 }
615
616
617 BOOL isSameFace(S32 idx, const LLFace* face) const { return mFace[idx] == face; }
618
619 void initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
620 {
621 LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
622 sun_direction.normVec();
623 mSun.setDirection(sun_direction);
624 mSun.renewDirection();
625 mSun.setAngularVelocity(sun_ang_velocity);
626 mMoon.setDirection(-mSun.getDirection());
627 mMoon.renewDirection();
628 mLastLightingDirection = mSun.getDirection();
629
630 if ( !isReady() )
631 {
632 init();
633 LLSkyTex::stepCurrent();
634 }
635 }
636
637 void setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity);
638
639 void updateHaze();
640
641 BOOL updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 side, const BOOL is_sun,
642 LLHeavenBody& hb, const F32 sin_max_angle,
643 const LLVector3 &up, const LLVector3 &right);
644
645 LLVector3 toHorizon(const LLVector3& dir, F32 delta = 0) const
646 {
647 return move_vec(dir, cosHorizon(delta));
648 }
649 F32 cosHorizon(const F32 delta = 0) const
650 {
651 const F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mCameraPosAgent.mV[2]);
652 return delta - (F32)sqrt(1.f - sin_angle * sin_angle);
653 }
654
655 void updateSunHaloGeometry(LLDrawable *drawable);
656 void updateReflectionGeometry(LLDrawable *drawable, F32 H, const LLHeavenBody& HB);
657
658
659 const LLHaze& getHaze() const { return mHaze; }
660 LLHaze& getHaze() { return mHaze; }
661 F32 getHazeConcentration() const { return mHazeConcentration; }
662 void setHaze(const LLHaze& h) { mHaze = h; }
663 F32 getWorldScale() const { return mWorldScale; }
664 void setWorldScale(const F32 s) { mWorldScale = s; }
665 void updateFog(const F32 distance);
666 void setFogRatio(const F32 fog_ratio) { mFogRatio = fog_ratio; }
667 LLColor4U getFadeColor() const { return mFadeColor; }
668 F32 getFogRatio() const { return mFogRatio; }
669 void setCloudDensity(F32 cloud_density) { mCloudDensity = cloud_density; }
670 void setWind ( const LLVector3& wind ) { mWind = wind.magVec(); }
671
672 const LLVector3 &getCameraPosAgent() const { return mCameraPosAgent; }
673 LLVector3 getEarthCenter() const { return mEarthCenter; }
674
675 LLCubeMap *getCubeMap() const { return mCubeMap; }
676 S32 getDrawRefl() const { return mDrawRefl; }
677 void setDrawRefl(const S32 r) { mDrawRefl = r; }
678 BOOL isReflFace(const LLFace* face) const { return face == mFace[FACE_REFLECTION]; }
679 LLFace* getReflFace() const { return mFace[FACE_REFLECTION]; }
680
681 F32 calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const;
682 F32 calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const;
683 LLViewerImage* getSunTex() const { return mSunTexturep; }
684 LLViewerImage* getMoonTex() const { return mMoonTexturep; }
685 LLViewerImage* getBloomTex() const { return mBloomTexturep; }
686
687 void generateScatterMap();
688 LLImageGL* getScatterMap() { return mScatterMap; }
689
690public:
691 static F32 sNighttimeBrightness; // [0,2] default = 1.0
692
693protected:
694 LLPointer<LLViewerImage> mSunTexturep;
695 LLPointer<LLViewerImage> mMoonTexturep;
696 LLPointer<LLViewerImage> mBloomTexturep;
697
698 static S32 sResolution;
699 static S32 sTileResX;
700 static S32 sTileResY;
701 LLSkyTex mSkyTex[6];
702 LLHeavenBody mSun;
703 LLHeavenBody mMoon;
704 LLVector3 mSunDefaultPosition;
705 LLVector3 mSunAngVel;
706 F32 mAtmHeight;
707 LLVector3 mEarthCenter;
708 LLVector3 mCameraPosAgent;
709 F32 mBrightnessScale;
710 LLColor3 mBrightestPoint;
711 F32 mBrightnessScaleNew;
712 LLColor3 mBrightestPointNew;
713 F32 mBrightnessScaleGuess;
714 LLColor3 mBrightestPointGuess;
715 LLTranspMapSet mTransp;
716 LLHaze mHaze;
717 F32 mHazeConcentration;
718 BOOL mWeatherChange;
719 F32 mCloudDensity;
720 F32 mWind;
721 LLFace *mFace[FACE_COUNT];
722
723 BOOL mInitialized;
724 BOOL mForceUpdate; //flag to force instantaneous update of cubemap
725 LLVector3 mLastLightingDirection;
726 LLColor3 mLastTotalAmbient;
727 F32 mAmbientScale;
728 LLColor3 mNightColorShift;
729 F32 sInterpVal;
730
731 LLColor4 mFogColor;
732 F32 mFogRatio;
733 F32 mWorldScale;
734
735 LLColor4 mSunAmbient;
736 LLColor4 mMoonAmbient;
737 LLColor4 mTotalAmbient;
738 LLColor3 mSunDiffuse;
739 LLColor3 mMoonDiffuse;
740 LLColor4U mFadeColor; // Color to fade in from
741
742 LLCubeMap *mCubeMap; // Cube map for the sky
743 S32 mDrawRefl;
744
745 LLFrameTimer mUpdateTimer;
746
747 LLPointer<LLImageGL> mScatterMap;
748 LLPointer<LLImageRaw> mScatterMapRaw;
749};
750
751// Utility functions
752F32 azimuth(const LLVector3 &v);
753F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
754
755
756/* Proportion of light that is scattered into 'path' from 'in' over distance dt. */
757/* assumes that vectors 'path' and 'in' are normalized. Scattering coef / 2pi */
758
759inline LLColor3 LLHaze::calcAirSca(const F32 h)
760{
761 static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
762 return calcFalloff(h) * air_sca_sea_level;
763}
764
765inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result)
766{
767 static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
768 result = air_sca_sea_level;
769 result *= calcFalloff(h);
770}
771
772// Given cos of the angle between direction of interest and zenith,
773// compute transparency by interpolation of known values.
774inline void LLTranspMap::calcAirTransp(const F32 cos_angle, LLColor3 &result) const
775{
776 if (cos_angle > 1.f)
777 {
778 result = mT[0];
779 return;
780 }
781 if (cos_angle < mCosMaxAngle - 0.1f)
782 {
783 result.setVec(0.f, 0.f, 0.f);
784 return;
785 }
786 if (cos_angle < mCosMaxAngle)
787 {
788 result = mT[mMapSize-1];
789 return;
790 }
791
792
793 const F32 relative = (1 - cos_angle)*mStepInv;
794 const S32 index = llfloor(relative);
795 const F32 dt = relative - index;
796
797 if (index >= (mMapSize-1))
798 {
799 result = mT[0];
800 return;
801 }
802// result = mT[index];
803// LLColor3 res2(mT[index+1]);
804// result *= 1 - dt;
805// res2 *= dt;
806// result += res2;
807
808 const LLColor3& color1 = mT[index];
809 const LLColor3& color2 = mT[index + 1];
810
811 const F32 x1 = color1.mV[VX];
812 const F32 x2 = color2.mV[VX];
813 result.mV[VX] = x1 - dt * (x1 - x2);
814
815 const F32 y1 = color1.mV[VY];
816 const F32 y2 = color2.mV[VY];
817 result.mV[VY] = y1 - dt * (y1 - y2);
818
819 const F32 z1 = color1.mV[VZ];
820 const F32 z2 = color2.mV[VZ];
821 result.mV[VZ] = z1 - dt * (z1 - z2);
822}
823
824
825
826// Returns the translucency of the atmosphere along the ray in the sky.
827// dir is assumed to be normalized
828inline void LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const
829{
830 S32 indx = 0;
831 F32 dt = 0.f;
832 const S32 status = lerp(dt, indx, h);
833
834 if (status < 0)
835 {
836 mTransp[0].calcAirTransp(cos_angle, result);
837 return;
838 }
839 if (status > 0)
840 {
841 mTransp[NO_STEPS].calcAirTransp(cos_angle, result);
842 return;
843 }
844
845 mTransp[indx].calcAirTransp(cos_angle, result);
846 result *= 1 - dt;
847
848 LLColor3 transp_above;
849
850 mTransp[indx + 1].calcAirTransp(cos_angle, transp_above);
851 transp_above *= dt;
852 result += transp_above;
853}
854
855
856inline LLColor3 LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h) const
857{
858 LLColor3 result;
859 S32 indx = 0;
860 F32 dt = 0;
861 const S32 status = lerp(dt, indx, h);
862
863 if (status < 0)
864 {
865 mTransp[0].calcAirTransp(cos_angle, result);
866 return result;
867 }
868 if (status > 0)
869 {
870 mTransp[NO_STEPS].calcAirTransp(cos_angle, result);
871 return result;
872 }
873
874 mTransp[indx].calcAirTransp(cos_angle, result);
875 result *= 1 - dt;
876
877 LLColor3 transp_above;
878
879 mTransp[indx + 1].calcAirTransp(cos_angle, transp_above);
880 transp_above *= dt;
881 result += transp_above;
882 return result;
883}
884
885
886// Returns -1 if height < 0; +1 if height > max height; 0 if within range
887inline S32 LLTranspMapSet::lerp(F32& dt, S32& indx, const F32 h) const
888{
889 static S32 last_indx = 0;
890
891 if (h < 0)
892 {
893 return -1;
894 }
895 if (h > getLastHeight())
896 {
897 return 1;
898 }
899
900 if (h < mHeights[last_indx])
901 {
902 indx = last_indx-1;
903 while (mHeights[indx] > h)
904 {
905 indx--;
906 }
907 last_indx = indx;
908 }
909 else if (h > mHeights[last_indx+1])
910 {
911 indx = last_indx+1;
912 while (mHeights[indx+1] < h)
913 {
914 indx++;
915 }
916 last_indx = indx;
917 }
918 else
919 {
920 indx = last_indx;
921 }
922
923 const F32 h_below = mHeights[indx];
924 const F32 h_above = mHeights[indx+1];
925 dt = (h - h_below) / (h_above - h_below);
926 return 0;
927}
928
929#endif