osg粒子场景

雨雪效果:
#include <osgParticle/PrecipitationEffect>
void main()
{
osgViewer::Viewer viewer;

//设置雪花类
osg::ref_ptr<osgParticle::PrecipitationEffect> precipitationEffect = new osgParticle::PrecipitationEffect;

//设置雪花浓度
precipitationEffect->snow(0.5);

//设置雪花颜色 
precipitationEffect->setParticleColor(osg::Vec4(1, 1, 1, 1));

//设置风向
precipitationEffect->setWind(osg::Vec3(2, 0, 0));

osg::ref_ptr <osg::Group> pRoot = new osg::Group();

//把雪花加入到场景结点
pRoot->addChild(precipitationEffect.get());
osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("D:\\data\\cessna.osgt");
pRoot->addChild(glider.get());
viewer.setSceneData(pRoot);

//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
viewer.addEventHandler(new osgViewer::WindowSizeHandler);

//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
viewer.addEventHandler(new osgViewer::StatsHandler);

viewer.realize();
viewer.run();

}
爆炸效果:
#include <osgParticle/ExplosionDebrisEffect>
#include <osgParticle/ExplosionEffect>
#include <osgParticle/SmokeEffect>
#include <osgParticle/FireEffect>
#include <osgUtil/Optimizer>

//创建爆炸效果:
osg::ref_ptrosg::Node createExplode()
{
osg::ref_ptrosg::Group explode = new osg::Group();
//风向
osg::Vec3 wind(1.0f, 0.0f, 0.0f);
osg::Vec3 position(0.0f, 0.0f, -1.0f);
//爆炸模拟,10.0f为缩放比,默认为1.0f,不缩放
osg::ref_ptrosgParticle::ExplosionEffect explosion = new osgParticle::ExplosionEffect(position, 10.0f);
osg::ref_ptrosgParticle::ExplosionDebrisEffect explosionDebri =
new osgParticle::ExplosionDebrisEffect(position, 10.0f);
//烟模拟
osg::ref_ptrosgParticle::SmokeEffect smoke = new osgParticle::SmokeEffect(position, 10.0f);
//火焰模拟
osg::ref_ptrosgParticle::FireEffect fire = new osgParticle::FireEffect(position, 10.0f);
//设置风向
explosion->setWind(wind);
explosionDebri->setWind(wind);
smoke->setWind(wind);
fire->setWind(wind);

//添加子节点
explode->addChild(explosion.get());
explode->addChild(explosionDebri.get());
explode->addChild(smoke.get());
explode->addChild(fire.get());
return explode.get();

}

int main()
{
osg::ref_ptrosgViewer::Viewer viewer = new osgViewer::Viewer();
osg::ref_ptrosg::Group root = new osg::Group();
//添加爆炸效果
root->addChild(createExplode());
//优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
//设置场景数据
viewer->setSceneData(root.get());
//初始化并创建窗口
viewer->realize();
//viewer->setUpViewInWindow(200, 200, 800, 800);
viewer->run();
}

飞机坠落:
#include
#include <windows.h>
#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/Billboard>
#include <osg/Texture2D>
#include <osg/Image>
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>

#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Simplifier> //简化几何体

#include <osgParticle/PrecipitationEffect>
#include <osgParticle/Particle>

#include <osgParticle/LinearInterpolator>
#include <osgParticle/ParticleSystem>
#include < osgParticle/RandomRateCounter>
#include <osgParticle/PointPlacer>
#include <osgParticle/RadialShooter>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ParticleSystemUpdater>
#include < osgParticle/ModularProgram>

#pragma comment(lib, “OpenThreadsd.lib”)
#pragma comment(lib, “osgd.lib”)
#pragma comment(lib, “osgDBd.lib”)
#pragma comment(lib, “osgUtild.lib”)
#pragma comment(lib, “osgGAd.lib”)
#pragma comment(lib, “osgViewerd.lib”)
#pragma comment(lib, “osgTextd.lib”)
#pragma comment(lib, “osgParticled.lib”)

