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,更新器。
