Osg粒子效果

粒子系统(osgParticle::ParticleSystem)- 维护并管理一系列粒子的生成,更新,渲染和销毁。粒子系统类继承自Drawable类。粒子的渲染控制因此与其它Drawable对象的渲染类似:控制其渲染属性StateAttribute即可。OSG提供了一个方便的函数以允许用户控制三个常用的渲染状态属性。方法setDefaultAttributes可以用于指定材质(或者指定为NULL以禁用材质),允许/禁止附加的图像融合,允许/禁止光照。

粒子(osgParticle::Particle)- 粒子系统的基本单元。粒子类同时具有物理属性和图像属性。它的形状可以是任意的点(POINT),四边形(QUAD),四边形带(QUAD_TRIPSTRIP),六角形(HEXAGON)或者线(LINE)。每个粒子都有自己的生命周期。生命周期也就是每个粒子可以存活的秒数。(生命周期为负数的粒子可以存活无限长时间)所有的粒子都具有大小(SIZE),ALPHA值和颜色(COLOR)属性。每一组粒子都可以指定其最大和最小值。为了便于粒子生命周期的管理,粒子系统通过改变生命周期的最大和最小值来控制单个粒子的渲染。(根据已经消耗的时间,在最小和最大值之间进行线性插值) 程序员也可以自行指定最小到最大值的插值方法。(参见osgParticle::Interpolator的代码)

放置器(osgParticle::Placer)- 设置粒子的初始位置。用户可以使用预定义的放置器或者定义自己的放置器。已定义的放置器包括:点放置器PointPlacer(所有的粒子从同一点出生),扇面放置器SectorPlacer(所有的粒子从一个指定中心点,半径范围和角度范围的扇面出生),以及多段放置器MultiSegmentPlacer(用户指定一系列的点,粒子沿着这些点定义的线段出生)。

发射器(osgParticle::Shooter)- 指定粒子的初始速度。RadialShooter类允许用户指定一个速度范围(米/秒)以及弧度值表示的方向。方向由两个角度指定:theta角 - 与Z轴夹角,phi角 - 与XY平面夹角。

计数器(osgParticle::Counter)- 控制每一帧产生的粒子数。RandomRateCounter类允许用户指定每帧产生粒子的最大和最小数目。

标准放射极(osgParticle::ModularEmitter)- 一个标准放射极包括一个计数器,一个放置器和一个发射器。它为用户控制粒子系统中多个元素提供了一个标准机制。

粒子系统更新器(osgParticle::ParticleSystemUpdater)- 用于自动更新粒子。将其置于场景中时,它会在拣选遍历中调用所有“存活”粒子的更新方法。

标准编程器(osgParticle::ModularProgram)- 在单个粒子的生命周期中,用户可以使用ModularProgram实例控制粒子的位置。ModularProgram需要与Operator对象组合使用。

计算器(osgParticle::Operator)- 提供了控制粒子在其生命周期中的运动特性的方法。用户可以改变现有Operator类实例的参数,或者定义自己的Operator类。OSG提供的Operator类包括:AccelOperator(应用常加速度),AngularAccelOperator(应用常角加速度),FluidFrictionOperator(基于指定密度和粘性的流体运动进行计算),以及ForceOperator(应用常力)。

代码.h

#include <osgParticle/PrecipitationEffect>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ModularProgram>
#include <osgParticle/AccelOperator>
#include <osgParticle/FluidFrictionOperator>
#include <osgParticle/ParticleSystemUpdater>

//粒子系统,以下函数依次调用,Run执行默认的一个生成器
class QuickParticleSys
{
public:
	QuickParticleSys(osg::ref_ptr<osg::Group> parent, const std::string path);//设置材质文件
	virtual ~QuickParticleSys(void);

public:
	//编写粒子模板,子类必需实现
	virtual osgParticle::Particle ImplParticleTemp();

	//设置每帧粒子数,必需的
	void SetNumPerFrame(int min, int max);

	//设置放置器,设置粒子的初始位置:
	//点放置器PointPlacer(所有的粒子从同一点出生),
	//扇面放置器SectorPlacer(所有的粒子从一个指定中心点,半径范围和角度范围的扇面出生),
	//多段放置器MultiSegmentPlacer(用户指定一系列的点,粒子沿着这些点定义的线段出生)
	void SetPlacer(osgParticle::Placer* placer);

	//设置发射器,指定粒子的初始速度。必需的
	//RadialShooter类允许用户指定一个速度范围(米/秒)以及弧度值表示的方向。
	//方向由两个角度指定:theta角 - 与Z轴夹角,phi角 - 与XY平面夹角。
	void SetShooter(osgParticle::Shooter* shooter=nullptr);

	//设置速度控制细节:ModularProgram需要与Operator对象组合使用,必需的
	//计算器(osgParticle::Operator)- 提供了控制粒子在其生命周期中的运动特性的方法。
	//用户可以改变现有Operator类实例的参数,或者定义自己的Operator类。
	//OSG提供的Operator类包括:AccelOperator(应用常加速度),
	//AngularAccelOperator(应用常角加速度),
	//FluidFrictionOperator(基于指定密度和粘性的流体运动进行计算),
	//ForceOperator(应用常力)
	void SetProgramer(osgParticle::ModularProgram* pragram=nullptr);

