More behavior control for particles:
- ParticleSystemSceneNode does now affect the particle movement direction by default. Can be disabled to get old behavior. - Allow interpolating postions which is useful when particles are attached to fast-moving nodes (to avoid regular patterns). - Invisible behavior flags from check-in yesterday re-implemented with new general behavior flags. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4770 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
ca6029b564
commit
322b1abef1
|
@ -1,7 +1,7 @@
|
|||
--------------------------
|
||||
Changes in 1.9 (not yet released)
|
||||
|
||||
- Allow more control over particle behavior when the ParticleSystemSceneNode is invisible.
|
||||
- Allow more control over particle behavior. This also changed the default behavior.
|
||||
- ISceneNodeAnimators can now be disabled and paused.
|
||||
- Maya camera no longer get's stuck in "rotating" state when a mouse-up event is lost (thx @ JLouisB for reporting).
|
||||
- Focus behavior of IGUIEnvironment now controllable (right-click focus, mouse-over focus). Disabled elements no longer get the focus unless users enforce it.
|
||||
|
|
|
@ -43,17 +43,29 @@ You can for example easily create a campfire by doing this:
|
|||
\endcode
|
||||
*/
|
||||
|
||||
//! Bitflags to control particle behavior when the IParticleSystemSceneNode is invisible
|
||||
enum EParticleInvisible
|
||||
//! Bitflags to control particle behavior
|
||||
enum EParticleBehavior
|
||||
{
|
||||
//! Stop emitting new particles when invisible
|
||||
EPI_STOP_EMITTERS = 1,
|
||||
//! No longer affect particles when invisible
|
||||
EPI_STOP_AFFECTORS = 2,
|
||||
//! Stop updating particle positions or deleting them when invisible
|
||||
EPI_STOP_ANIMATING = 4,
|
||||
//! Continue emitting new particles even when the node is invisible
|
||||
EPB_INVISIBLE_EMITTING = 1,
|
||||
|
||||
//! Continue affecting particles even when the node is invisible
|
||||
EPB_INVISIBLE_AFFECTING = 2,
|
||||
|
||||
//! Continue updating particle positions or deleting them even when the node is invisible
|
||||
EPB_INVISIBLE_ANIMATING = 4,
|
||||
|
||||
//! Clear all particles when node gets invisible
|
||||
EPI_CLEAR_ON_INVISIBLE = 8
|
||||
EPB_CLEAR_ON_INVISIBLE = 8,
|
||||
|
||||
//! Particle movement direction on emitting ignores the node rotation
|
||||
//! This is mainly to allow backward compatible behavior to Irrlicht 1.8
|
||||
EPB_EMITTER_VECTOR_IGNORE_ROTATION = 16,
|
||||
|
||||
//! On emitting global particles interpolate the positions randomly between the last and current node transformations.
|
||||
//! This can be set to avoid gaps caused by fast node movement or low framerates, but will be somewhat
|
||||
//! slower to calculate.
|
||||
EPB_EMITTER_FRAME_INTERPOLATION = 32
|
||||
};
|
||||
|
||||
class IParticleSystemSceneNode : public ISceneNode
|
||||
|
@ -66,7 +78,7 @@ public:
|
|||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f))
|
||||
: ISceneNode(parent, mgr, id, position, rotation, scale)
|
||||
, ParticleInvisibleBehavior(EPI_STOP_EMITTERS|EPI_STOP_AFFECTORS|EPI_STOP_ANIMATING|EPI_CLEAR_ON_INVISIBLE)
|
||||
, ParticleBehavior(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -80,22 +92,22 @@ public:
|
|||
Default is true. */
|
||||
virtual void setParticlesAreGlobal(bool global=true) = 0;
|
||||
|
||||
//! Sets how particles behave when this node is invisible
|
||||
/** Default is: EPIB_STOP_EMITTERS|EPIB_STOP_AFFECTORS|EPIB_STOP_ANIMATING|EPI_CLEAR_ON_INVISIBLE
|
||||
\param flags Any combination of ::EParticleInvisibleBehavior flags
|
||||
*/
|
||||
virtual void setInvisibleBehavior(irr::u32 flags)
|
||||
|
||||
//! Bitflags to change the particle behavior
|
||||
/**
|
||||
\param flags A combination of ::EParticleBehavior bit-flags. Default is 0. */
|
||||
virtual void setParticleBehavior(irr::u32 flags)
|
||||
{
|
||||
ParticleInvisibleBehavior = flags;
|
||||
ParticleBehavior = flags;
|
||||
}
|
||||
|
||||
//! Gets how particles behave when this node is invisible
|
||||
|
||||
//! Gets how particles behave in different situations
|
||||
/**
|
||||
\return A combination of ::EParticleInvisibleBehavior flags
|
||||
*/
|
||||
virtual irr::u32 getInvisibleBehavior() const
|
||||
\return A combination of ::EParticleBehavior flags */
|
||||
virtual irr::u32 getParticleBehavior() const
|
||||
{
|
||||
return ParticleInvisibleBehavior;
|
||||
return ParticleBehavior;
|
||||
}
|
||||
|
||||
//! Remove all currently visible particles
|
||||
|
@ -541,17 +553,17 @@ public:
|
|||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_
|
||||
{
|
||||
out->addInt("ParticleInvisibleBehavior", ParticleInvisibleBehavior);
|
||||
out->addInt("ParticleBehavior", ParticleBehavior);
|
||||
}
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) _IRR_OVERRIDE_
|
||||
{
|
||||
ParticleInvisibleBehavior = in->getAttributeAsInt("ParticleInvisibleBehavior", ParticleInvisibleBehavior);
|
||||
ParticleBehavior = in->getAttributeAsInt("ParticleBehavior", ParticleBehavior);
|
||||
}
|
||||
|
||||
protected:
|
||||
s32 ParticleInvisibleBehavior;
|
||||
s32 ParticleBehavior;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
|
|
|
@ -410,6 +410,7 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
|
|||
if (LastEmitTime==0)
|
||||
{
|
||||
LastEmitTime = time;
|
||||
LastAbsoluteTransformation = AbsoluteTransformation;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -418,10 +419,11 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
|
|||
LastEmitTime = time;
|
||||
|
||||
|
||||
int stop = isVisible() ? 0 : getInvisibleBehavior();
|
||||
bool visible = isVisible();
|
||||
int behavior = getParticleBehavior();
|
||||
// run emitter
|
||||
|
||||
if (Emitter && !(stop & EPI_STOP_EMITTERS) )
|
||||
if (Emitter && (visible || behavior & EPB_INVISIBLE_EMITTING) )
|
||||
{
|
||||
SParticle* array = 0;
|
||||
s32 newParticles = Emitter->emitt(now, timediff, array);
|
||||
|
@ -435,15 +437,54 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
|
|||
for (s32 i=j; i<j+newParticles; ++i)
|
||||
{
|
||||
Particles[i]=array[i-j];
|
||||
AbsoluteTransformation.rotateVect(Particles[i].startVector);
|
||||
if (ParticlesAreGlobal)
|
||||
AbsoluteTransformation.transformVect(Particles[i].pos);
|
||||
|
||||
if ( ParticlesAreGlobal && behavior & EPB_EMITTER_FRAME_INTERPOLATION )
|
||||
{
|
||||
// Interpolate between current node transformations and last ones.
|
||||
// (Lazy solution - calculating twice and interpolating results)
|
||||
f32 randInterpolate = (f32)(os::Randomizer::rand() % 101) / 100.f; // 0 to 1
|
||||
core::vector3df posNow(Particles[i].pos);
|
||||
core::vector3df posLast(Particles[i].pos);
|
||||
|
||||
AbsoluteTransformation.transformVect(posNow);
|
||||
LastAbsoluteTransformation.transformVect(posLast);
|
||||
Particles[i].pos = posNow.getInterpolated(posLast, randInterpolate);
|
||||
|
||||
if ( !(behavior & EPB_EMITTER_VECTOR_IGNORE_ROTATION) )
|
||||
{
|
||||
core::vector3df vecNow(Particles[i].startVector);
|
||||
core::vector3df vecOld(Particles[i].startVector);
|
||||
AbsoluteTransformation.rotateVect(vecNow);
|
||||
LastAbsoluteTransformation.rotateVect(vecOld);
|
||||
Particles[i].startVector = vecNow.getInterpolated(vecOld, randInterpolate);
|
||||
|
||||
vecNow = Particles[i].vector;
|
||||
vecOld = Particles[i].vector;
|
||||
AbsoluteTransformation.rotateVect(vecNow);
|
||||
LastAbsoluteTransformation.rotateVect(vecOld);
|
||||
Particles[i].vector = vecNow.getInterpolated(vecOld, randInterpolate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ParticlesAreGlobal)
|
||||
AbsoluteTransformation.transformVect(Particles[i].pos);
|
||||
|
||||
if ( !(behavior & EPB_EMITTER_VECTOR_IGNORE_ROTATION) )
|
||||
{
|
||||
if (!ParticlesAreGlobal)
|
||||
AbsoluteTransformation.rotateVect(Particles[i].pos);
|
||||
|
||||
AbsoluteTransformation.rotateVect(Particles[i].startVector);
|
||||
AbsoluteTransformation.rotateVect(Particles[i].vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run affectors
|
||||
if ( !(stop & EPI_STOP_AFFECTORS) )
|
||||
if ( visible || behavior & EPB_INVISIBLE_AFFECTING )
|
||||
{
|
||||
core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
|
||||
for (; ait != AffectorList.end(); ++ait)
|
||||
|
@ -456,7 +497,7 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
|
|||
Buffer->BoundingBox.reset(core::vector3df(0,0,0));
|
||||
|
||||
// animate all particles
|
||||
if ( !(stop & EPI_STOP_ANIMATING) )
|
||||
if ( visible || behavior & EPB_INVISIBLE_ANIMATING )
|
||||
{
|
||||
f32 scale = (f32)timediff;
|
||||
|
||||
|
@ -495,6 +536,8 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time)
|
|||
core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE );
|
||||
absinv.transformBoxEx(Buffer->BoundingBox);
|
||||
}
|
||||
|
||||
LastAbsoluteTransformation = AbsoluteTransformation;
|
||||
}
|
||||
|
||||
|
||||
|
@ -516,8 +559,11 @@ void CParticleSystemSceneNode::clearParticles()
|
|||
void CParticleSystemSceneNode::setVisible(bool isVisible)
|
||||
{
|
||||
IParticleSystemSceneNode::setVisible(isVisible);
|
||||
if ( !isVisible && getInvisibleBehavior() & EPI_CLEAR_ON_INVISIBLE )
|
||||
if ( !isVisible && getParticleBehavior() & EPB_CLEAR_ON_INVISIBLE )
|
||||
{
|
||||
clearParticles();
|
||||
LastEmitTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! Sets the size of all particles.
|
||||
|
|
|
@ -220,6 +220,7 @@ private:
|
|||
core::array<SParticle> Particles;
|
||||
core::dimension2d<f32> ParticleSize;
|
||||
u32 LastEmitTime;
|
||||
core::matrix4 LastAbsoluteTransformation;
|
||||
|
||||
SMeshBuffer* Buffer;
|
||||
|
||||
|
|
Loading…
Reference in New Issue