aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerpartsim.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llviewerpartsim.cpp')
-rw-r--r--linden/indra/newview/llviewerpartsim.cpp200
1 files changed, 115 insertions, 85 deletions
diff --git a/linden/indra/newview/llviewerpartsim.cpp b/linden/indra/newview/llviewerpartsim.cpp
index 571e0b4..0766a01 100644
--- a/linden/indra/newview/llviewerpartsim.cpp
+++ b/linden/indra/newview/llviewerpartsim.cpp
@@ -43,8 +43,7 @@
43#include "llvopartgroup.h" 43#include "llvopartgroup.h"
44#include "llworld.h" 44#include "llworld.h"
45#include "pipeline.h" 45#include "pipeline.h"
46 46#include "llspatialpartition.h"
47const S32 MAX_PART_COUNT = 8192; // VWR-1105
48 47
49const F32 PART_SIM_BOX_SIDE = 16.f; 48const F32 PART_SIM_BOX_SIDE = 16.f;
50const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE; 49const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE;
@@ -53,6 +52,18 @@ const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
53//static 52//static
54S32 LLViewerPartSim::sMaxParticleCount = 0; 53S32 LLViewerPartSim::sMaxParticleCount = 0;
55S32 LLViewerPartSim::sParticleCount = 0; 54S32 LLViewerPartSim::sParticleCount = 0;
55// This controls how greedy individual particle burst sources are allowed to be, and adapts according to how near the particle-count limit we are.
56F32 LLViewerPartSim::sParticleAdaptiveRate = 0.0625f;
57F32 LLViewerPartSim::sParticleBurstRate = 0.5f;
58
59//static
60const S32 LLViewerPartSim::MAX_PART_COUNT = 8192;
61const F32 LLViewerPartSim::PART_THROTTLE_THRESHOLD = 0.9f;
62const F32 LLViewerPartSim::PART_ADAPT_RATE_MULT = 2.0f;
63
64//static
65const F32 LLViewerPartSim::PART_THROTTLE_RESCALE = PART_THROTTLE_THRESHOLD / (1.0f-PART_THROTTLE_THRESHOLD);
66const F32 LLViewerPartSim::PART_ADAPT_RATE_MULT_RECIP = 1.0f/PART_ADAPT_RATE_MULT;
56 67
57 68
58U32 LLViewerPart::sNextPartID = 1; 69U32 LLViewerPart::sNextPartID = 1;
@@ -76,36 +87,6 @@ LLViewerPart::~LLViewerPart()
76 mPartSourcep = NULL; 87 mPartSourcep = NULL;
77} 88}
78 89
79LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
80{
81 LLMemType mt(LLMemType::MTYPE_PARTICLES);
82 mPartID = part.mPartID;
83 mFlags = part.mFlags;
84 mMaxAge = part.mMaxAge;
85
86 mStartColor = part.mStartColor;
87 mEndColor = part.mEndColor;
88 mStartScale = part.mStartScale;
89 mEndScale = part.mEndScale;
90
91 mPosOffset = part.mPosOffset;
92 mParameter = part.mParameter;
93
94 mLastUpdateTime = part.mLastUpdateTime;
95 mVPCallback = part.mVPCallback;
96 mPartSourcep = part.mPartSourcep;
97
98 mImagep = part.mImagep;
99 mPosAgent = part.mPosAgent;
100 mVelocity = part.mVelocity;
101 mAccel = part.mAccel;
102 mColor = part.mColor;
103 mScale = part.mScale;
104
105
106 return *this;
107}
108
109void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb) 90void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb)
110{ 91{
111 LLMemType mt(LLMemType::MTYPE_PARTICLES); 92 LLMemType mt(LLMemType::MTYPE_PARTICLES);
@@ -114,6 +95,7 @@ void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *im
114 mFlags = 0x00f; 95 mFlags = 0x00f;
115 mLastUpdateTime = 0.f; 96 mLastUpdateTime = 0.f;
116 mMaxAge = 10.f; 97 mMaxAge = 10.f;
98 mSkipOffset = 0.0f;
117 99
118 mVPCallback = cb; 100 mVPCallback = cb;
119 mPartSourcep = sourcep; 101 mPartSourcep = sourcep;
@@ -155,11 +137,23 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 bo
155 137
156 LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); 138 LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup();
157 139
158 LLVector3 center(group->mOctreeNode->getCenter()); 140 if (group != NULL)
159 LLVector3 size(group->mOctreeNode->getSize()); 141 {
160 size += LLVector3(0.01f, 0.01f, 0.01f); 142 LLVector3 center(group->mOctreeNode->getCenter());
161 mMinObjPos = center - size; 143 LLVector3 size(group->mOctreeNode->getSize());
162 mMaxObjPos = center + size; 144 size += LLVector3(0.01f, 0.01f, 0.01f);
145 mMinObjPos = center - size;
146 mMaxObjPos = center + size;
147 }
148 else
149 {
150 // Not sure what else to set the obj bounds to when the drawable has no spatial group.
151 LLVector3 extents(mBoxRadius, mBoxRadius, mBoxRadius);
152 mMinObjPos = center_agent - extents;
153 mMaxObjPos = center_agent + extents;
154 }
155
156 mSkippedTime = 0.f;
163 157
164 static U32 id_seed = 0; 158 static U32 id_seed = 0;
165 mID = ++id_seed; 159 mID = ++id_seed;
@@ -233,27 +227,17 @@ BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size)
233 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); 227 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
234 228
235 mParticles.push_back(part); 229 mParticles.push_back(part);
230 part->mSkipOffset=mSkippedTime;
236 LLViewerPartSim::incPartCount(1); 231 LLViewerPartSim::incPartCount(1);
237 return TRUE; 232 return TRUE;
238} 233}
239 234
240 235
241void LLViewerPartGroup::removePart(const S32 part_num) 236void LLViewerPartGroup::updateParticles(const F32 lastdt)
242{
243 LLMemType mt(LLMemType::MTYPE_PARTICLES);
244 // Remove the entry for the particle we just deleted.
245 mParticles.erase(mParticles.begin() + part_num);
246 if (mVOPartGroupp.notNull())
247 {
248 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
249 }
250 LLViewerPartSim::decPartCount(1);
251}
252
253void LLViewerPartGroup::updateParticles(const F32 dt)
254{ 237{
255 LLMemType mt(LLMemType::MTYPE_PARTICLES); 238 LLMemType mt(LLMemType::MTYPE_PARTICLES);
256 S32 i; 239 S32 i;
240 F32 dt;
257 241
258 LLVector3 gravity(0.f, 0.f, -9.8f); 242 LLVector3 gravity(0.f, 0.f, -9.8f);
259 243
@@ -264,6 +248,9 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
264 LLVector3 a(0.f, 0.f, 0.f); 248 LLVector3 a(0.f, 0.f, 0.f);
265 LLViewerPart& part = *((LLViewerPart*) mParticles[i]); 249 LLViewerPart& part = *((LLViewerPart*) mParticles[i]);
266 250
251 dt=lastdt+mSkippedTime-part.mSkipOffset;
252 part.mSkipOffset=0.f;
253
267 // Update current time 254 // Update current time
268 const F32 cur_time = part.mLastUpdateTime + dt; 255 const F32 cur_time = part.mLastUpdateTime + dt;
269 const F32 frac = cur_time/part.mMaxAge; 256 const F32 frac = cur_time/part.mMaxAge;
@@ -347,10 +334,11 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
347 if (part.mFlags & LLPartData::LL_PART_INTERP_COLOR_MASK) 334 if (part.mFlags & LLPartData::LL_PART_INTERP_COLOR_MASK)
348 { 335 {
349 part.mColor.setVec(part.mStartColor); 336 part.mColor.setVec(part.mStartColor);
350 part.mColor *= 1.f - frac; 337 // note: LLColor4's v%k means multiply-alpha-only,
351 part.mColor.mV[3] *= (1.f - frac)*part.mStartColor.mV[3]; 338 // LLColor4's v*k means multiply-rgb-only
352 part.mColor += frac*part.mEndColor; 339 part.mColor *= 1.f - frac; // rgb*k
353 part.mColor.mV[3] += frac*part.mEndColor.mV[3]; 340 part.mColor %= 1.f - frac; // alpha*k
341 part.mColor += frac%(frac*part.mEndColor); // rgb,alpha
354 } 342 }
355 343
356 // Do scale interpolation 344 // Do scale interpolation
@@ -370,6 +358,8 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
370 { 358 {
371 end--; 359 end--;
372 LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]); 360 LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]);
361 // be sure to process the particle we just swapped-in
362 i--;
373 } 363 }
374 else 364 else
375 { 365 {
@@ -380,6 +370,8 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
380 gWorldPointer->mPartSim.put(&part); 370 gWorldPointer->mPartSim.put(&part);
381 end--; 371 end--;
382 LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]); 372 LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]);
373 // be sure to process the particle we just swapped-in
374 i--;
383 } 375 }
384 } 376 }
385 } 377 }
@@ -470,12 +462,12 @@ LLViewerPartSim::~LLViewerPartSim()
470BOOL LLViewerPartSim::shouldAddPart() 462BOOL LLViewerPartSim::shouldAddPart()
471{ 463{
472 LLMemType mt(LLMemType::MTYPE_PARTICLES); 464 LLMemType mt(LLMemType::MTYPE_PARTICLES);
473 if (sParticleCount > 0.75f*sMaxParticleCount) 465 if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount)
474 { 466 {
475 467
476 F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount; 468 F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount;
477 frac -= 0.75; 469 frac -= PART_THROTTLE_THRESHOLD;
478 frac *= 3.f; 470 frac *= PART_THROTTLE_RESCALE;
479 if (ll_frand() < frac) 471 if (ll_frand() < frac)
480 { 472 {
481 // Skip... 473 // Skip...
@@ -573,21 +565,13 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
573 } 565 }
574} 566}
575 567
576S32 dist_rate_func(F32 distance)
577{
578 //S32 dist = (S32) sqrtf(distance);
579 //dist /= 2;
580 //return llmax(dist,1);
581 return 1;
582}
583
584void LLViewerPartSim::updateSimulation() 568void LLViewerPartSim::updateSimulation()
585{ 569{
586 LLMemType mt(LLMemType::MTYPE_PARTICLES); 570 LLMemType mt(LLMemType::MTYPE_PARTICLES);
587 571
588 static LLFrameTimer update_timer; 572 static LLFrameTimer update_timer;
589 573
590 const F32 dt = update_timer.getElapsedTimeAndResetF32(); 574 const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);
591 575
592 if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) 576 if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
593 { 577 {
@@ -605,9 +589,11 @@ void LLViewerPartSim::updateSimulation()
605 S32 count = (S32) mViewerPartSources.size(); 589 S32 count = (S32) mViewerPartSources.size();
606 S32 start = (S32)ll_frand((F32)count); 590 S32 start = (S32)ll_frand((F32)count);
607 S32 dir = 1; 591 S32 dir = 1;
592 S32 deldir = 0;
608 if (ll_frand() > 0.5f) 593 if (ll_frand() > 0.5f)
609 { 594 {
610 dir = -1; 595 dir = -1;
596 deldir = -1;
611 } 597 }
612 598
613 S32 num_updates = 0; 599 S32 num_updates = 0;
@@ -624,25 +610,14 @@ void LLViewerPartSim::updateSimulation()
624 610
625 if (!mViewerPartSources[i]->isDead()) 611 if (!mViewerPartSources[i]->isDead())
626 { 612 {
627 LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp; 613 mViewerPartSources[i]->update(dt);
628 if (source_object && source_object->mDrawable.notNull())
629 {
630 S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera);
631 if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0)
632 {
633 mViewerPartSources[i]->update(dt*dist);
634 }
635 }
636 else
637 {
638 mViewerPartSources[i]->update(dt);
639 }
640 } 614 }
641 615
642 if (mViewerPartSources[i]->isDead()) 616 if (mViewerPartSources[i]->isDead())
643 { 617 {
644 mViewerPartSources.erase(mViewerPartSources.begin() + i); 618 mViewerPartSources.erase(mViewerPartSources.begin() + i);
645 count--; 619 count--;
620 i+=deldir;
646 } 621 }
647 else 622 else
648 { 623 {
@@ -657,24 +632,24 @@ void LLViewerPartSim::updateSimulation()
657 { 632 {
658 LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; 633 LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp;
659 634
660 S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ? 635 S32 visirate = 1;
661 dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1;
662 if (vobj) 636 if (vobj)
663 { 637 {
664 LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); 638 LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
665 if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) 639 if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
666 { 640 {
667 dist *= 8; 641 visirate = 8;
668 } 642 }
669 } 643 }
670 644
671 if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0) 645 if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0)
672 { 646 {
673 if (vobj) 647 if (vobj)
674 { 648 {
675 gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE); 649 gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
676 } 650 }
677 mViewerPartGroups[i]->updateParticles(dt*dist); 651 mViewerPartGroups[i]->updateParticles(dt * visirate);
652 mViewerPartGroups[i]->mSkippedTime=0.0f;
678 if (!mViewerPartGroups[i]->getCount()) 653 if (!mViewerPartGroups[i]->getCount())
679 { 654 {
680 delete mViewerPartGroups[i]; 655 delete mViewerPartGroups[i];
@@ -683,10 +658,64 @@ void LLViewerPartSim::updateSimulation()
683 count--; 658 count--;
684 } 659 }
685 } 660 }
661 else
662 {
663 mViewerPartGroups[i]->mSkippedTime+=dt;
664 }
665
666 }
667 if (LLDrawable::getCurrentFrame()%16==0)
668 {
669 if (sParticleCount > sMaxParticleCount * 0.875f
670 && sParticleAdaptiveRate < 2.0f)
671 {
672 sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT;
673 }
674 else
675 {
676 if (sParticleCount < sMaxParticleCount * 0.5f
677 && sParticleAdaptiveRate > 0.03125f)
678 {
679 sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT_RECIP;
680 }
681 }
686 } 682 }
687 //llinfos << "Particles: " << sParticleCount << llendl; 683
684 updatePartBurstRate() ;
685
686 //llinfos << "Particles: " << sParticleCount << " Adaptive Rate: " << sParticleAdaptiveRate << llendl;
688} 687}
689 688
689void LLViewerPartSim::updatePartBurstRate()
690{
691 if (!(LLDrawable::getCurrentFrame() & 0xf))
692 {
693 if (sParticleCount >= MAX_PART_COUNT) //set rate to zero
694 {
695 sParticleBurstRate = 0.0f ;
696 }
697 else if(sParticleCount > 0)
698 {
699 if(sParticleBurstRate > 0.0000001f)
700 {
701 F32 total_particles = sParticleCount / sParticleBurstRate ; //estimated
702 F32 new_rate = llclamp(0.9f * sMaxParticleCount / total_particles, 0.0f, 1.0f) ;
703 F32 delta_rate_threshold = llmin(0.1f * llmax(new_rate, sParticleBurstRate), 0.1f) ;
704 F32 delta_rate = llclamp(new_rate - sParticleBurstRate, -1.0f * delta_rate_threshold, delta_rate_threshold) ;
705
706 sParticleBurstRate = llclamp(sParticleBurstRate + 0.5f * delta_rate, 0.0f, 1.0f) ;
707 }
708 else
709 {
710 sParticleBurstRate += 0.0000001f ;
711 }
712 }
713 else
714 {
715 sParticleBurstRate += 0.00125f ;
716 }
717 }
718}
690 719
691void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep) 720void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep)
692{ 721{
@@ -696,6 +725,7 @@ void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep)
696 llwarns << "Null part source!" << llendl; 725 llwarns << "Null part source!" << llendl;
697 return; 726 return;
698 } 727 }
728 sourcep->setStart() ;
699 mViewerPartSources.push_back(sourcep); 729 mViewerPartSources.push_back(sourcep);
700} 730}
701 731