1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
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.
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.
13//osgParticle - Copyright (C) 2002 Marco Jez
15#ifndef OSGPARTICLE_PARTICLE
16#define OSGPARTICLE_PARTICLE 1
18#include <osgParticle/Export>
19#include <osgParticle/Interpolator>
20#include <osgParticle/range>
30 // forward declare so we can reference it
33 /** Implementation of a <B>particle</B>.
34 Objects of this class are particles, they have some graphical properties
35 and some physical properties. Particles are created by emitters and then placed
36 into Particle Systems, where they live and get updated at each frame.
37 Particles can either live forever (lifeTime < 0), or die after a specified
38 time (lifeTime >= 0). For each property which is defined as a range of values, a
39 "current" value will be evaluated at each frame by interpolating the <I>min</I>
40 and <I>max</I> values so that <I>curr_value = min</I> when <I>t == 0</I>, and
41 <I>curr_value = max</I> when <I>t == lifeTime</I>.
42 You may customize the interpolator objects to achieve any kind of transition.
43 If you want the particle to live forever, set its lifetime to any value <= 0;
44 in that case, no interpolation is done to compute real-time properties, and only
45 minimum values are used.
47 class OSGPARTICLE_EXPORT Particle {
48 friend class ParticleSystem;
58 NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem).
61 POINT, // uses GL_POINTS as primitive
62 QUAD, // uses GL_QUADS as primitive
63 QUAD_TRIANGLESTRIP, // no longer supported, falls back to QUAD
64 HEXAGON, // no longer supported, falls back to QUAD
65 LINE, // uses GL_LINES to draw line segments that point to the direction of motion
66 USER // no longer supported, falls back to QUAD
71 /// Get the shape of the particle.
72 inline Shape getShape() const;
74 /// Set the shape of the particle.
75 inline void setShape(Shape s);
77 /// Get whether the particle is still alive.
78 inline bool isAlive() const;
80 /// Get the life time of the particle (in seconds).
81 inline double getLifeTime() const;
83 /// Get the age of the particle (in seconds).
84 inline double getAge() const;
86 /// Get the minimum and maximum values for polygon size.
87 inline const rangef& getSizeRange() const;
89 /// Get the minimum and maximum values for alpha.
90 inline const rangef& getAlphaRange() const;
92 /// Get the minimum and maximum values for color.
93 inline const rangev4& getColorRange() const;
95 /// Get the interpolator for computing the size of polygons.
96 inline const Interpolator* getSizeInterpolator() const;
98 /// Get the interpolator for computing alpha values.
99 inline const Interpolator* getAlphaInterpolator() const;
101 /// Get the interpolator for computing color values.
102 inline const Interpolator* getColorInterpolator() const;
104 /** Get the physical radius of the particle.
105 For built-in operators to work correctly, lengths must be expressed in meters.
107 inline float getRadius() const;
109 /** Get the mass of the particle.
110 For built-in operators to work correctly, remember that the mass is expressed in kg.
112 inline float getMass() const;
114 /// Get <CODE>1 / getMass()</CODE>.
115 inline float getMassInv() const;
117 /// Get the position vector.
118 inline const osg::Vec3& getPosition() const;
120 /** Get the velocity vector.
121 For built-in operators to work correctly, remember that velocity components are expressed
122 in meters per second.
124 inline const osg::Vec3& getVelocity() const;
126 /// Get the previous position (the position before last update).
127 inline const osg::Vec3& getPreviousPosition() const;
129 /// Get the angle vector.
130 inline const osg::Vec3& getAngle() const;
132 /// Get the rotational velocity vector.
133 inline const osg::Vec3& getAngularVelocity() const;
135 /// Get the previous angle vector.
136 inline const osg::Vec3& getPreviousAngle() const;
138 /// Get the current color
139 inline const osg::Vec4& getCurrentColor() const { return _current_color; }
141 /// Get the current alpha
142 inline float getCurrentAlpha() const { return _current_alpha; }
144 /// Get the s texture coordinate of the bottom left of the particle
145 inline float getSTexCoord() const { return _s_coord; }
147 /// Get the t texture coordinate of the bottom left of the particle
148 inline float getTTexCoord() const { return _t_coord; }
150 /// Get the texture coordinate width of the particle
151 inline float getSTexTile() const { return _s_tile; }
153 /// Get the texture coordinate height of the particle
154 inline float getTTexTile() const { return _t_tile; }
157 /// Get width of texture tile
158 inline int getTileS() const;
160 /// Get height of texture tile
161 inline int getTileT() const;
163 /// Get number of texture tiles
164 inline int getNumTiles() const { return _end_tile - _start_tile + 1; }
166 /** Kill the particle on next update
167 NOTE: after calling this function, the <CODE>isAlive()</CODE> method will still
168 return true until the particle is updated again.
172 /// Set the life time of the particle.
173 inline void setLifeTime(double t);
175 /// Set the minimum and maximum values for polygon size.
176 inline void setSizeRange(const rangef& r);
178 /// Set the minimum and maximum values for alpha.
179 inline void setAlphaRange(const rangef& r);
181 /// Set the minimum and maximum values for color.
182 inline void setColorRange(const rangev4& r);
184 /// Set the interpolator for computing size values.
185 inline void setSizeInterpolator(Interpolator* ri);
186 template<class T> void setSizeInterpolator(const osg::ref_ptr<T>& ri) { setSizeInterpolator(ri.get()); }
188 /// Set the interpolator for computing alpha values.
189 inline void setAlphaInterpolator(Interpolator* ai);
190 template<class T> void setAlphaInterpolator(const osg::ref_ptr<T>& ri) { setAlphaInterpolator(ri.get()); }
192 /// Set the interpolator for computing color values.
193 inline void setColorInterpolator(Interpolator* ci);
194 template<class T> void setColorInterpolator(const osg::ref_ptr<T>& ri) { setColorInterpolator(ri.get()); }
196 /** Set the physical radius of the particle.
197 For built-in operators to work correctly, lengths must be expressed in meters.
199 inline void setRadius(float r);
201 /** Set the mass of the particle.
202 For built-in operators to work correctly, remember that the mass is expressed in kg.
204 inline void setMass(float m);
206 /// Set the position vector.
207 inline void setPosition(const osg::Vec3& p);
209 /** Set the velocity vector.
210 For built-in operators to work correctly, remember that velocity components are expressed
211 in meters per second.
213 inline void setVelocity(const osg::Vec3& v);
215 /// Add a vector to the velocity vector.
216 inline void addVelocity(const osg::Vec3& dv);
218 /// Transform position and velocity vectors by a matrix.
219 inline void transformPositionVelocity(const osg::Matrix& xform);
221 /// Transform position and velocity vectors by a combination of two matrices
222 void transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r);
224 /// Set the angle vector.
225 inline void setAngle(const osg::Vec3& a);
228 Set the angular velocity vector.
229 Components x, y and z are angles of rotation around the respective axis (in radians).
231 inline void setAngularVelocity(const osg::Vec3& v);
233 /// Add a vector to the angular velocity vector.
234 inline void addAngularVelocity(const osg::Vec3& dv);
236 /// Transform angle and angularVelocity vectors by a matrix.
237 inline void transformAngleVelocity(const osg::Matrix& xform);
239 /** Update the particle (don't call this method manually).
240 This method is called automatically by <CODE>ParticleSystem::update()</CODE>; it
241 updates the graphical properties of the particle for the current time,
242 checks whether the particle is still alive, and then updates its position
243 by computing <I>P = P + V * dt</I> (where <I>P</I> is the position and <I>V</I> is the velocity).
245 bool update(double dt, bool onlyTimeStamp);
247 /// Get the current (interpolated) polygon size. Valid only after the first call to update().
248 inline float getCurrentSize() const;
250 /// Specify how the particle texture is tiled.
251 /// All tiles in the given range are sequentially displayed during the lifetime
252 /// of the particle. When no range is given, all tiles are displayed during the lifetime.
253 inline void setTextureTileRange(int sTile, int tTile, int startTile, int endTile);
255 /// Same as above, range starts at 0 and ends at end
256 inline void setTextureTile(int sTile, int tTile, int end = -1);
258 inline int getStartTile() const;
260 inline int getEndTile() const;
262 /// Set the previous particle
263 inline void setPreviousParticle(int previous) { _previousParticle = previous; }
265 /// Get the previous particle
266 inline int getPreviousParticle() const { return _previousParticle; }
268 /// Set the next particle
269 inline void setNextParticle(int next) { _nextParticle = next; }
271 /// Get the const next particle
272 inline int getNextParticle() const { return _nextParticle; }
274 /// Set the depth of the particle
275 inline void setDepth(double d) { _depth = d; }
277 /// Get the depth of the particle
278 inline double getDepth() const { return _depth; }
281 bool operator<(const Particle &P) const { return _depth < P._depth; }
283 /// Method for initializing a particles texture coords as part of a connected particle system.
284 void setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps);
294 osg::ref_ptr<Interpolator> _si;
295 osg::ref_ptr<Interpolator> _ai;
296 osg::ref_ptr<Interpolator> _ci;
308 osg::Vec3 _prev_angle;
310 osg::Vec3 _angul_arvel;
316 float _current_alpha;
317 osg::Vec3 _base_prop; // [0] _alive [1] _current_size [2] _current_alpha
318 osg::Vec4 _current_color;
328 // previous and next Particles are only used in ConnectedParticleSystems
329 int _previousParticle;
332 // the depth of the particle is used only when sorting is enabled
338 inline Particle::Shape Particle::getShape() const
343 inline void Particle::setShape(Shape s)
348 inline bool Particle::isAlive() const
353 inline double Particle::getLifeTime() const
358 inline double Particle::getAge() const
363 inline float Particle::getRadius() const
368 inline void Particle::setRadius(float r)
373 inline const rangef& Particle::getSizeRange() const
378 inline const rangef& Particle::getAlphaRange() const
383 inline const rangev4& Particle::getColorRange() const
388 inline const Interpolator* Particle::getSizeInterpolator() const
393 inline const Interpolator* Particle::getAlphaInterpolator() const
398 inline const Interpolator* Particle::getColorInterpolator() const
403 inline const osg::Vec3& Particle::getPosition() const
408 inline const osg::Vec3& Particle::getVelocity() const
413 inline const osg::Vec3& Particle::getPreviousPosition() const
418 inline const osg::Vec3& Particle::getAngle() const
423 inline const osg::Vec3& Particle::getAngularVelocity() const
428 inline const osg::Vec3& Particle::getPreviousAngle() const
433 inline int Particle::getTileS() const
435 return (_s_tile>0.0f) ? static_cast<int>(1.0f / _s_tile) : 1;
438 inline int Particle::getTileT() const
440 return (_t_tile>0.0f) ? static_cast<int>(1.0f / _t_tile) : 1;
443 inline void Particle::kill()
448 inline void Particle::setLifeTime(double t)
453 inline void Particle::setSizeRange(const rangef& r)
458 inline void Particle::setAlphaRange(const rangef& r)
463 inline void Particle::setColorRange(const rangev4& r)
468 inline void Particle::setSizeInterpolator(Interpolator* ri)
473 inline void Particle::setAlphaInterpolator(Interpolator* ai)
478 inline void Particle::setColorInterpolator(Interpolator* ci)
483 inline void Particle::setPosition(const osg::Vec3& p)
488 inline void Particle::setVelocity(const osg::Vec3& v)
493 inline void Particle::addVelocity(const osg::Vec3& dv)
498 inline void Particle::transformPositionVelocity(const osg::Matrix& xform)
500 _position = xform.preMult(_position);
501 _velocity = osg::Matrix::transform3x3(_velocity, xform);
504 inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
506 osg::Vec3 position1 = xform1.preMult(_position);
507 osg::Vec3 velocity1 = osg::Matrix::transform3x3(_velocity, xform1);
508 osg::Vec3 position2 = xform2.preMult(_position);
509 osg::Vec3 velocity2 = osg::Matrix::transform3x3(_velocity, xform2);
510 float one_minus_r = 1.0f-r;
511 _position = position1*r + position2*one_minus_r;
512 _velocity = velocity1*r + velocity2*one_minus_r;
515 inline void Particle::setAngle(const osg::Vec3& a)
520 inline void Particle::setAngularVelocity(const osg::Vec3& v)
525 inline void Particle::addAngularVelocity(const osg::Vec3& dv)
530 inline void Particle::transformAngleVelocity(const osg::Matrix& xform)
532 // this should be optimized!
534 osg::Vec3 a1 = _angle + _angul_arvel;
536 _angle = xform.preMult(_angle);
537 a1 = xform.preMult(a1);
539 _angul_arvel = a1 - _angle;
542 inline float Particle::getMass() const
547 inline float Particle::getMassInv() const
552 inline void Particle::setMass(float m)
558 inline float Particle::getCurrentSize() const
560 return _current_size;
564 inline void Particle::setTextureTile(int sTile, int tTile, int end)
566 setTextureTileRange(sTile, tTile, -1, end);
569 inline void Particle::setTextureTileRange(int sTile, int tTile, int startTile, int endTile)
571 _s_tile = (sTile>0) ? 1.0f / static_cast<float>(sTile) : 1.0f;
572 _t_tile = (tTile>0) ? 1.0f / static_cast<float>(tTile) : 1.0f;
580 _start_tile = startTile;
585 _end_tile = sTile * tTile;
593 inline int Particle::getStartTile() const
598 inline int Particle::getEndTile() const