aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerpartsim.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:50 -0500
committerJacek Antonelli2008-08-15 23:44:50 -0500
commit89fe5dab825a62a0e3fd8d248cbc91c65eb2a426 (patch)
treebcff14b7888d04a2fec799c59369f6095224bd08 /linden/indra/newview/llviewerpartsim.cpp
parentSecond Life viewer sources 1.13.3.2 (diff)
downloadmeta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.zip
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.gz
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.bz2
meta-impy-89fe5dab825a62a0e3fd8d248cbc91c65eb2a426.tar.xz
Second Life viewer sources 1.14.0.0
Diffstat (limited to 'linden/indra/newview/llviewerpartsim.cpp')
-rw-r--r--linden/indra/newview/llviewerpartsim.cpp305
1 files changed, 181 insertions, 124 deletions
diff --git a/linden/indra/newview/llviewerpartsim.cpp b/linden/indra/newview/llviewerpartsim.cpp
index be2c90f..2658e67 100644
--- a/linden/indra/newview/llviewerpartsim.cpp
+++ b/linden/indra/newview/llviewerpartsim.cpp
@@ -32,6 +32,7 @@
32#include "llviewercontrol.h" 32#include "llviewercontrol.h"
33 33
34#include "llagent.h" 34#include "llagent.h"
35#include "llviewercamera.h"
35#include "llviewerobjectlist.h" 36#include "llviewerobjectlist.h"
36#include "llviewerpartsource.h" 37#include "llviewerpartsource.h"
37#include "llviewerregion.h" 38#include "llviewerregion.h"
@@ -41,7 +42,7 @@
41 42
42const S32 MAX_PART_COUNT = 4096; 43const S32 MAX_PART_COUNT = 4096;
43 44
44const F32 PART_SIM_BOX_SIDE = 32.f; 45const F32 PART_SIM_BOX_SIDE = 16.f;
45const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE; 46const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE;
46const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE; 47const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
47 48
@@ -52,18 +53,28 @@ S32 LLViewerPartSim::sParticleCount = 0;
52 53
53U32 LLViewerPart::sNextPartID = 1; 54U32 LLViewerPart::sNextPartID = 1;
54 55
56F32 calc_desired_size(LLVector3 pos, LLVector2 scale)
57{
58 F32 desired_size = (pos-gCamera->getOrigin()).magVec();
59 desired_size /= 4;
60 return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2);
61}
62
55LLViewerPart::LLViewerPart() 63LLViewerPart::LLViewerPart()
56{ 64{
65 LLMemType mt(LLMemType::MTYPE_PARTICLES);
57 mPartSourcep = NULL; 66 mPartSourcep = NULL;
58} 67}
59 68
60LLViewerPart::~LLViewerPart() 69LLViewerPart::~LLViewerPart()
61{ 70{
71 LLMemType mt(LLMemType::MTYPE_PARTICLES);
62 mPartSourcep = NULL; 72 mPartSourcep = NULL;
63} 73}
64 74
65LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part) 75LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
66{ 76{
77 LLMemType mt(LLMemType::MTYPE_PARTICLES);
67 mPartID = part.mPartID; 78 mPartID = part.mPartID;
68 mFlags = part.mFlags; 79 mFlags = part.mFlags;
69 mMaxAge = part.mMaxAge; 80 mMaxAge = part.mMaxAge;
@@ -93,6 +104,7 @@ LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
93 104
94void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVPCallback cb) 105void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVPCallback cb)
95{ 106{
107 LLMemType mt(LLMemType::MTYPE_PARTICLES);
96 mPartID = LLViewerPart::sNextPartID; 108 mPartID = LLViewerPart::sNextPartID;
97 LLViewerPart::sNextPartID++; 109 LLViewerPart::sNextPartID++;
98 mFlags = 0x00f; 110 mFlags = 0x00f;
@@ -115,8 +127,13 @@ void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVP
115 127
116LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 box_side) 128LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 box_side)
117{ 129{
130 LLMemType mt(LLMemType::MTYPE_PARTICLES);
118 mVOPartGroupp = NULL; 131 mVOPartGroupp = NULL;
132 mUniformParticles = TRUE;
133
119 mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent); 134 mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent);
135 llassert_always(center_agent.isFinite());
136
120 if (!mRegionp) 137 if (!mRegionp)
121 { 138 {
122 //llwarns << "No region at position, using agent region!" << llendl; 139 //llwarns << "No region at position, using agent region!" << llendl;
@@ -125,28 +142,39 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 bo
125 mCenterAgent = center_agent; 142 mCenterAgent = center_agent;
126 mBoxRadius = F_SQRT3*box_side*0.5f; 143 mBoxRadius = F_SQRT3*box_side*0.5f;
127 144
128 LLVector3 rad_vec(box_side*0.5f, box_side*0.5f, box_side*0.5f); 145 mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
129 rad_vec += LLVector3(0.001f, 0.001f, 0.001f); 146 mVOPartGroupp->setViewerPartGroup(this);
130 mMinObjPos = mCenterAgent - rad_vec; 147 mVOPartGroupp->setPositionAgent(getCenterAgent());
131 mMaxObjPos = mCenterAgent + rad_vec; 148 F32 scale = box_side * 0.5f;
149 mVOPartGroupp->setScale(LLVector3(scale,scale,scale));
150 gPipeline.addObject(mVOPartGroupp);
151
152 LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup();
153
154 LLVector3 center(group->mOctreeNode->getCenter());
155 LLVector3 size(group->mOctreeNode->getSize());
156 size += LLVector3(0.01f, 0.01f, 0.01f);
157 mMinObjPos = center - size;
158 mMaxObjPos = center + size;
159
160 static U32 id_seed = 0;
161 mID = ++id_seed;
132} 162}
133 163
134LLViewerPartGroup::~LLViewerPartGroup() 164LLViewerPartGroup::~LLViewerPartGroup()
135{ 165{
166 LLMemType mt(LLMemType::MTYPE_PARTICLES);
136 cleanup(); 167 cleanup();
137 S32 count = mParticles.count(); 168
138 S32 i; 169 S32 count = (S32) mParticles.size();
139 170 mParticles.clear();
140 for (i = 0; i < count; i++) 171
141 {
142 mParticles[i].mPartSourcep = NULL;
143 }
144 mParticles.reset();
145 LLViewerPartSim::decPartCount(count); 172 LLViewerPartSim::decPartCount(count);
146} 173}
147 174
148void LLViewerPartGroup::cleanup() 175void LLViewerPartGroup::cleanup()
149{ 176{
177 LLMemType mt(LLMemType::MTYPE_PARTICLES);
150 if (mVOPartGroupp) 178 if (mVOPartGroupp)
151 { 179 {
152 if (!mVOPartGroupp->isDead()) 180 if (!mVOPartGroupp->isDead())
@@ -157,8 +185,9 @@ void LLViewerPartGroup::cleanup()
157 } 185 }
158} 186}
159 187
160BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos) 188BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size)
161{ 189{
190 LLMemType mt(LLMemType::MTYPE_PARTICLES);
162 if ((pos.mV[VX] < mMinObjPos.mV[VX]) 191 if ((pos.mV[VX] < mMinObjPos.mV[VX])
163 || (pos.mV[VY] < mMinObjPos.mV[VY]) 192 || (pos.mV[VY] < mMinObjPos.mV[VY])
164 || (pos.mV[VZ] < mMinObjPos.mV[VZ])) 193 || (pos.mV[VZ] < mMinObjPos.mV[VZ]))
@@ -173,29 +202,33 @@ BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos)
173 return FALSE; 202 return FALSE;
174 } 203 }
175 204
205 if (desired_size > 0 &&
206 (desired_size < mBoxRadius*0.5f ||
207 desired_size > mBoxRadius*2.f))
208 {
209 return FALSE;
210 }
211
176 return TRUE; 212 return TRUE;
177} 213}
178 214
179 215
180BOOL LLViewerPartGroup::addPart(LLViewerPart &part) 216BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size)
181{ 217{
182 if (!posInGroup(part.mPosAgent) || 218 LLMemType mt(LLMemType::MTYPE_PARTICLES);
183 (mVOPartGroupp.notNull() && (part.mImagep != mVOPartGroupp->getTEImage(0)))) 219 BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] &&
220 !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK);
221
222 if (!posInGroup(part->mPosAgent, desired_size) ||
223 (mUniformParticles && !uniform_part) ||
224 (!mUniformParticles && uniform_part))
184 { 225 {
185 return FALSE; 226 return FALSE;
186 } 227 }
187 228
188 if (!mVOPartGroupp) 229 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
189 {
190 mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
191 mVOPartGroupp->setViewerPartGroup(this);
192 mVOPartGroupp->setPositionAgent(getCenterAgent());
193 mVOPartGroupp->setScale(LLVector3(PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE));
194 mVOPartGroupp->setTEImage(0, part.mImagep);
195 gPipeline.addObject(mVOPartGroupp);
196 }
197 230
198 mParticles.put(part); 231 mParticles.push_back(part);
199 LLViewerPartSim::incPartCount(1); 232 LLViewerPartSim::incPartCount(1);
200 return TRUE; 233 return TRUE;
201} 234}
@@ -203,33 +236,29 @@ BOOL LLViewerPartGroup::addPart(LLViewerPart &part)
203 236
204void LLViewerPartGroup::removePart(const S32 part_num) 237void LLViewerPartGroup::removePart(const S32 part_num)
205{ 238{
239 LLMemType mt(LLMemType::MTYPE_PARTICLES);
206 // Remove the entry for the particle we just deleted. 240 // Remove the entry for the particle we just deleted.
207 LLPointer<LLViewerPartSource> ps = mParticles[mParticles.count() - 1].mPartSourcep; 241 mParticles.erase(mParticles.begin() + part_num);
208 242 if (mVOPartGroupp.notNull())
209 mParticles[mParticles.count() - 1].mPartSourcep = NULL;
210 mParticles.remove(part_num);
211 if (part_num < mParticles.count())
212 { 243 {
213 mParticles[part_num].mPartSourcep = ps; 244 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
214 } 245 }
215
216 LLViewerPartSim::decPartCount(1); 246 LLViewerPartSim::decPartCount(1);
217} 247}
218 248
219
220void LLViewerPartGroup::updateParticles(const F32 dt) 249void LLViewerPartGroup::updateParticles(const F32 dt)
221{ 250{
251 LLMemType mt(LLMemType::MTYPE_PARTICLES);
222 S32 i, count; 252 S32 i, count;
223 253
224
225 LLVector3 gravity(0.f, 0.f, -9.8f); 254 LLVector3 gravity(0.f, 0.f, -9.8f);
226 255
227 LLViewerRegion *regionp = getRegion(); 256 LLViewerRegion *regionp = getRegion();
228 count = mParticles.count(); 257 count = (S32) mParticles.size();
229 for (i = 0; i < count; i++) 258 for (i = 0; i < count; i++)
230 { 259 {
231 LLVector3 a(0.f, 0.f, 0.f); 260 LLVector3 a(0.f, 0.f, 0.f);
232 LLViewerPart &part = mParticles[i]; 261 LLViewerPart& part = *((LLViewerPart*) mParticles[i]);
233 262
234 // Update current time 263 // Update current time
235 const F32 cur_time = part.mLastUpdateTime + dt; 264 const F32 cur_time = part.mLastUpdateTime + dt;
@@ -271,8 +300,6 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
271 300
272 part.mVelocity *= (1.f - step); 301 part.mVelocity *= (1.f - step);
273 part.mVelocity += step*delta_pos; 302 part.mVelocity += step*delta_pos;
274 //part.mPosAgent *= 1.f - to_target_frac;
275 //part.mPosAgent += to_target_frac*part.mPartSourcep->mTargetPosAgent;
276 } 303 }
277 304
278 305
@@ -341,18 +368,22 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
341 i--; 368 i--;
342 count--; 369 count--;
343 } 370 }
344 else if (!posInGroup(part.mPosAgent)) 371 else
345 { 372 {
346 // Transfer particles between groups 373 F32 desired_size = calc_desired_size(part.mPosAgent, part.mScale);
347 gWorldPointer->mPartSim.put(part); 374 if (!posInGroup(part.mPosAgent, desired_size))
348 removePart(i); 375 {
349 i--; 376 // Transfer particles between groups
350 count--; 377 gWorldPointer->mPartSim.put(&part);
378 removePart(i);
379 i--;
380 count--;
381 }
351 } 382 }
352 } 383 }
353 384
354 // Kill the viewer object if this particle group is empty 385 // Kill the viewer object if this particle group is empty
355 if (!mParticles.count()) 386 if (mParticles.empty())
356 { 387 {
357 gObjectList.killObject(mVOPartGroupp); 388 gObjectList.killObject(mVOPartGroupp);
358 mVOPartGroupp = NULL; 389 mVOPartGroupp = NULL;
@@ -362,15 +393,16 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
362 393
363void LLViewerPartGroup::shift(const LLVector3 &offset) 394void LLViewerPartGroup::shift(const LLVector3 &offset)
364{ 395{
396 LLMemType mt(LLMemType::MTYPE_PARTICLES);
365 mCenterAgent += offset; 397 mCenterAgent += offset;
366 mMinObjPos += offset; 398 mMinObjPos += offset;
367 mMaxObjPos += offset; 399 mMaxObjPos += offset;
368 400
369 S32 count = mParticles.count(); 401 S32 count = (S32) mParticles.size();
370 S32 i; 402 S32 i;
371 for (i = 0; i < count; i++) 403 for (i = 0; i < count; i++)
372 { 404 {
373 mParticles[i].mPosAgent += offset; 405 mParticles[i]->mPosAgent += offset;
374 } 406 }
375} 407}
376 408
@@ -384,34 +416,34 @@ void LLViewerPartGroup::shift(const LLVector3 &offset)
384 416
385LLViewerPartSim::LLViewerPartSim() 417LLViewerPartSim::LLViewerPartSim()
386{ 418{
419 LLMemType mt(LLMemType::MTYPE_PARTICLES);
387 sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); 420 sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount");
421 static U32 id_seed = 0;
422 mID = ++id_seed;
388} 423}
389 424
390 425
391LLViewerPartSim::~LLViewerPartSim() 426LLViewerPartSim::~LLViewerPartSim()
392{ 427{
428 LLMemType mt(LLMemType::MTYPE_PARTICLES);
393 S32 i; 429 S32 i;
394 S32 count; 430 S32 count;
395 431
396 // Kill all of the groups (and particles) 432 // Kill all of the groups (and particles)
397 count = mViewerPartGroups.count(); 433 count = (S32) mViewerPartGroups.size();
398 for (i = 0; i < count; i++) 434 for (i = 0; i < count; i++)
399 { 435 {
400 delete mViewerPartGroups[i]; 436 delete mViewerPartGroups[i];
401 } 437 }
402 mViewerPartGroups.reset(); 438 mViewerPartGroups.clear();
403 439
404 // Kill all of the sources 440 // Kill all of the sources
405 count = mViewerPartSources.count(); 441 mViewerPartSources.clear();
406 for (i = 0; i < count; i++)
407 {
408 mViewerPartSources[i] = NULL;
409 }
410 mViewerPartSources.reset();
411} 442}
412 443
413BOOL LLViewerPartSim::shouldAddPart() 444BOOL LLViewerPartSim::shouldAddPart()
414{ 445{
446 LLMemType mt(LLMemType::MTYPE_PARTICLES);
415 if (sParticleCount > 0.75f*sMaxParticleCount) 447 if (sParticleCount > 0.75f*sMaxParticleCount)
416 { 448 {
417 449
@@ -432,33 +464,35 @@ BOOL LLViewerPartSim::shouldAddPart()
432 return TRUE; 464 return TRUE;
433} 465}
434 466
435void LLViewerPartSim::addPart(LLViewerPart &part) 467void LLViewerPartSim::addPart(LLViewerPart* part)
436{ 468{
469 LLMemType mt(LLMemType::MTYPE_PARTICLES);
437 if (sParticleCount < MAX_PART_COUNT) 470 if (sParticleCount < MAX_PART_COUNT)
438 { 471 {
439 put(part); 472 put(part);
440 } 473 }
441} 474}
442 475
443LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part) 476
477LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
444{ 478{
479 LLMemType mt(LLMemType::MTYPE_PARTICLES);
445 const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million 480 const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
446 if (part.mPosAgent.magVecSquared() > MAX_MAG) 481 if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite())
447 { 482 {
448#ifndef LL_RELEASE_FOR_DOWNLOAD 483#if !LL_RELEASE_FOR_DOWNLOAD
449 llwarns << "LLViewerPartSim::put Part out of range!" << llendl; 484 llwarns << "LLViewerPartSim::put Part out of range!" << llendl;
450 llwarns << part.mPosAgent << llendl; 485 llwarns << part->mPosAgent << llendl;
451#endif 486#endif
452 return NULL; 487 return NULL;
453 } 488 }
489
490 F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
454 491
455 S32 i; 492 S32 count = (S32) mViewerPartGroups.size();
456 S32 count; 493 for (S32 i = 0; i < count; i++)
457
458 count = mViewerPartGroups.count();
459 for (i = 0; i < count; i++)
460 { 494 {
461 if (mViewerPartGroups[i]->addPart(part)) 495 if (mViewerPartGroups[i]->addPart(part, desired_size))
462 { 496 {
463 // We found a spatial group that we fit into, add us and exit 497 // We found a spatial group that we fit into, add us and exit
464 return mViewerPartGroups[i]; 498 return mViewerPartGroups[i];
@@ -467,43 +501,27 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part)
467 501
468 // Hmm, we didn't fit in any of the existing spatial groups 502 // Hmm, we didn't fit in any of the existing spatial groups
469 // Create a new one... 503 // Create a new one...
470 LLViewerPartGroup *groupp = createViewerPartGroup(part.mPosAgent); 504 llassert_always(part->mPosAgent.isFinite());
505 LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size);
506 groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] &&
507 !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK));
471 if (!groupp->addPart(part)) 508 if (!groupp->addPart(part))
472 { 509 {
473 llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl; 510 llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl;
474 llinfos << groupp->getCenterAgent() << llendl; 511 llinfos << groupp->getCenterAgent() << llendl;
475 llinfos << part.mPosAgent << llendl; 512 llinfos << part->mPosAgent << llendl;
476 return NULL; 513 return NULL;
477 } 514 }
478 return groupp; 515 return groupp;
479} 516}
480 517
481LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent) 518LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size)
482{ 519{
483 F32 x_origin = ((S32)(pos_agent.mV[VX]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE; 520 LLMemType mt(LLMemType::MTYPE_PARTICLES);
484 if (x_origin > pos_agent.mV[VX]) 521 //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses
485 { 522 //pos_agent
486 x_origin -= PART_SIM_BOX_SIDE; 523 LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size);
487 } 524 mViewerPartGroups.push_back(groupp);
488
489 F32 y_origin = ((S32)(pos_agent.mV[VY]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
490 if (y_origin > pos_agent.mV[VY])
491 {
492 y_origin -= PART_SIM_BOX_SIDE;
493 }
494
495 F32 z_origin = ((S32)(pos_agent.mV[VZ]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
496 if (z_origin > pos_agent.mV[VZ])
497 {
498 z_origin -= PART_SIM_BOX_SIDE;
499 }
500
501 LLVector3 group_center(x_origin + PART_SIM_BOX_OFFSET,
502 y_origin + PART_SIM_BOX_OFFSET,
503 z_origin + PART_SIM_BOX_OFFSET);
504
505 LLViewerPartGroup *groupp = new LLViewerPartGroup(group_center, PART_SIM_BOX_SIDE);
506 mViewerPartGroups.put(groupp);
507 return groupp; 525 return groupp;
508} 526}
509 527
@@ -513,7 +531,7 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
513 S32 i; 531 S32 i;
514 S32 count; 532 S32 count;
515 533
516 count = mViewerPartSources.count(); 534 count = (S32) mViewerPartSources.size();
517 for (i = 0; i < count; i++) 535 for (i = 0; i < count; i++)
518 { 536 {
519 mViewerPartSources[i]->mPosAgent += offset; 537 mViewerPartSources[i]->mPosAgent += offset;
@@ -521,13 +539,20 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
521 mViewerPartSources[i]->mLastUpdatePosAgent += offset; 539 mViewerPartSources[i]->mLastUpdatePosAgent += offset;
522 } 540 }
523 541
524 count = mViewerPartGroups.count(); 542 count = (S32) mViewerPartGroups.size();
525 for (i = 0; i < count; i++) 543 for (i = 0; i < count; i++)
526 { 544 {
527 mViewerPartGroups[i]->shift(offset); 545 mViewerPartGroups[i]->shift(offset);
528 } 546 }
529} 547}
530 548
549S32 dist_rate_func(F32 distance)
550{
551 //S32 dist = (S32) sqrtf(distance);
552 //dist /= 2;
553 //return llmax(dist,1);
554 return 1;
555}
531 556
532void LLViewerPartSim::updateSimulation() 557void LLViewerPartSim::updateSimulation()
533{ 558{
@@ -542,13 +567,15 @@ void LLViewerPartSim::updateSimulation()
542 return; 567 return;
543 } 568 }
544 569
570 LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES);
571
545 // Start at a random particle system so the same 572 // Start at a random particle system so the same
546 // particle system doesn't always get first pick at the 573 // particle system doesn't always get first pick at the
547 // particles. Theoretically we'd want to do this in distance 574 // particles. Theoretically we'd want to do this in distance
548 // order or something, but sorting particle sources will be a big 575 // order or something, but sorting particle sources will be a big
549 // pain. 576 // pain.
550 S32 i; 577 S32 i;
551 S32 count = mViewerPartSources.count(); 578 S32 count = (S32) mViewerPartSources.size();
552 S32 start = (S32)ll_frand((F32)count); 579 S32 start = (S32)ll_frand((F32)count);
553 S32 dir = 1; 580 S32 dir = 1;
554 if (ll_frand() > 0.5f) 581 if (ll_frand() > 0.5f)
@@ -570,12 +597,24 @@ void LLViewerPartSim::updateSimulation()
570 597
571 if (!mViewerPartSources[i]->isDead()) 598 if (!mViewerPartSources[i]->isDead())
572 { 599 {
573 mViewerPartSources[i]->update(dt); 600 LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp;
601 if (source_object && source_object->mDrawable.notNull())
602 {
603 S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera);
604 if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0)
605 {
606 mViewerPartSources[i]->update(dt*dist);
607 }
608 }
609 else
610 {
611 mViewerPartSources[i]->update(dt);
612 }
574 } 613 }
575 614
576 if (mViewerPartSources[i]->isDead()) 615 if (mViewerPartSources[i]->isDead())
577 { 616 {
578 mViewerPartSources.remove(i); 617 mViewerPartSources.erase(mViewerPartSources.begin() + i);
579 count--; 618 count--;
580 } 619 }
581 else 620 else
@@ -586,16 +625,36 @@ void LLViewerPartSim::updateSimulation()
586 } 625 }
587 626
588 627
589 count = mViewerPartGroups.count(); 628 count = (S32) mViewerPartGroups.size();
590 for (i = 0; i < count; i++) 629 for (i = 0; i < count; i++)
591 { 630 {
592 mViewerPartGroups[i]->updateParticles(dt); 631 LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp;
593 if (!mViewerPartGroups[i]->getCount()) 632
633 S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ?
634 dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1;
635 if (vobj)
594 { 636 {
595 delete mViewerPartGroups[i]; 637 LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
596 mViewerPartGroups.remove(i); 638 if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
597 i--; 639 {
598 count--; 640 dist *= 8;
641 }
642 }
643
644 if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0)
645 {
646 if (vobj)
647 {
648 gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
649 }
650 mViewerPartGroups[i]->updateParticles(dt*dist);
651 if (!mViewerPartGroups[i]->getCount())
652 {
653 delete mViewerPartGroups[i];
654 mViewerPartGroups.erase(mViewerPartGroups.begin() + i);
655 i--;
656 count--;
657 }
599 } 658 }
600 } 659 }
601 //llinfos << "Particles: " << sParticleCount << llendl; 660 //llinfos << "Particles: " << sParticleCount << llendl;
@@ -604,42 +663,40 @@ void LLViewerPartSim::updateSimulation()
604 663
605void LLViewerPartSim::addPartSource(LLViewerPartSource *sourcep) 664void LLViewerPartSim::addPartSource(LLViewerPartSource *sourcep)
606{ 665{
666 LLMemType mt(LLMemType::MTYPE_PARTICLES);
607 if (!sourcep) 667 if (!sourcep)
608 { 668 {
609 llwarns << "Null part source!" << llendl; 669 llwarns << "Null part source!" << llendl;
610 return; 670 return;
611 } 671 }
612 mViewerPartSources.put(sourcep); 672 mViewerPartSources.push_back(sourcep);
613} 673}
614 674
615 675
616void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp) 676void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp)
617{ 677{
618 S32 i, count; 678 LLMemType mt(LLMemType::MTYPE_PARTICLES);
619 count = mViewerPartGroups.count(); 679 for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); )
620 for (i = 0; i < count; i++)
621 { 680 {
622 if (mViewerPartGroups[i]->getRegion() == regionp) 681 group_list_t::iterator iter = i++;
682
683 if ((*iter)->getRegion() == regionp)
623 { 684 {
624 delete mViewerPartGroups[i]; 685 i = mViewerPartGroups.erase(iter);
625 mViewerPartGroups.remove(i);
626 i--;
627 count--;
628 } 686 }
629 } 687 }
630} 688}
631 689
632void LLViewerPartSim::cleanMutedParticles(const LLUUID& task_id) 690void LLViewerPartSim::cleanMutedParticles(const LLUUID& task_id)
633{ 691{
634 S32 i; 692 LLMemType mt(LLMemType::MTYPE_PARTICLES);
635 S32 count = mViewerPartSources.count(); 693 for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); )
636 for (i = 0; i < count; ++i)
637 { 694 {
638 if (mViewerPartSources[i]->getOwnerUUID() == task_id) 695 source_list_t::iterator iter = i++;
696
697 if ((*iter)->getOwnerUUID() == task_id)
639 { 698 {
640 mViewerPartSources.remove(i); 699 i = mViewerPartSources.erase(iter);
641 i--;
642 count--;
643 } 700 }
644 } 701 }
645} 702}