diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvosky.h | |
parent | README.txt (diff) | |
download | meta-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.h | 929 |
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 | |||
46 | const F32 HORIZON_DIST = 1024.0f; | ||
47 | const F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 10.f; | ||
48 | const F32 HEAVENLY_BODY_FACTOR = 0.1f; | ||
49 | const F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR; | ||
50 | const F32 EARTH_RADIUS = 6.4e6f; // exact radius = 6.37 x 10^6 m | ||
51 | const F32 ATM_EXP_FALLOFF = 0.000126f; | ||
52 | const F32 ATM_SEA_LEVEL_NDENS = 2.55e25f; | ||
53 | // Somewhat arbitrary: | ||
54 | const F32 ATM_HEIGHT = 100000.f; | ||
55 | |||
56 | const F32 FIRST_STEP = 5000.f; | ||
57 | const F32 INV_FIRST_STEP = 1.f/FIRST_STEP; | ||
58 | const S32 NO_STEPS = 15; | ||
59 | const F32 INV_NO_STEPS = 1.f/NO_STEPS; | ||
60 | |||
61 | |||
62 | // constants used in calculation of scattering coeff of clear air | ||
63 | const F32 sigma = 0.035f; | ||
64 | const F32 fsigma = (6+3*sigma)/(6.f-7.f*sigma); | ||
65 | const F64 Ndens = 2.55e25; | ||
66 | const 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 | |||
84 | LLColor3 color_norm(const LLColor3 &col); | ||
85 | LLVector3 move_vec (const LLVector3& v, F32 cos_max_angle); | ||
86 | BOOL 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); | ||
88 | F32 clip_side_to_horizon(const LLVector3& v0, const LLVector3& v1, const F32 cos_max_angle); | ||
89 | |||
90 | inline F32 color_intens ( const LLColor3 &col ) | ||
91 | { | ||
92 | return col.mV[0] + col.mV[1] + col.mV[2]; | ||
93 | } | ||
94 | |||
95 | inline F32 color_max(const LLColor3 &col) | ||
96 | { | ||
97 | return llmax(col.mV[0], col.mV[1], col.mV[2]); | ||
98 | } | ||
99 | |||
100 | inline F32 color_max(const LLColor4 &col) | ||
101 | { | ||
102 | return llmax(col.mV[0], col.mV[1], col.mV[2]); | ||
103 | } | ||
104 | |||
105 | |||
106 | inline F32 color_min(const LLColor3 &col) | ||
107 | { | ||
108 | return llmin(col.mV[0], col.mV[1], col.mV[2]); | ||
109 | } | ||
110 | |||
111 | inline 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 | |||
123 | class LLFace; | ||
124 | class LLHaze; | ||
125 | |||
126 | |||
127 | class LLSkyTex | ||
128 | { | ||
129 | friend class LLVOSky; | ||
130 | private: | ||
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 | |||
140 | public: | ||
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 | |||
147 | protected: | ||
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 | |||
204 | class LLHeavenBody | ||
205 | { | ||
206 | protected: | ||
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 | |||
226 | public: | ||
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 | |||
341 | const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level(); | ||
342 | const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel); | ||
343 | const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3; | ||
344 | |||
345 | class LLHaze | ||
346 | { | ||
347 | public: | ||
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; } | ||
430 | public: | ||
431 | static LLColor3 sAirScaSeaLevel; | ||
432 | |||
433 | protected: | ||
434 | F32 mG; | ||
435 | LLColor3 mSigSca; | ||
436 | F32 mFalloff; // 1 - slow, >1 - faster | ||
437 | F32 mAbsCoef; | ||
438 | }; | ||
439 | |||
440 | class LLTranspMap | ||
441 | { | ||
442 | public: | ||
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 | |||
472 | protected: | ||
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 | |||
485 | class LLTranspMapSet | ||
486 | { | ||
487 | protected: | ||
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; | ||
494 | public: | ||
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 | |||
511 | class LLCubeMap; | ||
512 | |||
513 | |||
514 | class LLVOSky : public LLViewerObject | ||
515 | { | ||
516 | public: | ||
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 | |||
690 | public: | ||
691 | static F32 sNighttimeBrightness; // [0,2] default = 1.0 | ||
692 | |||
693 | protected: | ||
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 | ||
752 | F32 azimuth(const LLVector3 &v); | ||
753 | F32 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 | |||
759 | inline 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 | |||
765 | inline 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. | ||
774 | inline 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 | ||
828 | inline 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 | |||
856 | inline 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 | ||
887 | inline 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 | ||