短視頻培訓(xùn)機(jī)構(gòu)seo入門到精通
自定義粒子系統(tǒng)示例(二)
????????目前自定義粒子的方法有很多,在OSG 中使用的是 Billboard 技術(shù)與色彩融合技術(shù)。色彩融合是一種高級的渲染技術(shù),如果讀者有興趣,可參看 OSG 粒子系統(tǒng)實(shí)現(xiàn)的源代碼。這里采用簡單的布告牌技術(shù)(osg::Billboard)與動畫來實(shí)現(xiàn)。這種方法也可以生成比較好的粒子系統(tǒng)的效果。最好使用同名的貼圖,示例中并沒有對這些貼圖進(jìn)行處理,它只是向讀者展示如何模擬一個(gè)自定義的粒子系統(tǒng),讀者可仔細(xì)體會。
????????自定義粒子系統(tǒng)示例(二)的代碼如程序清單11-6所示。
/* 自定義粒子系統(tǒng)示例2 */
void particleSystem_11_6(const string &strDataFolder)
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;traits->x = 40;traits->y = 40;traits->width = 600;traits->height = 480;traits->windowDecoration = true;traits->doubleBuffer = true;traits->sharedContext = 0;osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());osg::ref_ptr<osg::Camera> camera = viewer->getCamera();camera->setGraphicsContext(gc.get());camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;camera->setDrawBuffer(buffer);camera->setReadBuffer(buffer);osg::ref_ptr<osg::Group> root = new osg::Group();// 向場景中添加幀動畫osg::ref_ptr<osg::Sequence>sq = new osg::Sequence();sq = createSequence(strDataFolder);root->addChild(sq.get());// 優(yōu)化場景數(shù)據(jù)osgUtil::Optimizer optimize;optimize.optimize(root.get());viewer->setSceneData(root.get());viewer->realize();viewer->run();
}osg::ref_ptr<osg::Node> createBillBoard(osg::ref_ptr<osg::Image> image)
{// 創(chuàng)建四邊形osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();// 設(shè)置頂點(diǎn)osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();v->push_back(osg::Vec3(-0.5, 0.0, -0.5));v->push_back(osg::Vec3(0.5, 0.0, -0.5));v->push_back(osg::Vec3(0.5, 0.0, 0.5));v->push_back(osg::Vec3(-0.5, 0.0, 0.5));geometry->setVertexArray(v.get());// 設(shè)置法線osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array();normal->push_back(osg::Vec3(1.0, 0.0, 0.0) ^ osg::Vec3(0.0, 0.0, 1.0));geometry->setNormalArray(normal.get());geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);// 設(shè)置紋理坐標(biāo)osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();vt->push_back(osg::Vec2(0.0, 0.0));vt->push_back(osg::Vec2(1.0, 0.0));vt->push_back(osg::Vec2(1.0, 1.0));vt->push_back(osg::Vec2(0.0, 1.0));geometry->setTexCoordArray(0, vt.get());// 繪制四邊形geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));if (image.get()){// 屬性對象osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();// 創(chuàng)建一個(gè)Texture2D屬性對象osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();// 關(guān)聯(lián)imagetexture->setImage(image.get());// 關(guān)聯(lián)Texture2D紋理對象,第三個(gè)參數(shù)默認(rèn)為ONstateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);// 啟用混合stateset->setMode(GL_BLEND, osg::StateAttribute::ON);// 關(guān)閉光照stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);geometry->setStateSet(stateset.get());}// 創(chuàng)建BillBoard對象1osg::ref_ptr<osg::Billboard> billboard1 = new osg::Billboard();// 設(shè)置旋轉(zhuǎn)模式為繞視點(diǎn)billboard1->setMode(osg::Billboard::POINT_ROT_EYE);// 添加Drawable,并設(shè)置其位置,默認(rèn)位置為osg::Vec3(0,0,0)billboard1->addDrawable(geometry.get(), osg::Vec3(5.0, 0.0, 0.0));//osg::ref_ptr<osg::Billboard> billboard2 = new osg::Billboard();osg::ref_ptr<osg::Group> billboard = new osg::Group();billboard->addChild(billboard1.get());return billboard.get();
}// 創(chuàng)建幀動畫
osg::ref_ptr<osg::Sequence> createSequence(const string &strDataFolder)
{// 創(chuàng)建幀動畫對象osg::ref_ptr<osg::Sequence> seq = new osg::Sequence();// 文件名向量對象typedef std::vector<string> Filenames;Filenames filenames;char name_count[256];for (int i = 0; i < 60; ++i){sprintf_s(name_count, "%sosgVR\\bz%d.jpg", strDataFolder.c_str(),i);filenames.push_back(name_count);}for (Filenames::iterator itr = filenames.begin(); itr != filenames.end(); ++itr){// 加載模型osg::Image *image = osgDB::readImageFile(*itr);if (image){// 添加子節(jié)點(diǎn)seq->addChild(createBillBoard(image));// 設(shè)定節(jié)點(diǎn)的持續(xù)時(shí)間seq->setTime(seq->getNumChildren() - 1, 0.1);}}// 設(shè)置幀動畫持續(xù)的時(shí)間seq->setInterval(osg::Sequence::LOOP, 0, -1);// 設(shè)置播放的速度及重復(fù)的次數(shù)seq->setDuration(1.0, -1);// 開始播放seq->setMode(osg::Sequence::START);return seq.get();
}
????????運(yùn)行程序,截圖如圖 11-8 所示
圖11-8自定義粒子系統(tǒng)示例(二)截圖