123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960 |
- /**
- * @file llviewerpartsource.cpp
- * @brief LLViewerPartSource class implementation
- *
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- *
- * Copyright (c) 2003-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llviewerpartsource.h"
- #include "llrender.h"
- #include "llagent.h"
- #include "lldrawable.h"
- #include "llpipeline.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewerobjectlist.h"
- #include "llviewertexturelist.h"
- #include "llworld.h"
- static LLVOAvatar* find_avatar(const LLUUID& id)
- {
- LLViewerObject* obj = gObjectList.findObject(id);
- while (obj && obj->isAttachment())
- {
- obj = (LLViewerObject*)obj->getParent();
- }
- if (obj && obj->isAvatar())
- {
- return (LLVOAvatar*)obj;
- }
- return NULL;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLViewerPartSource base class
- ///////////////////////////////////////////////////////////////////////////////
- LLViewerPartSource::LLViewerPartSource(U32 type)
- : mType(type),
- mOwnerUUID(LLUUID::null),
- mLastPart(NULL),
- mPartFlags(0),
- mIsDead(false),
- mIsSuspended(false),
- mLastUpdateTime(0.f),
- mLastPartTime(0.f),
- mDistFromCamera(0.f),
- mDelay(0),
- mPartCount(0),
- mPartUpdates(1)
- {
- static U32 id_seed = 0;
- mID = ++id_seed;
- }
- void LLViewerPartSource::setDead()
- {
- mIsDead = true;
- }
- const LLUUID& LLViewerPartSource::getImageUUID() const
- {
- return mImagep.notNull() ? mImagep->getID() : LLUUID::null;
- }
- void LLViewerPartSource::incPartCount()
- {
- if (++mPartCount > U32_MAX)
- {
- mPartCount /= mPartUpdates;
- mPartUpdates = 1;
- }
- }
- U64 LLViewerPartSource::getAveragePartCount()
- {
- return mPartCount / mPartUpdates;
- }
- //static
- void LLViewerPartSource::updatePart(LLViewerPart& part, F32 dt)
- {
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLViewerPartSourceScript sub-class
- ///////////////////////////////////////////////////////////////////////////////
- LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject* source_objp)
- : LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
- {
- llassert(source_objp);
- mSourceObjectp = source_objp;
- mPosAgent = mSourceObjectp->getPositionAgent();
- mImagep = gImgPixieSmall;
- mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
- LLMuteList::addObserver(this);
- }
- LLViewerPartSourceScript::~LLViewerPartSourceScript()
- {
- LLMuteList::removeObserver(this);
- }
- void LLViewerPartSourceScript::setDead()
- {
- mIsDead = true;
- mSourceObjectp = NULL;
- mTargetObjectp = NULL;
- }
- //virtual
- void LLViewerPartSourceScript::onChange()
- {
- if ((mOwnerUUID.notNull() &&
- LLMuteList::isMuted(mOwnerUUID, LLMute::flagParticles)) ||
- (mSourceObjectp.notNull() &&
- LLMuteList::isMuted(mSourceObjectp->getID())))
- {
- // Kill particle source because it has been muted !
- setDead();
- }
- }
- void LLViewerPartSourceScript::update(F32 dt)
- {
- if (mIsSuspended)
- {
- return;
- }
- // By default (for particles that will not be updated), set a far distance
- mDistFromCamera = 1024.f;
- if (mOwnerAvatarp.isNull() && mOwnerUUID.notNull())
- {
- mOwnerAvatarp = find_avatar(mOwnerUUID);
- }
- if (mOwnerAvatarp.notNull() &&
- mOwnerAvatarp->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER)
- {
- return;
- }
- F32 old_update_time = mLastUpdateTime;
- mLastUpdateTime += dt;
- F32 travelspeed = llmin(gViewerPartSim.getRefRate(), 1.f);
- F32 dt_update = mLastUpdateTime - mLastPartTime;
- // Update this for objects which have the follow flag set...
- if (mSourceObjectp.notNull())
- {
- if (mSourceObjectp->isDead())
- {
- mSourceObjectp = NULL;
- }
- else if (mSourceObjectp->mDrawable.notNull())
- {
- mPosAgent = mSourceObjectp->getRenderPosition();
- }
- }
- if (mTargetObjectp.isNull() && mPartSysData.mTargetUUID.notNull())
- {
- // Hmm, missing object, let's see if we can find it...
- LLViewerObject* target_objp =
- gObjectList.findObject(mPartSysData.mTargetUUID);
- setTargetObject(target_objp);
- }
- if (mTargetObjectp.notNull())
- {
- if (mTargetObjectp->isDead())
- {
- mTargetObjectp = NULL;
- }
- else if (mTargetObjectp->mDrawable.notNull())
- {
- mTargetPosAgent = mTargetObjectp->getRenderPosition();
- }
- }
- if (mTargetObjectp.isNull())
- {
- mTargetPosAgent = mPosAgent;
- }
- if (mPartSysData.mMaxAge &&
- mPartSysData.mStartAge + mLastUpdateTime + dt_update > mPartSysData.mMaxAge)
- {
- // Kill particle source because it has outlived its max age...
- setDead();
- return;
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
- {
- if (mSourceObjectp.notNull())
- {
- std::ostringstream ostr;
- ostr << mPartSysData;
- mSourceObjectp->setDebugText(ostr.str());
- }
- }
- bool first_run = false;
- if (old_update_time <= 0.f)
- {
- first_run = true;
- // Check we are not already muted...
- onChange();
- if (mIsDead) return;
- }
- // Distance from camera
- static LLCachedControl<F32> far_clip(gSavedSettings, "RenderFarClip");
- mDistFromCamera = (mPosAgent - gViewerCamera.getOrigin()).length();
- if (mDistFromCamera > far_clip)
- {
- // Do not even bother !
- LL_DEBUGS("Particles") << "Particle source " << mID
- << " skipped because it is too far away."
- << LL_ENDL;
- return;
- }
- F32 pixel_meter_ratio = gViewerCamera.getPixelMeterRatio();
- F32 max_time = llmax(1.f, 10.f * mPartSysData.mBurstRate);
- dt_update = llmin(max_time, dt_update);
- while (dt_update > mPartSysData.mBurstRate || first_run)
- {
- first_run = false;
- // Update the rotation of the particle source by the angular velocity
- // First check to see if there is still an angular velocity.
- F32 angular_velocity_mag = mPartSysData.mAngularVelocity.length();
- if (angular_velocity_mag != 0.f)
- {
- F32 av_angle = dt * angular_velocity_mag;
- LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
- mRotation *= dquat;
- }
- else
- {
- // No angular velocity. Reset our rotation.
- mRotation.setEulerAngles(0.f, 0.f, 0.f);
- }
- if (LLViewerPartSim::aboveParticleLimit())
- {
- // Do not bother doing any more updates if we are above the
- // particle limit, just give up.
- mLastPartTime = mLastUpdateTime;
- break;
- }
- // Find the greatest length that the shortest side of a system particle
- // is expected to have
- F32 max_short_side =
- llmax(llmax(llmin(mPartSysData.mPartData.mStartScale[0],
- mPartSysData.mPartData.mStartScale[1]),
- llmin(mPartSysData.mPartData.mEndScale[0],
- mPartSysData.mPartData.mEndScale[1])),
- llmin((mPartSysData.mPartData.mStartScale[0] +
- mPartSysData.mPartData.mEndScale[0]) * 0.5f,
- (mPartSysData.mPartData.mStartScale[1] +
- mPartSysData.mPartData.mEndScale[1]) * 0.5f));
- // Maximum distance at which spawned particles will be viewable
- F32 max_dist = max_short_side * pixel_meter_ratio;
- if (max_dist < 0.25f)
- {
- // < 1 pixel wide at a distance of >= 25cm. Particles this tiny are
- // useless and mostly spawned by buggy sources
- mLastPartTime = mLastUpdateTime;
- LL_DEBUGS("Particles") << "Particle source " << mID
- << " skipped because it is too small."
- << LL_ENDL;
- break;
- }
- // Particle size vs distance vs maxage throttling
- F32 limited_rate = 0.f;
- if (mDistFromCamera - max_dist > 0.f)
- {
- F32 max_age = mPartSysData.mPartData.mMaxAge;
- if ((mDistFromCamera - max_dist) * travelspeed > max_age - 0.2f)
- {
- // You need to travel faster than 1 divided by reference rate
- // m/s directly towards these particles to see them at least
- // 0.2s.
- LL_DEBUGS("Particles") << "Particle source " << mID
- << " skipped because it won't have time to show up."
- << LL_ENDL;
- mLastPartTime = mLastUpdateTime;
- break;
- }
- limited_rate = (mDistFromCamera - max_dist) * travelspeed / max_age;
- }
- if (mDelay)
- {
- limited_rate = llmax(limited_rate, 0.01f * mDelay--);
- }
- bool ribbon = (mPartSysData.mPartData.mFlags &
- LLPartData::LL_PART_RIBBON_MASK) != 0;
- for (S32 i = 0; i < mPartSysData.mBurstPartCount; ++i)
- {
- F32 burst_rate = gViewerPartSim.getBurstRate();
- if (burst_rate == 0.f)
- {
- LL_DEBUGS("Particles") << "Particle source " << mID
- << " skipped because MAX_PART_COUNT was reached."
- << LL_ENDL;
- break; // Do not insist, we reached MAX_PART_COUNT...
- }
- // Always create at least one particle
- if (i > 0 && ll_frand() < llmax(1.f - burst_rate, limited_rate))
- {
- // Limit particle generation
- continue;
- }
- if (ribbon && mLastPart &&
- (mLastPart->mPosAgent - mPosAgent).length() <= .005f)
- {
- // Do not generate a new ribbon particle if its length is too
- // small to be visible
- continue;
- }
- LLViewerPart* part = new LLViewerPart();
- part->init(this, mImagep, NULL);
- part->mFlags = mPartSysData.mPartData.mFlags;
- if (mSourceObjectp.notNull() && mSourceObjectp->isHUDAttachment())
- {
- part->mFlags |= LLPartData::LL_PART_HUD;
- }
- if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart)
- {
- // Set previous particle parent to this particle to chain
- // ribbons together
- mLastPart->mParent = part;
- part->mChild = mLastPart;
- part->mAxis = LLVector3::z_axis;
- if (mSourceObjectp.notNull())
- {
- LLQuaternion rot = mSourceObjectp->getRenderRotation();
- part->mAxis *= rot;
- }
- }
- mLastPart = part;
- part->mMaxAge = mPartSysData.mPartData.mMaxAge;
- part->mStartColor = mPartSysData.mPartData.mStartColor;
- part->mEndColor = mPartSysData.mPartData.mEndColor;
- part->mColor = part->mStartColor;
- part->mStartScale = mPartSysData.mPartData.mStartScale;
- part->mEndScale = mPartSysData.mPartData.mEndScale;
- part->mScale = part->mStartScale;
- part->mAccel = mPartSysData.mPartAccel;
- part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest;
- part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource;
- part->mStartGlow = mPartSysData.mPartData.mStartGlow;
- part->mEndGlow = mPartSysData.mPartData.mEndGlow;
- part->mGlow = LLColor4U(0, 0, 0,
- (U8)ll_roundp(part->mStartGlow * 255.f));
- if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
- {
- part->mPosAgent = mPosAgent;
- part->mVelocity.clear();
- }
- else if (mPartSysData.mPattern &
- LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
- {
- part->mPosAgent = mPosAgent;
- LLVector3 part_dir_vector;
- F32 mvs;
- do
- {
- part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
- part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
- part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
- mvs = part_dir_vector.lengthSquared();
- }
- while (mvs > 1.f || mvs < 0.01f);
- part_dir_vector.normalize();
- part->mPosAgent += mPartSysData.mBurstRadius * part_dir_vector;
- part->mVelocity = part_dir_vector;
- F32 speed = mPartSysData.mBurstSpeedMin +
- ll_frand(mPartSysData.mBurstSpeedMax -
- mPartSysData.mBurstSpeedMin);
- part->mVelocity *= speed;
- }
- else if ((mPartSysData.mPattern &
- LLPartSysData::LL_PART_SRC_PATTERN_ANGLE) ||
- (mPartSysData.mPattern &
- LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE))
- {
- part->mPosAgent = mPosAgent;
- // Original implemenetation for part_dir_vector was just:
- LLVector3 part_dir_vector = LLVector3::z_axis;
- // params from the script...
- // outer = outer cone angle
- // inner = inner cone angle
- // between outer and inner there will be particles
- F32 inner_angle = mPartSysData.mInnerAngle;
- F32 outer_angle = mPartSysData.mOuterAngle;
- // Generate a random angle within the given space...
- F32 angle = inner_angle + ll_frand(outer_angle - inner_angle);
- // Split which side it will go on randomly...
- if (ll_frand() < 0.5)
- {
- angle = -angle;
- }
- // Both patterns rotate around the x-axis first:
- part_dir_vector.rotVec(angle, 1.f, 0.f, 0.f);
- // If this is a cone pattern, rotate again to create the cone.
- if (mPartSysData.mPattern &
- LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
- {
- part_dir_vector.rotVec(ll_frand(4 * F_PI), 0.f, 0.f, 1.f);
- }
- // Only apply this rotation if using the deprecated angles.
- if (!(mPartSysData.mFlags &
- LLPartSysData::LL_PART_USE_NEW_ANGLE))
- {
- // Deprecated...
- part_dir_vector.rotVec(outer_angle, 1.f, 0.f, 0.f);
- }
- if (mSourceObjectp)
- {
- part_dir_vector = part_dir_vector *
- mSourceObjectp->getRenderRotation();
- }
- part_dir_vector = part_dir_vector * mRotation;
- part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
- part->mVelocity = part_dir_vector;
- F32 speed = mPartSysData.mBurstSpeedMin +
- ll_frand(mPartSysData.mBurstSpeedMax -
- mPartSysData.mBurstSpeedMin);
- part->mVelocity *= speed;
- }
- else
- {
- part->mPosAgent = mPosAgent;
- part->mVelocity.set(0.f, 0.f, 0.f);
- LL_DEBUGS("Particles") << "Unknown source pattern: "
- << (S32)mPartSysData.mPattern
- << LL_ENDL;
- }
- if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK ||
- part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
- {
- mPartSysData.mBurstRadius = 0;
- }
- gViewerPartSim.addPart(part);
- }
- mLastPartTime = mLastUpdateTime;
- dt_update -= mPartSysData.mBurstRate;
- }
- }
- //static
- LLPointer<LLViewerPartSourceScript>
- LLViewerPartSourceScript::unpackPSS(LLViewerObject* source_objp,
- LLPointer<LLViewerPartSourceScript> pssp,
- S32 block_num)
- {
- if (LLPartSysData::isNullPS(block_num))
- {
- return NULL;
- }
- if (!pssp)
- {
- LLPointer<LLViewerPartSourceScript> new_pssp =
- new LLViewerPartSourceScript(source_objp);
- if (!new_pssp->mPartSysData.unpackBlock(block_num))
- {
- return NULL;
- }
- if (new_pssp->mPartSysData.mTargetUUID.notNull())
- {
- LLViewerObject* target_objp =
- gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
- new_pssp->setTargetObject(target_objp);
- }
- return new_pssp;
- }
- if (!pssp->mPartSysData.unpackBlock(block_num))
- {
- return NULL;
- }
- F32 prev_max_age = pssp->mPartSysData.mMaxAge;
- F32 prev_start_age = pssp->mPartSysData.mStartAge;
- if (pssp->mPartSysData.mMaxAge &&
- (prev_max_age != pssp->mPartSysData.mMaxAge ||
- prev_start_age != pssp->mPartSysData.mStartAge))
- {
- // Reusing existing pss, so reset time to allow particles to start
- // again
- pssp->mLastUpdateTime = pssp->mLastPartTime = 0.f;
- }
- if (pssp->mPartSysData.mTargetUUID.notNull())
- {
- LLViewerObject* target_objp =
- gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
- pssp->setTargetObject(target_objp);
- }
- return pssp;
- }
- LLPointer<LLViewerPartSourceScript>
- LLViewerPartSourceScript::unpackPSS(LLViewerObject* source_objp,
- LLPointer<LLViewerPartSourceScript> pssp,
- LLDataPacker& dp, bool legacy)
- {
- if (!pssp)
- {
- LLPointer<LLViewerPartSourceScript> new_pssp =
- new LLViewerPartSourceScript(source_objp);
- bool res = legacy ? new_pssp->mPartSysData.unpackLegacy(dp)
- : new_pssp->mPartSysData.unpack(dp);
- if (!res)
- {
- return NULL;
- }
- if (new_pssp->mPartSysData.mTargetUUID.notNull())
- {
- LLViewerObject* target_objp =
- gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
- new_pssp->setTargetObject(target_objp);
- }
- return new_pssp;
- }
- bool res = legacy ? pssp->mPartSysData.unpackLegacy(dp)
- : pssp->mPartSysData.unpack(dp);
- if (!res)
- {
- return NULL;
- }
- if (pssp->mPartSysData.mTargetUUID.notNull())
- {
- LLViewerObject* target_objp =
- gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
- pssp->setTargetObject(target_objp);
- }
- return pssp;
- }
- //static
- LLPointer<LLViewerPartSourceScript>
- LLViewerPartSourceScript::createPSS(LLViewerObject* source_objp,
- const LLPartSysData& part_params)
- {
- LLPointer<LLViewerPartSourceScript> new_pssp =
- new LLViewerPartSourceScript(source_objp);
- new_pssp->mPartSysData = part_params;
- if (new_pssp->mPartSysData.mTargetUUID.notNull())
- {
- LLViewerObject* target_objp =
- gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
- new_pssp->setTargetObject(target_objp);
- }
- return new_pssp;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLViewerPartSourceSpiral sub-class
- ///////////////////////////////////////////////////////////////////////////////
- LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3& pos)
- : LLViewerPartSource(LL_PART_SOURCE_CHAT)
- {
- mPosAgent = pos;
- }
- void LLViewerPartSourceSpiral::setDead()
- {
- mIsDead = true;
- mSourceObjectp = NULL;
- }
- //static
- void LLViewerPartSourceSpiral::updatePart(LLViewerPart& part, F32 dt)
- {
- F32 frac = part.mLastUpdateTime / part.mMaxAge;
- LLVector3 center_pos;
- LLViewerPartSourceSpiral* pss =
- (LLViewerPartSourceSpiral*)part.mPartSourcep.get();
- if (pss->mSourceObjectp.notNull() &&
- pss->mSourceObjectp->mDrawable.notNull())
- {
- part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
- }
- else
- {
- part.mPosAgent = pss->mPosAgent;
- }
- F32 x = sinf(F_TWO_PI * frac + part.mParameter);
- F32 y = cosf(F_TWO_PI * frac + part.mParameter);
- part.mPosAgent.mV[VX] += x;
- part.mPosAgent.mV[VY] += y;
- part.mPosAgent.mV[VZ] += -0.5f + frac;
- }
- void LLViewerPartSourceSpiral::update(F32 dt)
- {
- if (!mImagep)
- {
- mImagep = gImgPixieSmall;
- }
- constexpr F32 RATE = 0.025f;
- mLastUpdateTime += dt;
- F32 dt_update = mLastUpdateTime - mLastPartTime;
- F32 max_time = llmax(1.f, 10.f * RATE);
- dt_update = llmin(max_time, dt_update);
- if (dt_update > RATE)
- {
- mLastPartTime = mLastUpdateTime;
- if (!LLViewerPartSim::shouldAddPart())
- {
- // Particle simulation says we have too many particles, skip all
- // this
- return;
- }
- if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
- {
- mPosAgent = mSourceObjectp->getRenderPosition();
- }
- LLViewerPart* part = new LLViewerPart();
- part->init(this, mImagep, updatePart);
- part->mStartColor = mColor;
- part->mEndColor = mColor;
- part->mEndColor.mV[3] = 0.f;
- part->mPosAgent = mPosAgent;
- part->mMaxAge = 1.f;
- part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
- part->mLastUpdateTime = 0.f;
- part->mScale.mV[0] = part->mScale.mV[1] = 0.25f;
- part->mParameter = ll_frand(F_TWO_PI);
- part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
- part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
- part->mStartGlow = part->mEndGlow = 0.f;
- part->mGlow = LLColor4U(0, 0, 0, 0);
- gViewerPartSim.addPart(part);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLViewerPartSourceBeam sub-class
- ///////////////////////////////////////////////////////////////////////////////
- LLViewerPartSourceBeam::LLViewerPartSourceBeam()
- : LLViewerPartSource(LL_PART_SOURCE_BEAM)
- {
- }
- void LLViewerPartSourceBeam::setDead()
- {
- mIsDead = true;
- mSourceObjectp = NULL;
- mTargetObjectp = NULL;
- }
- //static
- void LLViewerPartSourceBeam::updatePart(LLViewerPart& part, F32 dt)
- {
- F32 frac = part.mLastUpdateTime/part.mMaxAge;
- LLViewerPartSourceBeam* psb =
- (LLViewerPartSourceBeam*)part.mPartSourcep.get();
- if (psb->mSourceObjectp.isNull())
- {
- part.mFlags = LLPartData::LL_PART_DEAD_MASK;
- return;
- }
- LLVector3 source_pos_agent;
- LLVector3 target_pos_agent;
- if (psb->mSourceObjectp.notNull() &&
- psb->mSourceObjectp->mDrawable.notNull())
- {
- if (psb->mSourceObjectp->isAvatar())
- {
- LLViewerObject* objp = psb->mSourceObjectp;
- LLVOAvatar* avp = (LLVOAvatar*)objp;
- source_pos_agent = avp->mWristLeftp->getWorldPosition();
- }
- else
- {
- source_pos_agent = psb->mSourceObjectp->getRenderPosition();
- }
- }
- if (psb->mTargetObjectp.notNull() &&
- psb->mTargetObjectp->mDrawable.notNull())
- {
- target_pos_agent = psb->mTargetObjectp->getRenderPosition();
- }
- part.mPosAgent = (1.f - frac) * source_pos_agent;
- if (psb->mTargetObjectp.isNull())
- {
- part.mPosAgent += frac *
- gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal);
- }
- else
- {
- part.mPosAgent += frac * target_pos_agent;
- }
- }
- void LLViewerPartSourceBeam::update(F32 dt)
- {
- mLastUpdateTime += dt;
- if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
- {
- if (mSourceObjectp->isAvatar())
- {
- LLViewerObject* objp = mSourceObjectp;
- LLVOAvatar* avp = (LLVOAvatar*)objp;
- mPosAgent = avp->mWristLeftp->getWorldPosition();
- }
- else
- {
- mPosAgent = mSourceObjectp->getRenderPosition();
- }
- }
- if (mTargetObjectp.notNull() && mTargetObjectp->mDrawable.notNull())
- {
- mTargetPosAgent = mTargetObjectp->getRenderPosition();
- }
- else if (!mLKGTargetPosGlobal.isExactlyZero())
- {
- mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
- }
- F32 dt_update = mLastUpdateTime - mLastPartTime;
- constexpr F32 RATE = 0.025f;
- F32 max_time = llmax(1.f, 10.f * RATE);
- dt_update = llmin(max_time, dt_update);
- if (dt_update <= RATE)
- {
- return;
- }
- mLastPartTime = mLastUpdateTime;
- if (!LLViewerPartSim::shouldAddPart())
- {
- // Particle simulation says we have too many particles, skip all this
- return;
- }
- if (!mImagep)
- {
- mImagep = gImgPixieSmall;
- }
- LLViewerPart* part = new LLViewerPart();
- part->init(this, mImagep, updatePart);
- part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
- LLPartData::LL_PART_INTERP_SCALE_MASK |
- LLPartData::LL_PART_TARGET_POS_MASK |
- LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
- part->mMaxAge = 0.5f;
- part->mStartColor = mColor;
- part->mEndColor = part->mStartColor;
- part->mEndColor.mV[3] = 0.4f;
- part->mColor = part->mStartColor;
- part->mStartScale = LLVector2(0.1f, 0.1f);
- part->mEndScale = LLVector2(0.1f, 0.1f);
- part->mScale = part->mStartScale;
- part->mPosAgent = mPosAgent;
- part->mVelocity = mTargetPosAgent - mPosAgent;
- part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
- part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
- part->mStartGlow = 0.f;
- part->mEndGlow = 0.f;
- part->mGlow = LLColor4U(0, 0, 0, 0);
- gViewerPartSim.addPart(part);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLViewerPartSourceChat sub-class
- ///////////////////////////////////////////////////////////////////////////////
- LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3& pos)
- : LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
- {
- mPosAgent = pos;
- }
- void LLViewerPartSourceChat::setDead()
- {
- mIsDead = true;
- mSourceObjectp = NULL;
- }
- //static
- void LLViewerPartSourceChat::updatePart(LLViewerPart& part, F32 dt)
- {
- F32 frac = part.mLastUpdateTime / part.mMaxAge;
- LLVector3 center_pos;
- LLViewerPartSourceChat* pss =
- (LLViewerPartSourceChat*)part.mPartSourcep.get();
- if (pss->mSourceObjectp.notNull() &&
- pss->mSourceObjectp->mDrawable.notNull())
- {
- part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
- }
- else
- {
- part.mPosAgent = pss->mPosAgent;
- }
- F32 x = sinf(F_TWO_PI * frac + part.mParameter);
- F32 y = cosf(F_TWO_PI * frac + part.mParameter);
- part.mPosAgent.mV[VX] += x;
- part.mPosAgent.mV[VY] += y;
- part.mPosAgent.mV[VZ] += -0.5f + frac;
- }
- void LLViewerPartSourceChat::update(F32 dt)
- {
- if (!mImagep)
- {
- mImagep = gImgPixieSmall;
- }
- mLastUpdateTime += dt;
- if (mLastUpdateTime > 2.f)
- {
- // Kill particle source because it has outlived its max age...
- setDead();
- return;
- }
- F32 dt_update = mLastUpdateTime - mLastPartTime;
- // Clamp us to generating at most one second's worth of particles on a
- // frame
- constexpr F32 RATE = 0.025f;
- F32 max_time = llmax(1.f, 10.f * RATE);
- dt_update = llmin(max_time, dt_update);
- if (dt_update > RATE)
- {
- mLastPartTime = mLastUpdateTime;
- if (!LLViewerPartSim::shouldAddPart())
- {
- // Particle simulation says we have too many particles, skip all this
- return;
- }
- if (mSourceObjectp.notNull() && mSourceObjectp->mDrawable.notNull())
- {
- mPosAgent = mSourceObjectp->getRenderPosition();
- }
- LLViewerPart* part = new LLViewerPart();
- part->init(this, mImagep, updatePart);
- part->mStartColor = mColor;
- part->mEndColor = mColor;
- part->mEndColor.mV[3] = 0.f;
- part->mPosAgent = mPosAgent;
- part->mMaxAge = 1.f;
- part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
- part->mLastUpdateTime = 0.f;
- part->mScale.mV[0] = part->mScale.mV[1] = 0.25f;
- part->mParameter = ll_frand(F_TWO_PI);
- part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
- part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
- part->mStartGlow = part->mEndGlow = 0.f;
- part->mGlow = LLColor4U(0, 0, 0, 0);
- gViewerPartSim.addPart(part);
- }
- }
|