aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llcloud.cpp
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/llcloud.cpp
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/llcloud.cpp')
-rw-r--r--linden/indra/newview/llcloud.cpp574
1 files changed, 574 insertions, 0 deletions
diff --git a/linden/indra/newview/llcloud.cpp b/linden/indra/newview/llcloud.cpp
new file mode 100644
index 0000000..e1b2281
--- /dev/null
+++ b/linden/indra/newview/llcloud.cpp
@@ -0,0 +1,574 @@
1/**
2 * @file llcloud.cpp
3 * @brief Implementation of viewer LLCloudLayer class
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#include "llviewerprecompiledheaders.h"
29
30#include "llmath.h"
31//#include "vmath.h"
32#include "v3math.h"
33#include "v4math.h"
34#include "llquaternion.h"
35#include "v4color.h"
36
37#include "llwind.h"
38#include "llcloud.h"
39#include "llgl.h"
40#include "llviewerobjectlist.h"
41#include "llvoclouds.h"
42#include "llvosky.h"
43#include "llsky.h"
44#include "llviewerregion.h"
45#include "patch_dct.h"
46#include "patch_code.h"
47#include "llglheaders.h"
48#include "pipeline.h"
49#include "lldrawpool.h"
50#include "llworld.h"
51
52extern LLPipeline gPipeline;
53
54const F32 CLOUD_UPDATE_RATE = 1.0f; // Global time dilation for clouds
55const F32 CLOUD_GROW_RATE = 0.05f;
56const F32 CLOUD_DECAY_RATE = -0.05f;
57const F32 CLOUD_VELOCITY_SCALE = 0.01f;
58const F32 CLOUD_DENSITY = 25.f;
59const S32 CLOUD_COUNT_MAX = 20;
60const F32 CLOUD_HEIGHT_RANGE = 48.f;
61const F32 CLOUD_HEIGHT_MEAN = 192.f;
62
63enum
64{
65 LL_PUFF_GROWING = 0,
66 LL_PUFF_DYING = 1
67};
68
69// Used for patch decoder
70S32 gBuffer[16*16];
71
72
73//static
74S32 LLCloudPuff::sPuffCount = 0;
75
76LLCloudPuff::LLCloudPuff() :
77 mAlpha(0.01f),
78 mRate(CLOUD_GROW_RATE*CLOUD_UPDATE_RATE),
79 mLifeState(LL_PUFF_GROWING)
80{
81}
82
83LLCloudGroup::LLCloudGroup() :
84 mCloudLayerp(NULL),
85 mDensity(0.f),
86 mTargetPuffCount(0),
87 mVOCloudsp(NULL)
88{
89}
90
91void LLCloudGroup::cleanup()
92{
93 if (mVOCloudsp)
94 {
95 if (!mVOCloudsp->isDead())
96 {
97 gObjectList.killObject(mVOCloudsp);
98 }
99 mVOCloudsp = NULL;
100 }
101}
102
103void LLCloudGroup::setCenterRegion(const LLVector3 &center)
104{
105 mCenterRegion = center;
106}
107
108void LLCloudGroup::updatePuffs(const F32 dt)
109{
110 mDensity = mCloudLayerp->getDensityRegion(mCenterRegion);
111
112 if (!mVOCloudsp)
113 {
114 mVOCloudsp = (LLVOClouds *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_CLOUDS, mCloudLayerp->getRegion());
115 mVOCloudsp->setCloudGroup(this);
116 mVOCloudsp->setPositionRegion(mCenterRegion);
117 mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
118 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
119 CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT));
120 gPipeline.addObject(mVOCloudsp);
121 }
122
123 S32 i;
124
125 LLVector3 velocity;
126 LLVector3d vel_d;
127 // Update the positions of all of the clouds
128 for (i = 0; i < mCloudPuffs.count(); i++)
129 {
130 LLCloudPuff &puff = mCloudPuffs[i];
131 velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal));
132 velocity *= CLOUD_VELOCITY_SCALE*CLOUD_UPDATE_RATE;
133 vel_d.setVec(velocity);
134 mCloudPuffs[i].mPositionGlobal += vel_d;
135 mCloudPuffs[i].mAlpha += mCloudPuffs[i].mRate * dt;
136 mCloudPuffs[i].mAlpha = llmin(1.f, mCloudPuffs[i].mAlpha);
137 mCloudPuffs[i].mAlpha = llmax(0.f, mCloudPuffs[i].mAlpha);
138 }
139}
140
141void LLCloudGroup::updatePuffOwnership()
142{
143 S32 i = 0;
144 while (i < mCloudPuffs.count())
145 {
146 if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING)
147 {
148 i++;
149 continue;
150 }
151 if (inGroup(mCloudPuffs[i]))
152 {
153 i++;
154 continue;
155 }
156
157 //llinfos << "Cloud moving to new group" << llendl;
158 LLCloudGroup *new_cgp = gWorldPointer->findCloudGroup(mCloudPuffs[i]);
159 if (!new_cgp)
160 {
161 //llinfos << "Killing puff not in group" << llendl;
162 mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
163 mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
164 i++;
165 continue;
166 }
167 //llinfos << "Puff handed off!" << llendl;
168 LLCloudPuff *puffp = new_cgp->mCloudPuffs.reserve_block(1);
169 puffp->mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
170 puffp->mAlpha = mCloudPuffs[i].mAlpha;
171 mCloudPuffs.remove(i);
172 }
173
174 //llinfos << "Puff count: " << LLCloudPuff::sPuffCount << llendl;
175}
176
177void LLCloudGroup::updatePuffCount()
178{
179 if (!mVOCloudsp)
180 {
181 return;
182 }
183 S32 i;
184 S32 target_puff_count = llround(CLOUD_DENSITY * mDensity);
185 target_puff_count = llmax(0, target_puff_count);
186 target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count);
187 S32 current_puff_count = mCloudPuffs.count();
188 // Create a new cloud if we need one
189 if (current_puff_count < target_puff_count)
190 {
191 LLVector3d puff_pos_global;
192 mCloudPuffs.resize(target_puff_count);
193 for (i = current_puff_count; i < target_puff_count; i++)
194 {
195 puff_pos_global = mVOCloudsp->getPositionGlobal();
196 F32 x = frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
197 F32 y = frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
198 F32 z = frand(CLOUD_HEIGHT_RANGE) - 0.5f*CLOUD_HEIGHT_RANGE;
199 puff_pos_global += LLVector3d(x, y, z);
200 mCloudPuffs[i].mPositionGlobal = puff_pos_global;
201 mCloudPuffs[i].mAlpha = 0.01f;
202 LLCloudPuff::sPuffCount++;
203 }
204 }
205
206 // Count the number of live puffs
207 S32 live_puff_count = 0;
208 for (i = 0; i < mCloudPuffs.count(); i++)
209 {
210 if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
211 {
212 live_puff_count++;
213 }
214 }
215
216
217 // Start killing enough puffs so the live puff count == target puff count
218 S32 new_dying_count = llmax(0, live_puff_count - target_puff_count);
219 i = 0;
220 while (new_dying_count > 0)
221 {
222 if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
223 {
224 //llinfos << "Killing extra live cloud" << llendl;
225 mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
226 mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
227 new_dying_count--;
228 }
229 i++;
230 }
231
232 // Remove fully dead puffs
233 i = 0;
234 while (i < mCloudPuffs.count())
235 {
236 if (mCloudPuffs[i].isDead())
237 {
238 //llinfos << "Removing dead puff!" << llendl;
239 mCloudPuffs.remove(i);
240 LLCloudPuff::sPuffCount--;
241 }
242 else
243 {
244 i++;
245 }
246 }
247}
248
249BOOL LLCloudGroup::inGroup(const LLCloudPuff &puff) const
250{
251 // Do min/max check on center of the cloud puff
252 F32 min_x, min_y, max_x, max_y;
253 F32 delta = 128.f/CLOUD_GROUPS_PER_EDGE;
254 min_x = mCenterRegion.mV[VX] - delta;
255 min_y = mCenterRegion.mV[VY] - delta;
256 max_x = mCenterRegion.mV[VX] + delta;
257 max_y = mCenterRegion.mV[VY] + delta;
258
259 LLVector3 pos_region = mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.getPositionGlobal());
260
261 if ((pos_region.mV[VX] < min_x)
262 || (pos_region.mV[VY] < min_y)
263 || (pos_region.mV[VX] > max_x)
264 || (pos_region.mV[VY] > max_y))
265 {
266 return FALSE;
267 }
268 return TRUE;
269}
270
271LLCloudLayer::LLCloudLayer()
272: mOriginGlobal(0.0f, 0.0f, 0.0f),
273 mMetersPerEdge(1.0f),
274 mMetersPerGrid(1.0f),
275 mWindp(NULL),
276 mDensityp(NULL)
277{
278 S32 i, j;
279 for (i = 0; i < 4; i++)
280 {
281 mNeighbors[i] = NULL;
282 }
283
284 F32 x, y;
285 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
286 {
287 y = (0.5f + i)*(256.f/CLOUD_GROUPS_PER_EDGE);
288 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
289 {
290 x = (0.5f + j)*(256.f/CLOUD_GROUPS_PER_EDGE);
291
292 mCloudGroups[i][j].setCloudLayerp(this);
293 mCloudGroups[i][j].setCenterRegion(LLVector3(x, y, CLOUD_HEIGHT_MEAN));
294 }
295 }
296}
297
298
299
300LLCloudLayer::~LLCloudLayer()
301{
302 destroy();
303}
304
305
306void LLCloudLayer::create(LLViewerRegion *regionp)
307{
308 llassert(regionp);
309
310 mRegionp = regionp;
311 mDensityp = new F32 [CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE];
312
313 U32 i;
314 for (i = 0; i < CLOUD_GRIDS_PER_EDGE*CLOUD_GRIDS_PER_EDGE; i++)
315 {
316 mDensityp[i] = 0.f;
317 }
318}
319
320void LLCloudLayer::setRegion(LLViewerRegion *regionp)
321{
322 mRegionp = regionp;
323}
324
325void LLCloudLayer::destroy()
326{
327 // Kill all of the existing puffs
328 S32 i, j;
329
330 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
331 {
332 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
333 {
334 mCloudGroups[i][j].cleanup();
335 }
336 }
337
338 delete [] mDensityp;
339 mDensityp = NULL;
340 mWindp = NULL;
341}
342
343
344void LLCloudLayer::reset()
345{
346}
347
348
349void LLCloudLayer::setWindPointer(LLWind *windp)
350{
351 if (mWindp)
352 {
353 mWindp->setCloudDensityPointer(NULL);
354 }
355 mWindp = windp;
356 if (mWindp)
357 {
358 mWindp->setCloudDensityPointer(mDensityp);
359 }
360}
361
362
363void LLCloudLayer::setWidth(F32 width)
364{
365 mMetersPerEdge = width;
366 mMetersPerGrid = width / CLOUD_GRIDS_PER_EDGE;
367}
368
369
370F32 LLCloudLayer::getDensityRegion(const LLVector3 &pos_region)
371{
372 // "position" is region-local
373 S32 i, j, ii, jj;
374
375 i = lltrunc(pos_region.mV[VX] / mMetersPerGrid);
376 j = lltrunc(pos_region.mV[VY] / mMetersPerGrid);
377 ii = i + 1;
378 jj = j + 1;
379
380
381 // clamp
382 if (i >= (S32)CLOUD_GRIDS_PER_EDGE)
383 {
384 i = CLOUD_GRIDS_PER_EDGE - 1;
385 ii = i;
386 }
387 else if (i < 0)
388 {
389 i = 0;
390 ii = i;
391 }
392 else if (ii >= (S32)CLOUD_GRIDS_PER_EDGE || ii < 0)
393 {
394 ii = i;
395 }
396
397 if (j >= (S32)CLOUD_GRIDS_PER_EDGE)
398 {
399 j = CLOUD_GRIDS_PER_EDGE - 1;
400 jj = j;
401 }
402 else if (j < 0)
403 {
404 j = 0;
405 jj = j;
406 }
407 else if (jj >= (S32)CLOUD_GRIDS_PER_EDGE || jj < 0)
408 {
409 jj = j;
410 }
411
412 F32 dx = (pos_region.mV[VX] - (F32) i * mMetersPerGrid) / mMetersPerGrid;
413 F32 dy = (pos_region.mV[VY] - (F32) j * mMetersPerGrid) / mMetersPerGrid;
414 F32 omdx = 1.0f - dx;
415 F32 omdy = 1.0f - dy;
416
417 F32 density = dx * dy * *(mDensityp + ii + jj * CLOUD_GRIDS_PER_EDGE) +
418 dx * omdy * *(mDensityp + i + jj * CLOUD_GRIDS_PER_EDGE) +
419 omdx * dy * *(mDensityp + ii + j * CLOUD_GRIDS_PER_EDGE) +
420 omdx * omdy * *(mDensityp + i + j * CLOUD_GRIDS_PER_EDGE);
421
422 return density;
423}
424
425// a debug method that may yet be useful
426void LLCloudLayer::renderDensityField()
427{
428// F32 x, y, z;
429// U32 i, j, k;
430// LLGLSNoTexture gls_ui_no_texture;
431// // Render a bunch of triangles to represent the cloud density field
432// glBegin(GL_TRIANGLES);
433// for(j=0; j<CLOUD_GRIDS_PER_EDGE-1; j++)
434// {
435// y = j * mMetersPerGrid;
436
437// for(i=0; i<CLOUD_GRIDS_PER_EDGE; i++)
438// {
439// k = i + j*CLOUD_GRIDS_PER_EDGE;
440// x = i * mMetersPerGrid;
441
442// z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k + CLOUD_GRIDS_PER_EDGE);
443// glColor3f(1.0f - *(mDensityp + k + CLOUD_GRIDS_PER_EDGE), *(mDensityp + k + CLOUD_GRIDS_PER_EDGE), 0.0f);
444// glVertex3f(x, y+mMetersPerGrid, z);
445
446// z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k);
447// glColor3f(1.0f - *(mDensityp + k), *(mDensityp + k), 0.0f);
448// glVertex3f(x, y, z);
449
450// z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k + 1);
451// glColor3f(1.0f - *(mDensityp + k + 1), *(mDensityp + k + 1), 0.0f);
452// glVertex3f(x+mMetersPerGrid, y, z);
453
454// }
455// }
456// glEnd();
457}
458
459
460void LLCloudLayer::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
461{
462 LLPatchHeader patch_header;
463
464 init_patch_decompressor(group_headerp->patch_size);
465
466 // Don't use the packed group_header stride because the strides used on
467 // simulator and viewer are not equal.
468 group_headerp->stride = group_headerp->patch_size; // offset required to step up one row
469 set_group_of_patch_header(group_headerp);
470
471 decode_patch_header(bitpack, &patch_header);
472 decode_patch(bitpack, gBuffer);
473 decompress_patch(mDensityp, gBuffer, &patch_header);
474}
475
476void LLCloudLayer::updatePuffs(const F32 dt)
477{
478 // We want to iterate through all of the cloud groups
479 // and update their density targets
480
481 S32 i, j;
482
483 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
484 {
485 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
486 {
487 mCloudGroups[i][j].updatePuffs(dt);
488 }
489 }
490}
491
492void LLCloudLayer::updatePuffOwnership()
493{
494 S32 i, j;
495
496 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
497 {
498 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
499 {
500 mCloudGroups[i][j].updatePuffOwnership();
501 }
502 }
503}
504
505void LLCloudLayer::updatePuffCount()
506{
507 S32 i, j;
508
509 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
510 {
511 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
512 {
513 mCloudGroups[i][j].updatePuffCount();
514 }
515 }
516}
517
518LLCloudGroup *LLCloudLayer::findCloudGroup(const LLCloudPuff &puff)
519{
520 S32 i, j;
521
522 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
523 {
524 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
525 {
526 if (mCloudGroups[i][j].inGroup(puff))
527 {
528 return &(mCloudGroups[i][j]);
529 }
530 }
531 }
532 return NULL;
533}
534
535
536
537void LLCloudLayer::connectNeighbor(LLCloudLayer *cloudp, U32 direction)
538{
539 if (direction >= 4)
540 {
541 // Only care about cardinal 4 directions.
542 return;
543 }
544
545 mNeighbors[direction] = cloudp;
546 if (cloudp)
547 mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = this;
548}
549
550
551void LLCloudLayer::disconnectNeighbor(U32 direction)
552{
553 if (direction >= 4)
554 {
555 // Only care about cardinal 4 directions.
556 return;
557 }
558
559 if (mNeighbors[direction])
560 {
561 mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL;
562 mNeighbors[direction] = NULL;
563 }
564}
565
566
567void LLCloudLayer::disconnectAllNeighbors()
568{
569 S32 i;
570 for (i = 0; i < 4; i++)
571 {
572 disconnectNeighbor(i);
573 }
574}