Mage小组 著
Email: norman_chen@163.com
renwind@163.com
QQ: 18725262
http://www.173d8.com
http://blog.csdn.net/pizi0475
粒子系统及粒子脚本
粒子系统在三维显示中占有很重要的地位,如3D中的雨,雪,喷泉,爆炸效果等都是粒子系统神奇魅力的表现。
我们可以用程序的方式虚拟美国哥伦比亚号航天飞机在太空中爆炸的场景:大大小小的碎片向四处飞溅,耀眼的火花,滚滚的浓烟,在这其中多数元素都是混乱的。从技术的角度讲本场景中的大多数效果得益于一个优秀的粒子系统。烟,火花,这些3D中的效果通常使用粒子系统来创建的。
基本概念
粒子是用四边形来表示的。它有长宽,和其方向,有数量和材质,还有重量。这些属性封在粒子属性变换器(Affector)中,Affector中包含颜色衰退变换器(¬ColourFaderAffector)和线形影响变换器(LinearForceAffector)。粒子的产生由粒子发生器(Emmiter)产生。它包含有盒状粒子发生器(BoxEmmitter)和点状粒子发生器( ¬PointEmmiter),由这些组成粒子脚本文件,以.particle为其扩展名。点状粒子发生器随机地从单一的点发射粒子;盒状粒子发生器随机的从一个区域发射粒子。通过创建Plugins你可以向ogre里增加一个新的发射器。当前ogre只支持点状粒子发生器和盒状粒子发射器。
当粒子发生器不停的喷发出大量粒子时,就可以形成烟、火和爆炸等效果。
粒子系统结构图:
粒子系统脚本
OGRE提供了粒子系统脚本语言,可以在脚本中设置粒子的各种属性,而不用重新编译程序。这样给使用者带来了方便。需要注意的粒子系统脚本文件有自己的语法,类似C++:注释用“//”,用“{ }”来区分界限。但不支持在代码后跟注释。
粒子系统在脚本中是以模板的形式定义的,你可以在程序运行期创建多个实例。
载入粒子脚本
粒子系统脚本是在系统初始化的时候载入的,缺省情况下系统在公共资源路径(Root::addResourceLocation函数指定)下查找所有扩展名为“.particle”的文件并解析它们。如果你想指定其它扩展名可使用ParticleSystemManager::getSingleton().parseAllSources方法,如果想解析单个的粒子系统脚本文件可使用ParticleSystemManager::getSingleton().parseScript方法。
一旦粒子系统脚本被载入,你可以使用ParticleSystemManager::getSingleton().createSystem()方法来创建一个实例化的粒子系统,该方法接收两个参数,一个该粒子系统的名称,而另外一个参数是要参照的模板名称(也就是脚本中定义过的模板名称。
格式
可以在一个脚本文件中定义多个粒子系统模板。
以下是一个典型的粒子脚本,该脚本包含三个粒子系统模板,它被用于OGRE的粒子DEMO中,你可以运行该DEMO来查看实际效果。当然你也可以修改这些属性来改变效果。
// 粒子系统模板名
// Exudes greeny particles which float upwards
Examples/GreenyNimbus
{
// 粒子的Material
material Examples/Flare
// 粒子的宽度
particle_width 30
// 粒子的高度
particle_height 30
// 粒子的裁剪模式:整体包围盒裁剪或单个粒子裁剪。
cull_each false
// 粒子数目
quota 10000
// 公告板的类型:point指代表粒子的四边形总是面向摄像机。
billboard_type point
// 盒状粒子发射器
emitter Box
{
// 粒子发射时偏离direction的最大角度
angle 30
// 发射速率(个/秒)
emission_rate 30
// 粒子生存时间(秒)
time_to_live 50
// 粒子的发射方向
direction 0 1 0
// 速率
velocity 10
// 颜色起始值
colour_range_start 1 1 0
// 颜色结束值(在起始值和结束值之间取随机数)
colour_range_end 0.3 1 0.3
// 定义粒子发射器BOX的大小
width 60
height 60
depth 60
}
// LinearForce:对运动中的粒子的加上一个外力,影响其运动轨迹。
// Make em float upwards
affector LinearForce
{
// 指定外力的影响(用向量表示)
force_vector 0 100 0
// add:粒子的运动向量加上外力的向量。效果:匀加速运动。
force_application add
}
// ColourFader:影响粒子中的颜色
// Fader
affector ColourFader
{
// 每秒衰减0.25
red -0.25
green -0.25
blue -0.25
}
}
// A sparkly purple fountain
Examples/PurpleFountain
{
material Examples/Flare2
particle_width 20
particle_height 20
cull_each false
quota 10000
billboard_type oriented_self
// Area emitter
emitter Point
{
angle 15
emission_rate 75
time_to_live 3
direction 0 1 0
velocity_min 250
velocity_max 300
//颜色变换上下限
colour_range_start 0 0 0
colour_range_end 1 1 1
}
// Gravity
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
// Fader
affector ColourFader
{
red -0.25
green -0.25
blue -0.25
}
}
// A downpour
Examples/Rain
{
material Examples/Droplet
particle_width 50
particle_height 100
cull_each true
quota 10000
// Make common direction straight down (faster than self oriented)
billboard_type oriented_common
common_direction 0 -1 0
// Area emitter
emitter Box
{
angle 0
emission_rate 100
time_to_live 5
direction 0 -1 0
velocity 50
colour_range_start 0.3 1 0.3
colour_range_end 0.7 1 0.7
width 1000
height 1000
depth 0
}
// Gravity
affector LinearForce
{
force_vector 0 -200 0
force_application add
}
}
脚本中的每一个粒子系统模板都必须有一个名字,且必须是在“{”前的第一行。这个名称必须是唯一的。名字中可以包含“/”来构成路径,但OGRE引擎只把它当成字符串看待,并不真正来分析这个路径,它仅仅方便程序员来区分层次。
一个粒子系统可以设置一些上层属性,如:quota 表示允许的最大粒子个数。除了基本属性外,还必须在一个粒子系统模板内嵌套定义发射器Emitters和属性变换器affectors。它们内部的属性与它们的类型有关。
粒子系统脚本的属性较多,请参考OGRE Tutorial中的Particle Scripts部分。
示例一
打开OGRE DEMO中Emample.particle试着改变粒子发射器(emitter Box和emitter Point)和粒子的发射速率(比如将emission_rate 100改为emission_rate 30),粒子生存时间(秒)(time_to_live )等等,注意区分大小写,存盘,然后再运行Demo_ParticleFX.exe看看效果。
示例二
打开OGRE中的Demo_ParticleFX工程,查看其中的代码,理解粒子系统的调用方法。
该程序在运行时,场景中有一个食人魔,头上冒着绿色的烟雾(粒子系统),旁边有两个运动的粒子发生器喷发着五颜六色光点(还是粒子系统)。
OGRE引擎在初始化的时候会自动载入粒子系统脚本文件,我们不用管它。
在程序的createScene函数里,通过ParticleSystem* pSys1 = ParticleSystemManager::getSingleton().createSystem("Nimbus", "Examples/GreenyNimbus");创建出一个实际的粒子系统Nimbus,它采用的模板"Examples/GreenyNimbus"就是在粒子系统脚本中定义的。
本程序共有三个粒子系统,创建方法都一样,只不过采用的模板不同。
粒子系统被创建好后,可以将其attach到场景节点上去,便于运动控制。代码如下:
mSceneMgr->getRootSceneNode()->createChild()->attachObject(pSys1);
一旦粒子系统被attach到场景节点上,就可以通过FrameListener的frameStarted方法来控制节点运动,当然粒子也就边运动边喷发了。