/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.htmlYou may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
/*
-----------------------------------------------------------------------------
Filename: ParticleApplication.cpp
Description: Specialisation of OGRE's framework application to show the
environment mapping feature.
粒子系统的烟雾
-----------------------------------------------------------------------------
*/#include "ExampleApplication.h"
// Event handler to add ability to alter curvature
class ParticleFrameListener : public ExampleFrameListener
{
protected:
//场景节点指针
SceneNode* mFountainNode;
public: ParticleFrameListener(RenderWindow* win, Camera* cam, SceneNode* fountainNode)
: ExampleFrameListener(win, cam)
{
mFountainNode = fountainNode;
} bool frameStarted(const FrameEvent& evt)
{ // Rotate fountains
// 旋转
// mFountainNode->yaw(evt.timeSinceLastFrame * 30); // Call default
return ExampleFrameListener::frameStarted(evt); }
};
class ParticleApplication : public ExampleApplication
{
public:
ParticleApplication() {}protected:
//场景节点指针
SceneNode* mFountainNode; // Just override the mandatory create scene method
void createScene(void)
{
// Set ambient light
// 设置世界的环境光
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5)); // Create a skydome
// 设置天空穹
mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
// Create shared node for 2 fountains
//
//创建一个子场景节点,我不明白他为什么不用createChildSceneNode();
mFountainNode = static_cast<SceneNode*>(mSceneMgr->getRootSceneNode()->createChild()); // smoke
// 创建一个粒子系统,名字为"fountain1",材质为"Examples/Smoke"
ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("fountain1",
"Examples/Smoke");
// Point the fountain at an angle
//在子场景中再创建一个子场景节点
SceneNode* fNode = static_cast<SceneNode*>(mFountainNode->createChild());
//将粒子系统绑定到第二个子场景节点
fNode->attachObject(pSys2); }
// Create new frame listener
void createFrameListener(void)
{
//传入场景节点指针
mFrameListener= new ParticleFrameListener(mWindow, mCamera, mFountainNode);
mRoot->addFrameListener(mFrameListener);
}};
对应的粒子脚本:
// Example particle systems
// 烟
Examples/Smoke
{
//材质
material Examples/Smoke
//粒子宽
particle_width 55
//粒子高
particle_height 55
//渲染时每面都捡选
cull_each true
//数量
quota 500
//点精灵方式
billboard_type point
//排序
sorted true
// 发射器
emitter Point
{ //角度
angle 11
emission_rate 15
time_to_live 4
direction 0 1 0
velocity_min 150
velocity_max 240
} //效果
affector ColourImage
{
image smokecolors.png
} affector Rotator
{
rotation_range_start 0
rotation_range_end 360
rotation_speed_range_start -60
rotation_speed_range_end 200
} affector Scaler
{
rate 100
}}
对应的材质脚本
material Examples/Smoke
{
technique
{
pass
{
lighting off
scene_blend alpha_blend
depth_write off texture_unit
{
texture smoke.png
tex_address_mode clamp //纹理寻址为夹子方式
}
}
}
}
网上资料:
粒子系统
ogre中的粒子系统既可用脚本描述,也可用代码完成。用粒子脚本定义的粒子系统实际上是个模板,因此它定义的粒子系统可在程序中方便地重用。
粒子系统与场景
粒子系统会被挂到场景结点上,因此,结点的平移,缩放,旋转会关联到粒子系统,影响粒子反射的向。
粒子会被发射到世界空间中,这意味着当场景移动时,它会牵连到发射器,但已经发射出去的粒子不受影响。假如需要这些粒子受结点的影响,可以把粒子发射到本地空间(local space)中。粒子系统不能无限制的发射粒子,它有一个限额(quota)。一旦到达限额,粒子系统不会再发射粒子,直到已经存在的粒子消亡。缺省的限额是10。
粒子系统约束(Bounds)
粒子系统的动态特征意味着它们的绑定盒必须规律地被重新计算。缺省情况下,ogre会在10秒之后,停止
更新绑定盒。可以用ParticleSystem::setBoundsAutoUpdated( bool autoUpdate, Real stopIn = 0.0f )来改变缺省行为。stopIn这个参数告诉ogre多长时间后停止更新。假如有个粒子系统,可以知道它的增长不会超过某个范围,可以事先用ParticleSystem::setBounds()设置绑定盒尺寸。这样做效率很高,如果无法事先确定粒子系统的增长情况,可先用setBounds()设定一个初始尺寸,而用setBoundsAutoUpdated()让它在一段时间之后更新。
粒子系统更新
对于粒子系统的更新,ogre采用适度启发式的策略。举例来说,当粒子系统不在视锥体之内,ogre仍会对粒子系统进行更新,这是考虑到不久之后,粒子系统有可能会重新进入视锥体之内。这就避免了这种情况下的视觉上的不和谐。但是出于性能上的考虑,当粒子系统退出视锥体一段时间之后,粒子确实会停止更新。这又会碰到上面的问题:被冻结的粒子系统突然重新进入视锥体的情况。ogre提供了一个所谓的
"fast-forward"机制,允许粒子系统在被冻结之后,快速超越当前状态。这种特性也可以用在刚创建的粒子系统,使它们状态提前一段时间,使用的方法是ParticleSystem::fastForward ();
粒子系统排序
可以指示ogre根据与相机之间的距离,对粒子进行排序。虽然这会影响性能,但有时不得不用。在烟的
例子中,不使用排序的结果是,从烟的顶部依然清晰地看到火苗,而使用了排序之后火苗被烟雾模糊掉了。显然后者更加真实。
发射器
点发射器从空间中单一点发射粒子。box发射器可以从规则四方体的任何位置发射粒子。cylinder定义了一个圆柱体。ellipsoid定义了一个椭球体。hollow elipsoid只是椭球体的外壳。ring只出平面圆环的边发射。被发射粒子的速度,方向也可以配置。粒子系统会被挂到场景结点上,因此发射器与父结点有一个相对的位置。粒子通常不会沿直线发射,它们在发射器方向的一个锥内发射,有一个angle参数来定义。假如希望沿直线发射,angle应该设为0,假如希望全方向发射,angle设为180, 90表示会在方向向量的半球内随机发射。
发射率用 粒子数/秒 表示。发射器可以按某个发射率发射,也可以使用一个范围内的随机值。粒子可
以有固定的生命期,也可以从一个范围随机指定。颜色也一样,固定值,随机值都可以。也可以在运动时,以插件的形式提供定制发射器,这是扩展ogre粒子系统最简单的方法。
影响器
粒子一旦被发射到世界中,影响器可被用来影响粒子的运动路径与生命期。
LinearForce:加一个力到粒子上,力是一个向量,有方向与大小(模)。
ColourFader:用于改变粒子颜色。表示每秒减少的值,是一个绝对值。
ColorFader2:与ColourFader相似,但是粒子生命到到达其生命期的某个阶段时,可以转换到另一个褪色函数。
ColourInterpolator:与上面两个相似,但是它最多可以有6个阶段,分别对每个阶段的时间与颜色进行定义,然后不同阶段之间进行插值,这与关键帧动画的思想有点像。
Scaler:用来缩放粒子尺寸,以时间为函数来定义一个缩放因子。
Rotator:通过一组随机数量,或是随机速率来旋转粒子的纹理,这些被定义在某个范围之内。
colourImage:从图像中攻取颜色,方向从左到右,适合一维纹理 。