//创建火球(燃烧)
void createFireBall(osg::MatrixTransform* smokeNode)
{
// 创建粒子对象,设置其属性并交由粒子系统使用。
osgParticle::Particle particleTempalte;
particleTempalte.setShape(osgParticle::Particle::QUAD);
particleTempalte.setLifeTime(1.5); // 单位:秒
particleTempalte.setSizeRange(osgParticle::rangef(3.0f, 1.0f)); // 单位:米
particleTempalte.setAlphaRange(osgParticle::rangef(1, 0));
particleTempalte.setColorRange(osgParticle::rangev4(osg::Vec4(1.0f, 0.2f, 0.0f, 1.0f),//0.1f,0.3f,0.4f,1.0f
osg::Vec4(0.1f, 0.1f, 0.1f, 0)//0.95f,0.75f,0,1(1,1,1,1)
));
particleTempalte.setPosition(osg::Vec3(0.0f, 0.0f, 0.0f));
particleTempalte.setVelocity(osg::Vec3(0.0f, 0.0f, 0.0f));
particleTempalte.setMass(0.1f); //单位:千克
particleTempalte.setRadius(0.2f);
particleTempalte.setSizeInterpolator(new osgParticle::LinearInterpolator);
particleTempalte.setAlphaInterpolator(new osgParticle::LinearInterpolator);
particleTempalte.setColorInterpolator(new osgParticle::LinearInterpolator);
// 创建并初始化粒子系统。
osgParticle::ParticleSystem* particleSystem = new osgParticle::ParticleSystem;
particleSystem->setDataVariance(osg::Node::STATIC);
// 设置材质,是否放射粒子,以及是否使用光照。
particleSystem->setDefaultAttributes(“D:\data\Images\smoke.rgb”, true, false);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(particleSystem);
smokeNode->addChild(geode);
//设置为粒子系统的缺省粒子对象。
particleSystem->setDefaultParticleTemplate(particleTempalte);
//获取放射极中缺省计数器的句柄,调整每帧增加的新粒子数目
osgParticle::RandomRateCounter* particleGenerateRate = new osgParticle::RandomRateCounter();
particleGenerateRate->setRateRange(30, 50);
// 每秒新生成的粒子范围
particleGenerateRate->setDataVariance(osg::Node::DYNAMIC);
// 自定义一个放置器,这里创建并初始化一个点放置器
osgParticle::PointPlacer* particlePlacer = new osgParticle::PointPlacer;
particlePlacer->setCenter(osg::Vec3(0.0f, 0.0f, 0.0f));
particlePlacer->setDataVariance(osg::Node::DYNAMIC);
// 自定义一个弧度发射器
osgParticle::RadialShooter* particleShooter = new osgParticle::RadialShooter;
// 设置发射器的属性
particleShooter->setDataVariance(osg::Node::DYNAMIC);
particleShooter->setThetaRange(-0.1f, 0.1f);
// 弧度值,与Z 轴夹角
particleShooter->setPhiRange(-0.1f, 0.1f);
particleShooter->setInitialSpeedRange(5, 7.5f);//单位:米/秒
//创建标准放射极对象
osgParticle::ModularEmitter* emitter = new osgParticle::ModularEmitter;
emitter->setDataVariance(osg::Node::DYNAMIC);
emitter->setCullingActive(false);
// 将放射极对象与粒子系统关联。
emitter->setParticleSystem(particleSystem);
// 设置计数器
emitter->setCounter(particleGenerateRate);
// 设置放置器
emitter->setPlacer(particlePlacer);
// 设置发射器
emitter->setShooter(particleShooter);
// 把放射极添加为变换节点
smokeNode->addChild(emitter);
// 添加更新器,以实现每帧的粒子管理。
osgParticle::ParticleSystemUpdater* particleSystemUpdater = new osgParticle::ParticleSystemUpdater;
// 将更新器与粒子系统对象关联。
particleSystemUpdater->addParticleSystem(particleSystem);
// 将更新器节点添加到场景中。
smokeNode->addChild(particleSystemUpdater);
// 创建标准编程器对象并与粒子系统相关联。
osgParticle::ModularProgram* particleMoveProgram = new osgParticle::ModularProgram;
particleMoveProgram->setParticleSystem(particleSystem);
// 最后,将编程器添加到场景中。
smokeNode->addChild(particleMoveProgram);
}

