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/SmokeTrailEffect>
15 
16 #include <osgParticle/ConstantRateCounter>
17 #include <osgParticle/RadialShooter>
18 #include <osgParticle/SectorPlacer>
19 #include <osgParticle/ParticleSystemUpdater>
20 #include <osgParticle/ConnectedParticleSystem>
21 
22 #include <osg/Geode>
23 
24 using namespace osgParticle;
SmokeEffect(bool automaticSetup)25 
26 SmokeTrailEffect::SmokeTrailEffect(bool automaticSetup):
27     ParticleEffect(automaticSetup)
28 {
29     setDefaults();
30 
31     _position.set(0.0f,0.0f,0.0f);
32     _scale = 1.0f;
33     _intensity = 1.0f;
34 
35     _emitterDuration = 65.0;
36     _defaultParticleTemplate.setLifeTime(5.0*_scale);
37 
38     if (_automaticSetup) buildEffect();
39 }
SmokeEffect(const osg::Vec3 & position,float scale,float intensity)40 
41 SmokeTrailEffect::SmokeTrailEffect(const osg::Vec3& position, float scale, float intensity)
42 {
43     setDefaults();
44 
45     _position = position;
46     _scale = scale;
47     _intensity = intensity;
48 
49     _emitterDuration = 65.0;
50     _defaultParticleTemplate.setLifeTime(5.0*_scale);
51 
52     if (_automaticSetup) buildEffect();
53 }
SmokeEffect(const SmokeEffect & copy,const osg::CopyOp & copyop)54 
55 SmokeTrailEffect::SmokeTrailEffect(const SmokeTrailEffect& copy, const osg::CopyOp& copyop):
56     ParticleEffect(copy,copyop)
57 {
58     if (_automaticSetup) buildEffect();
59 }
setDefaults()60 
61 void SmokeTrailEffect::setDefaults()
62 {
63     ParticleEffect::setDefaults();
64 
65     _textureFileName = "Images/continous_smoke.rgb";
66     _emitterDuration = 65.0;
67 
68     // set up unit particle.
69     _defaultParticleTemplate.setLifeTime(5.0*_scale);
70     _defaultParticleTemplate.setSizeRange(osgParticle::rangef(0.75f, 2.0f));
71     _defaultParticleTemplate.setAlphaRange(osgParticle::rangef(0.7f, 1.0f));
72     _defaultParticleTemplate.setColorRange(osgParticle::rangev4(
73                                             osg::Vec4(1, 1.0f, 1.0f, 1.0f),
74                                             osg::Vec4(1, 1.0f, 1.f, 0.0f)));
75 
76 
77 }
setUpEmitterAndProgram()78 
79 void SmokeTrailEffect::setUpEmitterAndProgram()
80 {
81     // set up particle system
82     if (!_particleSystem)
83     {
84         _particleSystem = new osgParticle::ConnectedParticleSystem;
85     }
86 
87     if (_particleSystem.valid())
88     {
89         _particleSystem->setDefaultAttributes(_textureFileName, false, false);
90 
91         osgParticle::Particle& ptemplate = _particleSystem->getDefaultParticleTemplate();
92 
93         float radius = 0.5f*_scale;
94         float density = 1.0f; // 1.0kg/m^3
95 
96         ptemplate.setLifeTime(_defaultParticleTemplate.getLifeTime());
97 
98         // the following ranges set the envelope of the respective
99         // graphical properties in time.
100         ptemplate.setSizeRange(osgParticle::rangef(radius*_defaultParticleTemplate.getSizeRange().minimum,
101                                                    radius*_defaultParticleTemplate.getSizeRange().maximum));
102         ptemplate.setAlphaRange(_defaultParticleTemplate.getAlphaRange());
103         ptemplate.setColorRange(_defaultParticleTemplate.getColorRange());
104 
105         // these are physical properties of the particle
106         ptemplate.setRadius(radius);
107         ptemplate.setMass(density*radius*radius*radius*osg::PI*4.0f/3.0f);
108 
109     }
110 
111 
112     // set up emitter
113     if (!_emitter)
114     {
115         _emitter = new osgParticle::ModularEmitter;
116         _emitter->setCounter(new osgParticle::ConstantRateCounter);
117         _emitter->setPlacer(new osgParticle::SectorPlacer);
118         _emitter->setShooter(new osgParticle::RadialShooter);
119     }
120 
121     if (_emitter.valid())
122     {
123         _emitter->setParticleSystem(_particleSystem.get());
124         _emitter->setReferenceFrame(_useLocalParticleSystem?
125                                     osgParticle::ParticleProcessor::ABSOLUTE_RF:
126                                     osgParticle::ParticleProcessor::RELATIVE_RF);
127 
128         _emitter->setStartTime(_startTime);
129         _emitter->setLifeTime(_emitterDuration);
130         _emitter->setEndless(false);
131 
132         osgParticle::ConstantRateCounter* counter = dynamic_cast<osgParticle::ConstantRateCounter*>(_emitter->getCounter());
133         if (counter)
134         {
135             counter->setMinimumNumberOfParticlesToCreate(1);
136             counter->setNumberOfParticlesPerSecondToCreate(0.0);
137         }
138 
139         osgParticle::SectorPlacer* placer = dynamic_cast<osgParticle::SectorPlacer*>(_emitter->getPlacer());
140         if (placer)
141         {
142             placer->setCenter(_position);
143             placer->setRadiusRange(0.0f*_scale,0.0f*_scale);
144         }
145 
146         osgParticle::RadialShooter* shooter = dynamic_cast<osgParticle::RadialShooter*>(_emitter->getShooter());
147         if (shooter)
148         {
149             shooter->setThetaRange(0.0f, 0.0f);
150             shooter->setInitialSpeedRange(0.0f*_scale,0.0f*_scale);
151         }
152     }
153 
154     // set up program.
155     if (!_program)
156     {
157         _program = new osgParticle::FluidProgram;
158     }
159 
160     if (_program.valid())
161     {
162         _program->setParticleSystem(_particleSystem.get());
163         _program->setWind(_wind);
164     }
165 }
166