llcloud.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llmath.h"
00035 //#include "vmath.h"
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;  // Global time dilation for clouds
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 // Used for patch decoder
00074 S32 gBuffer[16*16];
00075 
00076 
00077 //static
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 &center)
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         // Update the positions of all of the clouds
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                 //llinfos << "Cloud moving to new group" << llendl;
00160                 LLCloudGroup *new_cgp = gWorldPointer->findCloudGroup(mCloudPuffs[i]);
00161                 if (!new_cgp)
00162                 {
00163                         //llinfos << "Killing puff not in group" << llendl;
00164                         mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
00165                         mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
00166                         i++;
00167                         continue;
00168                 }
00169                 //llinfos << "Puff handed off!" << llendl;
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         //llinfos << "Puff count: " << LLCloudPuff::sPuffCount << llendl;
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         // Create a new cloud if we need one
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         // Count the number of live puffs
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         // Start killing enough puffs so the live puff count == target puff count
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                         //llinfos << "Killing extra live cloud" << llendl;
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         // Remove fully dead puffs
00236         i = 0;
00237         while (i < (S32) mCloudPuffs.size())
00238         {
00239                 if (mCloudPuffs[i].isDead())
00240                 {
00241                         //llinfos << "Removing dead puff!" << llendl;
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         // Do min/max check on center of the cloud puff
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         // Kill all of the existing puffs
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         // "position" is region-local
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         // clamp 
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 // a debug method that may yet be useful
00429 void LLCloudLayer::renderDensityField()
00430 {
00431 //      F32 x, y, z;
00432 //      U32 i, j, k;
00433 //      LLGLSNoTexture gls_ui_no_texture;
00434 //      // Render a bunch of triangles to represent the cloud density field
00435 //      glBegin(GL_TRIANGLES);
00436 //      for(j=0; j<CLOUD_GRIDS_PER_EDGE-1; j++)
00437 //      {
00438 //              y = j * mMetersPerGrid;
00439 
00440 //              for(i=0; i<CLOUD_GRIDS_PER_EDGE; i++)
00441 //              {
00442 //                      k = i + j*CLOUD_GRIDS_PER_EDGE;
00443 //                      x = i * mMetersPerGrid;
00444 
00445 //                      z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k + CLOUD_GRIDS_PER_EDGE);
00446 //                      glColor3f(1.0f - *(mDensityp + k + CLOUD_GRIDS_PER_EDGE), *(mDensityp + k + CLOUD_GRIDS_PER_EDGE), 0.0f);
00447 //                      glVertex3f(x, y+mMetersPerGrid, z);
00448 
00449 //                      z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k);
00450 //                      glColor3f(1.0f - *(mDensityp + k), *(mDensityp + k), 0.0f);
00451 //                      glVertex3f(x, y, z);
00452 
00453 //                      z = 0.5f * CLOUD_MAX_HEIGHT + 40.0f * *(mDensityp + k + 1);
00454 //                      glColor3f(1.0f - *(mDensityp + k + 1), *(mDensityp + k + 1), 0.0f);
00455 //                      glVertex3f(x+mMetersPerGrid, y, z);
00456 
00457 //              }
00458 //      }
00459 //      glEnd();
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         // Don't use the packed group_header stride because the strides used on
00470         // simulator and viewer are not equal.
00471         group_headerp->stride = group_headerp->patch_size;              // offset required to step up one row
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         // We want to iterate through all of the cloud groups
00482         // and update their density targets
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                 // Only care about cardinal 4 directions.
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                 // Only care about cardinal 4 directions.
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 }

Generated on Thu Jul 1 06:08:22 2010 for Second Life Viewer by  doxygen 1.4.7