//创建浓烟
void createDarkSmoke(osg::MatrixTransform* smokeNode)
{
// 创建粒子对象,设置其属性并交由粒子系统使用。
osgParticle::Particle particleTempalte;
particleTempalte.setShape(osgParticle::Particle::QUAD);
particleTempalte.setLifeTime(10); // 单位:秒
particleTempalte.setSizeRange(osgParticle::rangef(1.0f, 12.0f)); // 单位:米
particleTempalte.setAlphaRange(osgParticle::rangef(1, 0));
particleTempalte.setColorRange(osgParticle::rangev4(
osg::Vec4(0.0f, 0.0f, 0.0f, 0.5f),//(0.1f,0.1f,0.1f,0.5f)
osg::Vec4(0.5f, 0.5f, 0.5f, 1.5f)//0.95f,0.75f,0,1
));
particleTempalte.setPosition(osg::Vec3(0.0f, 0.0f, 0.0f));
particleTempalte.setVelocity(osg::Vec3(0.0f, 0.0f, 0.0f));
particleTempalte.setMass(0.1f); //单位:千克
particleTempalte.setRadius(0.2f);
particleTempalte.setSizeInterpolator(new osgParticle::LinearInterpolator);
particleTempalte.setAlphaInterpolator(new osgParticle::LinearInterpolator);
particleTempalte.setColorInterpolator(new osgParticle::LinearInterpolator);
// 创建并初始化粒子系统。
osgParticle::ParticleSystem* particleSystem = new osgParticle::ParticleSystem;
particleSystem->setDataVariance(osg::Node::STATIC);
// 设置材质,是否放射粒子,以及是否使用光照。
particleSystem->setDefaultAttributes(“D:\data\Images\smoke.rgb”, false, false);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(particleSystem);
smokeNode->addChild(geode);
//设置为粒子系统的缺省粒子对象。
particleSystem->setDefaultParticleTemplate(particleTempalte);
//获取放射极中缺省计数器的句柄,调整每帧增加的新粒
//子数目
osgParticle::RandomRateCounter* particleGenerateRate = new osgParticle::RandomRateCounter();
particleGenerateRate->setRateRange(30, 50);
// 每秒新生成的粒子范围
particleGenerateRate->setDataVariance(osg::Node::DYNAMIC);
// 自定义一个放置器,这里我们创建并初始化一个点放置器
osgParticle::PointPlacer* particlePlacer = new osgParticle::PointPlacer;
particlePlacer->setCenter(osg::Vec3(0.0f, 0.0f, 0.05f));
particlePlacer->setDataVariance(osg::Node::DYNAMIC);
// 自定义一个弧度发射器
osgParticle::RadialShooter* particleShooter = new osgParticle::RadialShooter;
// 设置发射器的属性
particleShooter->setDataVariance(osg::Node::DYNAMIC);
particleShooter->setThetaRange(-0.1f, 0.1f);
// 弧度值,与Z 轴夹角0.392699f
particleShooter->setPhiRange(-0.1f, 0.1f);
particleShooter->setInitialSpeedRange(10, 15);
//单位:米/秒
//创建标准放射极对象
osgParticle::ModularEmitter* emitter = new osgParticle::
ModularEmitter;
emitter->setDataVariance(osg::Node::DYNAMIC);
emitter->setCullingActive(false);
// 将放射极对象与粒子系统关联。
emitter->setParticleSystem(particleSystem);
// 设置计数器
emitter->setCounter(particleGenerateRate);
// 设置放置器
emitter->setPlacer(particlePlacer);
// 设置发射器
emitter->setShooter(particleShooter);
// 把放射极添加为变换节点
smokeNode->addChild(emitter);
// 添加更新器,以实现每帧的粒子管理。
osgParticle::ParticleSystemUpdater* particleSystemUpdater = new osgParticle::ParticleSystemUpdater;
// 将更新器与粒子系统对象关联。
particleSystemUpdater->addParticleSystem(particleSystem);
// 将更新器节点添加到场景中。
smokeNode->addChild(particleSystemUpdater);
osgParticle::ModularProgram* particleMoveProgram = new osgParticle::ModularProgram;
particleMoveProgram->setParticleSystem(particleSystem);
// 最后,将编程器添加到场景中。
smokeNode->addChild(particleMoveProgram);
}

