diff options
Diffstat (limited to 'linden/indra/newview/llviewerpartsim.cpp')
-rw-r--r-- | linden/indra/newview/llviewerpartsim.cpp | 200 |
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" | |
47 | const S32 MAX_PART_COUNT = 8192; // VWR-1105 | ||
48 | 47 | ||
49 | const F32 PART_SIM_BOX_SIDE = 16.f; | 48 | const F32 PART_SIM_BOX_SIDE = 16.f; |
50 | const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE; | 49 | const 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 |
54 | S32 LLViewerPartSim::sMaxParticleCount = 0; | 53 | S32 LLViewerPartSim::sMaxParticleCount = 0; |
55 | S32 LLViewerPartSim::sParticleCount = 0; | 54 | S32 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. | ||
56 | F32 LLViewerPartSim::sParticleAdaptiveRate = 0.0625f; | ||
57 | F32 LLViewerPartSim::sParticleBurstRate = 0.5f; | ||
58 | |||
59 | //static | ||
60 | const S32 LLViewerPartSim::MAX_PART_COUNT = 8192; | ||
61 | const F32 LLViewerPartSim::PART_THROTTLE_THRESHOLD = 0.9f; | ||
62 | const F32 LLViewerPartSim::PART_ADAPT_RATE_MULT = 2.0f; | ||
63 | |||
64 | //static | ||
65 | const F32 LLViewerPartSim::PART_THROTTLE_RESCALE = PART_THROTTLE_THRESHOLD / (1.0f-PART_THROTTLE_THRESHOLD); | ||
66 | const F32 LLViewerPartSim::PART_ADAPT_RATE_MULT_RECIP = 1.0f/PART_ADAPT_RATE_MULT; | ||
56 | 67 | ||
57 | 68 | ||
58 | U32 LLViewerPart::sNextPartID = 1; | 69 | U32 LLViewerPart::sNextPartID = 1; |
@@ -76,36 +87,6 @@ LLViewerPart::~LLViewerPart() | |||
76 | mPartSourcep = NULL; | 87 | mPartSourcep = NULL; |
77 | } | 88 | } |
78 | 89 | ||
79 | LLViewerPart &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 | |||
109 | void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb) | 90 | void 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 ¢er_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 | ||
241 | void LLViewerPartGroup::removePart(const S32 part_num) | 236 | void 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 | |||
253 | void 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() | |||
470 | BOOL LLViewerPartSim::shouldAddPart() | 462 | BOOL 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 | ||
576 | S32 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 | |||
584 | void LLViewerPartSim::updateSimulation() | 568 | void 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 | ||
689 | void 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 | ||
691 | void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep) | 720 | void 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 | ||