• OSG粒子系统特效-----雨雪、爆炸、烟雾


    1、烟雾效果

    飞机坠毁飞机坠毁
    在这里插入图片描述
    陨石坠落

    源码:

    // CMyOSGParticle.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include  //事件监听
    #include  //事件响应类,对渲染状态进行控制
    #include  //简化几何体
    
    #include 
    #include 
    
    #include 
    #include 
    #include < osgParticle/RandomRateCounter>
    #include 
    #include 
    #include 
    #include 
    #include < osgParticle/ModularProgram>
    
    
    #pragma comment(lib, "OpenThreadsd.lib")
    #pragma comment(lib, "osgd.lib")
    #pragma comment(lib, "osgDBd.lib")
    #pragma comment(lib, "osgUtild.lib")
    #pragma comment(lib, "osgGAd.lib")
    #pragma comment(lib, "osgViewerd.lib")
    #pragma comment(lib, "osgTextd.lib")
    #pragma comment(lib, "osgParticled.lib")
    
    //创建火球(燃烧)
    void createFireBall(osg::MatrixTransform* smokeNode)
    {
    	// 创建粒子对象,设置其属性并交由粒子系统使用。
    	osgParticle::Particle particleTempalte;
    	particleTempalte.setShape(osgParticle::Particle::QUAD);
    	particleTempalte.setLifeTime(1.5); // 单位:秒
    	particleTempalte.setSizeRange(osgParticle::rangef(3.0f, 1.0f)); // 单位:米
    	particleTempalte.setAlphaRange(osgParticle::rangef(1, 0));
    	particleTempalte.setColorRange(osgParticle::rangev4(osg::Vec4(1.0f, 0.2f, 0.0f, 1.0f),//0.1f,0.3f,0.4f,1.0f
    		osg::Vec4(0.1f, 0.1f, 0.1f, 0)//0.95f,0.75f,0,1(1,1,1,1)
    	));
    	particleTempalte.setPosition(osg::Vec3(0.0f, 0.0f, 0.0f));
    	particleTempalte.setVelocity(osg::Vec3(0.0f, 0.0f, 0.0f));
    	particleTempalte.setMass(0.1f); //单位:千克
    	particleTempalte.setRadius(0.2f);
    	particleTempalte.setSizeInterpolator(new osgParticle::LinearInterpolator);
    	particleTempalte.setAlphaInterpolator(new osgParticle::LinearInterpolator);
    	particleTempalte.setColorInterpolator(new osgParticle::LinearInterpolator);
    	// 创建并初始化粒子系统。
    	osgParticle::ParticleSystem* particleSystem = new osgParticle::ParticleSystem;
    	particleSystem->setDataVariance(osg::Node::STATIC);
    	// 设置材质,是否放射粒子,以及是否使用光照。
    	particleSystem->setDefaultAttributes("D:\\data\\Images\\smoke.rgb", true, false);
    	osg::Geode* geode = new osg::Geode;
    	geode->addDrawable(particleSystem);
    	smokeNode->addChild(geode);
    	//设置为粒子系统的缺省粒子对象。
    	particleSystem->setDefaultParticleTemplate(particleTempalte);
    	//获取放射极中缺省计数器的句柄,调整每帧增加的新粒子数目
    	osgParticle::RandomRateCounter* particleGenerateRate = new osgParticle::RandomRateCounter();
    	particleGenerateRate->setRateRange(30, 50);
    	// 每秒新生成的粒子范围
    	particleGenerateRate->setDataVariance(osg::Node::DYNAMIC);
    	// 自定义一个放置器,这里创建并初始化一个点放置器
    	osgParticle::PointPlacer* particlePlacer = new osgParticle::PointPlacer;
    	particlePlacer->setCenter(osg::Vec3(0.0f, 0.0f, 0.0f));
    	particlePlacer->setDataVariance(osg::Node::DYNAMIC);
    	// 自定义一个弧度发射器
    	osgParticle::RadialShooter* particleShooter = new osgParticle::RadialShooter;
    	// 设置发射器的属性
    	particleShooter->setDataVariance(osg::Node::DYNAMIC);
    	particleShooter->setThetaRange(-0.1f, 0.1f);
    	// 弧度值,与Z 轴夹角
    	particleShooter->setPhiRange(-0.1f, 0.1f);
    	particleShooter->setInitialSpeedRange(5, 7.5f);//单位:米/秒
    												   //创建标准放射极对象
    	osgParticle::ModularEmitter* emitter = new osgParticle::ModularEmitter;
    	emitter->setDataVariance(osg::Node::DYNAMIC);
    	emitter->setCullingActive(false);
    	// 将放射极对象与粒子系统关联。
    	emitter->setParticleSystem(particleSystem);
    	// 设置计数器
    	emitter->setCounter(particleGenerateRate);
    	// 设置放置器
    	emitter->setPlacer(particlePlacer);
    	// 设置发射器
    	emitter->setShooter(particleShooter);
    	// 把放射极添加为变换节点
    	smokeNode->addChild(emitter);
    	// 添加更新器,以实现每帧的粒子管理。
    	osgParticle::ParticleSystemUpdater* particleSystemUpdater = new osgParticle::ParticleSystemUpdater;
    	// 将更新器与粒子系统对象关联。
    	particleSystemUpdater->addParticleSystem(particleSystem);
    	// 将更新器节点添加到场景中。
    	smokeNode->addChild(particleSystemUpdater);
    	// 创建标准编程器对象并与粒子系统相关联。
    	osgParticle::ModularProgram* particleMoveProgram = new osgParticle::ModularProgram;
    	particleMoveProgram->setParticleSystem(particleSystem);
    	// 最后,将编程器添加到场景中。
    	smokeNode->addChild(particleMoveProgram);
    }
    
    //创建浓烟
    void createDarkSmoke(osg::MatrixTransform* smokeNode)
    {
    	// 创建粒子对象,设置其属性并交由粒子系统使用。
    	osgParticle::Particle particleTempalte;
    	particleTempalte.setShape(osgParticle::Particle::QUAD);
    	particleTempalte.setLifeTime(10); // 单位:秒
    	particleTempalte.setSizeRange(osgParticle::rangef(1.0f, 12.0f)); // 单位:米
    	particleTempalte.setAlphaRange(osgParticle::rangef(1, 0));
    	particleTempalte.setColorRange(osgParticle::rangev4(
    		osg::Vec4(0.0f, 0.0f, 0.0f, 0.5f),//(0.1f,0.1f,0.1f,0.5f)
    		osg::Vec4(0.5f, 0.5f, 0.5f, 1.5f)//0.95f,0.75f,0,1
    	));
    	particleTempalte.setPosition(osg::Vec3(0.0f, 0.0f, 0.0f));
    	particleTempalte.setVelocity(osg::Vec3(0.0f, 0.0f, 0.0f));
    	particleTempalte.setMass(0.1f); //单位:千克
    	particleTempalte.setRadius(0.2f);
    	particleTempalte.setSizeInterpolator(new osgParticle::LinearInterpolator);
    	particleTempalte.setAlphaInterpolator(new osgParticle::LinearInterpolator);
    	particleTempalte.setColorInterpolator(new osgParticle::LinearInterpolator);
    	// 创建并初始化粒子系统。
    	osgParticle::ParticleSystem* particleSystem = new osgParticle::ParticleSystem;
    	particleSystem->setDataVariance(osg::Node::STATIC);
    	// 设置材质,是否放射粒子,以及是否使用光照。
    	particleSystem->setDefaultAttributes("D:\\data\\Images\\smoke.rgb", false, false);
    	osg::Geode* geode = new osg::Geode;
    	geode->addDrawable(particleSystem);
    	smokeNode->addChild(geode);
    	//设置为粒子系统的缺省粒子对象。
    	particleSystem->setDefaultParticleTemplate(particleTempalte);
    	//获取放射极中缺省计数器的句柄,调整每帧增加的新粒
    	//子数目
    	osgParticle::RandomRateCounter* particleGenerateRate = new osgParticle::RandomRateCounter();
    	particleGenerateRate->setRateRange(30, 50);
    	// 每秒新生成的粒子范围
    	particleGenerateRate->setDataVariance(osg::Node::DYNAMIC);
    	// 自定义一个放置器,这里我们创建并初始化一个点放置器
    	osgParticle::PointPlacer* particlePlacer = new osgParticle::PointPlacer;
    	particlePlacer->setCenter(osg::Vec3(0.0f, 0.0f, 0.05f));
    	particlePlacer->setDataVariance(osg::Node::DYNAMIC);
    	// 自定义一个弧度发射器
    	osgParticle::RadialShooter* particleShooter = new osgParticle::RadialShooter;
    	// 设置发射器的属性
    	particleShooter->setDataVariance(osg::Node::DYNAMIC);
    	particleShooter->setThetaRange(-0.1f, 0.1f);
    	// 弧度值,与Z 轴夹角0.392699f
    	particleShooter->setPhiRange(-0.1f, 0.1f);
    	particleShooter->setInitialSpeedRange(10, 15);
    	//单位:米/秒
    	//创建标准放射极对象
    	osgParticle::ModularEmitter* emitter = new osgParticle::
    		ModularEmitter;
    	emitter->setDataVariance(osg::Node::DYNAMIC);
    	emitter->setCullingActive(false);
    	// 将放射极对象与粒子系统关联。
    	emitter->setParticleSystem(particleSystem);
    	// 设置计数器
    	emitter->setCounter(particleGenerateRate);
    	// 设置放置器
    	emitter->setPlacer(particlePlacer);
    	// 设置发射器
    	emitter->setShooter(particleShooter);
    	// 把放射极添加为变换节点
    	smokeNode->addChild(emitter);
    	// 添加更新器,以实现每帧的粒子管理。
    	osgParticle::ParticleSystemUpdater* particleSystemUpdater = new osgParticle::ParticleSystemUpdater;
    	// 将更新器与粒子系统对象关联。
    	particleSystemUpdater->addParticleSystem(particleSystem);
    	// 将更新器节点添加到场景中。
    	smokeNode->addChild(particleSystemUpdater);
    	osgParticle::ModularProgram* particleMoveProgram = new osgParticle::ModularProgram;
    	particleMoveProgram->setParticleSystem(particleSystem);
    	// 最后,将编程器添加到场景中。
    	smokeNode->addChild(particleMoveProgram);
    }
    
    void WriteFireballAndSmoke()
    {
    	osg::ref_ptr<osg::Group> root = new osg::Group();
    	osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
    	root->addChild(flightTransform);
    	//引擎烟雾
    	osg::MatrixTransform* fireballAndSmoke = new osg::MatrixTransform();
    	createFireBall(fireballAndSmoke);
    
    	fireballAndSmoke->setMatrix(osg::Matrix::rotate(-osg::PI / 2, 1, 0, 0) * osg::Matrix::translate(-8, -10, -3));
    	flightTransform->addChild(fireballAndSmoke);
    	createDarkSmoke(fireballAndSmoke);
    
    	osgDB::writeNodeFile(*(root.get()), "D:\\data\\Images\\MyScene.osg");
    }
    
    void ReadFireballAndSmoke()
    {
    	osg::ref_ptr<osg::Group> root = new osg::Group();
    	osg::Node* flightNode = osgDB::readNodeFile("D:\\data\\Images\\MyScene.osg");
    	if (!flightNode)
    	{
    		return;
    	}
    	osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
    	flightTransform->addChild(flightNode);
    	root->addChild(flightTransform);
    	osgViewer::Viewer viewer;
    
    	osgUtil::Simplifier simplifier(0.3f, 4.0f);
    	osgUtil::Optimizer optimzer;
    
    	optimzer.optimize(root.get());
    	viewer.setSceneData(root.get());
    
    	//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
    	viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
    
    	//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
    	viewer.addEventHandler(new osgViewer::WindowSizeHandler);
    
    	//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
    	viewer.addEventHandler(new osgViewer::StatsHandler);
    	viewer.realize();
    	viewer.run();
    }
    
    //陨石坠落
    //int main()
    //{
    //	WriteFireballAndSmoke();
    //	ReadFireballAndSmoke();
    //
    //	return 0;
    //}
    
    int main()
    {
    	osg::ref_ptr<osg::Group> root = new osg::Group();
    	osg::Node* flightNode = osgDB::readNodeFile("D:\\data\\cessna.osgt");//需要经模型放在项目根目录下(而不是在cpp所在目录)
    	if (!flightNode)
    	{
    		return -1;
    	}
    	//飞机变换节点
    	osg::MatrixTransform* flightTransform = new osg::MatrixTransform();
    	flightTransform->addChild(flightNode);
    	root->addChild(flightTransform);
    	//引擎烟雾
    	osg::MatrixTransform* fireballAndSmoke = new osg::MatrixTransform();
    	createFireBall(fireballAndSmoke);
    
    	fireballAndSmoke->setMatrix(osg::Matrix::rotate(-osg::PI / 2, 1, 0, 0) * osg::Matrix::translate(-8, -10, -3));
    	flightTransform->addChild(fireballAndSmoke);
    	createDarkSmoke(fireballAndSmoke);
    	osgViewer::Viewer viewer;
    
    	osgUtil::Simplifier simplifier(0.3f, 4.0f);
    	osgUtil::Optimizer optimzer;
    
    	optimzer.optimize(root.get());
    	viewer.setSceneData(root.get());
    
    	//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
    	viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
    
    	//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
    	viewer.addEventHandler(new osgViewer::WindowSizeHandler);
    
    	//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
    	viewer.addEventHandler(new osgViewer::StatsHandler);
    
    	viewer.realize();
    	viewer.run();
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294

    2、爆炸效果

    #include 
    #include 
    #include 
    #include 
    #include 
    
    //创建爆炸效果
    osg::ref_ptr<osg::Node> createExplode()
    {
    	osg::ref_ptr<osg::Group> explode = new osg::Group();
    	//风向
    	osg::Vec3 wind(1.0f, 0.0f, 0.0f);
    	osg::Vec3 position(0.0f, 0.0f, -1.0f);
    	//爆炸模拟,10.0f为缩放比,默认为1.0f,不缩放
    	osg::ref_ptr<osgParticle::ExplosionEffect> explosion = new osgParticle::ExplosionEffect(position, 10.0f);
    	osg::ref_ptr<osgParticle::ExplosionDebrisEffect> explosionDebri =
    		new osgParticle::ExplosionDebrisEffect(position, 10.0f);
    	//烟模拟
    	osg::ref_ptr<osgParticle::SmokeEffect> smoke = new osgParticle::SmokeEffect(position, 10.0f);
    	//火焰模拟
    	osg::ref_ptr<osgParticle::FireEffect> fire = new osgParticle::FireEffect(position, 10.0f);
    	//设置风向
    	explosion->setWind(wind);
    	explosionDebri->setWind(wind);
    	smoke->setWind(wind);
    	fire->setWind(wind);
    
    	//添加子节点
    	explode->addChild(explosion.get());
    	explode->addChild(explosionDebri.get());
    	explode->addChild(smoke.get());
    	explode->addChild(fire.get());
    	return explode.get();
    }
    
    int main()
    {
    	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    	osg::ref_ptr<osg::Group> root = new osg::Group();
    	//添加爆炸效果
    	root->addChild(createExplode());
    	//优化场景数据
    	osgUtil::Optimizer optimizer;
    	optimizer.optimize(root.get());
    	//设置场景数据
    	viewer->setSceneData(root.get());
    	//初始化并创建窗口
    	viewer->realize();
    	//viewer->setUpViewInWindow(200, 200, 800, 800);
    	viewer->run();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    3、雨雪效果

    在这里插入图片描述
    源码:

    #include 
    void main() 
    {
    	osgViewer::Viewer viewer;
    
    	//设置雪花类
    	osg::ref_ptr<osgParticle::PrecipitationEffect> precipitationEffect = new osgParticle::PrecipitationEffect;
    
    	//设置雪花浓度
    	precipitationEffect->snow(0.5);
    
    	//设置雪花颜色 
    	precipitationEffect->setParticleColor(osg::Vec4(1, 1, 1, 1));
    
    	//设置风向
    	precipitationEffect->setWind(osg::Vec3(2, 0, 0));
    
    	osg::ref_ptr <osg::Group> pRoot = new osg::Group();
    
    	//把雪花加入到场景结点
    	pRoot->addChild(precipitationEffect.get());
    	osg::ref_ptr<osg::Node> glider = osgDB::readNodeFile("D:\\data\\cessna.osgt");
    	pRoot->addChild(glider.get());
    	viewer.setSceneData(pRoot);
    
    	//添加一个事件句柄 相当于添加一个响应 响应鼠标或是键盘 响应L键(控制灯光开关)
    	viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
    
    	//窗口大小变化事件 添加窗口大小改变的句柄 这里响应的是F键
    	viewer.addEventHandler(new osgViewer::WindowSizeHandler);
    
    	//添加一些常用状态设置  添加常用的状态操作,这里会响应S键、W键等等 
    	viewer.addEventHandler(new osgViewer::StatsHandler);
    
    	viewer.realize();
    	viewer.run();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    交通地理信息系统实习教程(二)
    算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
    C++11的std::function和std::bind用法
    uni.createInnerAudioContext`在ios手机无法自动播放,可通过`jweixin-module`来解决
    朋友圈大佬都去读研了,这份备考书单我码住了
    实习面试复习
    【分布式】Rabbitmq死信队列模型、实战场景---订单延迟30min支付处理
    如何使用AI图片清晰度增强器软件增强和锐化图片、提高照片清晰度并去除噪点
    草莓熊python turtle绘图代码
    【批处理DOS-CMD命令-汇总和小结】-字符串搜索命令(find、findstr),Find和findstr的区别和辨析
  • 原文地址:https://blog.csdn.net/m0_37251750/article/details/133916634