openscenegraph
Particle
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_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
27namespace osgParticle
28{
29
30 // forward declare so we can reference it
31 class ParticleSystem;
32
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.
46 */
47 class OSGPARTICLE_EXPORT Particle {
48 friend class ParticleSystem;
49 public:
50
51 enum
52 {
53 INVALID_INDEX = -1
54 };
55
56 /**
57 Shape of particles.
58 NOTE: the LINE shape should be used in conjunction with FIXED alignment mode (see ParticleSystem).
59 */
60 enum Shape {
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
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 the texture coordinate width of the particle
151 inline float getSTexTile() const { return _s_tile; }
152
153 /// Get the texture coordinate height of the particle
154 inline float getTTexTile() const { return _t_tile; }
155
156
157 /// Get width of texture tile
158 inline int getTileS() const;
159
160 /// Get height of texture tile
161 inline int getTileT() const;
162
163 /// Get number of texture tiles
164 inline int getNumTiles() const { return _end_tile - _start_tile + 1; }
165
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.
169 */
170 inline void kill();
171
172 /// Set the life time of the particle.
173 inline void setLifeTime(double t);
174
175 /// Set the minimum and maximum values for polygon size.
176 inline void setSizeRange(const rangef& r);
177
178 /// Set the minimum and maximum values for alpha.
179 inline void setAlphaRange(const rangef& r);
180
181 /// Set the minimum and maximum values for color.
182 inline void setColorRange(const rangev4& r);
183
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()); }
187
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()); }
191
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()); }
195
196 /** Set the physical radius of the particle.
197 For built-in operators to work correctly, lengths must be expressed in meters.
198 */
199 inline void setRadius(float r);
200
201 /** Set the mass of the particle.
202 For built-in operators to work correctly, remember that the mass is expressed in kg.
203 */
204 inline void setMass(float m);
205
206 /// Set the position vector.
207 inline void setPosition(const osg::Vec3& p);
208
209 /** Set the velocity vector.
210 For built-in operators to work correctly, remember that velocity components are expressed
211 in meters per second.
212 */
213 inline void setVelocity(const osg::Vec3& v);
214
215 /// Add a vector to the velocity vector.
216 inline void addVelocity(const osg::Vec3& dv);
217
218 /// Transform position and velocity vectors by a matrix.
219 inline void transformPositionVelocity(const osg::Matrix& xform);
220
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);
223
224 /// Set the angle vector.
225 inline void setAngle(const osg::Vec3& a);
226
227 /**
228 Set the angular velocity vector.
229 Components x, y and z are angles of rotation around the respective axis (in radians).
230 */
231 inline void setAngularVelocity(const osg::Vec3& v);
232
233 /// Add a vector to the angular velocity vector.
234 inline void addAngularVelocity(const osg::Vec3& dv);
235
236 /// Transform angle and angularVelocity vectors by a matrix.
237 inline void transformAngleVelocity(const osg::Matrix& xform);
238
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).
244 */
245 bool update(double dt, bool onlyTimeStamp);
246
247 /// Get the current (interpolated) polygon size. Valid only after the first call to update().
248 inline float getCurrentSize() const;
249
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);
254
255 /// Same as above, range starts at 0 and ends at end
256 inline void setTextureTile(int sTile, int tTile, int end = -1);
257
258 inline int getStartTile() const;
259
260 inline int getEndTile() const;
261
262 /// Set the previous particle
263 inline void setPreviousParticle(int previous) { _previousParticle = previous; }
264
265 /// Get the previous particle
266 inline int getPreviousParticle() const { return _previousParticle; }
267
268 /// Set the next particle
269 inline void setNextParticle(int next) { _nextParticle = next; }
270
271 /// Get the const next particle
272 inline int getNextParticle() const { return _nextParticle; }
273
274 /// Set the depth of the particle
275 inline void setDepth(double d) { _depth = d; }
276
277 /// Get the depth of the particle
278 inline double getDepth() const { return _depth; }
279
280 /// Sorting operator
281 bool operator<(const Particle &P) const { return _depth < P._depth; }
282
283 /// Method for initializing a particles texture coords as part of a connected particle system.
284 void setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps);
285
286 protected:
287
288 Shape _shape;
289
290 rangef _sr;
291 rangef _ar;
292 rangev4 _cr;
293
294 osg::ref_ptr<Interpolator> _si;
295 osg::ref_ptr<Interpolator> _ai;
296 osg::ref_ptr<Interpolator> _ci;
297
298 bool _mustdie;
299 double _lifeTime;
300
301 float _radius;
302 float _mass;
303 float _massinv;
304 osg::Vec3 _prev_pos;
305 osg::Vec3 _position;
306 osg::Vec3 _velocity;
307
308 osg::Vec3 _prev_angle;
309 osg::Vec3 _angle;
310 osg::Vec3 _angul_arvel;
311
312 double _t0;
313
314 float _alive;
315 float _current_size;
316 float _current_alpha;
317 osg::Vec3 _base_prop; // [0] _alive [1] _current_size [2] _current_alpha
318 osg::Vec4 _current_color;
319
320 float _s_tile;
321 float _t_tile;
322 int _start_tile;
323 int _end_tile;
324 int _cur_tile;
325 float _s_coord;
326 float _t_coord;
327
328 // previous and next Particles are only used in ConnectedParticleSystems
329 int _previousParticle;
330 int _nextParticle;
331
332 // the depth of the particle is used only when sorting is enabled
333 double _depth;
334 };
335
336 // INLINE FUNCTIONS
337
338 inline Particle::Shape Particle::getShape() const
339 {
340 return _shape;
341 }
342
343 inline void Particle::setShape(Shape s)
344 {
345 _shape = s;
346 }
347
348 inline bool Particle::isAlive() const
349 {
350 return _alive>0.0f;
351 }
352
353 inline double Particle::getLifeTime() const
354 {
355 return _lifeTime;
356 }
357
358 inline double Particle::getAge() const
359 {
360 return _t0;
361 }
362
363 inline float Particle::getRadius() const
364 {
365 return _radius;
366 }
367
368 inline void Particle::setRadius(float r)
369 {
370 _radius = r;
371 }
372
373 inline const rangef& Particle::getSizeRange() const
374 {
375 return _sr;
376 }
377
378 inline const rangef& Particle::getAlphaRange() const
379 {
380 return _ar;
381 }
382
383 inline const rangev4& Particle::getColorRange() const
384 {
385 return _cr;
386 }
387
388 inline const Interpolator* Particle::getSizeInterpolator() const
389 {
390 return _si.get();
391 }
392
393 inline const Interpolator* Particle::getAlphaInterpolator() const
394 {
395 return _ai.get();
396 }
397
398 inline const Interpolator* Particle::getColorInterpolator() const
399 {
400 return _ci.get();
401 }
402
403 inline const osg::Vec3& Particle::getPosition() const
404 {
405 return _position;
406 }
407
408 inline const osg::Vec3& Particle::getVelocity() const
409 {
410 return _velocity;
411 }
412
413 inline const osg::Vec3& Particle::getPreviousPosition() const
414 {
415 return _prev_pos;
416 }
417
418 inline const osg::Vec3& Particle::getAngle() const
419 {
420 return _angle;
421 }
422
423 inline const osg::Vec3& Particle::getAngularVelocity() const
424 {
425 return _angul_arvel;
426 }
427
428 inline const osg::Vec3& Particle::getPreviousAngle() const
429 {
430 return _prev_angle;
431 }
432
433 inline int Particle::getTileS() const
434 {
435 return (_s_tile>0.0f) ? static_cast<int>(1.0f / _s_tile) : 1;
436 }
437
438 inline int Particle::getTileT() const
439 {
440 return (_t_tile>0.0f) ? static_cast<int>(1.0f / _t_tile) : 1;
441 }
442
443 inline void Particle::kill()
444 {
445 _mustdie = true;
446 }
447
448 inline void Particle::setLifeTime(double t)
449 {
450 _lifeTime = t;
451 }
452
453 inline void Particle::setSizeRange(const rangef& r)
454 {
455 _sr = r;
456 }
457
458 inline void Particle::setAlphaRange(const rangef& r)
459 {
460 _ar = r;
461 }
462
463 inline void Particle::setColorRange(const rangev4& r)
464 {
465 _cr = r;
466 }
467
468 inline void Particle::setSizeInterpolator(Interpolator* ri)
469 {
470 _si = ri;
471 }
472
473 inline void Particle::setAlphaInterpolator(Interpolator* ai)
474 {
475 _ai = ai;
476 }
477
478 inline void Particle::setColorInterpolator(Interpolator* ci)
479 {
480 _ci = ci;
481 }
482
483 inline void Particle::setPosition(const osg::Vec3& p)
484 {
485 _position = p;
486 }
487
488 inline void Particle::setVelocity(const osg::Vec3& v)
489 {
490 _velocity = v;
491 }
492
493 inline void Particle::addVelocity(const osg::Vec3& dv)
494 {
495 _velocity += dv;
496 }
497
498 inline void Particle::transformPositionVelocity(const osg::Matrix& xform)
499 {
500 _position = xform.preMult(_position);
501 _velocity = osg::Matrix::transform3x3(_velocity, xform);
502 }
503
504 inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
505 {
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;
513 }
514
515 inline void Particle::setAngle(const osg::Vec3& a)
516 {
517 _angle = a;
518 }
519
520 inline void Particle::setAngularVelocity(const osg::Vec3& v)
521 {
522 _angul_arvel = v;
523 }
524
525 inline void Particle::addAngularVelocity(const osg::Vec3& dv)
526 {
527 _angul_arvel += dv;
528 }
529
530 inline void Particle::transformAngleVelocity(const osg::Matrix& xform)
531 {
532 // this should be optimized!
533
534 osg::Vec3 a1 = _angle + _angul_arvel;
535
536 _angle = xform.preMult(_angle);
537 a1 = xform.preMult(a1);
538
539 _angul_arvel = a1 - _angle;
540 }
541
542 inline float Particle::getMass() const
543 {
544 return _mass;
545 }
546
547 inline float Particle::getMassInv() const
548 {
549 return _massinv;
550 }
551
552 inline void Particle::setMass(float m)
553 {
554 _mass = m;
555 _massinv = 1 / m;
556 }
557
558 inline float Particle::getCurrentSize() const
559 {
560 return _current_size;
561 }
562
563
564 inline void Particle::setTextureTile(int sTile, int tTile, int end)
565 {
566 setTextureTileRange(sTile, tTile, -1, end);
567 }
568
569 inline void Particle::setTextureTileRange(int sTile, int tTile, int startTile, int endTile)
570 {
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;
573
574 if(startTile == -1)
575 {
576 _start_tile = 0;
577 }
578 else
579 {
580 _start_tile = startTile;
581 }
582
583 if(endTile == -1)
584 {
585 _end_tile = sTile * tTile;
586 }
587 else
588 {
589 _end_tile = endTile;
590 }
591 }
592
593 inline int Particle::getStartTile() const
594 {
595 return _start_tile;
596 }
597
598 inline int Particle::getEndTile() const
599 {
600 return _end_tile;
601 }
602}
603
604#endif
605