]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/particles.hxx
Cleanup of particles contribution
[simgear.git] / simgear / scene / model / particles.hxx
1 // particles.hxx - classes to manage particles
2 // Copyright (C) 2008 Tiago Gusmão
3 //
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.
8 //
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.
13 //
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.
17 //
18
19 #ifndef _SG_PARTICLES_HXX
20 #define _SG_PARTICLES_HXX 1
21
22 #include <osg/ref_ptr>
23 #include <osg/Group>
24 #include <osg/Node>
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>
37 #include <osg/Notify>
38 #include <osg/Vec3>
39
40
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>
47
48
49 // Has anyone done anything *really* stupid, like making min and max macros?
50 #ifdef min
51 #undef min
52 #endif
53 #ifdef max
54 #undef max
55 #endif
56
57 #include "animation.hxx"
58
59 namespace simgear
60 {
61
62 class GlobalParticleCallback : public osg::NodeCallback 
63 {
64 public:
65     GlobalParticleCallback(const SGPropertyNode* modelRoot) 
66     {
67         this->modelRoot=modelRoot;
68     }
69
70     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
71     
72     static const osg::Vec3 &getGravityVector()
73     {
74         return gravity;
75     }
76
77     static const osg::Vec3 &getWindVector()
78     {
79         return wind;
80     }
81
82
83     static osg::Vec3 gravity;
84     static osg::Vec3 wind;
85 private:
86
87     const SGPropertyNode* modelRoot;
88 };
89
90
91
92 class Particles : public osg::NodeCallback 
93 {
94 public:
95     Particles() : 
96         shooterValue(NULL),
97         counterValue(NULL),
98         startSizeValue(NULL),
99         endSizeValue(NULL),
100         lifeValue(NULL),
101         refFrame(NULL),
102         program(NULL),
103         useGravity(false),
104         useWind(false),
105         counterCond(NULL)
106     {
107         memset(colorComponents, 0, sizeof(colorComponents));
108     }
109
110     static osg::Group * appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::ReaderWriter::Options* options);
111
112     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
113
114     void setupShooterSpeedData(const SGPropertyNode* configNode,
115                                SGPropertyNode* modelRoot)
116     {
117         shooterValue = read_value(configNode, modelRoot, "-m",
118                                   -SGLimitsd::max(), SGLimitsd::max());
119         if(!shooterValue){
120             SG_LOG(SG_GENERAL, SG_ALERT, "shooter property error!\n");
121         }
122         shooterExtraRange = configNode->getFloatValue("extrarange",0);
123     }
124
125     void setupCounterData(const SGPropertyNode* configNode,
126                           SGPropertyNode* modelRoot)
127     {
128         counterValue = read_value(configNode, modelRoot, "-m",
129                                   -SGLimitsd::max(), SGLimitsd::max());
130         if(!counterValue){
131             SG_LOG(SG_GENERAL, SG_ALERT, "counter property error!\n");
132         }
133         counterExtraRange = configNode->getFloatValue("extrarange",0);
134     }
135
136     void setupCounterCondition(const SGPropertyNode* configNode,
137                                SGPropertyNode* modelRoot)
138     {
139         counterCond = sgReadCondition(modelRoot, configNode);
140     }
141
142     void setupCounterCondition(float counterStaticValue,
143                                float counterStaticExtraRange)
144     {
145         this->counterStaticValue = counterStaticValue;
146         this->counterStaticExtraRange = counterStaticExtraRange;
147     }
148
149     void setupStartSizeData(const SGPropertyNode* configNode,
150                             SGPropertyNode* modelRoot)
151     {
152         startSizeValue = read_value(configNode, modelRoot, "-m",
153                                     -SGLimitsd::max(), SGLimitsd::max());
154         if(!startSizeValue) 
155         {
156             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
157         }
158     }
159
160     void setupEndSizeData(const SGPropertyNode* configNode,
161                           SGPropertyNode* modelRoot)
162     {
163         endSizeValue = read_value(configNode, modelRoot, "-m",
164                                   -SGLimitsd::max(), SGLimitsd::max());
165         if(!endSizeValue){
166             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
167         }
168     }
169
170     void setupLifeData(const SGPropertyNode* configNode,
171                        SGPropertyNode* modelRoot)
172     {
173         lifeValue = read_value(configNode, modelRoot, "-m",
174                                -SGLimitsd::max(), SGLimitsd::max());
175         if(!lifeValue){
176             SG_LOG(SG_GENERAL, SG_ALERT, "lifeValue error!\n");
177         }
178     }
179
180     void setupStaticSizeData(float startSize, float endSize)
181     {
182         this->startSize=startSize;
183         this->endSize=endSize;
184     }
185
186
187     void setGeneralData(osgParticle::RadialShooter* shooter,
188                         osgParticle::RandomRateCounter* counter,
189                         osgParticle::ParticleSystem* particleSys,
190                         osgParticle::FluidProgram* program)
191     {
192         this->shooter = shooter;
193         this->counter = counter;
194         this->particleSys = particleSys;
195         this->program = program;
196     }
197
198     void setupProgramGravity(bool useGravity)
199     {
200         this->useGravity = useGravity;
201     }
202
203     void setupProgramWind(bool useWind)
204     {
205         this->useWind = useWind;
206     }
207
208     //component: r=0, g=1, ... ; color: 0=start color, 1=end color
209     void setupColorComponent(const SGPropertyNode* configNode,
210                              SGPropertyNode* modelRoot, int color,
211                              int component)
212     {
213         SGExpressiond *colorValue = read_value(configNode, modelRoot, "-m",
214                                                -SGLimitsd::max(),
215                                                SGLimitsd::max());
216         if(!colorValue){
217             SG_LOG(SG_GENERAL, SG_ALERT, "color property error!\n");
218         }
219         colorComponents[(color*4)+component] = colorValue;
220         //number of color components = 4
221     }
222
223     void setupStaticColorComponent(float r1,float g1, float b1, float a1,
224                                    float r2, float g2, float b2, float a2)
225     {
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;
234     }
235
236     static osg::Group * getCommonRoot()
237     {
238         if(!commonRoot.valid())
239         {
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());
246         }
247         return commonRoot.get();
248     }
249
250     static osg::Geode * getCommonGeode()
251     {
252         return commonGeode.get();
253     }
254
255     static osgParticle::ParticleSystemUpdater * getPSU()
256     {
257         return psu.get();
258     }
259
260 protected:
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];
272     float startSize;
273     float endSize;
274     float counterStaticValue;
275     float counterStaticExtraRange;
276     osgParticle::RadialShooter* shooter;
277     osgParticle::RandomRateCounter* counter;
278     osgParticle::ParticleSystem* particleSys;
279     osgParticle::FluidProgram* program;
280     bool useGravity;
281     bool useWind;
282     static osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu;
283     static osg::ref_ptr<osg::Group> commonRoot;
284     static osg::ref_ptr<osg::Geode> commonGeode;
285 };
286 }
287 #endif
288
289
290 /*
291 class CustomModularEmitter : public osgParticle::ModularEmitter, public osg::Observer
292 {
293 public:
294
295 virtual void objectDeleted (void *)
296 {
297 SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
298
299 SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
300 SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
301 }
302
303
304 //   ~CustomModularEmitter()
305 //   {
306 //     SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
307 //     
308 //     SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
309 //     SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
310 //   }
311 };
312 */