root/OpenSceneGraph/trunk/include/osgParticle/Particle @ 10827

Revision 10827, 18.1 kB (checked in by robert, 4 years ago)

From Martin Scheffler, "osgParticle: method to set start and end tile for particle texture (for animated particles). I also updated examples/osgParticle to show the feature.
The texture in data/Images should be copied to osg-data. I created the texture myself with the help of an explosion generator, so no license issues there.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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_PARTICLE
16#define OSGPARTICLE_PARTICLE 1
17
18#include <osgParticle/Export>
19#include <osgParticle/Interpolator>
20#include <osgParticle/range>
21
22#include <osg/ref_ptr>
23#include <osg/Vec3>
24#include <osg/Vec4>
25#include <osg/Matrix>
26#include <osg/GL>
27#include <osg/GLBeginEndAdapter>
28
29namespace osgParticle
30{
31
32    // forward declare so we can reference it
33    class ParticleSystem;
34
35    /**    Implementation of a <B>particle</B>.
36        Objects of this class are particles, they have some graphical properties
37        and some physical properties. Particles are created by emitters and then placed
38        into Particle Systems, where they live and get updated at each frame.
39        Particles can either live forever (lifeTime < 0), or die after a specified
40        time (lifeTime >= 0). For each property which is defined as a range of values, a
41        "current" value will be evaluated at each frame by interpolating the <I>min</I>
42        and <I>max</I> values so that <I>curr_value = min</I> when <I>t == 0</I>, and
43        <I>curr_value = max</I> when <I>t == lifeTime</I>.
44        You may customize the interpolator objects to achieve any kind of transition.
45        If you want the particle to live forever, set its lifetime to any value <= 0;
46        in that case, no interpolation is done to compute real-time properties, and only
47        minimum values are used.
48    */
49    class OSGPARTICLE_EXPORT Particle {
50    public:
51       
52        enum
53        {
54            INVALID_INDEX = -1
55        };
56
57        /**
58         Shape of particles.
59         NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem).
60        */
61        enum Shape {
62            POINT,            // uses GL_POINTS as primitive
63            QUAD,            // uses GL_QUADS as primitive
64            QUAD_TRIANGLESTRIP,    // uses GL_TRI_angleSTRIP as primitive, but each particle needs a glBegin/glEnd pair
65            HEXAGON,            // may save some filling time, but uses more triangles
66            LINE                // uses GL_LINES to draw line segments that point to the direction of motion           
67        };
68       
69        Particle();
70
71        /// Get the shape of the particle.
72        inline Shape getShape() const;
73       
74        /// Set the shape of the particle.
75        inline void setShape(Shape s);
76
77        /// Get whether the particle is still alive.
78        inline bool isAlive() const;
79       
80        /// Get the life time of the particle (in seconds).
81        inline double getLifeTime() const;
82       
83        /// Get the age of the particle (in seconds).
84        inline double getAge() const;
85       
86        /// Get the minimum and maximum values for polygon size.
87        inline const rangef& getSizeRange() const;
88       
89        /// Get the minimum and maximum values for alpha.
90        inline const rangef& getAlphaRange() const;
91       
92        /// Get the minimum and maximum values for color.
93        inline const rangev4& getColorRange() const;
94       
95        /// Get the interpolator for computing the size of polygons.
96        inline const Interpolator* getSizeInterpolator() const;
97       
98        /// Get the interpolator for computing alpha values.
99        inline const Interpolator* getAlphaInterpolator() const;
100       
101        /// Get the interpolator for computing color values.
102        inline const Interpolator* getColorInterpolator() const;
103
104        /** Get the physical radius of the particle.
105            For built-in operators to work correctly, lengths must be expressed in meters.
106        */
107        inline float getRadius() const;
108       
109        /** Get the mass of the particle.
110            For built-in operators to work correctly, remember that the mass is expressed in kg.
111        */
112        inline float getMass() const;
113       
114        /// Get <CODE>1 / getMass()</CODE>.
115        inline float getMassInv() const;
116       
117        /// Get the position vector.
118        inline const osg::Vec3& getPosition() const;
119       
120        /**    Get the velocity vector.
121            For built-in operators to work correctly, remember that velocity components are expressed
122            in meters per second.
123        */
124        inline const osg::Vec3& getVelocity() const;       
125       
126        /// Get the previous position (the position before last update).
127        inline const osg::Vec3& getPreviousPosition() const;
128
129        /// Get the angle vector.
130        inline const osg::Vec3& getAngle() const;
131       
132        /// Get the rotational velocity vector.
133        inline const osg::Vec3& getAngularVelocity() const;
134       
135        /// Get the previous angle vector.
136        inline const osg::Vec3& getPreviousAngle() const;
137       
138        /// Get the current color
139        inline const osg::Vec4& getCurrentColor() const { return _current_color; }
140
141        /// Get the current alpha
142        inline float getCurrentAlpha() const { return _current_alpha; }
143       
144        /// Get the s texture coordinate of the bottom left of the particle
145        inline float getSTexCoord() const { return _s_coord; }
146
147        /// Get the t texture coordinate of the bottom left of the particle
148        inline float getTTexCoord() const { return _t_coord; }
149
150        /// Get width of texture tile
151        inline int getTileS() const;
152       
153        /// Get height of texture tile
154        inline int getTileT() const;
155       
156        /// Get number of texture tiles
157        inline int getNumTiles() const { return _end_tile - _start_tile + 1; }
158       
159        /** Kill the particle on next update
160            NOTE: after calling this function, the <CODE>isAlive()</CODE> method will still
161            return true until the particle is updated again.
162        */
163        inline void kill();
164       
165        /// Set the life time of the particle.
166        inline void setLifeTime(double t);
167       
168        /// Set the minimum and maximum values for polygon size.
169        inline void setSizeRange(const rangef& r);
170       
171        /// Set the minimum and maximum values for alpha.
172        inline void setAlphaRange(const rangef& r);
173       
174        /// Set the minimum and maximum values for color.
175        inline void setColorRange(const rangev4& r);
176       
177        /// Set the interpolator for computing size values.
178        inline void setSizeInterpolator(Interpolator* ri);
179       
180        /// Set the interpolator for computing alpha values.       
181        inline void setAlphaInterpolator(Interpolator* ai);
182       
183        /// Set the interpolator for computing color values.
184        inline void setColorInterpolator(Interpolator* ci);
185
186        /** Set the physical radius of the particle.
187            For built-in operators to work correctly, lengths must be expressed in meters.
188        */
189        inline void setRadius(float r);
190       
191        /** Set the mass of the particle.
192            For built-in operators to work correctly, remember that the mass is expressed in kg.
193        */
194        inline void setMass(float m);
195       
196        /// Set the position vector.       
197        inline void setPosition(const osg::Vec3& p);
198       
199        /**    Set the velocity vector.
200            For built-in operators to work correctly, remember that velocity components are expressed
201            in meters per second.
202        */
203        inline void setVelocity(const osg::Vec3& v);
204       
205        /// Add a vector to the velocity vector.
206        inline void addVelocity(const osg::Vec3& dv);
207       
208        /// Transform position and velocity vectors by a matrix.
209        inline void transformPositionVelocity(const osg::Matrix& xform);
210
211        /// Transform position and velocity vectors by a combination of two matrices
212        void transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r);
213
214        /// Set the angle vector.
215        inline void setAngle(const osg::Vec3& a);
216       
217        /**
218          Set the angular velocity vector.
219          Components x, y and z are angles of rotation around the respective axis (in radians).
220        */
221        inline void setAngularVelocity(const osg::Vec3& v);
222       
223        /// Add a vector to the angular velocity vector.
224        inline void addAngularVelocity(const osg::Vec3& dv);
225       
226        /// Transform angle and angularVelocity vectors by a matrix.
227        inline void transformAngleVelocity(const osg::Matrix& xform);
228       
229        /**    Update the particle (don't call this method manually).
230            This method is called automatically by <CODE>ParticleSystem::update()</CODE>; it
231            updates the graphical properties of the particle for the current time,
232            checks whether the particle is still alive, and then updates its position
233            by computing <I>P = P + V * dt</I> (where <I>P</I> is the position and <I>V</I> is the velocity).
234        */
235        bool update(double dt);
236
237        /// Perform some pre-rendering tasks. Called automatically by particle systems.
238        inline void beginRender(osg::GLBeginEndAdapter* gl) const;
239       
240        /// Render the particle. Called automatically by particle systems.
241        void render(osg::GLBeginEndAdapter* gl, const osg::Vec3& xpos, const osg::Vec3& px, const osg::Vec3& py, float scale = 1.0f) const;
242       
243        /// Perform some post-rendering tasks. Called automatically by particle systems.
244        inline void endRender(osg::GLBeginEndAdapter* gl) const;
245       
246        /// Get the current (interpolated) polygon size. Valid only after the first call to update().
247        inline float getCurrentSize() const;
248       
249        /// Specify how the particle texture is tiled.
250        /// All tiles in the given range are sequentially displayed during the lifetime
251        /// of the particle. When no range is given, all tiles are displayed during the lifetime.
252        inline void setTextureTileRange(int sTile, int tTile, int startTile, int endTile);
253
254        /// Same as above, range starts at 0 and ends at end
255        inline void setTextureTile(int sTile, int tTile, int end = -1);
256
257        /// Set the previous particle
258        inline void setPreviousParticle(int previous) { _previousParticle = previous; }
259
260        /// Get the previous particle
261        inline int getPreviousParticle() const { return _previousParticle; }
262
263        /// Set the next particle
264        inline void setNextParticle(int next) { _nextParticle = next; }
265
266        /// Get the const next particle
267        inline int getNextParticle() const { return _nextParticle; }
268
269        /// Method for initializing a particles texture coords as part of a connected particle system.
270        void setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps);
271
272    protected:
273   
274        Shape _shape;
275
276        rangef _sr;
277        rangef _ar;
278        rangev4 _cr;
279
280        osg::ref_ptr<Interpolator> _si;
281        osg::ref_ptr<Interpolator> _ai;
282        osg::ref_ptr<Interpolator> _ci;
283
284        bool _alive;
285        bool _mustdie;
286        double _lifeTime;
287
288        float _radius;
289        float _mass;
290        float _massinv;
291        osg::Vec3 _prev_pos;
292        osg::Vec3 _position;
293        osg::Vec3 _velocity;
294
295        osg::Vec3 _prev_angle;
296        osg::Vec3 _angle;
297        osg::Vec3 _angul_arvel;
298
299        double _t0;       
300
301        float _current_size;
302        float _current_alpha;
303        osg::Vec4 _current_color;
304       
305        float _s_tile;
306        float _t_tile;
307        int _start_tile;
308        int _end_tile;
309        int _cur_tile;
310        float _s_coord;
311        float _t_coord;
312       
313        // previous and next Particles are only used in ConnectedParticleSystems
314        int _previousParticle;
315        int _nextParticle;
316    };
317
318    // INLINE FUNCTIONS
319
320    inline Particle::Shape Particle::getShape() const
321    {
322        return _shape;
323    }
324
325    inline void Particle::setShape(Shape s)
326    {
327        _shape = s;
328    }
329
330    inline bool Particle::isAlive() const
331    {
332        return _alive;
333    }
334
335    inline double Particle::getLifeTime() const
336    {
337        return _lifeTime;
338    }
339   
340    inline double Particle::getAge() const
341    {
342        return _t0;
343    }
344   
345    inline float Particle::getRadius() const
346    {
347        return _radius;
348    }
349   
350    inline void Particle::setRadius(float r)
351    {
352        _radius = r;
353    }
354
355    inline const rangef& Particle::getSizeRange() const
356    {
357        return _sr;
358    }
359
360    inline const rangef& Particle::getAlphaRange() const
361    {
362        return _ar;
363    }
364
365    inline const rangev4& Particle::getColorRange() const
366    {
367        return _cr;
368    }
369
370    inline const Interpolator* Particle::getSizeInterpolator() const
371    {
372        return _si.get();
373    }
374
375    inline const Interpolator* Particle::getAlphaInterpolator() const
376    {
377        return _ai.get();
378    }
379
380    inline const Interpolator* Particle::getColorInterpolator() const
381    {
382        return _ci.get();
383    }
384
385    inline const osg::Vec3& Particle::getPosition() const
386    {
387        return _position;
388    }
389
390    inline const osg::Vec3& Particle::getVelocity() const
391    {
392        return _velocity;
393    }
394   
395    inline const osg::Vec3& Particle::getPreviousPosition() const
396    {
397        return _prev_pos;
398    }
399
400    inline const osg::Vec3& Particle::getAngle() const
401    {
402        return _angle;
403    }
404   
405    inline const osg::Vec3& Particle::getAngularVelocity() const
406    {
407        return _angul_arvel;
408    }
409   
410    inline const osg::Vec3& Particle::getPreviousAngle() const
411    {
412        return _prev_angle;
413    }
414   
415    inline int Particle::getTileS() const
416    {
417        return (_s_tile>0.0f) ? static_cast<int>(1.0f / _s_tile) : 1;
418    }
419
420    inline int Particle::getTileT() const
421    {
422        return (_t_tile>0.0f) ? static_cast<int>(1.0f / _t_tile) : 1;
423    }
424   
425    inline void Particle::kill()
426    {
427        _mustdie = true;
428    }
429
430    inline void Particle::setLifeTime(double t)
431    {
432        _lifeTime = t;
433    }
434
435    inline void Particle::setSizeRange(const rangef& r)
436    {
437        _sr = r;
438    }
439
440    inline void Particle::setAlphaRange(const rangef& r)
441    {
442        _ar = r;
443    }
444
445    inline void Particle::setColorRange(const rangev4& r)
446    {
447        _cr = r;
448    }
449
450    inline void Particle::setSizeInterpolator(Interpolator* ri)
451    {
452        _si = ri;
453    }
454
455    inline void Particle::setAlphaInterpolator(Interpolator* ai)
456    {
457        _ai = ai;
458    }
459
460    inline void Particle::setColorInterpolator(Interpolator* ci)
461    {
462        _ci = ci;
463    }
464
465    inline void Particle::setPosition(const osg::Vec3& p)
466    {
467        _position = p;
468    }
469
470    inline void Particle::setVelocity(const osg::Vec3& v)
471    {
472        _velocity = v;
473    }
474
475    inline void Particle::addVelocity(const osg::Vec3& dv)
476    {
477        _velocity += dv;
478    }
479
480    inline void Particle::transformPositionVelocity(const osg::Matrix& xform)
481    {
482        _position = xform.preMult(_position);
483        _velocity = osg::Matrix::transform3x3(_velocity, xform);
484    }
485   
486    inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
487    {
488        osg::Vec3 position1 = xform1.preMult(_position);
489        osg::Vec3 velocity1 = osg::Matrix::transform3x3(_velocity, xform1);
490        osg::Vec3 position2 = xform2.preMult(_position);
491        osg::Vec3 velocity2 = osg::Matrix::transform3x3(_velocity, xform2);
492        float one_minus_r = 1.0f-r;
493        _position = position1*r + position2*one_minus_r;
494        _velocity = velocity1*r + velocity2*one_minus_r;
495    }
496   
497    inline void Particle::setAngle(const osg::Vec3& a)
498    {
499        _angle = a;
500    }
501   
502    inline void Particle::setAngularVelocity(const osg::Vec3& v)
503    {
504        _angul_arvel = v;
505    }
506   
507    inline void Particle::addAngularVelocity(const osg::Vec3& dv)
508    {
509        _angul_arvel += dv;
510    }
511   
512    inline void Particle::transformAngleVelocity(const osg::Matrix& xform)
513    {
514        // this should be optimized!
515       
516        osg::Vec3 a1 = _angle + _angul_arvel;
517       
518        _angle = xform.preMult(_angle);
519        a1 = xform.preMult(a1);
520       
521        _angul_arvel = a1 - _angle;
522    }
523           
524    inline float Particle::getMass() const
525    {
526        return _mass;
527    }
528   
529    inline float Particle::getMassInv() const
530    {
531        return _massinv;
532    }
533   
534    inline void Particle::setMass(float m)
535    {
536        _mass = m;
537        _massinv = 1 / m;
538    }
539   
540    inline void Particle::beginRender(osg::GLBeginEndAdapter* gl) const
541    {
542        switch (_shape)
543        {
544        case POINT:
545            gl->Begin(GL_POINTS);
546            break;
547        case QUAD:
548            gl->Begin(GL_QUADS);
549            break;
550        case LINE:
551            gl->Begin(GL_LINES);
552            break;
553        default: ;
554        }
555    }
556
557    inline void Particle::endRender(osg::GLBeginEndAdapter* gl) const
558    {
559        switch (_shape)
560        {
561        case POINT:
562        case QUAD:
563        case LINE:
564            gl->End();
565            break;
566        default: ;
567        }
568    }
569
570    inline float Particle::getCurrentSize() const
571    {
572        return _current_size;
573    }
574
575
576    inline void Particle::setTextureTile(int sTile, int tTile, int end)
577    {
578        setTextureTileRange(sTile, tTile, -1, end);
579    }
580
581    inline void Particle::setTextureTileRange(int sTile, int tTile, int startTile, int endTile)
582    {
583       _s_tile = (sTile>0) ? 1.0f / static_cast<float>(sTile) : 1.0f;
584       _t_tile = (tTile>0) ? 1.0f / static_cast<float>(tTile) : 1.0f;
585       
586       if(startTile == -1)
587       {
588          _start_tile = 0;
589       }
590       else
591       {
592          _start_tile = startTile;
593       }
594
595       if(endTile == -1)
596       {
597          _end_tile = sTile * tTile;
598       }
599       else
600       {
601          _end_tile = endTile;
602       }
603    }
604
605}
606
607#endif
608
Note: See TracBrowser for help on using the browser.