]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/particles.hxx
Keep non-local particles in a Z-up frame that is periodically moved.
[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 private:
90     static osg::Vec3 gravity;
91     static osg::Vec3 wind;
92     const SGPropertyNode* modelRoot;
93 };
94
95
96
97 class Particles : public osg::NodeCallback 
98 {
99 public:
100     Particles();
101
102     static osg::Group * appendParticles(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const osgDB::ReaderWriter::Options* options);
103
104     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
105
106     void setupShooterSpeedData(const SGPropertyNode* configNode,
107                                SGPropertyNode* modelRoot)
108     {
109         shooterValue = read_value(configNode, modelRoot, "-m",
110                                   -SGLimitsd::max(), SGLimitsd::max());
111         if(!shooterValue){
112             SG_LOG(SG_GENERAL, SG_ALERT, "shooter property error!\n");
113         }
114         shooterExtraRange = configNode->getFloatValue("extrarange",0);
115     }
116
117     void setupCounterData(const SGPropertyNode* configNode,
118                           SGPropertyNode* modelRoot)
119     {
120         counterValue = read_value(configNode, modelRoot, "-m",
121                                   -SGLimitsd::max(), SGLimitsd::max());
122         if(!counterValue){
123             SG_LOG(SG_GENERAL, SG_ALERT, "counter property error!\n");
124         }
125         counterExtraRange = configNode->getFloatValue("extrarange",0);
126     }
127
128     void setupCounterCondition(const SGPropertyNode* configNode,
129                                SGPropertyNode* modelRoot)
130     {
131         counterCond = sgReadCondition(modelRoot, configNode);
132     }
133
134     void setupCounterCondition(float counterStaticValue,
135                                float counterStaticExtraRange)
136     {
137         this->counterStaticValue = counterStaticValue;
138         this->counterStaticExtraRange = counterStaticExtraRange;
139     }
140
141     void setupStartSizeData(const SGPropertyNode* configNode,
142                             SGPropertyNode* modelRoot)
143     {
144         startSizeValue = read_value(configNode, modelRoot, "-m",
145                                     -SGLimitsd::max(), SGLimitsd::max());
146         if(!startSizeValue) 
147         {
148             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
149         }
150     }
151
152     void setupEndSizeData(const SGPropertyNode* configNode,
153                           SGPropertyNode* modelRoot)
154     {
155         endSizeValue = read_value(configNode, modelRoot, "-m",
156                                   -SGLimitsd::max(), SGLimitsd::max());
157         if(!endSizeValue){
158             SG_LOG(SG_GENERAL, SG_ALERT, "startSizeValue error!\n");
159         }
160     }
161
162     void setupLifeData(const SGPropertyNode* configNode,
163                        SGPropertyNode* modelRoot)
164     {
165         lifeValue = read_value(configNode, modelRoot, "-m",
166                                -SGLimitsd::max(), SGLimitsd::max());
167         if(!lifeValue){
168             SG_LOG(SG_GENERAL, SG_ALERT, "lifeValue error!\n");
169         }
170     }
171
172     void setupStaticSizeData(float startSize, float endSize)
173     {
174         this->startSize=startSize;
175         this->endSize=endSize;
176     }
177
178
179     void setGeneralData(osgParticle::RadialShooter* shooter,
180                         osgParticle::RandomRateCounter* counter,
181                         osgParticle::ParticleSystem* particleSys,
182                         osgParticle::FluidProgram* program)
183     {
184         this->shooter = shooter;
185         this->counter = counter;
186         this->particleSys = particleSys;
187         this->program = program;
188     }
189
190     void setupProgramGravity(bool useGravity)
191     {
192         this->useGravity = useGravity;
193     }
194
195     void setupProgramWind(bool useWind)
196     {
197         this->useWind = useWind;
198     }
199
200     //component: r=0, g=1, ... ; color: 0=start color, 1=end color
201     void setupColorComponent(const SGPropertyNode* configNode,
202                              SGPropertyNode* modelRoot, int color,
203                              int component)
204     {
205         SGExpressiond *colorValue = read_value(configNode, modelRoot, "-m",
206                                                -SGLimitsd::max(),
207                                                SGLimitsd::max());
208         if(!colorValue){
209             SG_LOG(SG_GENERAL, SG_ALERT, "color property error!\n");
210         }
211         colorComponents[(color*4)+component] = colorValue;
212         //number of color components = 4
213     }
214
215     void setupStaticColorComponent(float r1,float g1, float b1, float a1,
216                                    float r2, float g2, float b2, float a2)
217     {
218         staticColorComponents[0] = r1;
219         staticColorComponents[1] = g1;
220         staticColorComponents[2] = b1;
221         staticColorComponents[3] = a1;
222         staticColorComponents[4] = r2;
223         staticColorComponents[5] = g2;
224         staticColorComponents[6] = b2;
225         staticColorComponents[7] = a2;
226     }
227
228     static osg::Group * getCommonRoot();
229
230     static osg::Geode * getCommonGeode()
231     {
232         return commonGeode.get();
233     }
234
235     static osgParticle::ParticleSystemUpdater * getPSU()
236     {
237         return psu.get();
238     }
239
240     /**
241      *  Set and get the wind vector for particles in the
242      * atmosphere. This vector is in the Z-up Y-north frame, and the
243      * magnitude is the velocity in meters per second.
244      */
245     static void setWindVector(const osg::Vec3& wind) { _wind = wind; }
246     static const osg::Vec3& getWindVector() { return _wind; }
247 protected:
248     float shooterExtraRange;
249     float counterExtraRange;
250     SGSharedPtr<SGExpressiond> shooterValue;
251     SGSharedPtr<SGExpressiond> counterValue;
252     SGSharedPtr<SGExpressiond> colorComponents[8];
253     SGSharedPtr<SGExpressiond> startSizeValue;
254     SGSharedPtr<SGExpressiond> endSizeValue;
255     SGSharedPtr<SGExpressiond> lifeValue;
256     SGSharedPtr<SGCondition> counterCond;
257     float staticColorComponents[8];
258     float startSize;
259     float endSize;
260     float counterStaticValue;
261     float counterStaticExtraRange;
262     osg::ref_ptr<osgParticle::RadialShooter> shooter;
263     osg::ref_ptr<osgParticle::RandomRateCounter> counter;
264     osg::ref_ptr<osgParticle::ParticleSystem> particleSys;
265     osg::ref_ptr<osgParticle::FluidProgram> program;
266     osg::ref_ptr<osg::MatrixTransform> particleFrame;
267     
268     bool useGravity;
269     bool useWind;
270     static osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu;
271     static osg::ref_ptr<osg::Group> commonRoot;
272     static osg::ref_ptr<osg::Geode> commonGeode;
273     static osg::Vec3 _wind;
274 };
275 }
276 #endif
277
278
279 /*
280 class CustomModularEmitter : public osgParticle::ModularEmitter, public osg::Observer
281 {
282 public:
283
284 virtual void objectDeleted (void *)
285 {
286 SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
287
288 SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
289 SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
290 }
291
292
293 //   ~CustomModularEmitter()
294 //   {
295 //     SG_LOG(SG_GENERAL, SG_ALERT, "object deleted!\n");
296 //     
297 //     SGParticles::getCommonRoot()->removeChild(this->getParticleSystem()->getParent(0));
298 //     SGParticles::getPSU()->removeParticleSystem(this->getParticleSystem());
299 //   }
300 };
301 */