OSG仿真案例(4)——创建烟雾粒子效果

创建烟雾的例子效果,并附在飞机上;

#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>

//创建火球(燃烧)
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("G:\\YCThirdParty\\Osg\\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("G:\\YCThirdParty\\Osg\\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 main()
{
    osg::ref_ptr<osg::Group> root = new osg::Group();
    osg::Node* flightNode = osgDB::readNodeFile("cessna.osg");//需要经模型放在项目根目录下(而不是在cpp所在目录)
    if (!flightNode)
    {
        std::cout << "no flight" << std::endl;
        return  ;
    }
//飞机变换节点
    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();
}

效果如下:

image.png

单独将“火球”“浓烟”以.osg形式输出

void main()
{
        osg::ref_ptr<osg::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()), "MyScene.osg");
}

验证输出的osg烟雾效果:

void main()
{
    osg::ref_ptr<osg::Group> root = new osg::Group();
    osg::Node* flightNode = osgDB::readNodeFile("MyScene.osg");
    if (!flightNode)
    {
        std::cout << "no flight" << std::endl;
        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();
}

效果展示:

image.png
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rexinx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值