1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 #include <osgParticle/ExplosionEffect>
15 
16 #include <osgParticle/ExplosionEffect>
17 #include <osgParticle/ModularEmitter>
18 #include <osgParticle/ModularProgram>
19 #include <osgParticle/RandomRateCounter>
20 #include <osgParticle/SectorPlacer>
21 #include <osgParticle/RadialShooter>
22 #include <osgParticle/AccelOperator>
23 #include <osgParticle/FluidFrictionOperator>
24 #include <osgParticle/ParticleSystemUpdater>
25 
26 #include <osg/Geode>
27 
28 using namespace osgParticle;
29 
ExplosionEffect(bool automaticSetup)30 ExplosionEffect::ExplosionEffect(bool automaticSetup):
31     ParticleEffect(automaticSetup)
32 {
33     setDefaults();
34 
35     _position.set(0.0f,0.0f,0.0f);
36     _scale = 1.0f;
37     _intensity = 1.0f;
38 
39     _emitterDuration = 1.0;
40 
41     if (_automaticSetup) buildEffect();
42 }
43 
ExplosionEffect(const osg::Vec3 & position,float scale,float intensity)44 ExplosionEffect::ExplosionEffect(const osg::Vec3& position, float scale, float intensity)
45 {
46     setDefaults();
47 
48     _position = position;
49     _scale = scale;
50     _intensity = intensity;
51 
52     _emitterDuration = 1.0;
53 
54     if (_automaticSetup) buildEffect();
55 }
56 
ExplosionEffect(const ExplosionEffect & copy,const osg::CopyOp & copyop)57 ExplosionEffect::ExplosionEffect(const ExplosionEffect& copy, const osg::CopyOp& copyop):
58     ParticleEffect(copy,copyop)
59 {
60     if (_automaticSetup) buildEffect();
61 }
62 
setDefaults()63 void ExplosionEffect::setDefaults()
64 {
65     ParticleEffect::setDefaults();
66 
67     _textureFileName = "Images/smoke.rgb";
68     _emitterDuration = 1.0;
69 
70     // set up unit particle.
71     _defaultParticleTemplate.setLifeTime(0.5+0.1*_scale);
72     _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 3.0f));
73     _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.1f, 1.0f));
74     _defaultParticleTemplate.setColorRange(osgParticle::rangev4(
75                                             osg::Vec4(1.0f, 0.8f, 0.2f, 1.0f),
76                                             osg::Vec4(1.0f, 0.4f, 0.1f, 0.0f)));
77 
78 }
79 
80 
setUpEmitterAndProgram()81 void ExplosionEffect::setUpEmitterAndProgram()
82 {
83     // set up particle system
84     if (!_particleSystem)
85     {
86         _particleSystem = new osgParticle::ParticleSystem;
87     }
88 
89     if (_particleSystem.valid())
90     {
91         _particleSystem->setDefaultAttributes(_textureFileName, false, false);
92 
93         osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
94 
95         float radius = 0.4f*_scale;
96         float density = 1.2f; // 1.0kg/m^3
97 
98         ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
99 
100         // the following ranges set the envelope of the respective
101         // graphical properties in time.
102         ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
103                                                    radius*_defaultParticleTemplate.getSizeRange().maximum));
104         ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
105         ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
106 
107         // these are physical properties of the particle
108         ptemplate.setRadius(radius);
109         ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f);
110 
111     }
112 
113 
114     // set up emitter
115     if (!_emitter)
116     {
117         _emitter = new osgParticle::ModularEmitter;
118         _emitter->setCounter(new osgParticle::RandomRateCounter);
119         _emitter->setPlacer(new osgParticle::SectorPlacer);
120         _emitter->setShooter(new osgParticle::RadialShooter);
121     }
122 
123     if (_emitter.valid())
124     {
125         _emitter->setParticleSystem(_particleSystem.get());
126         _emitter->setReferenceFrame(_useLocalParticleSystem?
127                                     osgParticle::ParticleProcessor::ABSOLUTE_RF:
128                                     osgParticle::ParticleProcessor::RELATIVE_RF);
129 
130         _emitter->setStartTime(_startTime);
131         _emitter->setLifeTime(_emitterDuration);
132         _emitter->setEndless(false);
133 
134         osgParticle::RandomRateCounter* counter = dynamic_cast<osgParticle::RandomRateCounter*>(_emitter->getCounter());
135         if (counter)
136         {
137             counter->setRateRange(50*_intensity,100*_intensity);
138         }
139 
140         osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
141         if (placer)
142         {
143             placer->setCenter(_position);
144             placer->setRadiusRange(0.0f*_scale,0.25f*_scale);
145         }
146 
147         osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
148         if (shooter)
149         {
150             shooter->setThetaRange(0.0f, osg::PI_2);
151             shooter->setInitialSpeedRange(1.0f*_scale,10.0f*_scale);
152         }
153     }
154 
155     // set up the program
156     if (!_program)
157     {
158         _program = new osgParticle::FluidProgram;
159     }
160 
161     if (_program.valid())
162     {
163         _program->setParticleSystem(_particleSystem.get());
164         _program->setWind(_wind);
165     }
166 
167 }
168 
169