void WriteFireballAndSmoke()
{
osg::ref_ptrosg::Group root = new osg::Group();
osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
root->addChild(flightTransform);
//引擎烟雾
osg::MatrixTransform* fireballAndSmoke = new osg::MatrixTransform();
createFireBall(fireballAndSmoke);

fireballAndSmoke->setMatrix(osg::Matrix::rotate(-osg::PI / 2, 1, 0, 0) * osg::Matrix::translate(-8, -10, -3));
flightTransform->addChild(fireballAndSmoke);
createDarkSmoke(fireballAndSmoke);

osgDB::writeNodeFile(*(root.get()), "D:\\data\\Images\\MyScene.osg");

}

void ReadFireballAndSmoke()
{
osg::ref_ptrosg::Group root = new osg::Group();
osg::Node* flightNode = osgDB::readNodeFile(“D:\data\Images\MyScene.osg”);
if (!flightNode)
{
return;
}
osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
flightTransform->addChild(flightNode);
root->addChild(flightTransform);
osgViewer::Viewer viewer;

osgUtil::Simplifier simplifier(0.3f, 4.0f);
osgUtil::Optimizer optimzer;

optimzer.optimize(root.get());
viewer.setSceneData(root.get());

//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
viewer.addEventHandler(new osgViewer::WindowSizeHandler);

//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.realize();
viewer.run();

}

//陨石坠落
//int main()
//{
// WriteFireballAndSmoke();
// ReadFireballAndSmoke();
//
// return 0;
//}

int main()
{
osg::ref_ptrosg::Group root = new osg::Group();
osg::Node* flightNode = osgDB::readNodeFile(“D:\data\cessna.osgt”);//需要经模型放在项目根目录下(而不是在cpp所在目录)
if (!flightNode)
{
return -1;
}
//飞机变换节点
osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
flightTransform->addChild(flightNode);
root->addChild(flightTransform);
//引擎烟雾
osg::MatrixTransform* fireballAndSmoke = new osg::MatrixTransform();
createFireBall(fireballAndSmoke);

fireballAndSmoke->setMatrix(osg::Matrix::rotate(-osg::PI / 2, 1, 0, 0) * osg::Matrix::translate(-8, -10, -3));
flightTransform->addChild(fireballAndSmoke);
createDarkSmoke(fireballAndSmoke);
osgViewer::Viewer viewer;

osgUtil::Simplifier simplifier(0.3f, 4.0f);
osgUtil::Optimizer optimzer;

optimzer.optimize(root.get());
viewer.setSceneData(root.get());

//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
viewer.addEventHandler(new osgViewer::WindowSizeHandler);

//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
viewer.addEventHandler(new osgViewer::StatsHandler);

viewer.realize();
viewer.run();

return 0;

}

// 创建并初始化粒子系统。
osgParticle::ParticleSystem *dustParticleSystem = new osgParticle::ParticleSystem;

