llviewerpartsim.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerpartsim.h"
00035 
00036 #include "llviewercontrol.h"
00037 
00038 #include "llagent.h"
00039 #include "llviewercamera.h"
00040 #include "llviewerobjectlist.h"
00041 #include "llviewerpartsource.h"
00042 #include "llviewerregion.h"
00043 #include "llvopartgroup.h"
00044 #include "llworld.h"
00045 #include "pipeline.h"
00046 
00047 const S32 MAX_PART_COUNT = 8192; // VWR-1105
00048 
00049 const F32 PART_SIM_BOX_SIDE = 16.f;
00050 const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE;
00051 const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
00052 
00053 //static
00054 S32 LLViewerPartSim::sMaxParticleCount = 0;
00055 S32 LLViewerPartSim::sParticleCount = 0;
00056 
00057 
00058 U32 LLViewerPart::sNextPartID = 1;
00059 
00060 F32 calc_desired_size(LLVector3 pos, LLVector2 scale)
00061 {
00062         F32 desired_size = (pos-gCamera->getOrigin()).magVec();
00063         desired_size /= 4;
00064         return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2);
00065 }
00066 
00067 LLViewerPart::LLViewerPart()
00068 {
00069         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00070         mPartSourcep = NULL;
00071 }
00072 
00073 LLViewerPart::~LLViewerPart()
00074 {
00075         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00076         mPartSourcep = NULL;
00077 }
00078 
00079 LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
00080 {
00081         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00082         mPartID = part.mPartID;
00083         mFlags = part.mFlags;
00084         mMaxAge = part.mMaxAge;
00085 
00086         mStartColor = part.mStartColor;
00087         mEndColor = part.mEndColor;
00088         mStartScale = part.mStartScale;
00089         mEndScale = part.mEndScale;
00090 
00091         mPosOffset = part.mPosOffset;
00092         mParameter = part.mParameter;
00093 
00094         mLastUpdateTime = part.mLastUpdateTime;
00095         mVPCallback = part.mVPCallback;
00096         mPartSourcep = part.mPartSourcep;
00097         
00098         mImagep = part.mImagep;
00099         mPosAgent = part.mPosAgent;
00100         mVelocity = part.mVelocity;
00101         mAccel = part.mAccel;
00102         mColor = part.mColor;
00103         mScale = part.mScale;
00104 
00105 
00106         return *this;
00107 }
00108 
00109 void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb)
00110 {
00111         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00112         mPartID = LLViewerPart::sNextPartID;
00113         LLViewerPart::sNextPartID++;
00114         mFlags = 0x00f;
00115         mLastUpdateTime = 0.f;
00116         mMaxAge = 10.f;
00117 
00118         mVPCallback = cb;
00119         mPartSourcep = sourcep;
00120 
00121         mImagep = imagep;
00122 }
00123 
00124 
00126 //
00127 // LLViewerPartGroup implementation
00128 //
00129 //
00130 
00131 
00132 LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 box_side)
00133 {
00134         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00135         mVOPartGroupp = NULL;
00136         mUniformParticles = TRUE;
00137 
00138         mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent);
00139         llassert_always(center_agent.isFinite());
00140         
00141         if (!mRegionp)
00142         {
00143                 //llwarns << "No region at position, using agent region!" << llendl;
00144                 mRegionp = gAgent.getRegion();
00145         }
00146         mCenterAgent = center_agent;
00147         mBoxRadius = F_SQRT3*box_side*0.5f;
00148 
00149         mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
00150         mVOPartGroupp->setViewerPartGroup(this);
00151         mVOPartGroupp->setPositionAgent(getCenterAgent());
00152         F32 scale = box_side * 0.5f;
00153         mVOPartGroupp->setScale(LLVector3(scale,scale,scale));
00154         gPipeline.addObject(mVOPartGroupp);
00155 
00156         LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup();
00157 
00158         LLVector3 center(group->mOctreeNode->getCenter());
00159         LLVector3 size(group->mOctreeNode->getSize());
00160         size += LLVector3(0.01f, 0.01f, 0.01f);
00161         mMinObjPos = center - size;
00162         mMaxObjPos = center + size;
00163 
00164         static U32 id_seed = 0;
00165         mID = ++id_seed;
00166 }
00167 
00168 LLViewerPartGroup::~LLViewerPartGroup()
00169 {
00170         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00171         cleanup();
00172         
00173         S32 count = (S32) mParticles.size();
00174         mParticles.clear();
00175         
00176         LLViewerPartSim::decPartCount(count);
00177 }
00178 
00179 void LLViewerPartGroup::cleanup()
00180 {
00181         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00182         if (mVOPartGroupp)
00183         {
00184                 if (!mVOPartGroupp->isDead())
00185                 {
00186                         gObjectList.killObject(mVOPartGroupp);
00187                 }
00188                 mVOPartGroupp = NULL;
00189         }
00190 }
00191 
00192 BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size)
00193 {
00194         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00195         if ((pos.mV[VX] < mMinObjPos.mV[VX])
00196                 || (pos.mV[VY] < mMinObjPos.mV[VY])
00197                 || (pos.mV[VZ] < mMinObjPos.mV[VZ]))
00198         {
00199                 return FALSE;
00200         }
00201 
00202         if ((pos.mV[VX] > mMaxObjPos.mV[VX])
00203                 || (pos.mV[VY] > mMaxObjPos.mV[VY])
00204                 || (pos.mV[VZ] > mMaxObjPos.mV[VZ]))
00205         {
00206                 return FALSE;
00207         }
00208 
00209         if (desired_size > 0 && 
00210                 (desired_size < mBoxRadius*0.5f ||
00211                 desired_size > mBoxRadius*2.f))
00212         {
00213                 return FALSE;
00214         }
00215 
00216         return TRUE;
00217 }
00218 
00219 
00220 BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size)
00221 {
00222         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00223         BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] && 
00224                                         !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK);
00225 
00226         if (!posInGroup(part->mPosAgent, desired_size) ||
00227                 (mUniformParticles && !uniform_part) ||
00228                 (!mUniformParticles && uniform_part))
00229         {
00230                 return FALSE;
00231         }
00232 
00233         gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00234         
00235         mParticles.push_back(part);
00236         LLViewerPartSim::incPartCount(1);
00237         return TRUE;
00238 }
00239 
00240 
00241 void LLViewerPartGroup::removePart(const S32 part_num)
00242 {
00243         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00244         // Remove the entry for the particle we just deleted.
00245         mParticles.erase(mParticles.begin() + part_num);
00246         if (mVOPartGroupp.notNull())
00247         {
00248                 gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00249         }
00250         LLViewerPartSim::decPartCount(1);
00251 }
00252 
00253 void LLViewerPartGroup::updateParticles(const F32 dt)
00254 {
00255         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00256         S32 i;
00257         
00258         LLVector3 gravity(0.f, 0.f, -9.8f);
00259 
00260         LLViewerRegion *regionp = getRegion();
00261         S32 end = (S32) mParticles.size();
00262         for (i = 0; i < end; i++)
00263         {
00264                 LLVector3 a(0.f, 0.f, 0.f);
00265                 LLViewerPart& part = *((LLViewerPart*) mParticles[i]);
00266 
00267                 // Update current time
00268                 const F32 cur_time = part.mLastUpdateTime + dt;
00269                 const F32 frac = cur_time/part.mMaxAge;
00270 
00271                 // "Drift" the object based on the source object
00272                 if (part.mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK)
00273                 {
00274                         part.mPosAgent = part.mPartSourcep->mPosAgent;
00275                         part.mPosAgent += part.mPosOffset;
00276                 }
00277 
00278                 // Do a custom callback if we have one...
00279                 if (part.mVPCallback)
00280                 {
00281                         (*part.mVPCallback)(part, dt);
00282                 }
00283 
00284                 if (part.mFlags & LLPartData::LL_PART_WIND_MASK)
00285                 {
00286                         LLVector3 tempVel(part.mVelocity);
00287                         part.mVelocity *= 1.f - 0.1f*dt;
00288                         part.mVelocity += 0.1f*dt*regionp->mWind.getVelocity(regionp->getPosRegionFromAgent(part.mPosAgent));
00289                 }
00290 
00291                 // Now do interpolation towards a target
00292                 if (part.mFlags & LLPartData::LL_PART_TARGET_POS_MASK)
00293                 {
00294                         F32 remaining = part.mMaxAge - part.mLastUpdateTime;
00295                         F32 step = dt / remaining;
00296 
00297                         step = llclamp(step, 0.f, 0.1f);
00298                         step *= 5.f;
00299                         // we want a velocity that will result in reaching the target in the 
00300                         // Interpolate towards the target.
00301                         LLVector3 delta_pos = part.mPartSourcep->mTargetPosAgent - part.mPosAgent;
00302 
00303                         delta_pos /= remaining;
00304 
00305                         part.mVelocity *= (1.f - step);
00306                         part.mVelocity += step*delta_pos;
00307                 }
00308 
00309 
00310                 if (part.mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
00311                 {
00312                         LLVector3 delta_pos = part.mPartSourcep->mTargetPosAgent - part.mPartSourcep->mPosAgent;                        
00313                         part.mPosAgent = part.mPartSourcep->mPosAgent;
00314                         part.mPosAgent += frac*delta_pos;
00315                         part.mVelocity = delta_pos;
00316                 }
00317                 else
00318                 {
00319                         // Do velocity interpolation
00320                         part.mPosAgent += dt*part.mVelocity;
00321                         part.mPosAgent += 0.5f*dt*dt*part.mAccel;
00322                         part.mVelocity += part.mAccel*dt;
00323                 }
00324 
00325                 // Do a bounce test
00326                 if (part.mFlags & LLPartData::LL_PART_BOUNCE_MASK)
00327                 {
00328                         // Need to do point vs. plane check...
00329                         // For now, just check relative to object height...
00330                         F32 dz = part.mPosAgent.mV[VZ] - part.mPartSourcep->mPosAgent.mV[VZ];
00331                         if (dz < 0)
00332                         {
00333                                 part.mPosAgent.mV[VZ] += -2.f*dz;
00334                                 part.mVelocity.mV[VZ] *= -0.75f;
00335                         }
00336                 }
00337 
00338 
00339                 // Reset the offset from the source position
00340                 if (part.mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK)
00341                 {
00342                         part.mPosOffset = part.mPosAgent;
00343                         part.mPosOffset -= part.mPartSourcep->mPosAgent;
00344                 }
00345 
00346                 // Do color interpolation
00347                 if (part.mFlags & LLPartData::LL_PART_INTERP_COLOR_MASK)
00348                 {
00349                         part.mColor.setVec(part.mStartColor);
00350                         part.mColor *= 1.f - frac;
00351                         part.mColor.mV[3] *= (1.f - frac)*part.mStartColor.mV[3];
00352                         part.mColor += frac*part.mEndColor;
00353                         part.mColor.mV[3] += frac*part.mEndColor.mV[3];
00354                 }
00355 
00356                 // Do scale interpolation
00357                 if (part.mFlags & LLPartData::LL_PART_INTERP_SCALE_MASK)
00358                 {
00359                         part.mScale.setVec(part.mStartScale);
00360                         part.mScale *= 1.f - frac;
00361                         part.mScale += frac*part.mEndScale;
00362                 }
00363 
00364                 // Set the last update time to now.
00365                 part.mLastUpdateTime = cur_time;
00366 
00367 
00368                 // Kill dead particles (either flagged dead, or too old)
00369                 if ((part.mLastUpdateTime > part.mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part.mFlags))
00370                 {
00371                         end--;
00372                         LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]);
00373                 }
00374                 else 
00375                 {
00376                         F32 desired_size = calc_desired_size(part.mPosAgent, part.mScale);
00377                         if (!posInGroup(part.mPosAgent, desired_size))
00378                         {
00379                                 // Transfer particles between groups
00380                                 gWorldPointer->mPartSim.put(&part);
00381                                 end--;
00382                                 LLPointer<LLViewerPart>::swap(mParticles[i], mParticles[end]);
00383                         }
00384                 }
00385         }
00386 
00387         S32 removed = (S32)mParticles.size() - end;
00388         if (removed > 0)
00389         {
00390                 // we removed one or more particles, so flag this group for update
00391                 mParticles.erase(mParticles.begin() + end, mParticles.end());
00392                 if (mVOPartGroupp.notNull())
00393                 {
00394                         gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00395                 }
00396                 LLViewerPartSim::decPartCount(removed);
00397         }
00398         
00399         // Kill the viewer object if this particle group is empty
00400         if (mParticles.empty())
00401         {
00402                 gObjectList.killObject(mVOPartGroupp);
00403                 mVOPartGroupp = NULL;
00404         }
00405 }
00406 
00407 
00408 void LLViewerPartGroup::shift(const LLVector3 &offset)
00409 {
00410         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00411         mCenterAgent += offset;
00412         mMinObjPos += offset;
00413         mMaxObjPos += offset;
00414 
00415         S32 count = (S32) mParticles.size();
00416         S32 i;
00417         for (i = 0; i < count; i++)
00418         {
00419                 mParticles[i]->mPosAgent += offset;
00420         }
00421 }
00422 
00423 void LLViewerPartGroup::removeParticlesByID(const U32 source_id)
00424 {
00425         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00426         S32 end = (S32) mParticles.size();
00427         for (int i = 0; i < end; i++)
00428         {
00429                 if(mParticles[i]->mPartSourcep->getID() == source_id)
00430                 {
00431                         mParticles[i]->mFlags = LLViewerPart::LL_PART_DEAD_MASK;
00432                 }               
00433         }
00434 }
00435 
00437 //
00438 // LLViewerPartSim implementation
00439 //
00440 //
00441 
00442 
00443 LLViewerPartSim::LLViewerPartSim()
00444 {
00445         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00446         sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount");
00447         static U32 id_seed = 0;
00448         mID = ++id_seed;
00449 }
00450 
00451 
00452 LLViewerPartSim::~LLViewerPartSim()
00453 {
00454         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00455         S32 i;
00456         S32 count;
00457 
00458         // Kill all of the groups (and particles)
00459         count = (S32) mViewerPartGroups.size();
00460         for (i = 0; i < count; i++)
00461         {
00462                 delete mViewerPartGroups[i];
00463         }
00464         mViewerPartGroups.clear();
00465 
00466         // Kill all of the sources 
00467         mViewerPartSources.clear();
00468 }
00469 
00470 BOOL LLViewerPartSim::shouldAddPart()
00471 {
00472         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00473         if (sParticleCount > 0.75f*sMaxParticleCount)
00474         {
00475 
00476                 F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount;
00477                 frac -= 0.75;
00478                 frac *= 3.f;
00479                 if (ll_frand() < frac)
00480                 {
00481                         // Skip...
00482                         return FALSE;
00483                 }
00484         }
00485         if (sParticleCount >= MAX_PART_COUNT)
00486         {
00487                 return FALSE;
00488         }
00489 
00490         return TRUE;
00491 }
00492 
00493 void LLViewerPartSim::addPart(LLViewerPart* part)
00494 {
00495         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00496         if (sParticleCount < MAX_PART_COUNT)
00497         {
00498                 put(part);
00499         }
00500 }
00501 
00502 
00503 LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
00504 {
00505         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00506         const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
00507         if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite())
00508         {
00509 #if 0 && !LL_RELEASE_FOR_DOWNLOAD
00510                 llwarns << "LLViewerPartSim::put Part out of range!" << llendl;
00511                 llwarns << part->mPosAgent << llendl;
00512 #endif
00513                 return NULL;
00514         }
00515         
00516         F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
00517 
00518         S32 count = (S32) mViewerPartGroups.size();
00519         for (S32 i = 0; i < count; i++)
00520         {
00521                 if (mViewerPartGroups[i]->addPart(part, desired_size))
00522                 {
00523                         // We found a spatial group that we fit into, add us and exit
00524                         return mViewerPartGroups[i];
00525                 }
00526         }
00527 
00528         // Hmm, we didn't fit in any of the existing spatial groups
00529         // Create a new one...
00530         llassert_always(part->mPosAgent.isFinite());
00531         LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size);
00532         groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] && 
00533                                                         !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK));
00534         if (!groupp->addPart(part))
00535         {
00536                 llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl;
00537                 llinfos << groupp->getCenterAgent() << llendl;
00538                 llinfos << part->mPosAgent << llendl;
00539                 delete groupp;
00540                 return NULL;
00541         }
00542         return groupp;
00543 }
00544 
00545 LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size)
00546 {
00547         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00548         //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses
00549         //pos_agent
00550         LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size);
00551         mViewerPartGroups.push_back(groupp);
00552         return groupp;
00553 }
00554 
00555 
00556 void LLViewerPartSim::shift(const LLVector3 &offset)
00557 {
00558         S32 i;
00559         S32 count;
00560 
00561         count = (S32) mViewerPartSources.size();
00562         for (i = 0; i < count; i++)
00563         {
00564                 mViewerPartSources[i]->mPosAgent += offset;
00565                 mViewerPartSources[i]->mTargetPosAgent += offset;
00566                 mViewerPartSources[i]->mLastUpdatePosAgent += offset;
00567         }
00568 
00569         count = (S32) mViewerPartGroups.size();
00570         for (i = 0; i < count; i++)
00571         {
00572                 mViewerPartGroups[i]->shift(offset);
00573         }
00574 }
00575 
00576 S32 dist_rate_func(F32 distance)
00577 {
00578         //S32 dist = (S32) sqrtf(distance);
00579         //dist /= 2;
00580         //return llmax(dist,1);
00581         return 1;
00582 }
00583 
00584 void LLViewerPartSim::updateSimulation()
00585 {
00586         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00587         
00588         static LLFrameTimer update_timer;
00589 
00590         const F32 dt = update_timer.getElapsedTimeAndResetF32();
00591 
00592         if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
00593         {
00594                 return;
00595         }
00596 
00597         LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES);
00598 
00599         // Start at a random particle system so the same
00600         // particle system doesn't always get first pick at the
00601         // particles.  Theoretically we'd want to do this in distance
00602         // order or something, but sorting particle sources will be a big
00603         // pain.
00604         S32 i;
00605         S32 count = (S32) mViewerPartSources.size();
00606         S32 start = (S32)ll_frand((F32)count);
00607         S32 dir = 1;
00608         if (ll_frand() > 0.5f)
00609         {
00610                 dir = -1;
00611         }
00612 
00613         S32 num_updates = 0;
00614         for (i = start; num_updates < count;)
00615         {
00616                 if (i >= count)
00617                 {
00618                         i = 0;
00619                 }
00620                 if (i < 0)
00621                 {
00622                         i = count - 1;
00623                 }
00624 
00625                 if (!mViewerPartSources[i]->isDead())
00626                 {
00627                         LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp;
00628                         if (source_object && source_object->mDrawable.notNull())
00629                         {
00630                 S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera);
00631                                 if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0)
00632                                 {
00633                                         mViewerPartSources[i]->update(dt*dist);
00634                                 }
00635                         }
00636                         else
00637                         {
00638                                 mViewerPartSources[i]->update(dt);
00639                         }
00640                 }
00641 
00642                 if (mViewerPartSources[i]->isDead())
00643                 {
00644                         mViewerPartSources.erase(mViewerPartSources.begin() + i);
00645                         count--;
00646                 }
00647                 else
00648         {
00649                          i += dir;
00650         }
00651                 num_updates++;
00652         }
00653 
00654 
00655         count = (S32) mViewerPartGroups.size();
00656         for (i = 0; i < count; i++)
00657         {
00658                 LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp;
00659 
00660                 S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ? 
00661                                 dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1;
00662                 if (vobj)
00663                 {
00664                         LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
00665                         if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
00666                         {
00667                                 dist *= 8;
00668                         }
00669                 }
00670 
00671                 if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0)
00672                 {
00673                         if (vobj)
00674                         {
00675                                 gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
00676                         }
00677                         mViewerPartGroups[i]->updateParticles(dt*dist);
00678                         if (!mViewerPartGroups[i]->getCount())
00679                         {
00680                                 delete mViewerPartGroups[i];
00681                                 mViewerPartGroups.erase(mViewerPartGroups.begin() + i);
00682                                 i--;
00683                                 count--;
00684                         }
00685                 }
00686         }
00687         //llinfos << "Particles: " << sParticleCount << llendl;
00688 }
00689 
00690 
00691 void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep)
00692 {
00693         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00694         if (!sourcep)
00695         {
00696                 llwarns << "Null part source!" << llendl;
00697                 return;
00698         }
00699         mViewerPartSources.push_back(sourcep);
00700 }
00701 
00702 void LLViewerPartSim::removeLastCreatedSource()
00703 {
00704         mViewerPartSources.pop_back();
00705 }
00706 
00707 void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp)
00708 {
00709         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00710         for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); )
00711         {
00712                 group_list_t::iterator iter = i++;
00713 
00714                 if ((*iter)->getRegion() == regionp)
00715                 {
00716                         delete *iter;
00717                         i = mViewerPartGroups.erase(iter);                      
00718                 }
00719         }
00720 }
00721 
00722 void LLViewerPartSim::clearParticlesByID(const U32 system_id)
00723 {
00724         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00725         for (group_list_t::iterator g = mViewerPartGroups.begin(); g != mViewerPartGroups.end(); ++g)
00726         {
00727                 (*g)->removeParticlesByID(system_id);
00728         }
00729         for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); ++i)
00730         {
00731                 if ((*i)->getID() == system_id)
00732                 {
00733                         (*i)->setDead();        
00734                         break;
00735                 }
00736         }
00737         
00738 }
00739 
00740 void LLViewerPartSim::clearParticlesByOwnerID(const LLUUID& task_id)
00741 {
00742         LLMemType mt(LLMemType::MTYPE_PARTICLES);
00743         for (source_list_t::iterator iter = mViewerPartSources.begin(); iter != mViewerPartSources.end(); ++iter)
00744         {
00745                 if ((*iter)->getOwnerUUID() == task_id)
00746                 {
00747                         clearParticlesByID((*iter)->getID());
00748                 }
00749         }
00750 }

Generated on Thu Jul 1 06:09:33 2010 for Second Life Viewer by  doxygen 1.4.7