osg示例解析之osgparticle(1)

  • 简介

osgParticle示例简单的演示了在osg中使用粒子系统的效果,用到了osgParticle库中的相关类,在osgParticle中主要有:

(以下部分材料摘取自osg向场景中添加osgParticle粒子效果一文,Google了一下未找到原创作者,贴出转载地址,在此谢过原创作者~)

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

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

放置器(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(应用常力)。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

接下来看代码:

首先代码中创建了一个Operator的子类,用来模拟涡流的效果,这个操作类会被添加到Program中从而对粒子系统中的每一个粒子产生作用:

    void operate(osgParticle::Particle *P, double dt)
    {
        float l = xf_axis_ * (P->getPosition() - xf_center_);
        osg::Vec3 lc = xf_center_ + xf_axis_ * l;
        osg::Vec3 R = P->getPosition() - lc;
        osg::Vec3 v = (R ^ xf_axis_) * P->getMassInv() * intensity_;

        osg::Vec3 newpos = P->getPosition() + v * dt;
        P->setPosition(newpos);    
    }
由于Operator是一个纯虚类,子类必须要重载它的operator方法。此外子类也可以重载beginOperator方法,实现在操作粒子之前完成一些准备工作。

下面我们看看create_simple_particle_system这个函数,它完整演示了最简单的创建粒子效果的步骤:

    //首先创建粒子系统对象
	osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
    ps->setDefaultAttributes("", true, false);
   //设置Emitter的参数(设置发射数量)
    osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
    emitter->setParticleSystem(ps);
    osgParticle::RandomRateCounter *rrc = 
        static_cast<osgParticle::RandomRateCounter *>(emitter->getCounter());
    rrc->setRateRange(20, 30);
    root->addChild(emitter);
   //将离子系统添加到叶节点
    osg::Geode *geode = new osg::Geode;    
    geode->addDrawable(ps);
    root->addChild(geode);
在create_complex_particle_system中只是设置了更多的参数,同时添加了一个作用于粒子系统的Program,并在里面添加了很多的operator,整个设置过程还是一样的
   //设置Emitter更多的参数
    osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;
    emitter->setParticleSystem(ps);

    osgParticle::RandomRateCounter *counter = new osgParticle::RandomRateCounter;
    counter->setRateRange(60, 60);
    emitter->setCounter(counter);

    osgParticle::SectorPlacer *placer = new osgParticle::SectorPlacer;
    placer->setCenter(8, 0, 10);
    placer->setRadiusRange(2.5, 5);
    placer->setPhiRange(0, 2 * osg::PI);
    emitter->setPlacer(placer);

    osgParticle::RadialShooter *shooter = new osgParticle::RadialShooter;
    shooter->setInitialSpeedRange(0, 0);
    emitter->setShooter(shooter);

    root->addChild(emitter);

	//添加Operator到Program之中
    osgParticle::ModularProgram *program = new osgParticle::ModularProgram;
    program->setParticleSystem(ps);

    osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
    op1->setToGravity();
    program->addOperator(op1);

    VortexOperator *op2 = new VortexOperator;
    op2->setCenter(osg::Vec3(8, 0, 0));
    program->addOperator(op2);

    osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
    op3->setFluidToAir();
    program->addOperator(op3);

    root->addChild(program);

    osg::Geode *geode = new osg::Geode;
    geode->addDrawable(ps);

    root->addChild(geode);
create_animated_particle_system创建了一个切换纹理的粒子效果动画:

这样粒子的纹理会在这些纹理切片之中不停地进行切换:

	//设置纹理所使用的纹理切片
    pexplosion.setTextureTileRange(8, 8, 0, 15);
    psmoke.setTextureTileRange(8, 8, 32, 45);
其他部分的设置与上面一致。

最后一个步骤,我们需要将这些粒子系统添加到一个Updater之中,由Updater再场景的拣选遍历中更新粒子系统

    osgParticle::ParticleSystem *ps1 = create_simple_particle_system(root);
    osgParticle::ParticleSystem *ps2 = create_complex_particle_system(root);
    osgParticle::ParticleSystem *ps3 = create_animated_particle_system(root);

    osgParticle::ParticleSystemUpdater *psu = new osgParticle::ParticleSystemUpdater;
    psu->addParticleSystem(ps1);
    psu->addParticleSystem(ps2);
    psu->addParticleSystem(ps3);

    root->addChild(psu);






你可能感兴趣的:(Examples,OSG,osgParticle)