]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/particles.hxx
Add preliminary spot light animation
[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 <osgParticle/SmokeTrailEffect>
24 #include <osgParticle/Particle>
25 #include <osgParticle/ModularEmitter>
26 #include <osgDB/ReaderWriter>
27 #include <osgDB/FileNameUtils>
28 #include <osgDB/FileUtils>
29 #include <osgDB/ReadFile>
30 #include <osg/Notify>
31 #include <osg/Vec3>
32
33 namespace osg
34 {
35 class Group;
36 class MatrixTransform;
37 class Node;
38 class NodeVisitor;
39 }
40
41 namespace osgParticle
42 {
43 class ParticleSystem;
44 class ParticleSystemUpdater;
45 }
46
47 #include <simgear/scene/util/SGNodeMasks.hxx>
48 #include <simgear/props/props.hxx>
49 #include <simgear/props/condition.hxx>
50 #include <simgear/structure/SGExpression.hxx>
51 #include <simgear/structure/SGSharedPtr.hxx>
52 #include <simgear/math/SGQuat.hxx>
53 #include <simgear/math/SGMatrix.hxx>
54
55
56 // Has anyone done anything *really* stupid, like making min and max macros?
57 #ifdef min
58 #undef min
59 #endif
60 #ifdef max
61 #undef max
62 #endif
63
64 #include "animation.hxx"
65
66 namespace simgear
67 {
68
69 class GlobalParticleCallback : public osg::NodeCallback 
70 {
71 public:
72     GlobalParticleCallback(const SGPropertyNode* modelRoot) 
73     {
74         this->modelRoot=modelRoot;
75     }
76
77     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
78
79     static const osg::Vec3 &getGravityVector()
80     {
81         return gravity;
82     }
83
84     static const osg::Vec3 &getWindVector()
85     {
86         return wind;
87     }
88
89     static void setSwitch(const SGPropertyNode* n)
90     {
91         enabledNode = n;
92     }
93
94     static bool getEnabled()
95     {
96         return enabled;
97     }
98
99 private:
100     static osg::Vec3 gravity;
101     static osg::Vec3 wind;
102     SGConstPropertyNode_ptr modelRoot;
103     static SGConstPropertyNode_ptr enabledNode;
104     static bool enabled;
105 };
106
107
108
109 class Particles : public osg::NodeCallback 
110 {
111 public:
112     Particles();
113
114     static osg::Group * appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::Options* options);
115
116     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
117
118     void setupShooterSpeedData(const SGPropertyNode* configNode,
119                                SGPropertyNode* modelRoot)
120     {
121         shooterValue = read_value(configNode, modelRoot, "-m",
122                                   -SGLimitsd::max(), SGLimitsd::max());
123         if(!shooterValue){
124             SG_LOG(SG_GENERAL, SG_ALERT, "shooter property error!\n");
125         }
126         shooterExtraRange = configNode->getFloatValue("extrarange",0);
127     }
128
129     void setupCounterData(const SGPropertyNode* configNode,
130                           SGPropertyNode* modelRoot)
131     {
132         counterValue = read_value(configNode, modelRoot, "-m",
133                                   -SGLimitsd::max(), SGLimitsd::max());
134         if(!counterValue){
135             SG_LOG(SG_GENERAL, SG_ALERT, "counter property error!\n");
136         }
137         counterExtraRange = configNode->getFloatValue("extrarange",0);
138     }
139
140     void setupCounterCondition(const SGPropertyNode* configNode,
141                                SGPropertyNode* modelRoot)
142     {
143         counterCond = sgReadCondition(modelRoot, configNode);
144     }
145
146     void setupCounterCondition(float counterStaticValue,
147                                float counterStaticExtraRange)
148     {
149         this->counterStaticValue = counterStaticValue;
150         this->counterStaticExtraRange = counterStaticExtraRange;
151     }
152
153     void setupStartSizeData(const SGPropertyNode* configNode,
154                             SGPropertyNode* modelRoot)
155     {
156         startSizeValue = read_value(configNode, modelRoot, "-m",
157                                     -SGLimitsd::max(), SGLimitsd::max());
158         if(!startSizeValue) 
159         {
160             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
161         }
162     }
163
164     void setupEndSizeData(const SGPropertyNode* configNode,
165                           SGPropertyNode* modelRoot)
166     {
167         endSizeValue = read_value(configNode, modelRoot, "-m",
168                                   -SGLimitsd::max(), SGLimitsd::max());
169         if(!endSizeValue){
170             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
171         }
172     }
173
174     void setupLifeData(const SGPropertyNode* configNode,
175                        SGPropertyNode* modelRoot)
176     {
177         lifeValue = read_value(configNode, modelRoot, "-m",
178                                -SGLimitsd::max(), SGLimitsd::max());
179         if(!lifeValue){
180             SG_LOG(SG_GENERAL, SG_ALERT, "lifeValue error!\n");
181         }
182     }
183
184     void setupStaticSizeData(float startSize, float endSize)
185     {
186         this->startSize=startSize;
187         this->endSize=endSize;
188     }
189
190
191     void setGeneralData(osgParticle::RadialShooter* shooter,
192                         osgParticle::RandomRateCounter* counter,
193                         osgParticle::ParticleSystem* particleSys,
194                         osgParticle::FluidProgram* program)
195     {
196         this->shooter = shooter;
197         this->counter = counter;
198         this->particleSys = particleSys;
199         this->program = program;
200     }
201
202     void setupProgramGravity(bool useGravity)
203     {
204         this->useGravity = useGravity;
205     }
206
207     void setupProgramWind(bool useWind)
208     {
209         this->useWind = useWind;
210     }
211
212     //component: r=0, g=1, ... ; color: 0=start color, 1=end color
213     void setupColorComponent(const SGPropertyNode* configNode,
214                              SGPropertyNode* modelRoot, int color,
215                              int component)
216     {
217         SGExpressiond *colorValue = read_value(configNode, modelRoot, "-m",
218                                                -SGLimitsd::max(),
219                                                SGLimitsd::max());
220         if(!colorValue){
221             SG_LOG(SG_GENERAL, SG_ALERT, "color property error!\n");
222         }
223         colorComponents[(color*4)+component] = colorValue;
224         //number of color components = 4
225     }
226
227     void setupStaticColorComponent(float r1,float g1, float b1, float a1,
228                                    float r2, float g2, float b2, float a2)
229     {
230         staticColorComponents[0] = r1;
231         staticColorComponents[1] = g1;
232         staticColorComponents[2] = b1;
233         staticColorComponents[3] = a1;
234         staticColorComponents[4] = r2;
235         staticColorComponents[5] = g2;
236         staticColorComponents[6] = b2;
237         staticColorComponents[7] = a2;
238     }
239
240     static osg::Group * getCommonRoot();
241
242     static osg::Geode * getCommonGeode()
243     {
244         return commonGeode.get();
245     }
246
247     static osgParticle::ParticleSystemUpdater * getPSU()
248     {
249         return psu.get();
250     }
251
252     static void setFrozen(bool e) { _frozen = e; }
253
254     /**
255      *  Set and get the wind vector for particles in the
256      * atmosphere. This vector is in the Z-up Y-north frame, and the
257      * magnitude is the velocity in meters per second.
258      */
259     static void setWindVector(const osg::Vec3& wind) { _wind = wind; }
260     static void setWindFrom(const double from_deg, const double speed_kt) {
261         double map_rad = -from_deg * SG_DEGREES_TO_RADIANS;
262         double speed_mps = speed_kt * SG_KT_TO_MPS;
263         _wind[0] = cos(map_rad) * speed_mps;
264         _wind[1] = sin(map_rad) * speed_mps;
265         _wind[2] = 0.0;
266     }
267     static const osg::Vec3& getWindVector() { return _wind; }
268 protected:
269     float shooterExtraRange;
270     float counterExtraRange;
271     SGSharedPtr<SGExpressiond> shooterValue;
272     SGSharedPtr<SGExpressiond> counterValue;
273     SGSharedPtr<SGExpressiond> colorComponents[8];
274     SGSharedPtr<SGExpressiond> startSizeValue;
275     SGSharedPtr<SGExpressiond> endSizeValue;
276     SGSharedPtr<SGExpressiond> lifeValue;
277     SGSharedPtr<SGCondition> counterCond;
278     float staticColorComponents[8];
279     float startSize;
280     float endSize;
281     float counterStaticValue;
282     float counterStaticExtraRange;
283     osg::ref_ptr<osgParticle::RadialShooter> shooter;
284     osg::ref_ptr<osgParticle::RandomRateCounter> counter;
285     osg::ref_ptr<osgParticle::ParticleSystem> particleSys;
286     osg::ref_ptr<osgParticle::FluidProgram> program;
287     osg::ref_ptr<osg::MatrixTransform> particleFrame;
288     
289     bool useGravity;
290     bool useWind;
291     static bool _frozen;
292     static osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu;
293     static osg::ref_ptr<osg::Group> commonRoot;
294     static osg::ref_ptr<osg::Geode> commonGeode;
295     static osg::Vec3 _wind;
296 };
297 }
298 #endif
299
300
301 /*
302 class CustomModularEmitter : public osgParticle::ModularEmitter, public osg::Observer
303 {
304 public:
305
306 virtual void objectDeleted (void *)
307 {
308 SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
309
310 SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
311 SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
312 }
313
314
315 //   ~CustomModularEmitter()
316 //   {
317 //     SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
318 //     
319 //     SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
320 //     SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
321 //   }
322 };
323 */