// 设置材质,是否放射粒子,以及是否使用光照。
dustParticleSystem->setDefaultAttributes(dust2.rgb", false, false);

// 由于粒子系统类继承自Drawable类,因此我们可以将其作为Geode的子节点加入场景。
osg::Geode *geode = new osg::Geode;

rootNode->addChild(geode);
geode->addDrawable(dustParticleSystem);

// 添加更新器,以实现每帧的粒子管理。
osgParticle::ParticleSystemUpdater *dustSystemUpdater = new osgParticle::ParticleSystemUpdater;

// 将更新器与粒子系统对象关联。
dustSystemUpdater->addParticleSystem(dustParticleSystem);
// 将更新器节点添加到场景中。
rootNode->addChild(dustSystemUpdater);

// 创建粒子对象,设置其属性并交由粒子系统使用。
osgParticle::Particle smokeParticle;
smokeParticle.setSizeRange(osgParticle::rangef(0.01,20.0)); // 单位:米
smokeParticle.setLifeTime(4); // 单位:秒
smokeParticle.setMass(0.01); // 单位:千克
// 设置为粒子系统的缺省粒子对象。
dustParticleSystem->setDefaultParticleTemplate(smokeParticle);

// 创建标准放射极对象。(包括缺省的计数器,放置器和发射器)
osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;

// 将放射极对象与粒子系统关联。
emitter->setParticleSystem(dustParticleSystem);

// 获取放射极中缺省计数器的句柄,调整每帧增加的新粒子数目。
osgParticle::RandomRateCounter *dustRate =
static_cast<osgParticle::RandomRateCounter *>(emitter->getCounter());
dustRate->setRateRange(5, 10); // 每秒新生成5到10个新粒子。

// 自定义一个放置器,这里我们创建并初始化一个多段放置器。
osgParticle::MultiSegmentPlacer* lineSegment = new osgParticle::MultiSegmentPlacer();

// 向放置器添加顶点,也就是定义粒子产生时所处的线段位置。
// (如果将坦克和标准放射极定义与同一位置,那么我们可以实现一种
// 灰尘粒子从坦克模型后下方的延长线上产生的效果。)
lineSegment->addVertex(0,0,-2);
lineSegment->addVertex(0,-2,-2);
lineSegment->addVertex(0,-16,0);

// 为标准放射极设置放置器。
emitter->setPlacer(lineSegment);

// 自定义一个发射器,这里我们创建并初始化一个RadialShooter弧度发射器。
osgParticle::RadialShooter* smokeShooter = new osgParticle::RadialShooter();

// 设置发射器的属性。
smokeShooter->setThetaRange(0.0, 3.14159/2); // 弧度值,与Z轴夹角。
smokeShooter->setInitialSpeedRange(50,100); // 单位:米/秒

// 为标准放射极设置发射器。
emitter->setShooter(smokeShooter);

现在我们将把放射极和坦克模型作为Transform变换节点的子节点添加到场景中。放射极和坦克均由变换节点决定其位置。刚才定义的放置器将会根据变换的参量安排粒子的位置。

osg::MatrixTransform * tankTransform = new osg::MatrixTransform();
tankTransform->setUpdateCallback( new orbit() ); // 回调函数,使节点环向运动。

// 把放射极和坦克模型添加为变换节点的子节点。
tankTransform->addChild(emitter);
tankTransform->addChild(tankNode);
rootNode->addChild(tankTransform);

下面的代码将创建一个标准编程器ModularProgram实例,用于控制粒子在生命周期中的更新情况。标准编程器对象使用Operator计算器来实现对粒子的控制。

// 创建标准编程器对象并与粒子系统相关联。
osgParticle::ModularProgram *moveDustInAir = new osgParticle::ModularProgram;
moveDustInAir->setParticleSystem(dustParticleSystem);

// 创建计算器对象,用于模拟重力的作用,调整其参数并添加给编程器对象。
osgParticle::AccelOperator *accelUp = new osgParticle::AccelOperator;
accelUp->setToGravity(-1); // 设置重力加速度的放缩因子。
moveDustInAir->addOperator(accelUp);

// 向编程器再添加一个计算器对象,用于计算空气阻力。
osgParticle::FluidFrictionOperator *airFriction = new osgParticle::FluidFrictionOperator;
airFriction->setFluidToAir();
moveDustInAir->addOperator(airFriction);

// 最后,将编程器添加到场景中。
rootNode->addChild(moveDustInAir);

下面的代码就是仿真循环的内容了。

viewer.setCameraManipulator(new osgGA::TrackballManipulator());
viewer.setSceneData(rootNode);
viewer.realize();

while( !viewer.done() ){
  viewer.frame();
}
return 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曾忆少年时~峥嵘岁月稠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值