Ejemplo n.º 1
0
void PUParticleSystem3D::calulateRotationOffset( void )
{
    if (_isMarkedForEmission)
    {
        // Use the uber particle system as centre of rotation and not the particle systems' own position.
        _rotationCentre = _parentParticleSystem->getDerivedPosition();
    }
    else
    {
        // Use its own position
        _rotationCentre = getDerivedPosition();
    }

    /** Use the derived orientation, which is the particle systems' own scenenode orientation,
        or the orientation of the uber particle system, if this particle system is emitted itself.
    */
    Quaternion latestOrientationInverse = _latestOrientation;
    latestOrientationInverse.inverse();
    _rotationOffset = getDerivedOrientation() * latestOrientationInverse;
}
Ejemplo n.º 2
0
void PUParticleSystem3D::forceUpdate( float delta )
{
    if (!_emitters.empty())
        calulateRotationOffset();

    prepared();

    Vec3 currentPos = getDerivedPosition();
    _latestPositionDiff = currentPos - _latestPosition;
    _latestPosition = currentPos;
    _latestOrientation = getDerivedOrientation();

    if (!_emitters.empty()) {
        emitParticles(delta);
        preUpdator(delta);
        updator(delta);
        postUpdator(delta);
    }

    _timeElapsedSinceStart += delta;
}
	//-----------------------------------------------------------------------
	void ParticleSystem::start(void)
	{
		// Generate the event; this must be done at the start
		_pushSystemEvent(PU_EVT_SYSTEM_STARTING);

		setVisible(true);
		mState = ParticleSystem::PSS_STARTED;
		mTimeElapsedSinceStart = 0;
		mLastVisibleFrame = 0;
		mTimeSinceLastVisible = 0;
		mTimeSinceLastUpdate = 0;
		mBoundsUpdateTime = mOriginalBoundsUpdateTime;
		ParticleTechniqueIterator it;
		ParticleTechniqueIterator itEnd = mTechniques.end();
		mAABB.setExtents(0, 0, 0, 0, 0, 0);
		mFastForwardSet = mOriginalFastForwardSet;
		position = Vector3::ZERO;
		mDerivedPosition = Vector3::ZERO;
		latestPosition = getDerivedPosition();
		mLatestOrientation = getDerivedOrientation(); // Added for 1.3 (orientation not pr)
		mEnabled = true;
		mStopFadeSet = false;
		mAtLeastOneParticleEmitted = false;
		mLastLodIndex = 0; // This triggers the event at least once if lod distances are used.

		// Run through the ParticleTechniques to perform some start-initialisation actions.
		for (it = mTechniques.begin(); it != itEnd; ++it)
		{
			(*it)->_notifyStart();
		}
		
		// Perform fast forward if needed (the fastforward() function determines whether it is needed)
		fastForward();

		// Generate the event; this must be done at the end
		_pushSystemEvent(PU_EVT_SYSTEM_STARTED);
	}
	//-----------------------------------------------------------------------
	void ParticleSystem::_update(Real timeElapsed)
	{
		// Only update if attached to a node
		if (!mParentNode)
			return;

		// Only update if the particle system is started or prepare the particle system before starting.
		if (mState == ParticleSystem::PSS_STARTED)
		{
			if (mNonvisibleUpdateTimeoutSet)
			{
				long frameDiff = Ogre::Root::getSingleton().getNextFrameNumber() - mLastVisibleFrame;
				if (frameDiff > 1 || frameDiff < 0)
				{
					mTimeSinceLastVisible += timeElapsed;
					if (mTimeSinceLastVisible >= mNonvisibleUpdateTimeout)
					{
						// No update
						return;
					}
				}
			}

			// Speedup or slowdown
			timeElapsed *= mParticleSystemScaleTime;

			// Only update the time since start if the ParticleSystem is in the 'start' state.
			// Stop the ParticleSystem if the fixed timeout has been reached (if applicable).
			mTimeElapsedSinceStart += timeElapsed;
			if (mFixedTimeoutSet)
			{
				if (mTimeElapsedSinceStart >= mFixedTimeout)
				{
					// Stop the ParticleSystem
					if (mStopFadeSet)
					{
						// Stop slowly
						stopFade();
						mFixedTimeoutSet = false;
					}
					else
					{
						// Stop immediately
						stop();
						return;
					}
				}
			}

			// Update bound timer (if not auto updated)
			if (!mBoundsAutoUpdate && mBoundsUpdateTime > 0.0f)
				mBoundsUpdateTime -= timeElapsed;

			// Calculate rotation of the node
			calulateRotationOffset();

			// Determine whether timeElapsed or iterationInterval is used
			size_t particlesLeft = 0;
			if (mIterationIntervalSet)
			{
				// Update time since last update
				mTimeSinceLastUpdate += timeElapsed;
				while (mTimeSinceLastUpdate >= mIterationInterval)
				{
					// Update all techniques using the iteration interval value
					particlesLeft = _updateTechniques(mIterationInterval);
					mTimeSinceLastUpdate -= mIterationInterval;
				}
			}
			else
			{
				// Update all techniques using the time elapsed (since last frame)
				particlesLeft = _updateTechniques(timeElapsed);
			}

			// Handle situation when no particles are emitted anymore
			if (particlesLeft == 0)
			{
				if (mAtLeastOneParticleEmitted)
				{
					// Generate the event
					_pushSystemEvent(PU_EVT_NO_PARTICLES_LEFT);
					mAtLeastOneParticleEmitted = false;
				}

				// Determine whether the particle system should be stopped because of a fade out
				if (mStopFadeSet)
				{
					if (!mFixedTimeoutSet || (mFixedTimeoutSet && mTimeElapsedSinceStart >= mFixedTimeout))
					{
						stop();
						return;
					}
				}
			}
			else
			{
				// At least one particle was emitted, so if 'particlesLef' becomes 0, it concerns the period after the last emitted particle.
				mAtLeastOneParticleEmitted = true;
			}
		}
		else if (mState == ParticleSystem::PSS_PREPARED)
		{
			// Generate the event
			_pushSystemEvent(PU_EVT_SYSTEM_PREPARING);

			// Prepare all techniques (perform some initialisation in advance)
			ParticleTechniqueIterator it;
			ParticleTechniqueIterator itEnd = mTechniques.end();
			for (it = mTechniques.begin(); it != itEnd; ++it)
			{
				(*it)->_prepare();
			}

			// Only do it once.
			mState = ParticleSystem::PSS_STOPPED;

			// Generate the event
			_pushSystemEvent(PU_EVT_SYSTEM_PREPARED);
		}
		else if (mState == ParticleSystem::PSS_PAUSED)
		{
			// Determine whether there is a limit to the pause
			if (mPauseTimeSet)
			{
				mPauseTimeElapsed += timeElapsed;
				if (mPauseTimeElapsed > mPauseTime)
				{
					mPauseTimeElapsed = 0.0f;
					resume();
				}
			}
		}

		// Set the latest position. This value is always needed, whether the Particle System is emitted or not.
		latestPosition = getDerivedPosition();
		mLatestOrientation = getDerivedOrientation();
	}
	//-----------------------------------------------------------------------
	bool ParticleSystem::hasRotatedBetweenUpdates(void) const
	{
		return mLatestOrientation != getDerivedOrientation();
	}