コード例 #1
0
void LLViewerPartGroup::updateParticles(const F32 lastdt)
{
	LLMemType mt(LLMemType::MTYPE_PARTICLES);
	F32 dt;
	
	LLVector3 gravity(0.f, 0.f, GRAVITY);

	LLViewerPartSim::checkParticleCount(mParticles.size());

	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)
		{
			LLVector3 tempVel(part->mVelocity);
			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;
		}

		// 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(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, TRUE);
		}
		LLViewerPartSim::decPartCount(removed);
	}
	
	// Kill the viewer object if this particle group is empty
	if (mParticles.empty())
	{
		gObjectList.killObject(mVOPartGroupp);
		mVOPartGroupp = NULL;
	}

	LLViewerPartSim::checkParticleCount() ;
}