OSG  3.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ParticleSystem.h
Go to the documentation of this file.
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 //osgParticle - Copyright (C) 2002 Marco Jez
14 
15 #ifndef OSGPARTICLE_PARTICLESYSTEM
16 #define OSGPARTICLE_PARTICLESYSTEM 1
17 
18 #include <osgParticle/Export>
19 #include <osgParticle/Particle>
20 
21 #include <vector>
22 #include <stack>
23 #include <algorithm>
24 #include <string>
25 
26 #include <osg/Object>
27 #include <osg/Drawable>
28 #include <osg/CopyOp>
29 #include <osg/State>
30 #include <osg/Vec3>
31 #include <osg/BoundingBox>
32 
33 // 9th Febrary 2009, disabled the use of ReadWriteMutex as it looks like this
34 // is introducing threading problems due to threading problems in OpenThreads::ReadWriteMutex.
35 // #define OSGPARTICLE_USE_ReadWriteMutex
36 
37 #ifdef OSGPARTICLE_USE_ReadWriteMutex
38  #include <OpenThreads/ReadWriteMutex>
39 #else
40  #include <OpenThreads/Mutex>
41  #include <OpenThreads/ScopedLock>
42 #endif
43 
44 
45 namespace osgParticle
46 {
47 
55  public:
56 
57  enum Alignment {
59  FIXED
60  };
61 
64 
66 
68  inline Alignment getParticleAlignment() const;
69 
71  inline void setParticleAlignment(Alignment a);
72 
74  inline const osg::Vec3& getAlignVectorX() const;
75 
77  inline void setAlignVectorX(const osg::Vec3& v);
78 
80  inline const osg::Vec3& getAlignVectorY() const;
81 
83  inline void setAlignVectorY(const osg::Vec3& v);
84 
86  inline void setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y);
87 
88 
89 
91  {
93  WORLD_COORDINATES
94  };
95 
97  void setParticleScaleReferenceFrame(ParticleScaleReferenceFrame rf) { _particleScaleReferenceFrame = rf; }
98 
100  ParticleScaleReferenceFrame getParticleScaleReferenceFrame() const { return _particleScaleReferenceFrame; }
101 
102 
103 
105  inline const osg::BoundingBox& getDefaultBoundingBox() const;
106 
111  inline void setDefaultBoundingBox(const osg::BoundingBox& bbox);
112 
114  bool getUseVertexArray() const { return _useVertexArray; }
115 
122  void setUseVertexArray(bool v) { _useVertexArray = v; }
123 
125  bool getUseShaders() const { return _useShaders; }
126 
131  void setUseShaders(bool v) { _useShaders = v; _dirty_uniforms = true; }
132 
134  inline bool getDoublePassRendering() const;
135 
143  inline void setDoublePassRendering(bool v);
144 
146  bool getFrozen() const { return _frozen; }
147  inline bool isFrozen() const;
148 
152  inline void setFrozen(bool v);
153 
155  inline int numParticles() const;
156 
158  inline int numDeadParticles() const;
159 
161  inline bool areAllParticlesDead() const { return numDeadParticles()==numParticles(); }
162 
164  inline Particle* getParticle(int i);
165 
167  inline const Particle* getParticle(int i) const;
168 
170  inline virtual Particle* createParticle(const Particle* ptemplate);
171 
173  inline virtual void destroyParticle(int i);
174 
176  inline virtual void reuseParticle(int i) { _deadparts.push(&(_particles[i])); }
177 
179  inline unsigned int getLastFrameNumber() const;
180 
182  inline double& getDeltaTime( double currentTime );
183 
185  inline Particle& getDefaultParticleTemplate();
186 
188  inline const Particle& getDefaultParticleTemplate() const;
189 
191  inline void setDefaultParticleTemplate(const Particle& p);
192 
194  inline bool getFreezeOnCull() const;
195 
197  inline void setFreezeOnCull(bool v);
198 
202  void setDefaultAttributes(const std::string& texturefile = "", bool emissive_particles = true, bool lighting = false, int texture_unit = 0);
203 
208  void setDefaultAttributesUsingShaders(const std::string& texturefile = "", bool emissive_particles = true, int texture_unit = 0);
209 
211  inline int getLevelOfDetail() const;
212 
216  inline void setLevelOfDetail(int v);
217 
218  enum SortMode
219  {
222  SORT_BACK_TO_FRONT
223  };
224 
226  inline SortMode getSortMode() const;
227 
231  inline void setSortMode(SortMode mode);
232 
234  inline double getVisibilityDistance() const;
235 
239  inline void setVisibilityDistance(double distance);
240 
242  virtual void update(double dt, osg::NodeVisitor& nv);
243 
244  virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
245 
246  virtual osg::BoundingBox computeBoundingBox() const;
247 
248 #ifdef OSGPARTICLE_USE_ReadWriteMutex
249  typedef OpenThreads::ReadWriteMutex ReadWriterMutex;
250  typedef OpenThreads::ScopedReadLock ScopedReadLock;
251  typedef OpenThreads::ScopedWriteLock ScopedWriteLock;
252 #else
256 #endif
257 
258  ReadWriterMutex* getReadWriteMutex() const { return &_readWriteMutex; }
259 
260  protected:
261 
262  virtual ~ParticleSystem();
263 
264  ParticleSystem& operator=(const ParticleSystem&) { return *this; }
265 
266  inline void update_bounds(const osg::Vec3& p, float r);
267  void single_pass_render(osg::RenderInfo& renderInfo, const osg::Matrix& modelview) const;
268  void render_vertex_array(osg::RenderInfo& renderInfo) const;
269 
270  typedef std::vector<Particle> Particle_vector;
271  typedef std::stack<Particle*> Death_stack;
272 
273  Particle_vector _particles;
274  Death_stack _deadparts;
275 
277 
282 
286 
288  bool _frozen;
289 
292 
295 
297  mutable unsigned int _last_frame;
298  mutable bool _dirty_dt;
300 
301  double _t0;
302  double _dt;
303 
304  int _detail;
307 
308  mutable int _draw_count;
309 
310  mutable ReadWriterMutex _readWriteMutex;
311  };
312 
313  // INLINE FUNCTIONS
314 
316  {
317  return _alignment;
318  }
319 
321  {
322  _alignment = a;
323  }
324 
326  {
327  return _align_X_axis;
328  }
329 
331  {
332  _align_X_axis = v;
333  }
334 
336  {
337  return _align_Y_axis;
338  }
339 
341  {
342  _align_Y_axis = v;
343  }
344 
345  inline void ParticleSystem::setAlignVectors(const osg::Vec3& X, const osg::Vec3& Y)
346  {
347  _align_X_axis = X;
348  _align_Y_axis = Y;
349  }
350 
351  inline bool ParticleSystem::isFrozen() const
352  {
353  return _frozen;
354  }
355 
356  inline void ParticleSystem::setFrozen(bool v)
357  {
358  _frozen = v;
359  }
360 
362  {
363  return _def_bbox;
364  }
365 
367  {
368  _def_bbox = bbox;
369  }
370 
372  {
373  return _doublepass;
374  }
375 
377  {
378  _doublepass = v;
379  }
380 
381  inline int ParticleSystem::numParticles() const
382  {
383  return static_cast<int>(_particles.size());
384  }
385 
387  {
388  return static_cast<int>(_deadparts.size());
389  }
390 
392  {
393  return &_particles[i];
394  }
395 
396  inline const Particle* ParticleSystem::getParticle(int i) const
397  {
398  return &_particles[i];
399  }
400 
402  {
403  _particles[i].kill();
404  }
405 
406  inline unsigned int ParticleSystem::getLastFrameNumber() const
407  {
408  return _last_frame;
409  }
410 
411  inline double& ParticleSystem::getDeltaTime( double currentTime )
412  {
413  if ( _dirty_dt )
414  {
415  _dt = currentTime - _t0;
416  if ( _dt<0.0 ) _dt = 0.0;
417 
418  _t0 = currentTime;
419  _dirty_dt = false;
420  }
421  return _dt;
422  }
423 
424  inline void ParticleSystem::update_bounds(const osg::Vec3& p, float r)
425  {
426  if (_reset_bounds_flag) {
427  _reset_bounds_flag = false;
428  _bmin = p - osg::Vec3(r,r,r);
429  _bmax = p + osg::Vec3(r,r,r);
430  } else {
431  if (p.x() - r < _bmin.x()) _bmin.x() = p.x() - r;
432  if (p.y() - r < _bmin.y()) _bmin.y() = p.y() - r;
433  if (p.z() - r < _bmin.z()) _bmin.z() = p.z() - r;
434  if (p.x() + r > _bmax.x()) _bmax.x() = p.x() + r;
435  if (p.y() + r > _bmax.y()) _bmax.y() = p.y() + r;
436  if (p.z() + r > _bmax.z()) _bmax.z() = p.z() + r;
437  }
438  if (!_bounds_computed)
439  _bounds_computed = true;
440  }
441 
443  {
444  return _def_ptemp;
445  }
446 
448  {
449  return _def_ptemp;
450  }
451 
453  {
454  _def_ptemp = p;
455  }
456 
458  {
459  return _freeze_on_cull;
460  }
461 
463  {
464  _freeze_on_cull = v;
465  }
466 
468  {
469  return _detail;
470  }
471 
473  {
474  if (v < 1) v = 1;
475  _detail = v;
476  }
477 
479  {
480  return _sortMode;
481  }
482 
484  {
485  _sortMode = mode;
486  }
487 
489  {
490  return _visibilityDistance;
491  }
492 
493  inline void ParticleSystem::setVisibilityDistance(double distance)
494  {
495  _visibilityDistance = distance;
496  if (_useShaders) _dirty_uniforms = true;
497  }
498 
499  // I'm not sure this function should be inlined...
500 
502  {
503  // is there any dead particle?
504  if (!_deadparts.empty()) {
505 
506  // retrieve a pointer to the last dead particle
507  Particle* P = _deadparts.top();
508 
509  // create a new (alive) particle in the same place
510  *P = ptemplate? *ptemplate: _def_ptemp;
511 
512  // remove the pointer from the death stack
513  _deadparts.pop();
514  return P;
515 
516  } else {
517 
518  // add a new particle to the vector
519  _particles.push_back(ptemplate? *ptemplate: _def_ptemp);
520  return &_particles.back();
521  }
522  }
523 
524 
525 }
526 
527 #endif
OpenThreads::Mutex ReadWriterMutex
int getLevelOfDetail() const
(EXPERIMENTAL) Get the level of detail.
bool areAllParticlesDead() const
Get whether all particles are dead.
ReadWriterMutex * getReadWriteMutex() const
This class provides an object-oriented thread mutex interface.
Definition: Mutex.h:31
bool getUseVertexArray() const
Return true if we use vertex arrays for rendering particles.
int numParticles() const
Get the number of allocated particles (alive + dead).
void setSortMode(SortMode mode)
void setAlignVectorY(const osg::Vec3 &v)
Set the Y-axis alignment vector.
ReadWriterMutex _readWriteMutex
value_type & x()
Definition: Vec3f.h:80
value_type & z()
Definition: Vec3f.h:82
virtual void destroyParticle(int i)
Destroy the i-th particle.
double & getDeltaTime(double currentTime)
Get the unique delta time for emitters and updaters to use.
double getVisibilityDistance() const
Get the visibility distance.
ParticleScaleReferenceFrame _particleScaleReferenceFrame
ParticleScaleReferenceFrame getParticleScaleReferenceFrame() const
virtual void reuseParticle(int i)
Reuse the i-th particle.
void setAlignVectors(const osg::Vec3 &X, const osg::Vec3 &Y)
Set the alignment vectors.
void setAlignVectorX(const osg::Vec3 &v)
Set the X-axis alignment vector.
#define OSGPARTICLE_EXPORT
Definition: Export.h:40
void setFreezeOnCull(bool v)
Set whether the particle system can freeze when culled (default is true)
const osg::BoundingBox & getDefaultBoundingBox() const
Get the default bounding box.
#define META_Object(library, name)
Definition: Object.h:42
OpenThreads::ScopedLock< OpenThreads::Mutex > ScopedReadLock
Vec3f Vec3
Definition: Vec3.h:21
void setVisibilityDistance(double distance)
void setDefaultBoundingBox(const osg::BoundingBox &bbox)
value_type & y()
Definition: Vec3f.h:81
const osg::Vec3 & getAlignVectorY() const
Get the Y-axis alignment vector.
ParticleSystem & operator=(const ParticleSystem &)
std::vector< Particle > Particle_vector
void setParticleScaleReferenceFrame(ParticleScaleReferenceFrame rf)
bool getUseShaders() const
Return true if shaders are required.
int numDeadParticles() const
Get the number of dead particles.
std::stack< Particle * > Death_stack
virtual Particle * createParticle(const Particle *ptemplate)
Create a new particle from the specified template (or the default one if ptemplate is null)...
void update_bounds(const osg::Vec3 &p, float r)
Alignment getParticleAlignment() const
Get the alignment type of particles.
SortMode getSortMode() const
Get the sort mode.
Particle * getParticle(int i)
Get a pointer to the i-th particle.
unsigned int getLastFrameNumber() const
Get the last frame number.
void setDefaultParticleTemplate(const Particle &p)
Set the default particle template (particle is copied).
void setParticleAlignment(Alignment a)
Set the alignment type of particles.
bool getFrozen() const
Return true if the particle system is frozen.
OpenThreads::ScopedLock< OpenThreads::Mutex > ScopedWriteLock
bool getDoublePassRendering() const
Get the double pass rendering flag.
bool getFreezeOnCull() const
Get whether the particle system can freeze when culled.
Particle & getDefaultParticleTemplate()
Get a reference to the default particle template.
const osg::Vec3 & getAlignVectorX() const
Get the X-axis alignment vector.