diff options
Diffstat (limited to 'kscreensaver/kdesavers/firesaverparticle.cpp')
-rw-r--r-- | kscreensaver/kdesavers/firesaverparticle.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/kscreensaver/kdesavers/firesaverparticle.cpp b/kscreensaver/kdesavers/firesaverparticle.cpp new file mode 100644 index 00000000..421115a7 --- /dev/null +++ b/kscreensaver/kdesavers/firesaverparticle.cpp @@ -0,0 +1,273 @@ +// This file is part of KFireSaver3D. + +// KFireSaver3D is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. + +// KFireSaver3D 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 +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with KFireSaver3D; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +// Author: Enrico Ros, based on the great work of David Sansome (kfiresaver) +// Email: asy@libero.it + +#include <math.h> +#include <stdlib.h> + +#include "firesaverparticle.h" +#include "firesaver.h" + +//current color scheme : red orng grn blue w m c +static const GLfloat c_red_min[7] = { 0.4, 0.9, 0, 0, 1, 0, 0 }; +static const GLfloat c_red_max[7] = { 1, 1, 0, 0, 1, 1, 0 }; +static const GLfloat c_green_min[7] = { 0, 0.4, 0.4, 0, 1, 0, 0 }; +static const GLfloat c_green_max[7] = { 0, 0.5, 1, 0.5, 1, 0, 1 }; +static const GLfloat c_blue_min[7] = { 0, 0.1, 0, 0.5, 1, 0, 0 }; +static const GLfloat c_blue_max[7] = { 0, 0.2, 0, 1, 1, 1, 1 }; + + +//default initialization (good for Leader / Fire) +Particle :: Particle( ParticleType pT ) + : particleType( pT ), explosionsDepth( 0 ), texture( 0 ), + xpos( 0.0 ), ypos( 0.0 ), zpos( -9.9 ), + xspeed( 0.0 ), yspeed( 0.0 ), zspeed( 0.0 ), zacc( -9.807 ), + life( 0.0 ), startLife( 0.0 ), + pixelSize( 5.0 ), useLife( true ), flicker( 0 ) +{ + colour[0] = 0; + colour[1] = 0; + colour[2] = 0; + colour[3] = 1; +} + + +void Particle :: initializeValues ( + int cs, + Particle* debrisParent, + GLfloat powermin, GLfloat powermax, + bool flickers, + GLfloat *displace ) +//note: this function is called when a particle needs a set of default parameters. +// these depends on the ParticleType. +{ + switch (particleType) + { +// -- FireParticle (params: [cs]) +// born in a rectangle centered in { 0, 0, -9.9 } +// speed 3-6 [m/s] blue/cyan colored +// this is only done at the beginning or when a particle dies + case FireParticle: + xpos = DRAND * FIELDWIDTH - FIELDW_2; + ypos = DRAND - 2.0; + + xspeed = DRAND * 4.0 - 2.0; + yspeed = DRAND * 2.0; + zspeed = DRAND * 3.0 + 3.0; + + useLife = false; + pixelSize = 2.0 + DRAND * 2.0; + break; + +// -- FireWorkLeaderParticle (params: none) +// they start in a rectangle at the same height but +// with different power and the same 'orange' colour + case FireWorkLeaderParticle: + xpos = DRAND * 14.0 - 7.0; + ypos = DRAND * 2.0 - 1.0; + + xspeed = DRAND * 8.0 - 4.0 - (xpos / 2.0)*DRAND; + yspeed = DRAND * 8.0 - 4.0; + zspeed = DRAND * 6.5 + 18.0; + + colour[0] = 0.6; + colour[1] = DRAND * 0.4; + colour[2] = 0.0; + + useLife = false; + break; + +// -- LogoParticle (params: none) +// they start in the middle of the screen. +// little g-force, constant life, weavy-y + case LogoParticle: + yspeed = 3*(DRAND - DRAND); + zacc = -9.807f / 5.0f; + + startLife = 0.7f; + life = 1.7f; + break; + +// -- StarParticle (params: none) +// spherically distributed. xpos and ypos are the +// transformed screen positions of the star. + case StarParticle: + colour[0] = DRAND * 0.2 + 0.5; + colour[1] = DRAND * 0.2 + 0.5; + colour[2] = DRAND * 0.2 + 0.5; + + {bool accepted = false; + while (!accepted) { + float module = 30, + theta = DRAND * M_PI * 2.0, + u = DRAND * 2.0 - 1.0, + root = sqrt( 1 - u*u ); + xpos = module * root * cos(theta); + ypos = fabs(module * root * sin(theta)) - 10.0; + zpos = fabs(module * u); + + float sfactor = 256.0 / (256.0 + PERSP_MAG_FACTOR*ypos); + xpos *= sfactor; + ypos = sfactor * zpos - FIELDW_2; + + pixelSize = sfactor * (2.0 + 3.0*DRAND); + + accepted = xpos > -FIELDW_2 && xpos < FIELDW_2 && + ypos > -FIELDW_2 && ypos < FIELDW_2; + }} + break; + +// -- FireWorkDebrisParticle (params: cs, parent, [powerm], [powerM], [flickers], [displace]) +// parameters are randomized for a 'spherical' explosion. +// power{min,max}, flickers and displace applies only for that +// kind of ParticleType. + case FireWorkDebrisParticle: + + //same origin of the dead leader + xpos = debrisParent->xpos; + ypos = debrisParent->ypos; + zpos = debrisParent->zpos; + + //true spherical randomization + float module = powermin + DRAND * (powermax - powermin), + theta = DRAND * M_PI * 2.0, + u = DRAND * 2.0 - 1.0, + root = sqrt( 1 - u*u ); + xspeed = debrisParent->xspeed + module * root * cos(theta) * (1.0 + DRAND/3.0); + yspeed = debrisParent->yspeed + module * root * sin(theta) * (1.0 + DRAND/3.0); + zspeed = module * u * (1.0 + DRAND/3.0); //was 0.9 + DRAND/3 + + //if set add a displace to speed + if ( displace ) { + xspeed += displace[0]; + yspeed += displace[1]; + zspeed += displace[2]; + } + + //randomize the color choosing on current palette + colour[0] = c_red_min[cs] + (c_red_max[cs]-c_red_min[cs]) * DRAND; + colour[1] = c_green_min[cs] + (c_green_max[cs]-c_green_min[cs]) * DRAND; + colour[2] = c_blue_min[cs] + (c_blue_max[cs]-c_blue_min[cs]) * DRAND; + + pixelSize = DRAND * 2.0 + 2.0; + zacc = -9.807 / (6.0 - pixelSize); + + life = startLife = pixelSize / 2.0; + + //if flickers is set the current visible delay is randomized + if ( flickers ) + flicker = (int) ((DRAND * 2.0 - 1.0) * (float)FLICKER_FRAMES_DELAY); + break; + } +} + + +void Particle :: updateParameters( float dT ) +//note: this procedure uses a reduced set of parameters +// x and y axis acceleration is no more used +// the only external iterations are: +// - the g force +// - a sort of air friction that limits speed in x,y and +// acceleration on z +{ + xpos += xspeed * dT; + ypos += yspeed * dT; + zpos += (zspeed + zacc*dT/2) * dT; + + zspeed += zacc * dT; + + xspeed *= 0.998; + yspeed *= 0.998; + zspeed *= 0.999; + + if (useLife) + life -= dT; +} + + +// BEGIN TurningParticle class + +TurningParticle :: TurningParticle( ParticleType pT ) + : Particle( pT ) {} + +void TurningParticle :: initializeValues ( + int cs, + Particle* leader, + GLfloat powermin, + GLfloat powermax, + bool /*flickers*/, + GLfloat * /*displace*/ ) +{ + //same origin of the parent + xpos = leader->xpos; + ypos = leader->ypos; + zpos = leader->zpos; + + //velocity : true spherical randomization + float module = powermin + (powermax - powermin) * DRAND * 0.6, + theta = DRAND * M_PI * 2.0, + u = DRAND * 2.0 - 1.0, + root = sqrt( 1 - u*u ); + xspeed = -module * root * cos(theta); + yspeed = -module * root * sin(theta); + zspeed = module * u; + + //spin axis : in quadrature with velocity + module = (1 + DRAND) / 40; + u = DRAND * 2.0 - 1.0; + root = sqrt( 1 - u*u ); + // axis to spin around + wx = module * root * cos(theta + M_PI_2); + wy = module * root * sin(theta + M_PI_2); + wz = module * u; + + //randomize the color choosing on current palette + colour[0] = c_red_min[cs] + (c_red_max[cs]-c_red_min[cs]) * DRAND; + colour[1] = c_green_min[cs] + (c_green_max[cs]-c_green_min[cs]) * DRAND; + colour[2] = c_blue_min[cs] + (c_blue_max[cs]-c_blue_min[cs]) * DRAND; + + pixelSize = DRAND * 2.0 + 2.0; + zacc = -9.807 / 5.0; + life = startLife = pixelSize / 2.0; +} + + +void TurningParticle :: updateParameters ( float dT ) +{ + //update position + xpos += xspeed * dT; + ypos += yspeed * dT; + zpos += zspeed * dT; + + //tan vector = velocity vector (vect producted by) spin axis + float vx = yspeed * wz - zspeed * wy, + vy = zspeed * wx - xspeed * wz, + vz = xspeed * wy - yspeed * wx; + + //update velocity adding a tangential component (aka infinitesimally + //rotating the vector) + xspeed += vx; + yspeed += vy; + zspeed += vz + zacc * dT; + + if (useLife) + life -= dT; +} + +//END TurningParticle |