llcloud.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /**
  2. * @file llcloud.cpp
  3. * @brief Implementation of viewer cloud classes
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. * Copyright (c) 2009-2024, Henri Beauchamp.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llcloud.h"
  35. #include "llgl.h"
  36. #include "llpatch_code.h"
  37. #include "llagent.h"
  38. #include "llappviewer.h" // For gFrameTimeSeconds
  39. #include "lldrawpool.h"
  40. #include "llpipeline.h"
  41. #include "llsky.h"
  42. #include "llstartup.h" // For LLStartUp::isLoggedIn()
  43. #include "llsurfacepatch.h" // For gDirOpposite
  44. #include "llviewercamera.h"
  45. #include "llviewercontrol.h"
  46. #include "llviewerobjectlist.h"
  47. #include "llviewerregion.h"
  48. #include "llvoclouds.h"
  49. #include "llvosky.h"
  50. #include "llworld.h"
  51. constexpr F32 CLOUD_GROW_RATE = 0.05f;
  52. constexpr F32 CLOUD_DECAY_RATE = -0.05f;
  53. constexpr F32 CLOUD_VELOCITY_SCALE = 0.6f;
  54. constexpr F32 CLOUD_DENSITY = 25.f;
  55. constexpr S32 CLOUD_COUNT_MAX = 20;
  56. constexpr F32 CLOUD_HEIGHT_RANGE = 48.f;
  57. //static
  58. F32 LLCloudLayer::sCloudsAltitude = 192.f; // Default at login
  59. enum
  60. {
  61. LL_PUFF_GROWING = 0,
  62. LL_PUFF_DYING = 1
  63. };
  64. // Used for patch decoder
  65. S32 gBuffer[256];
  66. LLCloudPuff::LLCloudPuff()
  67. : mAlpha(0.01f),
  68. mRate(CLOUD_GROW_RATE),
  69. mLifeState(LL_PUFF_GROWING)
  70. {
  71. }
  72. LLCloudGroup::LLCloudGroup()
  73. : mCloudLayerp(NULL),
  74. mDensity(0.f),
  75. mTargetPuffCount(0),
  76. mLastAltitudeUpdate(0.f),
  77. mVOCloudsp(NULL)
  78. {
  79. }
  80. void LLCloudGroup::cleanup()
  81. {
  82. if (mVOCloudsp)
  83. {
  84. if (!mVOCloudsp->isDead())
  85. {
  86. gObjectList.killObject(mVOCloudsp);
  87. }
  88. mVOCloudsp = NULL;
  89. }
  90. }
  91. void LLCloudGroup::setCenterRegion(F32 x, F32 y)
  92. {
  93. mLastAltitudeUpdate = gFrameTimeSeconds;
  94. mCenterRegion.set(x, y, LLCloudLayer::getCloudsAltitude());
  95. if (mVOCloudsp)
  96. {
  97. mVOCloudsp->setPositionRegion(mCenterRegion);
  98. }
  99. }
  100. void LLCloudGroup::updatePuffs(F32 dt)
  101. {
  102. mDensity = mCloudLayerp->getDensityRegion(mCenterRegion);
  103. LLViewerRegion* regionp = mCloudLayerp->getRegion();
  104. if (!regionp) return; // Paranoia
  105. if (!mVOCloudsp || gFrameTimeSeconds - mLastAltitudeUpdate >= 10.f)
  106. {
  107. // Account for possible altitude change:
  108. setCenterRegion(mCenterRegion.mV[VX], mCenterRegion.mV[VY]);
  109. }
  110. if (!mVOCloudsp)
  111. {
  112. mVOCloudsp =
  113. (LLVOClouds*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_CLOUDS,
  114. regionp);
  115. mVOCloudsp->setCloudGroup(this);
  116. mVOCloudsp->setPositionRegion(mCenterRegion);
  117. F32 hsize = mCloudLayerp->getMetersPerEdge() / CLOUD_GROUPS_PER_EDGE +
  118. CLOUD_PUFF_WIDTH;
  119. mVOCloudsp->setScale(LLVector3(hsize, hsize,
  120. CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT) * 0.5f);
  121. gPipeline.createObject(mVOCloudsp);
  122. }
  123. LLVector3 velocity;
  124. LLVector3d vel_d;
  125. S32 count = mCloudPuffs.size();
  126. // Update the positions of all of the clouds
  127. #if LL_OPENMP
  128. # pragma omp parallel for private(velocity, vel_d)
  129. #endif
  130. // NOTE: VS2017 OpenMP requires a signed integer loop index... HB
  131. for (S32 i = 0; i < count; ++i)
  132. {
  133. LLCloudPuff& puff = mCloudPuffs[i];
  134. velocity =
  135. regionp->mWind.getCloudVelocity(regionp->getPosRegionFromGlobal(puff.mPositionGlobal));
  136. velocity *= CLOUD_VELOCITY_SCALE * dt;
  137. vel_d.set(velocity);
  138. puff.mPositionGlobal += vel_d;
  139. puff.mAlpha += puff.mRate * dt;
  140. puff.mAlpha = llclamp(puff.mAlpha, 0.f, 1.f);
  141. }
  142. }
  143. void LLCloudGroup::updatePuffOwnership()
  144. {
  145. U32 i = 0;
  146. while (i < mCloudPuffs.size())
  147. {
  148. if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING)
  149. {
  150. ++i;
  151. continue;
  152. }
  153. if (inGroup(mCloudPuffs[i]))
  154. {
  155. ++i;
  156. continue;
  157. }
  158. LLCloudGroup* new_cgp = gWorld.findCloudGroup(mCloudPuffs[i]);
  159. if (!new_cgp)
  160. {
  161. mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
  162. mCloudPuffs[i++].mRate = CLOUD_DECAY_RATE;
  163. continue;
  164. }
  165. LLCloudPuff puff;
  166. puff.mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
  167. puff.mAlpha = mCloudPuffs[i].mAlpha;
  168. mCloudPuffs.erase(mCloudPuffs.begin() + i);
  169. new_cgp->mCloudPuffs.push_back(puff);
  170. }
  171. }
  172. void LLCloudGroup::updatePuffCount()
  173. {
  174. if (!mVOCloudsp)
  175. {
  176. return;
  177. }
  178. S32 target_puff_count = ll_roundp(CLOUD_DENSITY * mDensity);
  179. target_puff_count = llmax(0, target_puff_count);
  180. target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count);
  181. S32 current_puff_count = (S32)mCloudPuffs.size();
  182. // Create a new cloud if we need one
  183. if (current_puff_count < target_puff_count)
  184. {
  185. F32 hsize = mCloudLayerp->getMetersPerEdge() / CLOUD_GROUPS_PER_EDGE;
  186. LLVector3d puff_pos_global;
  187. mCloudPuffs.resize(target_puff_count);
  188. for (S32 i = current_puff_count; i < target_puff_count; ++i)
  189. {
  190. puff_pos_global = mVOCloudsp->getPositionGlobal();
  191. F32 x = ll_frand(hsize) - 0.5f * hsize;
  192. F32 y = ll_frand(hsize) - 0.5f * hsize;
  193. F32 z = ll_frand(CLOUD_HEIGHT_RANGE) - 0.5f * CLOUD_HEIGHT_RANGE;
  194. puff_pos_global += LLVector3d(x, y, z);
  195. mCloudPuffs[i].mPositionGlobal = puff_pos_global;
  196. mCloudPuffs[i].mAlpha = 0.01f;
  197. }
  198. }
  199. // Count the number of live puffs
  200. S32 live_puff_count = 0;
  201. for (S32 i = 0, count = mCloudPuffs.size(); i < count; ++i)
  202. {
  203. if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
  204. {
  205. ++live_puff_count;
  206. }
  207. }
  208. // Start killing enough puffs so the live puff count == target puff count
  209. S32 new_dying_count = llmax(0, live_puff_count - target_puff_count);
  210. S32 i = 0;
  211. while (new_dying_count > 0)
  212. {
  213. if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
  214. {
  215. mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
  216. mCloudPuffs[i].mRate = CLOUD_DECAY_RATE;
  217. --new_dying_count;
  218. }
  219. ++i;
  220. }
  221. // Remove fully dead puffs
  222. i = 0;
  223. while (i < (S32)mCloudPuffs.size())
  224. {
  225. if (mCloudPuffs[i].isDead())
  226. {
  227. mCloudPuffs.erase(mCloudPuffs.begin() + i);
  228. }
  229. else
  230. {
  231. ++i;
  232. }
  233. }
  234. }
  235. bool LLCloudGroup::inGroup(const LLCloudPuff& puff) const
  236. {
  237. LLViewerRegion* regionp = mCloudLayerp->getRegion();
  238. if (!regionp) return false; // Paranoia
  239. // Do min/max check on center of the cloud puff
  240. F32 min_x, min_y, max_x, max_y;
  241. F32 delta = mCloudLayerp->getMetersPerEdge() /
  242. CLOUD_GROUPS_PER_EDGE * 0.5f;
  243. min_x = mCenterRegion.mV[VX] - delta;
  244. min_y = mCenterRegion.mV[VY] - delta;
  245. max_x = mCenterRegion.mV[VX] + delta;
  246. max_y = mCenterRegion.mV[VY] + delta;
  247. LLVector3 pos_region =
  248. regionp->getPosRegionFromGlobal(puff.getPositionGlobal());
  249. if (pos_region.mV[VX] < min_x || pos_region.mV[VY] < min_y ||
  250. pos_region.mV[VX] > max_x || pos_region.mV[VY] > max_y)
  251. {
  252. return false;
  253. }
  254. return true;
  255. }
  256. LLCloudLayer::LLCloudLayer()
  257. : mOriginGlobal(0.f, 0.f, 0.f),
  258. mMetersPerEdge(1.f),
  259. mMetersPerGrid(1.f),
  260. mWindp(NULL),
  261. mDensityp(NULL),
  262. mLastDensityUpdate(0.f)
  263. {
  264. for (S32 i = 0; i < 4; ++i)
  265. {
  266. mNeighbors[i] = NULL;
  267. }
  268. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  269. {
  270. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  271. {
  272. mCloudGroups[i][j].setCloudLayerp(this);
  273. }
  274. }
  275. }
  276. LLCloudLayer::~LLCloudLayer()
  277. {
  278. destroy();
  279. }
  280. //static
  281. F32 LLCloudLayer::getCloudsAltitude()
  282. {
  283. static LLCachedControl<S32> clouds_altitude(gSavedSettings,
  284. "ClassicCloudsAvgAlt");
  285. static LLCachedControl<U32> max_clouds_alt(gSavedSettings,
  286. "ClassicCloudsMaxAlt");
  287. if (clouds_altitude > 0.f)
  288. {
  289. sCloudsAltitude = clouds_altitude;
  290. }
  291. // Wait until fully logged in before using the agent altitude (which is 0
  292. // until we get the region data and the correct agent position).
  293. else if (LLStartUp::isLoggedIn())
  294. {
  295. sCloudsAltitude = gAgent.getPositionAgent().mV[VZ] - clouds_altitude;
  296. }
  297. constexpr F32 MIN_ALT = CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT * 0.5f;
  298. sCloudsAltitude = llclamp(sCloudsAltitude, MIN_ALT, (F32)max_clouds_alt);
  299. return sCloudsAltitude;
  300. }
  301. //static
  302. bool LLCloudLayer::needClassicClouds()
  303. {
  304. // Do not use clouds if they are not wanted or when the camera is
  305. // underwater (in the latter case, clouds flicker when looking up at
  306. // the water surface and when in non-deferred rendering mode). HB
  307. static LLCachedControl<bool> use_classic_clouds(gSavedSettings,
  308. "SkyUseClassicClouds");
  309. if (!use_classic_clouds || gViewerCamera.cameraUnderWater())
  310. {
  311. return false;
  312. }
  313. // Do not use clouds if they are beyond the draw distance. HB
  314. static LLCachedControl<F32> draw_distance(gSavedSettings, "RenderFarClip");
  315. F32 delta = fabsf(sCloudsAltitude - gViewerCamera.getOrigin().mV[VZ]);
  316. return delta < draw_distance + CLOUD_HEIGHT_RANGE;
  317. }
  318. void LLCloudLayer::create(LLViewerRegion* regionp)
  319. {
  320. llassert(regionp);
  321. setRegion(regionp);
  322. mDensityp = new F32[CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE];
  323. for (U32 i = 0; i < CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE; ++i)
  324. {
  325. mDensityp[i] = 0.f;
  326. }
  327. }
  328. void LLCloudLayer::setRegion(LLViewerRegion* regionp)
  329. {
  330. mRegionp = regionp;
  331. if (regionp)
  332. {
  333. // Variable region size support. HB
  334. mMetersPerEdge = regionp->getWidth();
  335. mMetersPerGrid = mMetersPerEdge / CLOUD_GRIDS_PER_EDGE;
  336. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  337. {
  338. F32 y = (0.5f + i) * mMetersPerEdge / CLOUD_GROUPS_PER_EDGE;
  339. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  340. {
  341. F32 x = (0.5f + j) * mMetersPerEdge / CLOUD_GROUPS_PER_EDGE;
  342. mCloudGroups[i][j].setCenterRegion(x, y);
  343. }
  344. }
  345. }
  346. }
  347. void LLCloudLayer::destroy()
  348. {
  349. reset();
  350. delete[] mDensityp;
  351. mDensityp = NULL;
  352. mWindp = NULL;
  353. }
  354. void LLCloudLayer::reset()
  355. {
  356. // Kill all of the existing puffs
  357. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  358. {
  359. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  360. {
  361. mCloudGroups[i][j].cleanup();
  362. }
  363. }
  364. }
  365. void LLCloudLayer::setWindPointer(LLWind* windp)
  366. {
  367. if (mWindp)
  368. {
  369. mWindp->setCloudDensityPointer(NULL);
  370. }
  371. mWindp = windp;
  372. if (mWindp)
  373. {
  374. mWindp->setCloudDensityPointer(mDensityp);
  375. }
  376. }
  377. F32 LLCloudLayer::getDensityRegion(const LLVector3& pos_region)
  378. {
  379. // "position" is region-local
  380. S32 i, j, ii, jj;
  381. i = lltrunc(pos_region.mV[VX] / mMetersPerGrid);
  382. j = lltrunc(pos_region.mV[VY] / mMetersPerGrid);
  383. ii = i + 1;
  384. jj = j + 1;
  385. // clamp
  386. if (i >= (S32)CLOUD_GRIDS_PER_EDGE)
  387. {
  388. i = CLOUD_GRIDS_PER_EDGE - 1;
  389. ii = i;
  390. }
  391. else if (i < 0)
  392. {
  393. i = 0;
  394. ii = i;
  395. }
  396. else if (ii >= (S32)CLOUD_GRIDS_PER_EDGE || ii < 0)
  397. {
  398. ii = i;
  399. }
  400. if (j >= (S32)CLOUD_GRIDS_PER_EDGE)
  401. {
  402. j = CLOUD_GRIDS_PER_EDGE - 1;
  403. jj = j;
  404. }
  405. else if (j < 0)
  406. {
  407. j = 0;
  408. jj = j;
  409. }
  410. else if (jj >= (S32)CLOUD_GRIDS_PER_EDGE || jj < 0)
  411. {
  412. jj = j;
  413. }
  414. F32 dx = (pos_region.mV[VX] - (F32)i * mMetersPerGrid) / mMetersPerGrid;
  415. F32 dy = (pos_region.mV[VY] - (F32)j * mMetersPerGrid) / mMetersPerGrid;
  416. F32 omdx = 1.f - dx;
  417. F32 omdy = 1.f - dy;
  418. F32 density = dx * dy * *(mDensityp + ii + jj * CLOUD_GRIDS_PER_EDGE) +
  419. dx * omdy * *(mDensityp + i + jj * CLOUD_GRIDS_PER_EDGE) +
  420. omdx * dy * *(mDensityp + ii + j * CLOUD_GRIDS_PER_EDGE) +
  421. omdx * omdy * *(mDensityp + i + j * CLOUD_GRIDS_PER_EDGE);
  422. return density;
  423. }
  424. bool LLCloudLayer::shouldUpdateDensity()
  425. {
  426. // Not more often than once every second
  427. return gFrameTimeSeconds - mLastDensityUpdate >= 1.f;
  428. }
  429. // This method is called for regions not sending classic clouds layer data
  430. // (i.e. in SL's new servers). It gets called each time the viewer receives
  431. // a wind layer data packet (which happens once every second for each region
  432. // with SL's new sim servers). It generates (the first time it gets called) and
  433. // updates (the rest of the time) a local (viewer-side) cloud density matrix
  434. // in replacement for the missing data layer updates. HB
  435. void LLCloudLayer::generateDensity()
  436. {
  437. if (mLastDensityUpdate == 0.f)
  438. {
  439. for (U32 i = 0; i < CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE; ++i)
  440. {
  441. // Limits deduced from values sampled in old, classic-clouds
  442. // enabled SL sim servers. HB
  443. mDensityp[i] = ll_frand(4.f) - 1.f;
  444. }
  445. mLastDensityUpdate = gFrameTimeSeconds;
  446. }
  447. // Not more often than once every second
  448. else if (shouldUpdateDensity())
  449. {
  450. // Update the density probability matrix by averaging the value of
  451. // surrounding cells for each cell, with a weight factor of 2 for
  452. // the cell value itself and by adding a small random factor, i.e.:
  453. // average = (2 * this_cell + neighbors_total) / (neighbors + 2) + rand
  454. // For edges, we "wrap" around north/south west/east rows/columns. HB
  455. static F32 bufferp[CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE];
  456. #if LL_OPENMP
  457. # pragma omp parallel for
  458. #endif
  459. for (S32 x = 0; x < (S32)CLOUD_GRIDS_PER_EDGE; ++x)
  460. {
  461. S32 west = x - 1;
  462. if (west < 0)
  463. {
  464. west = CLOUD_GRIDS_PER_EDGE - 2; // wrap edges
  465. }
  466. S32 east = x + 1;
  467. if (east >= (S32)CLOUD_GRIDS_PER_EDGE)
  468. {
  469. east = 0; // wrap edges
  470. }
  471. for (S32 y = 0; y < (S32)CLOUD_GRIDS_PER_EDGE; ++y)
  472. {
  473. S32 south = y - 1;
  474. if (south < 0)
  475. {
  476. south = CLOUD_GRIDS_PER_EDGE - 2; // wrap edges
  477. }
  478. S32 north = y + 1;
  479. if (north >= (S32)CLOUD_GRIDS_PER_EDGE)
  480. {
  481. north = 0; // wrap edges
  482. }
  483. north *= CLOUD_GRIDS_PER_EDGE;
  484. south *= CLOUD_GRIDS_PER_EDGE;
  485. S32 here = y * CLOUD_GRIDS_PER_EDGE;
  486. F32 average = 2.f * mDensityp[here + x];
  487. average += mDensityp[north + west] + mDensityp[north + x];
  488. average += mDensityp[north + east] + mDensityp[here + east];
  489. average += mDensityp[south + east] + mDensityp[south + x];
  490. average += mDensityp[south + west] + mDensityp[here + west];
  491. average = llclamp(average * 0.1f + ll_frand(0.5f) - 0.25f,
  492. -1.f, 3.f);
  493. bufferp[here + x] = average;
  494. }
  495. }
  496. memcpy((void*)mDensityp, (void*)bufferp,
  497. sizeof(F32) * CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE);
  498. mLastDensityUpdate = gFrameTimeSeconds;
  499. }
  500. }
  501. void LLCloudLayer::resetDensity()
  502. {
  503. if (mLastDensityUpdate > 0.f)
  504. {
  505. for (U32 i = 0; i < CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE; ++i)
  506. {
  507. mDensityp[i] = 0.f;
  508. }
  509. reset();
  510. mLastDensityUpdate = 0.f;
  511. }
  512. }
  513. void LLCloudLayer::decompress(LLBitPack& bitpack, LLGroupHeader* group_headerp)
  514. {
  515. init_patch_decompressor(group_headerp->patch_size);
  516. // Do not use the packed group_header stride because the strides used on
  517. // simulator and viewer are not equal. Offset required to step up one row.
  518. group_headerp->stride = group_headerp->patch_size;
  519. LLPatchHeader patch_header;
  520. set_group_of_patch_header(group_headerp);
  521. decode_patch_header(bitpack, &patch_header);
  522. decode_patch(bitpack, gBuffer);
  523. decompress_patch(mDensityp, gBuffer, &patch_header);
  524. mLastDensityUpdate = gFrameTimeSeconds;
  525. }
  526. void LLCloudLayer::updatePuffs(F32 dt)
  527. {
  528. // We want to iterate through all of the cloud groups and update their
  529. // density targets
  530. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  531. {
  532. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  533. {
  534. mCloudGroups[i][j].updatePuffs(dt);
  535. }
  536. }
  537. }
  538. void LLCloudLayer::updatePuffOwnership()
  539. {
  540. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  541. {
  542. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  543. {
  544. mCloudGroups[i][j].updatePuffOwnership();
  545. }
  546. }
  547. }
  548. void LLCloudLayer::updatePuffCount()
  549. {
  550. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  551. {
  552. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  553. {
  554. mCloudGroups[i][j].updatePuffCount();
  555. }
  556. }
  557. }
  558. LLCloudGroup* LLCloudLayer::findCloudGroup(const LLCloudPuff& puff)
  559. {
  560. for (S32 i = 0; i < CLOUD_GROUPS_PER_EDGE; ++i)
  561. {
  562. for (S32 j = 0; j < CLOUD_GROUPS_PER_EDGE; ++j)
  563. {
  564. if (mCloudGroups[i][j].inGroup(puff))
  565. {
  566. return &(mCloudGroups[i][j]);
  567. }
  568. }
  569. }
  570. return NULL;
  571. }
  572. void LLCloudLayer::connectNeighbor(LLCloudLayer* cloudp, U32 direction)
  573. {
  574. if (direction >= 4)
  575. {
  576. // Only care about cardinal 4 directions.
  577. return;
  578. }
  579. if (!cloudp && mNeighbors[direction])
  580. {
  581. mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL;
  582. }
  583. mNeighbors[direction] = cloudp;
  584. if (cloudp)
  585. {
  586. cloudp->mNeighbors[gDirOpposite[direction]] = this;
  587. }
  588. }
  589. void LLCloudLayer::disconnectNeighbor(U32 direction)
  590. {
  591. if (direction >= 4)
  592. {
  593. // Only care about cardinal 4 directions.
  594. return;
  595. }
  596. LLCloudLayer* cloudp = mNeighbors[direction];
  597. if (cloudp)
  598. {
  599. cloudp->mNeighbors[gDirOpposite[direction]] = NULL;
  600. mNeighbors[direction] = NULL;
  601. }
  602. }
  603. void LLCloudLayer::disconnectAllNeighbors()
  604. {
  605. for (S32 i = 0; i < 4; ++i)
  606. {
  607. disconnectNeighbor(i);
  608. }
  609. }