123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
- *
- * This library is open source and may be redistributed and/or modified under
- * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
- * (at your option) any later version. The full license is in LICENSE file
- * included with this distribution, and on the openscenegraph.org website.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * OpenSceneGraph Public License for more details.
- */
- //osgParticle - Copyright (C) 2002 Marco Jez
- #ifndef OSGPARTICLE_PARTICLE
- #define OSGPARTICLE_PARTICLE 1
- #include <osgParticle/Export>
- #include <osgParticle/Interpolator>
- #include <osgParticle/range>
- #include <osg/ref_ptr>
- #include <osg/Vec3>
- #include <osg/Vec4>
- #include <osg/Matrix>
- namespace osgParticle
- {
- // forward declare so we can reference it
- class ParticleSystem;
- /** Implementation of a <B>particle</B>.
- Objects of this class are particles, they have some graphical properties
- and some physical properties. Particles are created by emitters and then placed
- into Particle Systems, where they live and get updated at each frame.
- Particles can either live forever (lifeTime < 0), or die after a specified
- time (lifeTime >= 0). For each property which is defined as a range of values, a
- "current" value will be evaluated at each frame by interpolating the <I>min</I>
- and <I>max</I> values so that <I>curr_value = min</I> when <I>t == 0</I>, and
- <I>curr_value = max</I> when <I>t == lifeTime</I>.
- You may customize the interpolator objects to achieve any kind of transition.
- If you want the particle to live forever, set its lifetime to any value <= 0;
- in that case, no interpolation is done to compute real-time properties, and only
- minimum values are used.
- */
- class OSGPARTICLE_EXPORT Particle {
- friend class ParticleSystem;
- public:
- enum
- {
- INVALID_INDEX = -1
- };
- /**
- Shape of particles.
- NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem).
- */
- enum Shape {
- POINT, // uses GL_POINTS as primitive
- QUAD, // uses GL_QUADS as primitive
- QUAD_TRIANGLESTRIP, // no longer supported, falls back to QUAD
- HEXAGON, // no longer supported, falls back to QUAD
- LINE, // uses GL_LINES to draw line segments that point to the direction of motion
- USER // no longer supported, falls back to QUAD
- };
- Particle();
- /// Get the shape of the particle.
- inline Shape getShape() const;
- /// Set the shape of the particle.
- inline void setShape(Shape s);
- /// Get whether the particle is still alive.
- inline bool isAlive() const;
- /// Get the life time of the particle (in seconds).
- inline double getLifeTime() const;
- /// Get the age of the particle (in seconds).
- inline double getAge() const;
- /// Get the minimum and maximum values for polygon size.
- inline const rangef& getSizeRange() const;
- /// Get the minimum and maximum values for alpha.
- inline const rangef& getAlphaRange() const;
- /// Get the minimum and maximum values for color.
- inline const rangev4& getColorRange() const;
- /// Get the interpolator for computing the size of polygons.
- inline const Interpolator* getSizeInterpolator() const;
- /// Get the interpolator for computing alpha values.
- inline const Interpolator* getAlphaInterpolator() const;
- /// Get the interpolator for computing color values.
- inline const Interpolator* getColorInterpolator() const;
- /** Get the physical radius of the particle.
- For built-in operators to work correctly, lengths must be expressed in meters.
- */
- inline float getRadius() const;
- /** Get the mass of the particle.
- For built-in operators to work correctly, remember that the mass is expressed in kg.
- */
- inline float getMass() const;
- /// Get <CODE>1 / getMass()</CODE>.
- inline float getMassInv() const;
- /// Get the position vector.
- inline const osg::Vec3& getPosition() const;
- /** Get the velocity vector.
- For built-in operators to work correctly, remember that velocity components are expressed
- in meters per second.
- */
- inline const osg::Vec3& getVelocity() const;
- /// Get the previous position (the position before last update).
- inline const osg::Vec3& getPreviousPosition() const;
- /// Get the angle vector.
- inline const osg::Vec3& getAngle() const;
- /// Get the rotational velocity vector.
- inline const osg::Vec3& getAngularVelocity() const;
- /// Get the previous angle vector.
- inline const osg::Vec3& getPreviousAngle() const;
- /// Get the current color
- inline const osg::Vec4& getCurrentColor() const { return _current_color; }
- /// Get the current alpha
- inline float getCurrentAlpha() const { return _current_alpha; }
- /// Get the s texture coordinate of the bottom left of the particle
- inline float getSTexCoord() const { return _s_coord; }
- /// Get the t texture coordinate of the bottom left of the particle
- inline float getTTexCoord() const { return _t_coord; }
- /// Get the texture coordinate width of the particle
- inline float getSTexTile() const { return _s_tile; }
- /// Get the texture coordinate height of the particle
- inline float getTTexTile() const { return _t_tile; }
- /// Get width of texture tile
- inline int getTileS() const;
- /// Get height of texture tile
- inline int getTileT() const;
- /// Get number of texture tiles
- inline int getNumTiles() const { return _end_tile - _start_tile + 1; }
- /** Kill the particle on next update
- NOTE: after calling this function, the <CODE>isAlive()</CODE> method will still
- return true until the particle is updated again.
- */
- inline void kill();
- /// Set the life time of the particle.
- inline void setLifeTime(double t);
- /// Set the minimum and maximum values for polygon size.
- inline void setSizeRange(const rangef& r);
- /// Set the minimum and maximum values for alpha.
- inline void setAlphaRange(const rangef& r);
- /// Set the minimum and maximum values for color.
- inline void setColorRange(const rangev4& r);
- /// Set the interpolator for computing size values.
- inline void setSizeInterpolator(Interpolator* ri);
- template<class T> void setSizeInterpolator(const osg::ref_ptr<T>& ri) { setSizeInterpolator(ri.get()); }
- /// Set the interpolator for computing alpha values.
- inline void setAlphaInterpolator(Interpolator* ai);
- template<class T> void setAlphaInterpolator(const osg::ref_ptr<T>& ri) { setAlphaInterpolator(ri.get()); }
- /// Set the interpolator for computing color values.
- inline void setColorInterpolator(Interpolator* ci);
- template<class T> void setColorInterpolator(const osg::ref_ptr<T>& ri) { setColorInterpolator(ri.get()); }
- /** Set the physical radius of the particle.
- For built-in operators to work correctly, lengths must be expressed in meters.
- */
- inline void setRadius(float r);
- /** Set the mass of the particle.
- For built-in operators to work correctly, remember that the mass is expressed in kg.
- */
- inline void setMass(float m);
- /// Set the position vector.
- inline void setPosition(const osg::Vec3& p);
- /** Set the velocity vector.
- For built-in operators to work correctly, remember that velocity components are expressed
- in meters per second.
- */
- inline void setVelocity(const osg::Vec3& v);
- /// Add a vector to the velocity vector.
- inline void addVelocity(const osg::Vec3& dv);
- /// Transform position and velocity vectors by a matrix.
- inline void transformPositionVelocity(const osg::Matrix& xform);
- /// Transform position and velocity vectors by a combination of two matrices
- void transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r);
- /// Set the angle vector.
- inline void setAngle(const osg::Vec3& a);
- /**
- Set the angular velocity vector.
- Components x, y and z are angles of rotation around the respective axis (in radians).
- */
- inline void setAngularVelocity(const osg::Vec3& v);
- /// Add a vector to the angular velocity vector.
- inline void addAngularVelocity(const osg::Vec3& dv);
- /// Transform angle and angularVelocity vectors by a matrix.
- inline void transformAngleVelocity(const osg::Matrix& xform);
- /** Update the particle (don't call this method manually).
- This method is called automatically by <CODE>ParticleSystem::update()</CODE>; it
- updates the graphical properties of the particle for the current time,
- checks whether the particle is still alive, and then updates its position
- by computing <I>P = P + V * dt</I> (where <I>P</I> is the position and <I>V</I> is the velocity).
- */
- bool update(double dt, bool onlyTimeStamp);
- /// Get the current (interpolated) polygon size. Valid only after the first call to update().
- inline float getCurrentSize() const;
- /// Specify how the particle texture is tiled.
- /// All tiles in the given range are sequentially displayed during the lifetime
- /// of the particle. When no range is given, all tiles are displayed during the lifetime.
- inline void setTextureTileRange(int sTile, int tTile, int startTile, int endTile);
- /// Same as above, range starts at 0 and ends at end
- inline void setTextureTile(int sTile, int tTile, int end = -1);
- inline int getStartTile() const;
- inline int getEndTile() const;
- /// Set the previous particle
- inline void setPreviousParticle(int previous) { _previousParticle = previous; }
- /// Get the previous particle
- inline int getPreviousParticle() const { return _previousParticle; }
- /// Set the next particle
- inline void setNextParticle(int next) { _nextParticle = next; }
- /// Get the const next particle
- inline int getNextParticle() const { return _nextParticle; }
- /// Set the depth of the particle
- inline void setDepth(double d) { _depth = d; }
- /// Get the depth of the particle
- inline double getDepth() const { return _depth; }
- /// Sorting operator
- bool operator<(const Particle &P) const { return _depth < P._depth; }
- /// Method for initializing a particles texture coords as part of a connected particle system.
- void setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps);
- protected:
- Shape _shape;
- rangef _sr;
- rangef _ar;
- rangev4 _cr;
- osg::ref_ptr<Interpolator> _si;
- osg::ref_ptr<Interpolator> _ai;
- osg::ref_ptr<Interpolator> _ci;
- bool _mustdie;
- double _lifeTime;
- float _radius;
- float _mass;
- float _massinv;
- osg::Vec3 _prev_pos;
- osg::Vec3 _position;
- osg::Vec3 _velocity;
- osg::Vec3 _prev_angle;
- osg::Vec3 _angle;
- osg::Vec3 _angul_arvel;
- double _t0;
- float _alive;
- float _current_size;
- float _current_alpha;
- osg::Vec3 _base_prop; // [0] _alive [1] _current_size [2] _current_alpha
- osg::Vec4 _current_color;
- float _s_tile;
- float _t_tile;
- int _start_tile;
- int _end_tile;
- int _cur_tile;
- float _s_coord;
- float _t_coord;
- // previous and next Particles are only used in ConnectedParticleSystems
- int _previousParticle;
- int _nextParticle;
- // the depth of the particle is used only when sorting is enabled
- double _depth;
- };
- // INLINE FUNCTIONS
- inline Particle::Shape Particle::getShape() const
- {
- return _shape;
- }
- inline void Particle::setShape(Shape s)
- {
- _shape = s;
- }
- inline bool Particle::isAlive() const
- {
- return _alive>0.0f;
- }
- inline double Particle::getLifeTime() const
- {
- return _lifeTime;
- }
- inline double Particle::getAge() const
- {
- return _t0;
- }
- inline float Particle::getRadius() const
- {
- return _radius;
- }
- inline void Particle::setRadius(float r)
- {
- _radius = r;
- }
- inline const rangef& Particle::getSizeRange() const
- {
- return _sr;
- }
- inline const rangef& Particle::getAlphaRange() const
- {
- return _ar;
- }
- inline const rangev4& Particle::getColorRange() const
- {
- return _cr;
- }
- inline const Interpolator* Particle::getSizeInterpolator() const
- {
- return _si.get();
- }
- inline const Interpolator* Particle::getAlphaInterpolator() const
- {
- return _ai.get();
- }
- inline const Interpolator* Particle::getColorInterpolator() const
- {
- return _ci.get();
- }
- inline const osg::Vec3& Particle::getPosition() const
- {
- return _position;
- }
- inline const osg::Vec3& Particle::getVelocity() const
- {
- return _velocity;
- }
- inline const osg::Vec3& Particle::getPreviousPosition() const
- {
- return _prev_pos;
- }
- inline const osg::Vec3& Particle::getAngle() const
- {
- return _angle;
- }
- inline const osg::Vec3& Particle::getAngularVelocity() const
- {
- return _angul_arvel;
- }
- inline const osg::Vec3& Particle::getPreviousAngle() const
- {
- return _prev_angle;
- }
- inline int Particle::getTileS() const
- {
- return (_s_tile>0.0f) ? static_cast<int>(1.0f / _s_tile) : 1;
- }
- inline int Particle::getTileT() const
- {
- return (_t_tile>0.0f) ? static_cast<int>(1.0f / _t_tile) : 1;
- }
- inline void Particle::kill()
- {
- _mustdie = true;
- }
- inline void Particle::setLifeTime(double t)
- {
- _lifeTime = t;
- }
- inline void Particle::setSizeRange(const rangef& r)
- {
- _sr = r;
- }
- inline void Particle::setAlphaRange(const rangef& r)
- {
- _ar = r;
- }
- inline void Particle::setColorRange(const rangev4& r)
- {
- _cr = r;
- }
- inline void Particle::setSizeInterpolator(Interpolator* ri)
- {
- _si = ri;
- }
- inline void Particle::setAlphaInterpolator(Interpolator* ai)
- {
- _ai = ai;
- }
- inline void Particle::setColorInterpolator(Interpolator* ci)
- {
- _ci = ci;
- }
- inline void Particle::setPosition(const osg::Vec3& p)
- {
- _position = p;
- }
- inline void Particle::setVelocity(const osg::Vec3& v)
- {
- _velocity = v;
- }
- inline void Particle::addVelocity(const osg::Vec3& dv)
- {
- _velocity += dv;
- }
- inline void Particle::transformPositionVelocity(const osg::Matrix& xform)
- {
- _position = xform.preMult(_position);
- _velocity = osg::Matrix::transform3x3(_velocity, xform);
- }
- inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
- {
- osg::Vec3 position1 = xform1.preMult(_position);
- osg::Vec3 velocity1 = osg::Matrix::transform3x3(_velocity, xform1);
- osg::Vec3 position2 = xform2.preMult(_position);
- osg::Vec3 velocity2 = osg::Matrix::transform3x3(_velocity, xform2);
- float one_minus_r = 1.0f-r;
- _position = position1*r + position2*one_minus_r;
- _velocity = velocity1*r + velocity2*one_minus_r;
- }
- inline void Particle::setAngle(const osg::Vec3& a)
- {
- _angle = a;
- }
- inline void Particle::setAngularVelocity(const osg::Vec3& v)
- {
- _angul_arvel = v;
- }
- inline void Particle::addAngularVelocity(const osg::Vec3& dv)
- {
- _angul_arvel += dv;
- }
- inline void Particle::transformAngleVelocity(const osg::Matrix& xform)
- {
- // this should be optimized!
- osg::Vec3 a1 = _angle + _angul_arvel;
- _angle = xform.preMult(_angle);
- a1 = xform.preMult(a1);
- _angul_arvel = a1 - _angle;
- }
- inline float Particle::getMass() const
- {
- return _mass;
- }
- inline float Particle::getMassInv() const
- {
- return _massinv;
- }
- inline void Particle::setMass(float m)
- {
- _mass = m;
- _massinv = 1 / m;
- }
- inline float Particle::getCurrentSize() const
- {
- return _current_size;
- }
- inline void Particle::setTextureTile(int sTile, int tTile, int end)
- {
- setTextureTileRange(sTile, tTile, -1, end);
- }
- inline void Particle::setTextureTileRange(int sTile, int tTile, int startTile, int endTile)
- {
- _s_tile = (sTile>0) ? 1.0f / static_cast<float>(sTile) : 1.0f;
- _t_tile = (tTile>0) ? 1.0f / static_cast<float>(tTile) : 1.0f;
- if(startTile == -1)
- {
- _start_tile = 0;
- }
- else
- {
- _start_tile = startTile;
- }
- if(endTile == -1)
- {
- _end_tile = sTile * tTile;
- }
- else
- {
- _end_tile = endTile;
- }
- }
- inline int Particle::getStartTile() const
- {
- return _start_tile;
- }
- inline int Particle::getEndTile() const
- {
- return _end_tile;
- }
- }
- #endif
|