//-----------------------------------------------------------------------
	size_t ParticleSystem::_updateTechniques(Real timeElapsed)
	{
		/** Update all techniques if particle system is started (only if the techniques aren't emitted 
			themselves) and return the total number of emitted particles.
			Note, that emitted techniques are updated by the technique that is responsible for emitting 
			them. The technique that is emitting pooled techniques is also responsible to take the 
			(world)AABB of that pooled technique into account.
		*/

		/** V 1.4: Bug http://www.fxpression.com/phpBB3/viewtopic.php?f=5&t=438&p=1453#p1453
			For some reason particle nodes get updated before the 'make particle local' call in the particle technique, and others do not.
			Some kind of timing issue.  Explicitly calling Node::_update here fixes the problem
			Note, the patch in the link was to put the code in each technique. It seems more obvious to put it in the particle system itself, so it
			is updated only once.
		*/
		if (isInScene() && getParentNode())
		{
			getParentNode()->_update(true, true);
		}

		ParticleTechniqueIterator it;
		ParticleTechniqueIterator itEnd = mTechniques.end();
		size_t particlesLeft = 0;
		bool mAABBUpdate = mParentNode && (mBoundsAutoUpdate || mBoundsUpdateTime > 0.0f);
		bool merge = mAABBUpdate;
		AxisAlignedBox worldAABB(mParentNode->_getDerivedPosition(), mParentNode->_getDerivedPosition());
		for (it = mTechniques.begin(); it != itEnd; ++it)
		{
			if (!(*it)->_isMarkedForEmission())
			{
				// Only call this if update bounds is needed.
				if (merge)
				{
					// Call _notifyUpdateBounds() for each Particle Technique, so the mWorldAABB in the 
					// ParticleTechnique::_update() function is (re)calculated.
					(*it)->_notifyUpdateBounds();
				}

				// Always update the ParticleTechniques
				(*it)->_update(timeElapsed);

				// Merge worldAABB's of all ParticleTechniques
				if (merge)
				{
					// Get the WorldAABB from each technique and merge it with the worldAABB.
					worldAABB.merge((*it)->getWorldBoundingBox());

					// If worldAABB is infinite, ignore the other Particle Techniques.
					if (worldAABB.isInfinite())
					{
						merge = false;
					}
				}

				// Count all left particles, used for anyone who needs it.
				particlesLeft += (*it)->getNumberOfEmittedParticles();
			}
		}

		if (mState == ParticleSystem::PSS_STOPPED)
		{
			/** Don't bother to update the mAABB, because the system is stopped in one of the techniques.
				The bounds must be reset, because even though the stop() has been called (which alread resets the
				bounds) another technique in the list might set the bounds again.
			*/
			_resetBounds();
		}
		else if (mAABBUpdate)
		{
			// If needed, update mAABB
			if (!worldAABB.isNull())
			{
				if (mTightBoundingBox)
				{
					// Wrap the bounding box tight around the particle system
					mAABB = worldAABB;
					mAABB.transformAffine(mParentNode->_getFullTransform().inverseAffine());
				}
				else
				{
					// Merge with the current bounding box
					// Note, that the mAABB must in localspace, so transformation of the worldAABB is required.
					AxisAlignedBox newAABB(worldAABB);
					newAABB.transformAffine(mParentNode->_getFullTransform().inverseAffine());
	
					// Merge calculated box with current AABB.
					mAABB.merge(newAABB);
				}

				// Update bounding radius
				Real sqDist = std::max(mAABB.getMinimum().squaredLength(), mAABB.getMaximum().squaredLength());
				mBoundingRadius = Math::Sqrt(sqDist);
			}
			else
			{
				_resetBounds();
			}

			// V1.4 Remove this part, because the node is updated each frame.
			// Notify the parent node that the bounds are changed
			// mParentNode->needUpdate();
		}

		return particlesLeft;
	}
Пример #2
0
bool MD5ModelNode::intersectsLight(const RendererLight& light) const
{
	return light.intersectsAABB(worldAABB());
}
Пример #3
0
bool MD5ModelNode::testLight(const RendererLight& light) const {
	return light.testAABB(worldAABB());
}