自定义粒子系统示例(二)
目前自定义粒子的方法有很多,在OSG 中使用的是 Billboard 技术与色彩融合技术。色彩融合是一种高级的渲染技术,如果读者有兴趣,可参看 OSG 粒子系统实现的源代码。这里采用简单的布告牌技术(osg::Billboard)与动画来实现。这种方法也可以生成比较好的粒子系统的效果。最好使用同名的贴图,示例中并没有对这些贴图进行处理,它只是向读者展示如何模拟一个自定义的粒子系统,读者可仔细体会。
自定义粒子系统示例(二)的代码如程序清单11-6所示。
/* 自定义粒子系统示例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());
// 优化场景数据
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)
{
// 创建四边形
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
// 设置顶点
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());
// 设置法线
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);
// 设置纹理坐标
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();
// 创建一个Texture2D属性对象
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();
// 关联image
texture->setImage(image.get());
// 关联Texture2D纹理对象,第三个参数默认为ON
stateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);
// 启用混合
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
// 关闭光照
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
geometry->setStateSet(stateset.get());
}
// 创建BillBoard对象1
osg::ref_ptr<osg::Billboard> billboard1 = new osg::Billboard();
// 设置旋转模式为绕视点
billboard1->setMode(osg::Billboard::POINT_ROT_EYE);
// 添加Drawable,并设置其位置,默认位置为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();
}
// 创建帧动画
osg::ref_ptr<osg::Sequence> createSequence(const string &strDataFolder)
{
// 创建帧动画对象
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)
{
// 添加子节点
seq->addChild(createBillBoard(image));
// 设定节点的持续时间
seq->setTime(seq->getNumChildren() - 1, 0.1);
}
}
// 设置帧动画持续的时间
seq->setInterval(osg::Sequence::LOOP, 0, -1);
// 设置播放的速度及重复的次数
seq->setDuration(1.0, -1);
// 开始播放
seq->setMode(osg::Sequence::START);
return seq.get();
}
运行程序,截图如图 11-8 所示
图11-8自定义粒子系统示例(二)截图