[粒子特效]osg的自帶粒子系統osgParticle::ParticleSystem


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);


/************************************************************************************************/

粒子

OSG中使用osgParticle::Particle這個類,來表示粒子。 
而本例子中,使用的是默認的粒子,所以沒出現粒子。 
如果要產生自定義的粒子,則要自己定義一個Particle對象,然后將這個Particle對象設置為粒子產生器的模板。 
這是通過函數Emitter::setParticleTemplate來實現的。

粒子產生

OSG中粒子的產生,使用的是一個叫做粒子發射器(Emiter)的東東。使用的類叫做osgParticle::Emitter。 
這個粒子發射器,不停地產生新的粒子,每個粒子都從粒子產生器的初始位置發出, 
然后以一定的初始發射角度和初始發射速度向外發出。 
這里使用的是OSG自己內置的一個標准發射器osgParticle::ModularEmitter。

粒子管理

粒子發射器,不停地發射粒子,這些發射出來的粒子,如何管理呢? 
這是通過粒子系統來進行的。 
對應的類叫osgParticle::ParticleSystem。 
粒子發射器,發射出來粒子后,交個粒子系統,就不用操心了。 
這個轉交的過程,是用過emitter->setParticleSystem(ps)實現的。

粒子顯示

由於粒子系統本身,只負責管理粒子,並不負責顯示粒子,所以,還需要一個東西,將粒子顯示出來。 
OSG中是通過osg::Geode將粒子系統顯示出來。 
然后通過geode->addDrawable(ps)將粒子系統與Geode結合起來。

粒子更新

由於粒子是在不停地運動,所以需要不停地更新。 
粒子系統的更新是通過類osgParticle::ParticleSystemUpdater來實現的。 
然后通過psu->addParticleSystem(ps);來將更新器和粒子系統進行關聯。

最后,將粒子系統,加到場景中,需要添加三個東西到場景樹中:發射器,顯示的Geode,更新器。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM