diff options
Diffstat (limited to 'indra/newview/llviewerpartsim.cpp')
-rw-r--r-- | indra/newview/llviewerpartsim.cpp | 1388 |
1 files changed, 694 insertions, 694 deletions
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 0f20076b04..b5505a42c4 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerpartsim.cpp * @brief LLViewerPart class implementation * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -67,62 +67,62 @@ U32 LLViewerPart::sNextPartID = 1; F32 calc_desired_size(LLViewerCamera* camera, LLVector3 pos, LLVector2 scale) { - F32 desired_size = (pos - camera->getOrigin()).magVec(); - desired_size /= 4; - return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2); + F32 desired_size = (pos - camera->getOrigin()).magVec(); + desired_size /= 4; + return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2); } LLViewerPart::LLViewerPart() : - mPartID(0), - mLastUpdateTime(0.f), - mSkipOffset(0.f), - mVPCallback(NULL), - mImagep(NULL) + mPartID(0), + mLastUpdateTime(0.f), + mSkipOffset(0.f), + mVPCallback(NULL), + mImagep(NULL) { - mPartSourcep = NULL; - mParent = NULL; - mChild = NULL; - ++LLViewerPartSim::sParticleCount2 ; + mPartSourcep = NULL; + mParent = NULL; + mChild = NULL; + ++LLViewerPartSim::sParticleCount2 ; } LLViewerPart::~LLViewerPart() { - if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) - { - mPartSourcep->mLastPart = NULL; - } - - //patch up holes in the ribbon - if (mParent) - { - llassert(mParent->mChild == this); - mParent->mChild = mChild; - } - - if (mChild) - { - llassert (mChild->mParent == this); - mChild->mParent = mParent; - } - - mPartSourcep = NULL; - - --LLViewerPartSim::sParticleCount2 ; + if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) + { + mPartSourcep->mLastPart = NULL; + } + + //patch up holes in the ribbon + if (mParent) + { + llassert(mParent->mChild == this); + mParent->mChild = mChild; + } + + if (mChild) + { + llassert (mChild->mParent == this); + mChild->mParent = mParent; + } + + mPartSourcep = NULL; + + --LLViewerPartSim::sParticleCount2 ; } void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerTexture *imagep, LLVPCallback cb) { - mPartID = LLViewerPart::sNextPartID; - LLViewerPart::sNextPartID++; - mFlags = 0x00f; - mLastUpdateTime = 0.f; - mMaxAge = 10.f; - mSkipOffset = 0.0f; + mPartID = LLViewerPart::sNextPartID; + LLViewerPart::sNextPartID++; + mFlags = 0x00f; + mLastUpdateTime = 0.f; + mMaxAge = 10.f; + mSkipOffset = 0.0f; - mVPCallback = cb; - mPartSourcep = sourcep; + mVPCallback = cb; + mPartSourcep = sourcep; - mImagep = imagep; + mImagep = imagep; } @@ -136,333 +136,333 @@ void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerTexture * LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 box_side, bool hud) : mHud(hud) { - mVOPartGroupp = NULL; - mUniformParticles = TRUE; - - mRegionp = LLWorld::getInstance()->getRegionFromPosAgent(center_agent); - llassert_always(center_agent.isFinite()); - - if (!mRegionp) - { - //LL_WARNS() << "No region at position, using agent region!" << LL_ENDL; - mRegionp = gAgent.getRegion(); - } - mCenterAgent = center_agent; - mBoxRadius = F_SQRT3*box_side*0.5f; - - if (mHud) - { - mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_HUD_PART_GROUP, getRegion()); - } - else - { - mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion()); - } - mVOPartGroupp->setViewerPartGroup(this); - mVOPartGroupp->setPositionAgent(getCenterAgent()); - - mBoxSide = box_side; - - F32 scale = box_side * 0.5f; - - mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); - - //gPipeline.addObject(mVOPartGroupp); - gPipeline.createObject(mVOPartGroupp); - - LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); - - if (group != NULL) - { - LLVector3 center(group->getOctreeNode()->getCenter().getF32ptr()); - LLVector3 size(group->getOctreeNode()->getSize().getF32ptr()); - size += LLVector3(0.01f, 0.01f, 0.01f); - mMinObjPos = center - size; - mMaxObjPos = center + size; - } - else - { - // Not sure what else to set the obj bounds to when the drawable has no spatial group. - LLVector3 extents(mBoxRadius, mBoxRadius, mBoxRadius); - mMinObjPos = center_agent - extents; - mMaxObjPos = center_agent + extents; - } - - mSkippedTime = 0.f; - - static U32 id_seed = 0; - mID = ++id_seed; + mVOPartGroupp = NULL; + mUniformParticles = TRUE; + + mRegionp = LLWorld::getInstance()->getRegionFromPosAgent(center_agent); + llassert_always(center_agent.isFinite()); + + if (!mRegionp) + { + //LL_WARNS() << "No region at position, using agent region!" << LL_ENDL; + mRegionp = gAgent.getRegion(); + } + mCenterAgent = center_agent; + mBoxRadius = F_SQRT3*box_side*0.5f; + + if (mHud) + { + mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_HUD_PART_GROUP, getRegion()); + } + else + { + mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion()); + } + mVOPartGroupp->setViewerPartGroup(this); + mVOPartGroupp->setPositionAgent(getCenterAgent()); + + mBoxSide = box_side; + + F32 scale = box_side * 0.5f; + + mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); + + //gPipeline.addObject(mVOPartGroupp); + gPipeline.createObject(mVOPartGroupp); + + LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); + + if (group != NULL) + { + LLVector3 center(group->getOctreeNode()->getCenter().getF32ptr()); + LLVector3 size(group->getOctreeNode()->getSize().getF32ptr()); + size += LLVector3(0.01f, 0.01f, 0.01f); + mMinObjPos = center - size; + mMaxObjPos = center + size; + } + else + { + // Not sure what else to set the obj bounds to when the drawable has no spatial group. + LLVector3 extents(mBoxRadius, mBoxRadius, mBoxRadius); + mMinObjPos = center_agent - extents; + mMaxObjPos = center_agent + extents; + } + + mSkippedTime = 0.f; + + static U32 id_seed = 0; + mID = ++id_seed; } LLViewerPartGroup::~LLViewerPartGroup() { - cleanup(); - - S32 count = (S32) mParticles.size(); - for(S32 i = 0 ; i < count ; i++) - { - delete mParticles[i] ; - } - mParticles.clear(); - - LLViewerPartSim::decPartCount(count); + cleanup(); + + S32 count = (S32) mParticles.size(); + for(S32 i = 0 ; i < count ; i++) + { + delete mParticles[i] ; + } + mParticles.clear(); + + LLViewerPartSim::decPartCount(count); } void LLViewerPartGroup::cleanup() { - if (mVOPartGroupp) - { - if (!mVOPartGroupp->isDead()) - { - gObjectList.killObject(mVOPartGroupp); - } - mVOPartGroupp = NULL; - } + if (mVOPartGroupp) + { + if (!mVOPartGroupp->isDead()) + { + gObjectList.killObject(mVOPartGroupp); + } + mVOPartGroupp = NULL; + } } BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size) { - if ((pos.mV[VX] < mMinObjPos.mV[VX]) - || (pos.mV[VY] < mMinObjPos.mV[VY]) - || (pos.mV[VZ] < mMinObjPos.mV[VZ])) - { - return FALSE; - } - - if ((pos.mV[VX] > mMaxObjPos.mV[VX]) - || (pos.mV[VY] > mMaxObjPos.mV[VY]) - || (pos.mV[VZ] > mMaxObjPos.mV[VZ])) - { - return FALSE; - } - - if (desired_size > 0 && - (desired_size < mBoxRadius*0.5f || - desired_size > mBoxRadius*2.f)) - { - return FALSE; - } - - return TRUE; + if ((pos.mV[VX] < mMinObjPos.mV[VX]) + || (pos.mV[VY] < mMinObjPos.mV[VY]) + || (pos.mV[VZ] < mMinObjPos.mV[VZ])) + { + return FALSE; + } + + if ((pos.mV[VX] > mMaxObjPos.mV[VX]) + || (pos.mV[VY] > mMaxObjPos.mV[VY]) + || (pos.mV[VZ] > mMaxObjPos.mV[VZ])) + { + return FALSE; + } + + if (desired_size > 0 && + (desired_size < mBoxRadius*0.5f || + desired_size > mBoxRadius*2.f)) + { + return FALSE; + } + + return TRUE; } BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size) { - if (part->mFlags & LLPartData::LL_PART_HUD && !mHud) - { - return FALSE; - } - - BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] && - !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK); - - if (!posInGroup(part->mPosAgent, desired_size) || - (mUniformParticles && !uniform_part) || - (!mUniformParticles && uniform_part)) - { - return FALSE; - } - - gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL); - - mParticles.push_back(part); - part->mSkipOffset=mSkippedTime; - LLViewerPartSim::incPartCount(1); - return TRUE; + if (part->mFlags & LLPartData::LL_PART_HUD && !mHud) + { + return FALSE; + } + + BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] && + !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK); + + if (!posInGroup(part->mPosAgent, desired_size) || + (mUniformParticles && !uniform_part) || + (!mUniformParticles && uniform_part)) + { + return FALSE; + } + + gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL); + + mParticles.push_back(part); + part->mSkipOffset=mSkippedTime; + LLViewerPartSim::incPartCount(1); + return TRUE; } void LLViewerPartGroup::updateParticles(const F32 lastdt) { - F32 dt; - - LLVector3 gravity(0.f, 0.f, GRAVITY); - - LLViewerPartSim::checkParticleCount(mParticles.size()); - - LLViewerCamera* camera = LLViewerCamera::getInstance(); - LLViewerRegion *regionp = getRegion(); - S32 end = (S32) mParticles.size(); - for (S32 i = 0 ; i < (S32)mParticles.size();) - { - LLVector3 a(0.f, 0.f, 0.f); - LLViewerPart* part = mParticles[i] ; - - dt = lastdt + mSkippedTime - part->mSkipOffset; - part->mSkipOffset = 0.f; - - // Update current time - const F32 cur_time = part->mLastUpdateTime + dt; - const F32 frac = cur_time / part->mMaxAge; - - // "Drift" the object based on the source object - if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK) - { - part->mPosAgent = part->mPartSourcep->mPosAgent; - part->mPosAgent += part->mPosOffset; - } - - // Do a custom callback if we have one... - if (part->mVPCallback) - { - (*part->mVPCallback)(*part, dt); - } - - if (part->mFlags & LLPartData::LL_PART_WIND_MASK) - { - part->mVelocity *= 1.f - 0.1f*dt; - part->mVelocity += 0.1f*dt*regionp->mWind.getVelocity(regionp->getPosRegionFromAgent(part->mPosAgent)); - } - - // Now do interpolation towards a target - if (part->mFlags & LLPartData::LL_PART_TARGET_POS_MASK) - { - F32 remaining = part->mMaxAge - part->mLastUpdateTime; - F32 step = dt / remaining; - - step = llclamp(step, 0.f, 0.1f); - step *= 5.f; - // we want a velocity that will result in reaching the target in the - // Interpolate towards the target. - LLVector3 delta_pos = part->mPartSourcep->mTargetPosAgent - part->mPosAgent; - - delta_pos /= remaining; - - part->mVelocity *= (1.f - step); - part->mVelocity += step*delta_pos; - } - - - if (part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK) - { - LLVector3 delta_pos = part->mPartSourcep->mTargetPosAgent - part->mPartSourcep->mPosAgent; - part->mPosAgent = part->mPartSourcep->mPosAgent; - part->mPosAgent += frac*delta_pos; - part->mVelocity = delta_pos; - } - else - { - // Do velocity interpolation - part->mPosAgent += dt*part->mVelocity; - part->mPosAgent += 0.5f*dt*dt*part->mAccel; - part->mVelocity += part->mAccel*dt; - } - - // Do a bounce test - if (part->mFlags & LLPartData::LL_PART_BOUNCE_MASK) - { - // Need to do point vs. plane check... - // For now, just check relative to object height... - F32 dz = part->mPosAgent.mV[VZ] - part->mPartSourcep->mPosAgent.mV[VZ]; - if (dz < 0) - { - part->mPosAgent.mV[VZ] += -2.f*dz; - part->mVelocity.mV[VZ] *= -0.75f; - } - } - - - // Reset the offset from the source position - if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK) - { - part->mPosOffset = part->mPosAgent; - part->mPosOffset -= part->mPartSourcep->mPosAgent; - } - - // Do color interpolation - if (part->mFlags & LLPartData::LL_PART_INTERP_COLOR_MASK) - { - part->mColor.setVec(part->mStartColor); - // note: LLColor4's v%k means multiply-alpha-only, - // LLColor4's v*k means multiply-rgb-only - part->mColor *= 1.f - frac; // rgb*k - part->mColor %= 1.f - frac; // alpha*k - part->mColor += frac%(frac*part->mEndColor); // rgb,alpha - } - - // Do scale interpolation - if (part->mFlags & LLPartData::LL_PART_INTERP_SCALE_MASK) - { - part->mScale.setVec(part->mStartScale); - part->mScale *= 1.f - frac; - part->mScale += frac*part->mEndScale; - } - - // Do glow interpolation - part->mGlow.mV[3] = (U8) ll_round(lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); - - // Set the last update time to now. - part->mLastUpdateTime = cur_time; - - - // Kill dead particles (either flagged dead, or too old) - if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags)) - { - mParticles[i] = mParticles.back() ; - mParticles.pop_back() ; - delete part ; - } - else - { - F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale); - if (!posInGroup(part->mPosAgent, desired_size)) - { - // Transfer particles between groups - LLViewerPartSim::getInstance()->put(part) ; - mParticles[i] = mParticles.back() ; - mParticles.pop_back() ; - } - else - { - i++ ; - } - } - } - - S32 removed = end - (S32)mParticles.size(); - if (removed > 0) - { - // we removed one or more particles, so flag this group for update - if (mVOPartGroupp.notNull()) - { - gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL); - } - LLViewerPartSim::decPartCount(removed); - } - - // Kill the viewer object if this particle group is empty - if (mParticles.empty()) - { - gObjectList.killObject(mVOPartGroupp); - mVOPartGroupp = NULL; - } - - LLViewerPartSim::checkParticleCount() ; + F32 dt; + + LLVector3 gravity(0.f, 0.f, GRAVITY); + + LLViewerPartSim::checkParticleCount(mParticles.size()); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + LLViewerRegion *regionp = getRegion(); + S32 end = (S32) mParticles.size(); + for (S32 i = 0 ; i < (S32)mParticles.size();) + { + LLVector3 a(0.f, 0.f, 0.f); + LLViewerPart* part = mParticles[i] ; + + dt = lastdt + mSkippedTime - part->mSkipOffset; + part->mSkipOffset = 0.f; + + // Update current time + const F32 cur_time = part->mLastUpdateTime + dt; + const F32 frac = cur_time / part->mMaxAge; + + // "Drift" the object based on the source object + if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK) + { + part->mPosAgent = part->mPartSourcep->mPosAgent; + part->mPosAgent += part->mPosOffset; + } + + // Do a custom callback if we have one... + if (part->mVPCallback) + { + (*part->mVPCallback)(*part, dt); + } + + if (part->mFlags & LLPartData::LL_PART_WIND_MASK) + { + part->mVelocity *= 1.f - 0.1f*dt; + part->mVelocity += 0.1f*dt*regionp->mWind.getVelocity(regionp->getPosRegionFromAgent(part->mPosAgent)); + } + + // Now do interpolation towards a target + if (part->mFlags & LLPartData::LL_PART_TARGET_POS_MASK) + { + F32 remaining = part->mMaxAge - part->mLastUpdateTime; + F32 step = dt / remaining; + + step = llclamp(step, 0.f, 0.1f); + step *= 5.f; + // we want a velocity that will result in reaching the target in the + // Interpolate towards the target. + LLVector3 delta_pos = part->mPartSourcep->mTargetPosAgent - part->mPosAgent; + + delta_pos /= remaining; + + part->mVelocity *= (1.f - step); + part->mVelocity += step*delta_pos; + } + + + if (part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK) + { + LLVector3 delta_pos = part->mPartSourcep->mTargetPosAgent - part->mPartSourcep->mPosAgent; + part->mPosAgent = part->mPartSourcep->mPosAgent; + part->mPosAgent += frac*delta_pos; + part->mVelocity = delta_pos; + } + else + { + // Do velocity interpolation + part->mPosAgent += dt*part->mVelocity; + part->mPosAgent += 0.5f*dt*dt*part->mAccel; + part->mVelocity += part->mAccel*dt; + } + + // Do a bounce test + if (part->mFlags & LLPartData::LL_PART_BOUNCE_MASK) + { + // Need to do point vs. plane check... + // For now, just check relative to object height... + F32 dz = part->mPosAgent.mV[VZ] - part->mPartSourcep->mPosAgent.mV[VZ]; + if (dz < 0) + { + part->mPosAgent.mV[VZ] += -2.f*dz; + part->mVelocity.mV[VZ] *= -0.75f; + } + } + + + // Reset the offset from the source position + if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK) + { + part->mPosOffset = part->mPosAgent; + part->mPosOffset -= part->mPartSourcep->mPosAgent; + } + + // Do color interpolation + if (part->mFlags & LLPartData::LL_PART_INTERP_COLOR_MASK) + { + part->mColor.setVec(part->mStartColor); + // note: LLColor4's v%k means multiply-alpha-only, + // LLColor4's v*k means multiply-rgb-only + part->mColor *= 1.f - frac; // rgb*k + part->mColor %= 1.f - frac; // alpha*k + part->mColor += frac%(frac*part->mEndColor); // rgb,alpha + } + + // Do scale interpolation + if (part->mFlags & LLPartData::LL_PART_INTERP_SCALE_MASK) + { + part->mScale.setVec(part->mStartScale); + part->mScale *= 1.f - frac; + part->mScale += frac*part->mEndScale; + } + + // Do glow interpolation + part->mGlow.mV[3] = (U8) ll_round(lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); + + // Set the last update time to now. + part->mLastUpdateTime = cur_time; + + + // Kill dead particles (either flagged dead, or too old) + if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags)) + { + mParticles[i] = mParticles.back() ; + mParticles.pop_back() ; + delete part ; + } + else + { + F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale); + if (!posInGroup(part->mPosAgent, desired_size)) + { + // Transfer particles between groups + LLViewerPartSim::getInstance()->put(part) ; + mParticles[i] = mParticles.back() ; + mParticles.pop_back() ; + } + else + { + i++ ; + } + } + } + + S32 removed = end - (S32)mParticles.size(); + if (removed > 0) + { + // we removed one or more particles, so flag this group for update + if (mVOPartGroupp.notNull()) + { + gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL); + } + LLViewerPartSim::decPartCount(removed); + } + + // Kill the viewer object if this particle group is empty + if (mParticles.empty()) + { + gObjectList.killObject(mVOPartGroupp); + mVOPartGroupp = NULL; + } + + LLViewerPartSim::checkParticleCount() ; } void LLViewerPartGroup::shift(const LLVector3 &offset) { - mCenterAgent += offset; - mMinObjPos += offset; - mMaxObjPos += offset; - - for (S32 i = 0 ; i < (S32)mParticles.size(); i++) - { - mParticles[i]->mPosAgent += offset; - } + mCenterAgent += offset; + mMinObjPos += offset; + mMaxObjPos += offset; + + for (S32 i = 0 ; i < (S32)mParticles.size(); i++) + { + mParticles[i]->mPosAgent += offset; + } } void LLViewerPartGroup::removeParticlesByID(const U32 source_id) { - for (S32 i = 0; i < (S32)mParticles.size(); i++) - { - if(mParticles[i]->mPartSourcep->getID() == source_id) - { - mParticles[i]->mFlags = LLViewerPart::LL_PART_DEAD_MASK; - } - } + for (S32 i = 0; i < (S32)mParticles.size(); i++) + { + if(mParticles[i]->mPartSourcep->getID() == source_id) + { + mParticles[i]->mFlags = LLViewerPart::LL_PART_DEAD_MASK; + } + } } ////////////////////////////////// @@ -474,423 +474,423 @@ void LLViewerPartGroup::removeParticlesByID(const U32 source_id) //static void LLViewerPartSim::checkParticleCount(U32 size) { - if(LLViewerPartSim::sParticleCount2 != LLViewerPartSim::sParticleCount) - { - LL_ERRS() << "sParticleCount: " << LLViewerPartSim::sParticleCount << " ; sParticleCount2: " << LLViewerPartSim::sParticleCount2 << LL_ENDL ; - } - - if(size > (U32)LLViewerPartSim::sParticleCount2) - { - LL_ERRS() << "curren particle size: " << LLViewerPartSim::sParticleCount2 << " array size: " << size << LL_ENDL ; - } + if(LLViewerPartSim::sParticleCount2 != LLViewerPartSim::sParticleCount) + { + LL_ERRS() << "sParticleCount: " << LLViewerPartSim::sParticleCount << " ; sParticleCount2: " << LLViewerPartSim::sParticleCount2 << LL_ENDL ; + } + + if(size > (U32)LLViewerPartSim::sParticleCount2) + { + LL_ERRS() << "curren particle size: " << LLViewerPartSim::sParticleCount2 << " array size: " << size << LL_ENDL ; + } } LLViewerPartSim::LLViewerPartSim() { - sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); - static U32 id_seed = 0; - mID = ++id_seed; + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); + static U32 id_seed = 0; + mID = ++id_seed; } //enable/disable particle system void LLViewerPartSim::enable(bool enabled) { - if(!enabled && sMaxParticleCount > 0) - { - sMaxParticleCount = 0; //disable - } - else if(enabled && sMaxParticleCount < 1) - { - sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); - } - - return; + if(!enabled && sMaxParticleCount > 0) + { + sMaxParticleCount = 0; //disable + } + else if(enabled && sMaxParticleCount < 1) + { + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); + } + + return; } void LLViewerPartSim::destroyClass() { - S32 i; - S32 count; - - // Kill all of the groups (and particles) - count = (S32) mViewerPartGroups.size(); - for (i = 0; i < count; i++) - { - delete mViewerPartGroups[i]; - } - mViewerPartGroups.clear(); - - // Kill all of the sources - mViewerPartSources.clear(); + S32 i; + S32 count; + + // Kill all of the groups (and particles) + count = (S32) mViewerPartGroups.size(); + for (i = 0; i < count; i++) + { + delete mViewerPartGroups[i]; + } + mViewerPartGroups.clear(); + + // Kill all of the sources + mViewerPartSources.clear(); } //static BOOL LLViewerPartSim::shouldAddPart() { - if (sParticleCount >= MAX_PART_COUNT) - { - return FALSE; - } - - if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount) - { - F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount; - frac -= PART_THROTTLE_THRESHOLD; - frac *= PART_THROTTLE_RESCALE; - if (ll_frand() < frac) - { - // Skip... - return FALSE; - } - } - - // Check frame rate, and don't add more if the viewer is really slow - const F32 MIN_FRAME_RATE_FOR_NEW_PARTICLES = 4.f; - if (gFPSClamped < MIN_FRAME_RATE_FOR_NEW_PARTICLES) - { - return FALSE; - } - - return TRUE; + if (sParticleCount >= MAX_PART_COUNT) + { + return FALSE; + } + + if (sParticleCount > PART_THROTTLE_THRESHOLD*sMaxParticleCount) + { + F32 frac = (F32)sParticleCount/(F32)sMaxParticleCount; + frac -= PART_THROTTLE_THRESHOLD; + frac *= PART_THROTTLE_RESCALE; + if (ll_frand() < frac) + { + // Skip... + return FALSE; + } + } + + // Check frame rate, and don't add more if the viewer is really slow + const F32 MIN_FRAME_RATE_FOR_NEW_PARTICLES = 4.f; + if (gFPSClamped < MIN_FRAME_RATE_FOR_NEW_PARTICLES) + { + return FALSE; + } + + return TRUE; } void LLViewerPartSim::addPart(LLViewerPart* part) { - if (sParticleCount < MAX_PART_COUNT) - { - put(part); - } - else - { - //delete the particle if can not add it in - delete part ; - part = NULL ; - } + if (sParticleCount < MAX_PART_COUNT) + { + put(part); + } + else + { + //delete the particle if can not add it in + delete part ; + part = NULL ; + } } LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part) { - const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million - LLViewerPartGroup *return_group = NULL ; - if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite()) - { + const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million + LLViewerPartGroup *return_group = NULL ; + if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite()) + { #if 0 && !LL_RELEASE_FOR_DOWNLOAD - LL_WARNS() << "LLViewerPartSim::put Part out of range!" << LL_ENDL; - LL_WARNS() << part->mPosAgent << LL_ENDL; + LL_WARNS() << "LLViewerPartSim::put Part out of range!" << LL_ENDL; + LL_WARNS() << part->mPosAgent << LL_ENDL; #endif - } - else - { - LLViewerCamera* camera = LLViewerCamera::getInstance(); - F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale); - - S32 count = (S32) mViewerPartGroups.size(); - for (S32 i = 0; i < count; i++) - { - if (mViewerPartGroups[i]->addPart(part, desired_size)) - { - // We found a spatial group that we fit into, add us and exit - return_group = mViewerPartGroups[i]; - break ; - } - } - - // Hmm, we didn't fit in any of the existing spatial groups - // Create a new one... - if(!return_group) - { - llassert_always(part->mPosAgent.isFinite()); - LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size, part->mFlags & LLPartData::LL_PART_HUD); - groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] && - !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)); - if (!groupp->addPart(part)) - { - LL_WARNS() << "LLViewerPartSim::put - Particle didn't go into its box!" << LL_ENDL; - LL_INFOS() << groupp->getCenterAgent() << LL_ENDL; - LL_INFOS() << part->mPosAgent << LL_ENDL; - mViewerPartGroups.pop_back() ; - delete groupp; - groupp = NULL ; - } - return_group = groupp; - } - } - - if(!return_group) //failed to insert the particle - { - delete part ; - part = NULL ; - } - - return return_group ; + } + else + { + LLViewerCamera* camera = LLViewerCamera::getInstance(); + F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale); + + S32 count = (S32) mViewerPartGroups.size(); + for (S32 i = 0; i < count; i++) + { + if (mViewerPartGroups[i]->addPart(part, desired_size)) + { + // We found a spatial group that we fit into, add us and exit + return_group = mViewerPartGroups[i]; + break ; + } + } + + // Hmm, we didn't fit in any of the existing spatial groups + // Create a new one... + if(!return_group) + { + llassert_always(part->mPosAgent.isFinite()); + LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size, part->mFlags & LLPartData::LL_PART_HUD); + groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] && + !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)); + if (!groupp->addPart(part)) + { + LL_WARNS() << "LLViewerPartSim::put - Particle didn't go into its box!" << LL_ENDL; + LL_INFOS() << groupp->getCenterAgent() << LL_ENDL; + LL_INFOS() << part->mPosAgent << LL_ENDL; + mViewerPartGroups.pop_back() ; + delete groupp; + groupp = NULL ; + } + return_group = groupp; + } + } + + if(!return_group) //failed to insert the particle + { + delete part ; + part = NULL ; + } + + return return_group ; } LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size, bool hud) { - //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses - //pos_agent - LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size, hud); - mViewerPartGroups.push_back(groupp); - return groupp; + //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses + //pos_agent + LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size, hud); + mViewerPartGroups.push_back(groupp); + return groupp; } void LLViewerPartSim::shift(const LLVector3 &offset) { - S32 i; - S32 count; - - count = (S32) mViewerPartSources.size(); - for (i = 0; i < count; i++) - { - mViewerPartSources[i]->mPosAgent += offset; - mViewerPartSources[i]->mTargetPosAgent += offset; - mViewerPartSources[i]->mLastUpdatePosAgent += offset; - } - - count = (S32) mViewerPartGroups.size(); - for (i = 0; i < count; i++) - { - mViewerPartGroups[i]->shift(offset); - } + S32 i; + S32 count; + + count = (S32) mViewerPartSources.size(); + for (i = 0; i < count; i++) + { + mViewerPartSources[i]->mPosAgent += offset; + mViewerPartSources[i]->mTargetPosAgent += offset; + mViewerPartSources[i]->mLastUpdatePosAgent += offset; + } + + count = (S32) mViewerPartGroups.size(); + for (i = 0; i < count; i++) + { + mViewerPartGroups[i]->shift(offset); + } } static LLTrace::BlockTimerStatHandle FTM_SIMULATE_PARTICLES("Simulate Particles"); void LLViewerPartSim::updateSimulation() { - static LLFrameTimer update_timer; - - const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f); - - if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) - { - return; - } - - LL_RECORD_BLOCK_TIME(FTM_SIMULATE_PARTICLES); - - // Start at a random particle system so the same - // particle system doesn't always get first pick at the - // particles. Theoretically we'd want to do this in distance - // order or something, but sorting particle sources will be a big - // pain. - S32 i; - S32 count = (S32) mViewerPartSources.size(); - S32 start = (S32)ll_frand((F32)count); - S32 dir = 1; - S32 deldir = 0; - if (ll_frand() > 0.5f) - { - dir = -1; - deldir = -1; - } - - S32 num_updates = 0; - for (i = start; num_updates < count;) - { - if (i >= count) - { - i = 0; - } - if (i < 0) - { - i = count - 1; - } - - if (!mViewerPartSources[i]->isDead()) - { - BOOL upd = TRUE; - LLViewerObject* vobj = mViewerPartSources[i]->mSourceObjectp; - - if (vobj && vobj->isAvatar() && ((LLVOAvatar*)vobj)->isInMuteList()) - { - upd = FALSE; - } - - if(vobj && vobj->isOwnerInMuteList(mViewerPartSources[i]->getOwnerUUID())) - { - upd = FALSE; - } - - if (upd && vobj && (vobj->getPCode() == LL_PCODE_VOLUME)) - { - if(vobj->getAvatar() && vobj->getAvatar()->isTooComplex() && vobj->getAvatar()->isTooSlow()) - { - upd = FALSE; - } - - LLVOVolume* vvo = (LLVOVolume *)vobj; - if (!LLPipeline::sRenderAttachedParticles && vvo && vvo->isAttachment()) - { - upd = FALSE; - } - } - - if (upd) - { - mViewerPartSources[i]->update(dt); - } - } - - if (mViewerPartSources[i]->isDead()) - { - mViewerPartSources.erase(mViewerPartSources.begin() + i); - count--; - i+=deldir; - } - else - { - i += dir; - } - num_updates++; - } - - count = (S32) mViewerPartGroups.size(); - for (i = 0; i < count; i++) - { - LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; - - S32 visirate = 1; - if (vobj && !vobj->isDead() && vobj->mDrawable && !vobj->mDrawable->isDead()) - { - LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); - if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) - { - visirate = 8; - } - } - - if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0) - { - if (vobj && !vobj->isDead()) - { - gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL); - } - mViewerPartGroups[i]->updateParticles(dt * visirate); - mViewerPartGroups[i]->mSkippedTime=0.0f; - if (!mViewerPartGroups[i]->getCount()) - { - delete mViewerPartGroups[i]; - mViewerPartGroups.erase(mViewerPartGroups.begin() + i); - i--; - count--; - } - } - else - { - mViewerPartGroups[i]->mSkippedTime+=dt; - } - - } - if (LLDrawable::getCurrentFrame()%16==0) - { - if (sParticleCount > sMaxParticleCount * 0.875f - && sParticleAdaptiveRate < 2.0f) - { - sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT; - } - else - { - if (sParticleCount < sMaxParticleCount * 0.5f - && sParticleAdaptiveRate > 0.03125f) - { - sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT_RECIP; - } - } - } - - updatePartBurstRate() ; - - //LL_INFOS() << "Particles: " << sParticleCount << " Adaptive Rate: " << sParticleAdaptiveRate << LL_ENDL; + static LLFrameTimer update_timer; + + const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f); + + if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) + { + return; + } + + LL_RECORD_BLOCK_TIME(FTM_SIMULATE_PARTICLES); + + // Start at a random particle system so the same + // particle system doesn't always get first pick at the + // particles. Theoretically we'd want to do this in distance + // order or something, but sorting particle sources will be a big + // pain. + S32 i; + S32 count = (S32) mViewerPartSources.size(); + S32 start = (S32)ll_frand((F32)count); + S32 dir = 1; + S32 deldir = 0; + if (ll_frand() > 0.5f) + { + dir = -1; + deldir = -1; + } + + S32 num_updates = 0; + for (i = start; num_updates < count;) + { + if (i >= count) + { + i = 0; + } + if (i < 0) + { + i = count - 1; + } + + if (!mViewerPartSources[i]->isDead()) + { + BOOL upd = TRUE; + LLViewerObject* vobj = mViewerPartSources[i]->mSourceObjectp; + + if (vobj && vobj->isAvatar() && ((LLVOAvatar*)vobj)->isInMuteList()) + { + upd = FALSE; + } + + if(vobj && vobj->isOwnerInMuteList(mViewerPartSources[i]->getOwnerUUID())) + { + upd = FALSE; + } + + if (upd && vobj && (vobj->getPCode() == LL_PCODE_VOLUME)) + { + if(vobj->getAvatar() && vobj->getAvatar()->isTooComplex() && vobj->getAvatar()->isTooSlow()) + { + upd = FALSE; + } + + LLVOVolume* vvo = (LLVOVolume *)vobj; + if (!LLPipeline::sRenderAttachedParticles && vvo && vvo->isAttachment()) + { + upd = FALSE; + } + } + + if (upd) + { + mViewerPartSources[i]->update(dt); + } + } + + if (mViewerPartSources[i]->isDead()) + { + mViewerPartSources.erase(mViewerPartSources.begin() + i); + count--; + i+=deldir; + } + else + { + i += dir; + } + num_updates++; + } + + count = (S32) mViewerPartGroups.size(); + for (i = 0; i < count; i++) + { + LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; + + S32 visirate = 1; + if (vobj && !vobj->isDead() && vobj->mDrawable && !vobj->mDrawable->isDead()) + { + LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); + if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) + { + visirate = 8; + } + } + + if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%visirate == 0) + { + if (vobj && !vobj->isDead()) + { + gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL); + } + mViewerPartGroups[i]->updateParticles(dt * visirate); + mViewerPartGroups[i]->mSkippedTime=0.0f; + if (!mViewerPartGroups[i]->getCount()) + { + delete mViewerPartGroups[i]; + mViewerPartGroups.erase(mViewerPartGroups.begin() + i); + i--; + count--; + } + } + else + { + mViewerPartGroups[i]->mSkippedTime+=dt; + } + + } + if (LLDrawable::getCurrentFrame()%16==0) + { + if (sParticleCount > sMaxParticleCount * 0.875f + && sParticleAdaptiveRate < 2.0f) + { + sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT; + } + else + { + if (sParticleCount < sMaxParticleCount * 0.5f + && sParticleAdaptiveRate > 0.03125f) + { + sParticleAdaptiveRate *= PART_ADAPT_RATE_MULT_RECIP; + } + } + } + + updatePartBurstRate() ; + + //LL_INFOS() << "Particles: " << sParticleCount << " Adaptive Rate: " << sParticleAdaptiveRate << LL_ENDL; } void LLViewerPartSim::updatePartBurstRate() { - if (!(LLDrawable::getCurrentFrame() & 0xf)) - { - if (sParticleCount >= MAX_PART_COUNT) //set rate to zero - { - sParticleBurstRate = 0.0f ; - } - else if(sParticleCount > 0) - { - if(sParticleBurstRate > 0.0000001f) - { - F32 total_particles = sParticleCount / sParticleBurstRate ; //estimated - F32 new_rate = llclamp(0.9f * sMaxParticleCount / total_particles, 0.0f, 1.0f) ; - F32 delta_rate_threshold = llmin(0.1f * llmax(new_rate, sParticleBurstRate), 0.1f) ; - F32 delta_rate = llclamp(new_rate - sParticleBurstRate, -1.0f * delta_rate_threshold, delta_rate_threshold) ; - - sParticleBurstRate = llclamp(sParticleBurstRate + 0.5f * delta_rate, 0.0f, 1.0f) ; - } - else - { - sParticleBurstRate += 0.0000001f ; - } - } - else - { - sParticleBurstRate += 0.00125f ; - } - } + if (!(LLDrawable::getCurrentFrame() & 0xf)) + { + if (sParticleCount >= MAX_PART_COUNT) //set rate to zero + { + sParticleBurstRate = 0.0f ; + } + else if(sParticleCount > 0) + { + if(sParticleBurstRate > 0.0000001f) + { + F32 total_particles = sParticleCount / sParticleBurstRate ; //estimated + F32 new_rate = llclamp(0.9f * sMaxParticleCount / total_particles, 0.0f, 1.0f) ; + F32 delta_rate_threshold = llmin(0.1f * llmax(new_rate, sParticleBurstRate), 0.1f) ; + F32 delta_rate = llclamp(new_rate - sParticleBurstRate, -1.0f * delta_rate_threshold, delta_rate_threshold) ; + + sParticleBurstRate = llclamp(sParticleBurstRate + 0.5f * delta_rate, 0.0f, 1.0f) ; + } + else + { + sParticleBurstRate += 0.0000001f ; + } + } + else + { + sParticleBurstRate += 0.00125f ; + } + } } void LLViewerPartSim::addPartSource(LLPointer<LLViewerPartSource> sourcep) { - if (!sourcep) - { - LL_WARNS() << "Null part source!" << LL_ENDL; - return; - } - sourcep->setStart() ; - mViewerPartSources.push_back(sourcep); + if (!sourcep) + { + LL_WARNS() << "Null part source!" << LL_ENDL; + return; + } + sourcep->setStart() ; + mViewerPartSources.push_back(sourcep); } void LLViewerPartSim::removeLastCreatedSource() { - mViewerPartSources.pop_back(); + mViewerPartSources.pop_back(); } void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp) { - for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); ) - { - group_list_t::iterator iter = i++; - - if ((*iter)->getRegion() == regionp) - { - delete *iter; - i = mViewerPartGroups.erase(iter); - } - } + for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); ) + { + group_list_t::iterator iter = i++; + + if ((*iter)->getRegion() == regionp) + { + delete *iter; + i = mViewerPartGroups.erase(iter); + } + } } void LLViewerPartSim::clearParticlesByID(const U32 system_id) { - for (group_list_t::iterator g = mViewerPartGroups.begin(); g != mViewerPartGroups.end(); ++g) - { - (*g)->removeParticlesByID(system_id); - } - for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); ++i) - { - if ((*i)->getID() == system_id) - { - (*i)->setDead(); - break; - } - } - + for (group_list_t::iterator g = mViewerPartGroups.begin(); g != mViewerPartGroups.end(); ++g) + { + (*g)->removeParticlesByID(system_id); + } + for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); ++i) + { + if ((*i)->getID() == system_id) + { + (*i)->setDead(); + break; + } + } + } void LLViewerPartSim::clearParticlesByOwnerID(const LLUUID& task_id) { - for (source_list_t::iterator iter = mViewerPartSources.begin(); iter != mViewerPartSources.end(); ++iter) - { - if ((*iter)->getOwnerUUID() == task_id) - { - clearParticlesByID((*iter)->getID()); - } - } + for (source_list_t::iterator iter = mViewerPartSources.begin(); iter != mViewerPartSources.end(); ++iter) + { + if ((*iter)->getOwnerUUID() == task_id) + { + clearParticlesByID((*iter)->getID()); + } + } } |