	//设置更新器,必需的
	void SetParticleSystemUpdater(osgParticle::ParticleSystemUpdater * updater=nullptr);

	//开始执行
	virtual void Run();
private:
	osg::ref_ptr<osg::Group> _parent;//父节点
	osg::ref_ptr<osgParticle::ParticleSystem> _pParticleSys;//粒子系统,材质、光照
	osg::ref_ptr<osgParticle::ModularEmitter> _pEmitter;	//标准标准放射极:计数器、放置器、发射器
};

.cpp

#include "QuickParticleSys.h"

QuickParticleSys::QuickParticleSys(osg::ref_ptr<osg::Group> parent, const std::string path )
{
	_parent = parent;

	//初始化粒子系统
	_pParticleSys =	new osgParticle::ParticleSystem;
	_pParticleSys->setDefaultAttributes(path, false, false);//是否放射粒子,是否光照
	
	// 标准发射器,关联粒子系统
	_pEmitter = new osgParticle::ModularEmitter;
	_pEmitter->setParticleSystem(_pParticleSys);
	_parent->addChild(_pEmitter);

	// 由于粒子系统类继承自Drawable类,因此我们可以将其作为Geode的子节点加入场景。
	osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
	pGeode->addDrawable(_pParticleSys);
	_parent->addChild(pGeode);
}

QuickParticleSys::~QuickParticleSys(void)
{
}

osgParticle::Particle QuickParticleSys::ImplParticleTemp()
{
	// 设置粒子模板的参数,包括生命周期、颜色、透明度、半径、重量等
	osgParticle::Particle pParticle;
	pParticle.setLifeTime(-1);
	pParticle.setColorRange(osgParticle::rangev4(
		osg::Vec4(0.7, 1.0, 1.0, 1.0),
		osg::Vec4(0.8, 1.0, 1.0, 0.0)));
	pParticle.setSizeRange(osgParticle::rangef(0.1f, 0.1f));
	pParticle.setAlphaRange(osgParticle::rangef(1.0f, 0.5f));
	pParticle.setRadius(0.1);
	pParticle.setMass(0.001);
	return pParticle;
}

void QuickParticleSys::SetNumPerFrame( int min, int max )
{
	osgParticle::RandomRateCounter *dustRate = 
		static_cast<osgParticle::RandomRateCounter *>(_pEmitter->getCounter());
	dustRate->setRateRange(min, max); // 每秒新生成5到10个新粒子。
}

void QuickParticleSys::SetPlacer(osgParticle::Placer* placer)
{
	_pEmitter->setPlacer(placer);
}

void QuickParticleSys::SetShooter( osgParticle::Shooter* shooter )
{
	if (!shooter)
	{
		// 粒子发射枪
		osg::ref_ptr<osgParticle::RadialShooter> pShooter = new osgParticle::RadialShooter;
		pShooter->setInitialSpeedRange(-1, 10);
		_pEmitter->setShooter(pShooter);
	}
	else
	{
		_pEmitter->setShooter(shooter);
	}
}

void QuickParticleSys::SetProgramer( osgParticle::ModularProgram* pragram )
{
	if (!pragram)
	{
		// 速度细节控制
		osg::ref_ptr<osgParticle::ModularProgram> pProgram = new osgParticle::ModularProgram;
		pProgram->setParticleSystem(_pParticleSys);
		osg::ref_ptr<osgParticle::AccelOperator> pAccelOperator = new osgParticle::AccelOperator;
		pAccelOperator->setToGravity();
		pProgram->addOperator(pAccelOperator);
		osg::ref_ptr<osgParticle::FluidFrictionOperator> pOperator = new osgParticle::FluidFrictionOperator;
		pOperator->setFluidToAir();
		pProgram->addOperator(pOperator);
		_parent->addChild(pProgram);
	} 
	else
	{
		pragram->setParticleSystem(_pParticleSys);
		_parent->addChild(pragram);
	}
}

void QuickParticleSys::SetParticleSystemUpdater( osgParticle::ParticleSystemUpdater * updater )
{
	//设置粒子对象模板
	osgParticle::Particle particle = ImplParticleTemp();
	_pParticleSys->setDefaultParticleTemplate(particle);

	if (!updater)
	{
		// 添加更新器,以实现每帧的粒子管理。
		osg::ref_ptr<osgParticle::ParticleSystemUpdater> pParticleSysUpdate =
			new osgParticle::ParticleSystemUpdater;
		pParticleSysUpdate->addParticleSystem(_pParticleSys);// 将更新器与粒子系统对象关联。
		_parent->addChild(pParticleSysUpdate);
	}
	else
	{
		updater->addParticleSystem(_pParticleSys);// 将更新器与粒子系统对象关联。
		_parent->addChild(updater);
	}
}

void QuickParticleSys::Run()
{
	SetNumPerFrame(10,25);
	SetShooter();
	SetProgramer();
	SetParticleSystemUpdater();
}

调用类:可继承,可用默认实现来学习

QuickParticleSys fountain(root,
	"D:/MyDocuments/c++_works/osgTest/osgTest/ImagesImage/smoke.rgb");
fountain.Run();

效果图:

效果图

参考:

  1. OSG向场景中添加osgParticle粒子效果