2012年3月8日 星期四 09时54分
Irrlicht中的Particle System主要由三个部分组成:
这里面:
CParticleSystemSceneNode : 表示这个Particle System,他也是作为一个Scene Node而存在,因此他有Scene Node的性质。他内部包含了一个Emitter指针和一个Affector列表。以及一个SParticle列表,SParticle代表一个Particle。
Emitter:表示Particle的释放器,在Irrlicht中内部实现了一些现有的释放器。
Affector:控制Particle的运动,他可以实时的更改Particle的属性,来实现一些特殊的效果。
///////////////////////////////////////////////////////////////////////////////////////////////
CParticleSystemSceneNode:
他本身又是Emitter和Affector的工厂类,因此提供了许多的createXXXEmitter和createXXXAffector。
在自己的Scene Node接口上驱动ParticleSystem:
OnAnimate:使用Scene Node的OnAnimate.
OnRegisterSceneNode:
doParticleSystem(os::Timer::getTime());
这里的doParticleSystem负责实时的驱动Particle System,包括Emitter的释放和当前的Particles的运动的驱动。
两个过程:
1:让Emitter释放新的Particle
2:对于每一个Affector更新当前的Particles
3:检测当前的Particles,
如果该Particle生命期已过,则删除;
否则,利用当前Particle的属性值(速度和位置),更新该Particle的位置。
4:更新Bounding Box
- void CParticleSystemSceneNode::doParticleSystem(u32 time)
- {
- if (LastEmitTime==0)
- {
- LastEmitTime = time;
- return;
- }
- u32 now = time;
- u32 timediff = time - LastEmitTime;
- LastEmitTime = time;
- // run emitter
- if (Emitter && IsVisible)
- {
- SParticle* array = 0;
- // newParticles is the amount of these new particles
- s32 newParticles = Emitter->emitt(now, timediff, array);
- if (newParticles && array)
- {
- s32 j=Particles.size();
- if (newParticles > 16250-j)
- newParticles=16250-j;
- Particles.set_used(j+newParticles);
- for (s32 i=j; i<j+newParticles; ++i)
- {
- Particles[i]=array[i-j];
- // The vector and start vector are always be in world space
- AbsoluteTransformation.rotateVect(Particles[i].vector);
- AbsoluteTransformation.rotateVect(Particles[i].startVector);
- // If the particles is moving in the world space
- if (ParticlesAreGlobal)
- {
- AbsoluteTransformation.translateVect(Particles[i].pos);
- }
- }
- }
- }
- // run affectors
- core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
- for (; ait != AffectorList.end(); ++ait)
- (*ait)->affect(now, Particles.pointer(), Particles.size());
- if (ParticlesAreGlobal)
- Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
- else
- Buffer->BoundingBox.reset(core::vector3df(0,0,0));
- // animate all particles
- f32 scale = (f32)timediff;
- for (u32 i=0; i<Particles.size();)
- {
- // erase is pretty
- if (now > Particles[i].endTime)
- Particles.erase(i);
- else
- {
- Particles[i].pos += (Particles[i].vector * scale);
- // Update the bounding box
- Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
- ++i;
- }
- }
- // Expanding the bounding box so that it will consider the size of a particle.
- const f32 m = (ParticleSize.Width > ParticleSize.Height ? ParticleSize.Width : ParticleSize.Height) * 0.5f;
- Buffer->BoundingBox.MaxEdge.X += m;
- Buffer->BoundingBox.MaxEdge.Y += m;
- Buffer->BoundingBox.MaxEdge.Z += m;
- Buffer->BoundingBox.MinEdge.X -= m;
- Buffer->BoundingBox.MinEdge.Y -= m;
- Buffer->BoundingBox.MinEdge.Z -= m;
- /*if (ParticlesAreGlobal)
- {
- core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE );
- absinv.transformBoxEx(Buffer->BoundingBox);
- }*/
- }
说明:
在CParticleSystemSceneNode中有一个ParticlesAreGlobal标识,但是在程序中对于他的名义不是很明确。
这里将原来的代码进行了改动:
ParticlesAreGlobal的名义改为:
true: 表示Particles都独立的在World Space中运动,与ParticleSystem Scene Node没有关联
false: 表示Particles跟随ParticleSystem Scene Node运动
注意:true和false之间仅仅相差一个偏移(就是Scene Node运动的距离),没有其他的区别。
render()
负责对所有的Particle进行渲染,在Particle System中,Particle都实现为一个Billboard(总是针对于View的观察方向)。
///////////////////////////////////////////////////////////////////////////////////////////////
Emitter:
Emitter主要负责释放Particle
他提供的接口为:
emitt,生成一个Particle Array,这个Array中就是当前新产生的Particle。
///////////////////////////////////////////////////////////////////////////////////////////////
Affector:
Affector主要负责实时的更新Particle的属性,来实现一些特殊的效果
提供的接口为:
virtual void affect(u32 now, SParticle* particlearray, u32 count)
注意:
1:在SParticle中vector和startVector都是在World Space中的速度?(实际上这一点在Irrlicht的代码里面表达并不是这么明确,他们两者的所在的空间并不是那么一致的)
阅读(1104) | 评论(0) | 转发(0) |