Chinaunix首页 | 论坛 | 博客
  • 博客访问: 178023
  • 博文数量: 43
  • 博客积分: 827
  • 博客等级: 准尉
  • 技术积分: 487
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-26 19:19
文章分类

全部博文(43)

文章存档

2015年(1)

2014年(1)

2013年(5)

2012年(36)

我的朋友

分类: WINDOWS

2012-05-06 17:19:58

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

点击(此处)折叠或打开

  1. void CParticleSystemSceneNode::doParticleSystem(u32 time)
  2. {
  3.         if (LastEmitTime==0)
  4.         {
  5.                 LastEmitTime = time;
  6.                 return;
  7.         }

  8.         u32 now = time;
  9.         u32 timediff = time - LastEmitTime;
  10.         LastEmitTime = time;

  11.         // run emitter

  12.         if (Emitter && IsVisible)
  13.         {
  14.                 SParticle* array = 0;
  15.                 // newParticles is the amount of these new particles
  16.                 s32 newParticles = Emitter->emitt(now, timediff, array);

  17.                 if (newParticles && array)
  18.                 {
  19.                         s32 j=Particles.size();
  20.                         if (newParticles > 16250-j)
  21.                                 newParticles=16250-j;
  22.                         Particles.set_used(j+newParticles);
  23.                         for (s32 i=j; i<j+newParticles; ++i)
  24.                         {
  25.                                 Particles[i]=array[i-j];
  26.                                 // The vector and start vector are always be in world space
  27.                                 AbsoluteTransformation.rotateVect(Particles[i].vector);
  28.                                 AbsoluteTransformation.rotateVect(Particles[i].startVector);
  29.                                 // If the particles is moving in the world space
  30.                                 if (ParticlesAreGlobal)
  31.                                 {
  32.                                         AbsoluteTransformation.translateVect(Particles[i].pos);
  33.                                 }
  34.                         }
  35.                 }
  36.         }

  37.         // run affectors
  38.         core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
  39.         for (; ait != AffectorList.end(); ++ait)
  40.                 (*ait)->affect(now, Particles.pointer(), Particles.size());

  41.         if (ParticlesAreGlobal)
  42.                 Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
  43.         else
  44.                 Buffer->BoundingBox.reset(core::vector3df(0,0,0));

  45.         // animate all particles
  46.         f32 scale = (f32)timediff;

  47.         for (u32 i=0; i<Particles.size();)
  48.         {
  49.                 // erase is pretty
  50.                 if (now > Particles[i].endTime)
  51.                         Particles.erase(i);
  52.                 else
  53.                 {
  54.                         Particles[i].pos += (Particles[i].vector * scale);
  55.                         // Update the bounding box
  56.                         Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
  57.                         ++i;
  58.                 }
  59.         }

  60.         // Expanding the bounding box so that it will consider the size of a particle.
  61.         const f32 m = (ParticleSize.Width > ParticleSize.Height ? ParticleSize.Width : ParticleSize.Height) * 0.5f;
  62.         Buffer->BoundingBox.MaxEdge.X += m;
  63.         Buffer->BoundingBox.MaxEdge.Y += m;
  64.         Buffer->BoundingBox.MaxEdge.Z += m;

  65.         Buffer->BoundingBox.MinEdge.X -= m;
  66.         Buffer->BoundingBox.MinEdge.Y -= m;
  67.         Buffer->BoundingBox.MinEdge.Z -= m;

  68.          /*if (ParticlesAreGlobal)
  69.         {
  70.                 core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE );
  71.                 absinv.transformBoxEx(Buffer->BoundingBox);
  72.         }*/
  73. }

说明:
在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的代码里面表达并不是这么明确,他们两者的所在的空间并不是那么一致的)


阅读(1101) | 评论(0) | 转发(0) |
0

上一篇:Light in Irrlicht

下一篇:Shadow Volume in Irrlicht

给主人留下些什么吧!~~