00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llmath.h"
00035
00036 #include "v3math.h"
00037 #include "v4math.h"
00038 #include "llquaternion.h"
00039 #include "v4color.h"
00040
00041 #include "llwind.h"
00042 #include "llcloud.h"
00043 #include "llgl.h"
00044 #include "llviewerobjectlist.h"
00045 #include "llvoclouds.h"
00046 #include "llvosky.h"
00047 #include "llsky.h"
00048 #include "llviewerregion.h"
00049 #include "patch_dct.h"
00050 #include "patch_code.h"
00051 #include "llglheaders.h"
00052 #include "pipeline.h"
00053 #include "lldrawpool.h"
00054 #include "llworld.h"
00055
00056 extern LLPipeline gPipeline;
00057
00058 const F32 CLOUD_UPDATE_RATE = 1.0f;
00059 const F32 CLOUD_GROW_RATE = 0.05f;
00060 const F32 CLOUD_DECAY_RATE = -0.05f;
00061 const F32 CLOUD_VELOCITY_SCALE = 0.01f;
00062 const F32 CLOUD_DENSITY = 25.f;
00063 const S32 CLOUD_COUNT_MAX = 20;
00064 const F32 CLOUD_HEIGHT_RANGE = 48.f;
00065 const F32 CLOUD_HEIGHT_MEAN = 192.f;
00066
00067 enum
00068 {
00069 LL_PUFF_GROWING = 0,
00070 LL_PUFF_DYING = 1
00071 };
00072
00073
00074 S32 gBuffer[16*16];
00075
00076
00077
00078 S32 LLCloudPuff::sPuffCount = 0;
00079
00080 LLCloudPuff::LLCloudPuff() :
00081 mAlpha(0.01f),
00082 mRate(CLOUD_GROW_RATE*CLOUD_UPDATE_RATE),
00083 mLifeState(LL_PUFF_GROWING)
00084 {
00085 }
00086
00087 LLCloudGroup::LLCloudGroup() :
00088 mCloudLayerp(NULL),
00089 mDensity(0.f),
00090 mTargetPuffCount(0),
00091 mVOCloudsp(NULL)
00092 {
00093 }
00094
00095 void LLCloudGroup::cleanup()
00096 {
00097 if (mVOCloudsp)
00098 {
00099 if (!mVOCloudsp->isDead())
00100 {
00101 gObjectList.killObject(mVOCloudsp);
00102 }
00103 mVOCloudsp = NULL;
00104 }
00105 }
00106
00107 void LLCloudGroup::setCenterRegion(const LLVector3 ¢er)
00108 {
00109 mCenterRegion = center;
00110 }
00111
00112 void LLCloudGroup::updatePuffs(const F32 dt)
00113 {
00114 mDensity = mCloudLayerp->getDensityRegion(mCenterRegion);
00115
00116 if (!mVOCloudsp)
00117 {
00118 mVOCloudsp = (LLVOClouds *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_CLOUDS, mCloudLayerp->getRegion());
00119 mVOCloudsp->setCloudGroup(this);
00120 mVOCloudsp->setPositionRegion(mCenterRegion);
00121 mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
00122 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
00123 CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f);
00124 gPipeline.addObject(mVOCloudsp);
00125 }
00126
00127 LLVector3 velocity;
00128 LLVector3d vel_d;
00129
00130 for (U32 i = 0; i < mCloudPuffs.size(); i++)
00131 {
00132 LLCloudPuff &puff = mCloudPuffs[i];
00133 velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal));
00134 velocity *= CLOUD_VELOCITY_SCALE*CLOUD_UPDATE_RATE;
00135 vel_d.setVec(velocity);
00136 mCloudPuffs[i].mPositionGlobal += vel_d;
00137 mCloudPuffs[i].mAlpha += mCloudPuffs[i].mRate * dt;
00138 mCloudPuffs[i].mAlpha = llmin(1.f, mCloudPuffs[i].mAlpha);
00139 mCloudPuffs[i].mAlpha = llmax(0.f, mCloudPuffs[i].mAlpha);
00140 }
00141 }
00142
00143 void LLCloudGroup::updatePuffOwnership()
00144 {
00145 U32 i = 0;
00146 while (i < mCloudPuffs.size())
00147 {
00148 if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING)
00149 {
00150 i++;
00151 continue;
00152 }
00153 if (inGroup(mCloudPuffs[i]))
00154 {
00155 i++;
00156 continue;
00157 }
00158
00159
00160 LLCloudGroup *new_cgp = gWorldPointer->findCloudGroup(mCloudPuffs[i]);
00161 if (!new_cgp)
00162 {
00163
00164 mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
00165 mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
00166 i++;
00167 continue;
00168 }
00169
00170 LLCloudPuff puff;
00171 puff.mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
00172 puff.mAlpha = mCloudPuffs[i].mAlpha;
00173 mCloudPuffs.erase(mCloudPuffs.begin() + i);
00174 new_cgp->mCloudPuffs.push_back(puff);
00175 }
00176
00177
00178 }
00179
00180 void LLCloudGroup::updatePuffCount()
00181 {
00182 if (!mVOCloudsp)
00183 {
00184 return;
00185 }
00186 S32 i;
00187 S32 target_puff_count = llround(CLOUD_DENSITY * mDensity);
00188 target_puff_count = llmax(0, target_puff_count);
00189 target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count);
00190 S32 current_puff_count = (S32) mCloudPuffs.size();
00191
00192 if (current_puff_count < target_puff_count)
00193 {
00194 LLVector3d puff_pos_global;
00195 mCloudPuffs.resize(target_puff_count);
00196 for (i = current_puff_count; i < target_puff_count; i++)
00197 {
00198 puff_pos_global = mVOCloudsp->getPositionGlobal();
00199 F32 x = ll_frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
00200 F32 y = ll_frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
00201 F32 z = ll_frand(CLOUD_HEIGHT_RANGE) - 0.5f*CLOUD_HEIGHT_RANGE;
00202 puff_pos_global += LLVector3d(x, y, z);
00203 mCloudPuffs[i].mPositionGlobal = puff_pos_global;
00204 mCloudPuffs[i].mAlpha = 0.01f;
00205 LLCloudPuff::sPuffCount++;
00206 }
00207 }
00208
00209
00210 S32 live_puff_count = 0;
00211 for (i = 0; i < (S32) mCloudPuffs.size(); i++)
00212 {
00213 if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
00214 {
00215 live_puff_count++;
00216 }
00217 }
00218
00219
00220
00221 S32 new_dying_count = llmax(0, live_puff_count - target_puff_count);
00222 i = 0;
00223 while (new_dying_count > 0)
00224 {
00225 if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
00226 {
00227
00228 mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
00229 mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
00230 new_dying_count--;
00231 }
00232 i++;
00233 }
00234
00235
00236 i = 0;
00237 while (i < (S32) mCloudPuffs.size())
00238 {
00239 if (mCloudPuffs[i].isDead())
00240 {
00241
00242 mCloudPuffs.erase(mCloudPuffs.begin() + i);
00243 LLCloudPuff::sPuffCount--;
00244 }
00245 else
00246 {
00247 i++;
00248 }
00249 }
00250 }
00251
00252 BOOL LLCloudGroup::inGroup(const LLCloudPuff &puff) const
00253 {
00254
00255 F32 min_x, min_y, max_x, max_y;
00256 F32 delta = 128.f/CLOUD_GROUPS_PER_EDGE;
00257 min_x = mCenterRegion.mV[VX] - delta;
00258 min_y = mCenterRegion.mV[VY] - delta;
00259 max_x = mCenterRegion.mV[VX] + delta;
00260 max_y = mCenterRegion.mV[VY] + delta;
00261
00262 LLVector3 pos_region = mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.getPositionGlobal());
00263
00264 if ((pos_region.mV[VX] < min_x)
00265 || (pos_region.mV[VY] < min_y)
00266 || (pos_region.mV[VX] > max_x)
00267 || (pos_region.mV[VY] > max_y))
00268 {
00269 return FALSE;
00270 }
00271 return TRUE;
00272 }
00273
00274 LLCloudLayer::LLCloudLayer()
00275 : mOriginGlobal(0.0f, 0.0f, 0.0f),
00276 mMetersPerEdge(1.0f),
00277 mMetersPerGrid(1.0f),
00278 mWindp(NULL),
00279 mDensityp(NULL)
00280 {
00281 S32 i, j;
00282 for (i = 0; i < 4; i++)
00283 {
00284 mNeighbors[i] = NULL;
00285 }
00286
00287 F32 x, y;
00288 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00289 {
00290 y = (0.5f + i)*(256.f/CLOUD_GROUPS_PER_EDGE);
00291 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00292 {
00293 x = (0.5f + j)*(256.f/CLOUD_GROUPS_PER_EDGE);
00294
00295 mCloudGroups[i][j].setCloudLayerp(this);
00296 mCloudGroups[i][j].setCenterRegion(LLVector3(x, y, CLOUD_HEIGHT_MEAN));
00297 }
00298 }
00299 }
00300
00301
00302
00303 LLCloudLayer::~LLCloudLayer()
00304 {
00305 destroy();
00306 }
00307
00308
00309 void LLCloudLayer::create(LLViewerRegion *regionp)
00310 {
00311 llassert(regionp);
00312
00313 mRegionp = regionp;
00314 mDensityp = new F32 [CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE];
00315
00316 U32 i;
00317 for (i = 0; i < CLOUD_GRIDS_PER_EDGE*CLOUD_GRIDS_PER_EDGE; i++)
00318 {
00319 mDensityp[i] = 0.f;
00320 }
00321 }
00322
00323 void LLCloudLayer::setRegion(LLViewerRegion *regionp)
00324 {
00325 mRegionp = regionp;
00326 }
00327
00328 void LLCloudLayer::destroy()
00329 {
00330
00331 S32 i, j;
00332
00333 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00334 {
00335 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00336 {
00337 mCloudGroups[i][j].cleanup();
00338 }
00339 }
00340
00341 delete [] mDensityp;
00342 mDensityp = NULL;
00343 mWindp = NULL;
00344 }
00345
00346
00347 void LLCloudLayer::reset()
00348 {
00349 }
00350
00351
00352 void LLCloudLayer::setWindPointer(LLWind *windp)
00353 {
00354 if (mWindp)
00355 {
00356 mWindp->setCloudDensityPointer(NULL);
00357 }
00358 mWindp = windp;
00359 if (mWindp)
00360 {
00361 mWindp->setCloudDensityPointer(mDensityp);
00362 }
00363 }
00364
00365
00366 void LLCloudLayer::setWidth(F32 width)
00367 {
00368 mMetersPerEdge = width;
00369 mMetersPerGrid = width / CLOUD_GRIDS_PER_EDGE;
00370 }
00371
00372
00373 F32 LLCloudLayer::getDensityRegion(const LLVector3 &pos_region)
00374 {
00375
00376 S32 i, j, ii, jj;
00377
00378 i = lltrunc(pos_region.mV[VX] / mMetersPerGrid);
00379 j = lltrunc(pos_region.mV[VY] / mMetersPerGrid);
00380 ii = i + 1;
00381 jj = j + 1;
00382
00383
00384
00385 if (i >= (S32)CLOUD_GRIDS_PER_EDGE)
00386 {
00387 i = CLOUD_GRIDS_PER_EDGE - 1;
00388 ii = i;
00389 }
00390 else if (i < 0)
00391 {
00392 i = 0;
00393 ii = i;
00394 }
00395 else if (ii >= (S32)CLOUD_GRIDS_PER_EDGE || ii < 0)
00396 {
00397 ii = i;
00398 }
00399
00400 if (j >= (S32)CLOUD_GRIDS_PER_EDGE)
00401 {
00402 j = CLOUD_GRIDS_PER_EDGE - 1;
00403 jj = j;
00404 }
00405 else if (j < 0)
00406 {
00407 j = 0;
00408 jj = j;
00409 }
00410 else if (jj >= (S32)CLOUD_GRIDS_PER_EDGE || jj < 0)
00411 {
00412 jj = j;
00413 }
00414
00415 F32 dx = (pos_region.mV[VX] - (F32) i * mMetersPerGrid) / mMetersPerGrid;
00416 F32 dy = (pos_region.mV[VY] - (F32) j * mMetersPerGrid) / mMetersPerGrid;
00417 F32 omdx = 1.0f - dx;
00418 F32 omdy = 1.0f - dy;
00419
00420 F32 density = dx * dy * *(mDensityp + ii + jj * CLOUD_GRIDS_PER_EDGE) +
00421 dx * omdy * *(mDensityp + i + jj * CLOUD_GRIDS_PER_EDGE) +
00422 omdx * dy * *(mDensityp + ii + j * CLOUD_GRIDS_PER_EDGE) +
00423 omdx * omdy * *(mDensityp + i + j * CLOUD_GRIDS_PER_EDGE);
00424
00425 return density;
00426 }
00427
00428
00429 void LLCloudLayer::renderDensityField()
00430 {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 }
00461
00462
00463 void LLCloudLayer::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
00464 {
00465 LLPatchHeader patch_header;
00466
00467 init_patch_decompressor(group_headerp->patch_size);
00468
00469
00470
00471 group_headerp->stride = group_headerp->patch_size;
00472 set_group_of_patch_header(group_headerp);
00473
00474 decode_patch_header(bitpack, &patch_header);
00475 decode_patch(bitpack, gBuffer);
00476 decompress_patch(mDensityp, gBuffer, &patch_header);
00477 }
00478
00479 void LLCloudLayer::updatePuffs(const F32 dt)
00480 {
00481
00482
00483
00484 S32 i, j;
00485
00486 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00487 {
00488 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00489 {
00490 mCloudGroups[i][j].updatePuffs(dt);
00491 }
00492 }
00493 }
00494
00495 void LLCloudLayer::updatePuffOwnership()
00496 {
00497 S32 i, j;
00498
00499 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00500 {
00501 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00502 {
00503 mCloudGroups[i][j].updatePuffOwnership();
00504 }
00505 }
00506 }
00507
00508 void LLCloudLayer::updatePuffCount()
00509 {
00510 S32 i, j;
00511
00512 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00513 {
00514 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00515 {
00516 mCloudGroups[i][j].updatePuffCount();
00517 }
00518 }
00519 }
00520
00521 LLCloudGroup *LLCloudLayer::findCloudGroup(const LLCloudPuff &puff)
00522 {
00523 S32 i, j;
00524
00525 for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
00526 {
00527 for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
00528 {
00529 if (mCloudGroups[i][j].inGroup(puff))
00530 {
00531 return &(mCloudGroups[i][j]);
00532 }
00533 }
00534 }
00535 return NULL;
00536 }
00537
00538
00539
00540 void LLCloudLayer::connectNeighbor(LLCloudLayer *cloudp, U32 direction)
00541 {
00542 if (direction >= 4)
00543 {
00544
00545 return;
00546 }
00547
00548 mNeighbors[direction] = cloudp;
00549 if (cloudp)
00550 mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = this;
00551 }
00552
00553
00554 void LLCloudLayer::disconnectNeighbor(U32 direction)
00555 {
00556 if (direction >= 4)
00557 {
00558
00559 return;
00560 }
00561
00562 if (mNeighbors[direction])
00563 {
00564 mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL;
00565 mNeighbors[direction] = NULL;
00566 }
00567 }
00568
00569
00570 void LLCloudLayer::disconnectAllNeighbors()
00571 {
00572 S32 i;
00573 for (i = 0; i < 4; i++)
00574 {
00575 disconnectNeighbor(i);
00576 }
00577 }