1 // particles.hxx - classes to manage particles
2 // Copyright (C) 2008 Tiago Gusmão
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License as
6 // published by the Free Software Foundation; either version 2 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #ifndef _SG_PARTICLES_HXX
20 #define _SG_PARTICLES_HXX 1
22 #include <osg/ref_ptr>
25 #include <osg/NodeVisitor>
26 #include <osg/Texture2D>
27 #include <osgParticle/SmokeTrailEffect>
28 #include <osgParticle/Particle>
29 #include <osgParticle/ModularEmitter>
30 #include <osgParticle/ParticleSystemUpdater>
31 #include <osgParticle/ParticleSystem>
32 #include <osg/MatrixTransform>
33 #include <osgDB/ReaderWriter>
34 #include <osgDB/FileNameUtils>
35 #include <osgDB/FileUtils>
36 #include <osgDB/ReadFile>
41 #include <simgear/scene/util/SGNodeMasks.hxx>
42 #include <simgear/props/props.hxx>
43 #include <simgear/props/condition.hxx>
44 #include <simgear/structure/SGExpression.hxx>
45 #include <simgear/math/SGQuat.hxx>
46 #include <simgear/math/SGMatrix.hxx>
49 // Has anyone done anything *really* stupid, like making min and max macros?
57 #include "animation.hxx"
62 class GlobalParticleCallback : public osg::NodeCallback
65 GlobalParticleCallback(const SGPropertyNode* modelRoot)
67 this->modelRoot=modelRoot;
70 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
72 static const osg::Vec3 &getGravityVector()
77 static const osg::Vec3 &getWindVector()
83 static osg::Vec3 gravity;
84 static osg::Vec3 wind;
87 const SGPropertyNode* modelRoot;
92 class Particles : public osg::NodeCallback
107 memset(colorComponents, 0, sizeof(colorComponents));
110 static osg::Group * appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::ReaderWriter::Options* options);
112 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
114 void setupShooterSpeedData(const SGPropertyNode* configNode,
115 SGPropertyNode* modelRoot)
117 shooterValue = read_value(configNode, modelRoot, "-m",
118 -SGLimitsd::max(), SGLimitsd::max());
120 SG_LOG(SG_GENERAL, SG_ALERT, "shooter property error!\n");
122 shooterExtraRange = configNode->getFloatValue("extrarange",0);
125 void setupCounterData(const SGPropertyNode* configNode,
126 SGPropertyNode* modelRoot)
128 counterValue = read_value(configNode, modelRoot, "-m",
129 -SGLimitsd::max(), SGLimitsd::max());
131 SG_LOG(SG_GENERAL, SG_ALERT, "counter property error!\n");
133 counterExtraRange = configNode->getFloatValue("extrarange",0);
136 void setupCounterCondition(const SGPropertyNode* configNode,
137 SGPropertyNode* modelRoot)
139 counterCond = sgReadCondition(modelRoot, configNode);
142 void setupCounterCondition(float counterStaticValue,
143 float counterStaticExtraRange)
145 this->counterStaticValue = counterStaticValue;
146 this->counterStaticExtraRange = counterStaticExtraRange;
149 void setupStartSizeData(const SGPropertyNode* configNode,
150 SGPropertyNode* modelRoot)
152 startSizeValue = read_value(configNode, modelRoot, "-m",
153 -SGLimitsd::max(), SGLimitsd::max());
156 SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
160 void setupEndSizeData(const SGPropertyNode* configNode,
161 SGPropertyNode* modelRoot)
163 endSizeValue = read_value(configNode, modelRoot, "-m",
164 -SGLimitsd::max(), SGLimitsd::max());
166 SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
170 void setupLifeData(const SGPropertyNode* configNode,
171 SGPropertyNode* modelRoot)
173 lifeValue = read_value(configNode, modelRoot, "-m",
174 -SGLimitsd::max(), SGLimitsd::max());
176 SG_LOG(SG_GENERAL, SG_ALERT, "lifeValue error!\n");
180 void setupStaticSizeData(float startSize, float endSize)
182 this->startSize=startSize;
183 this->endSize=endSize;
187 void setGeneralData(osgParticle::RadialShooter* shooter,
188 osgParticle::RandomRateCounter* counter,
189 osgParticle::ParticleSystem* particleSys,
190 osgParticle::FluidProgram* program)
192 this->shooter = shooter;
193 this->counter = counter;
194 this->particleSys = particleSys;
195 this->program = program;
198 void setupProgramGravity(bool useGravity)
200 this->useGravity = useGravity;
203 void setupProgramWind(bool useWind)
205 this->useWind = useWind;
208 //component: r=0, g=1, ... ; color: 0=start color, 1=end color
209 void setupColorComponent(const SGPropertyNode* configNode,
210 SGPropertyNode* modelRoot, int color,
213 SGExpressiond *colorValue = read_value(configNode, modelRoot, "-m",
217 SG_LOG(SG_GENERAL, SG_ALERT, "color property error!\n");
219 colorComponents[(color*4)+component] = colorValue;
220 //number of color components = 4
223 void setupStaticColorComponent(float r1,float g1, float b1, float a1,
224 float r2, float g2, float b2, float a2)
226 staticColorComponents[0] = r1;
227 staticColorComponents[1] = g1;
228 staticColorComponents[2] = b1;
229 staticColorComponents[3] = a1;
230 staticColorComponents[4] = r2;
231 staticColorComponents[5] = g2;
232 staticColorComponents[6] = b2;
233 staticColorComponents[7] = a2;
236 static osg::Group * getCommonRoot()
238 if(!commonRoot.valid())
240 SG_LOG(SG_GENERAL, SG_DEBUG, "Particle common root called!\n");
241 commonRoot = new osg::Group;
242 commonRoot.get()->setName("common particle system root");
243 commonGeode.get()->setName("common particle system geode");
244 commonRoot.get()->addChild(commonGeode.get());
245 commonRoot.get()->addChild(psu.get());
247 return commonRoot.get();
250 static osg::Geode * getCommonGeode()
252 return commonGeode.get();
255 static osgParticle::ParticleSystemUpdater * getPSU()
261 float shooterExtraRange;
262 float counterExtraRange;
263 SGExpressiond* shooterValue;
264 SGExpressiond* counterValue;
265 SGExpressiond* colorComponents[8];
266 SGExpressiond* startSizeValue;
267 SGExpressiond* endSizeValue;
268 SGExpressiond* lifeValue;
269 SGCondition* counterCond;
270 osg::MatrixTransform* refFrame;
271 float staticColorComponents[8];
274 float counterStaticValue;
275 float counterStaticExtraRange;
276 osgParticle::RadialShooter* shooter;
277 osgParticle::RandomRateCounter* counter;
278 osgParticle::ParticleSystem* particleSys;
279 osgParticle::FluidProgram* program;
282 static osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu;
283 static osg::ref_ptr<osg::Group> commonRoot;
284 static osg::ref_ptr<osg::Geode> commonGeode;
291 class CustomModularEmitter : public osgParticle::ModularEmitter, public osg::Observer
295 virtual void objectDeleted (void *)
297 SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
299 SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
300 SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
304 // ~CustomModularEmitter()
306 // SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
308 // SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
309 // SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());