ParticleEmitter.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <common/Defines.h>
00022 #include <graph/ParticleEmitter.h>
00023 #include <sprites/DebrisActionRenderer.h>
00024 #include <sprites/SmokeActionRenderer.h>
00025 #include <sprites/ExplosionTextures.h>
00026 #include <sprites/NapalmRenderer.h>
00027 #include <sprites/ExplosionNukeRenderer.h>
00028 #include <sprites/WallActionRenderer.h>
00029 #include <landscape/Landscape.h>
00030 #include <math.h>
00031 #include <stdlib.h>
00032 
00033 static void randomVector(Vector &result, Vector &start, Vector &end)
00034 {
00035         result[0] = start[0] + ((end[0] - start[0]) * RAND);
00036         result[1] = start[1] + ((end[1] - start[1]) * RAND);
00037         result[2] = start[2] + ((end[2] - start[2]) * RAND);
00038 }
00039 
00040 static void randomCounterVector(Vector &result, Vector &current, 
00041                                                                 Vector &start, Vector &end,
00042                                                                 float life)
00043 {
00044         randomVector(result, start, end);
00045         result -= current;
00046         result /= life;
00047 }
00048 
00049 static float randomScalar(float start, float end)
00050 {
00051         return start + ((end - start) * RAND);
00052 }
00053 
00054 static float randomCounterScalar(float current, 
00055                                                                 float start, float end,
00056                                                                 float life)
00057 {
00058         float result = randomScalar(start, end);
00059         result -= current;
00060         result /= life;
00061         return result;
00062 }
00063 
00064 ParticleEmitter::ParticleEmitter()
00065 {
00066 }
00067 
00068 ParticleEmitter::~ParticleEmitter()
00069 {
00070 }
00071 
00072 void ParticleEmitter::setLife(float life1, float life2)
00073 {
00074         life1_ = life1; life2_ = life2;
00075 }
00076 
00077 void ParticleEmitter::setMass(float mass1, float mass2)
00078 {
00079         mass1_ = mass1; mass2_ = mass2;
00080 }
00081 
00082 void ParticleEmitter::setFriction(float friction1, float friction2)
00083 {
00084         friction1_ = friction1; friction2_ = friction2;
00085 }
00086         
00087 void ParticleEmitter::setStartColor(
00088                 Vector startColor1, float startAlpha1,
00089                 Vector startColor2, float startAlpha2)
00090 {
00091         startAlpha1_ = startAlpha1; endAlpha1_ = startAlpha1; 
00092         startAlpha2_ = startAlpha2; endAlpha2_ = startAlpha2;
00093         startColor1_ = startColor1; endColor1_ = startColor1;
00094         startColor2_ = startColor2; endColor2_ = startColor2;
00095 }
00096 
00097 void ParticleEmitter::setEndColor(
00098                 Vector endColor1, float endAlpha1,
00099                 Vector endColor2, float endAlpha2)
00100 {
00101         endColor1_ = endColor1; endAlpha1_ = endAlpha1;
00102         endColor2_ = endColor2; endAlpha2_ = endAlpha2;
00103 }
00104 
00105 void ParticleEmitter::setVelocity(Vector velocity1, Vector velocity2)
00106 {
00107         velocity1_ = velocity1; velocity2_ = velocity2;
00108 }
00109 
00110 void ParticleEmitter::setStartSize(
00111                 float startX1, float startY1,
00112                 float startX2, float startY2)
00113 {
00114         startSize1_[0] = startX1; startSize1_[1] = startY1;
00115         startSize2_[0] = startX2; startSize2_[1] = startY2;
00116 }
00117 
00118 void ParticleEmitter::setEndSize(
00119                 float endX1, float endY1,
00120                 float endX2, float endY2)
00121 {
00122         endSize1_[0] = endX1; endSize1_[1] = endY1;
00123         endSize2_[0] = endX2; endSize2_[1] = endY2;
00124 }
00125 
00126 void ParticleEmitter::setGravity(Vector gravity)
00127 {
00128         gravity_ = gravity;
00129 }
00130 
00131 void ParticleEmitter::setAdditiveTexture(bool additiveTexture)
00132 {
00133         additiveTexture_ = additiveTexture;
00134 }
00135 
00136 void ParticleEmitter::setWindAffect(bool windAffect)
00137 {
00138         windAffect_ = windAffect;
00139 }
00140 
00141 void ParticleEmitter::setAttributes(
00142         float life1, float life2,
00143         float mass1, float mass2,
00144         float friction1, float friction2,
00145         Vector velocity1, Vector velocity2,
00146         Vector startColor1, float startAlpha1,
00147         Vector startColor2, float startAlpha2,
00148         Vector endColor1, float endAlpha1,
00149         Vector endColor2, float endAlpha2,
00150         float startX1, float startY1,
00151         float startX2, float startY2,
00152         float endX1, float endY1,
00153         float endX2, float endY2,
00154         Vector gravity,
00155         bool additiveTexture,
00156         bool windAffect)
00157 {
00158         setLife(life1, life2);
00159         setMass(mass1, mass2);
00160         setFriction(friction1, friction2);
00161         setVelocity(velocity1, velocity2);
00162         setStartColor(startColor1, startAlpha1,
00163                 startColor2, startAlpha2);
00164         setEndColor(endColor1, endAlpha1,
00165                 endColor2, endAlpha2);
00166         setStartSize(startX1, startY1,
00167                 startX2, startY2);
00168         setEndSize(endX1, endY1,
00169                 endX2, endY2);
00170         setGravity(gravity);
00171         setAdditiveTexture(additiveTexture);
00172         setWindAffect(windAffect);
00173 }
00174 
00175 void ParticleEmitter::createDefaultParticle(Particle &particle)
00176 {
00177         float life = randomScalar(life1_, life2_);
00178         float mass = randomScalar(mass1_, mass2_);
00179         float friction = randomScalar(friction1_, friction2_);
00180         float alpha = randomScalar(startAlpha1_, startAlpha2_);
00181         float alphac = randomCounterScalar(alpha, endAlpha1_, endAlpha2_, life);
00182 
00183         Vector velocity;
00184         randomVector(velocity, velocity1_, velocity2_);
00185         Vector color, colorc;
00186         randomVector(color, startColor1_, startColor2_);
00187         randomCounterVector(colorc, color, endColor1_, endColor2_, life);
00188         Vector size, sizec;
00189         randomVector(size, startSize1_, startSize2_);
00190         randomCounterVector(sizec, size, endSize1_, endSize2_, life);
00191 
00192         particle.setParticle(life, mass, 
00193                 friction, velocity, gravity_,
00194                 color, colorc, 
00195                 size, sizec, 
00196                 alpha, alphac,
00197                 additiveTexture_,
00198                 windAffect_);
00199 }
00200 
00201 void ParticleEmitter::emitLinear(int number, 
00202         Vector &position1, Vector &position2,
00203         ParticleEngine &engine,
00204         ParticleRenderer *renderer)
00205 {
00206         for (int i=0; i<number; i++)
00207         {
00208                 Particle *particle = engine.getNextAliveParticle();
00209                 if (!particle) return;
00210 
00211                 Vector position;
00212                 randomVector(position, position1, position2);
00213 
00214                 createDefaultParticle(*particle);
00215                 particle->texture_ = &ExplosionTextures::instance()->particleTexture;
00216                 particle->position_ = position;
00217                 particle->renderer_ = renderer;
00218         }
00219 }
00220 
00221 void ParticleEmitter::emitExplosionRing(int number,
00222         Vector &position,
00223         ParticleEngine &engine,
00224         ParticleRenderer *renderer)
00225 {
00226         for (int i=0; i<number; i++)
00227         {
00228                 Particle *particle = engine.getNextAliveParticle();
00229                 if (!particle) return;
00230 
00231                 createDefaultParticle(*particle);
00232 
00233                 Vector velocity;
00234                 float ang = RAND * 2.0f * 3.14f;
00235                 float speed = 45.0f;
00236                 velocity[0] = getFastSin(ang) * speed;
00237                 velocity[1] = getFastCos(ang) * speed;
00238                 velocity[2] = 0.0f;
00239 
00240                 particle->texture_ = &ExplosionTextures::instance()->particleTexture;
00241                 particle->velocity_ = velocity;
00242                 particle->position_ = position;
00243                 particle->renderer_ = renderer;
00244         }
00245 }
00246 
00247 void ParticleEmitter::emitDebris(int number,
00248         Vector &position,
00249         ParticleEngine &engine)
00250 {
00251         for (int i=0; i<number; i++)
00252         {
00253                 Particle *particle = engine.getNextAliveParticle();
00254                 if (!particle) return;
00255 
00256                 createDefaultParticle(*particle);
00257 
00258                 float direction = RAND * 3.14f * 2.0f;
00259                 float speed = RAND * 25.0f + 5.0f;
00260                 float height = RAND * 25.0f + 15.0f;
00261                 Vector velocity(getFastSin(direction) * speed, 
00262                         getFastCos(direction) * speed, height);
00263 
00264                 if (RAND > 0.5f)
00265                 {
00266                         DebrisActionRenderer *debris = new DebrisActionRenderer;
00267                         particle->velocity_ = velocity;
00268                         particle->position_ = position;
00269                         particle->renderer_ = ParticleRendererDebris::getInstance();
00270                         particle->userData_ = debris;
00271                 }
00272                 else
00273                 {
00274                         SmokeActionRenderer *smoke = new SmokeActionRenderer;
00275                         particle->velocity_ = velocity;
00276                         particle->position_ = position;
00277                         particle->renderer_ = ParticleRendererSmoke::getInstance();
00278                         particle->userData_ = smoke;
00279                 }
00280         }
00281 }
00282 
00283 void ParticleEmitter::emitSmoke(int number,
00284         Vector &position,
00285         ParticleEngine &engine)
00286 {
00287         for (int i=0; i<number; i++)
00288         {
00289                 Particle *particle = engine.getNextAliveParticle();
00290                 if (!particle) return;
00291 
00292                 createDefaultParticle(*particle);
00293 
00294                 particle->position_ = position;
00295                 particle->renderer_ = ParticleRendererQuads::getInstance();
00296                 particle->texture_ = &ExplosionTextures::instance()->smokeTexture;
00297                 particle->shadow_ = (RAND > 0.25f);
00298                 particle->textureCoord_ = (int) (RAND * 4.0f);
00299         }
00300 }
00301 
00302 void ParticleEmitter::emitNapalm(
00303         Vector &position,
00304         ParticleEngine &engine,
00305         GLTextureSet *set)
00306 {
00307         Particle *particle = engine.getNextAliveParticle();
00308         if (!particle) return;
00309 
00310         createDefaultParticle(*particle);
00311 
00312         particle->position_ = position;
00313         particle->renderer_ = ParticleRendererNapalm::getInstance();
00314         particle->textureCoord_ = 0;
00315         particle->userData_ = new NapalmRenderer(set);
00316 }
00317 
00318 void ParticleEmitter::emitSpray(
00319         Vector &position,
00320         ParticleEngine &engine,
00321         float width,
00322         GLTexture *texture)
00323 {
00324         for (int i=0; i<6 + int(width) * 2; i++)
00325         {
00326                 Particle *particle = engine.getNextAliveParticle();
00327                 if (!particle) return;
00328 
00329                 createDefaultParticle(*particle);
00330 
00331                 float rotation = RAND * 2.0f * 3.14f;
00332                 float x = sinf(rotation);
00333                 float y = cosf(rotation);
00334                 Vector pos = position;
00335                 pos[0] += (x * width * RAND);
00336                 pos[1] += (y * width * RAND);
00337                 Vector velocity;
00338                 velocity[0] = (x * RAND) / 10.0f;
00339                 velocity[1] = (y * RAND) / 10.0f;
00340                 velocity[2] = 25.0f * RAND + 15.0f;
00341 
00342                 particle->texture_ = texture;
00343                 particle->velocity_ = velocity;
00344                 particle->position_ = pos;
00345                 particle->renderer_ = ParticleRendererQuads::getInstance();
00346                 particle->textureCoord_ = (int) (RAND * 4.0f);
00347         }
00348 }
00349 
00350 void ParticleEmitter::emitTalk(
00351         Vector &position,
00352         ParticleEngine &engine)
00353 {
00354         Particle *particle = engine.getNextAliveParticle();
00355         if (!particle) return;
00356 
00357         createDefaultParticle(*particle);
00358 
00359         particle->position_ = position;
00360         particle->renderer_ = ParticleRendererQuads::getInstance();
00361         particle->textureCoord_ = 0;
00362         particle->texture_ = &ExplosionTextures::instance()->talkTexture;
00363 }
00364 
00365 void ParticleEmitter::emitWallHit(
00366         Vector &position,
00367         ParticleEngine &engine,
00368         OptionsTransient::WallSide type)
00369 {
00370         Particle *particle = engine.getNextAliveParticle();
00371         if (!particle) return;
00372 
00373         createDefaultParticle(*particle);
00374 
00375         particle->position_ = position;
00376         particle->renderer_ = ParticleRendererWall::getInstance();
00377         particle->userData_ = new WallActionRenderer(position, type);
00378 }
00379 
00380 void ParticleEmitter::emitTransport(
00381         Vector &position,
00382         ParticleEngine &engine,
00383         GLTextureSet *set)
00384 {
00385         Particle *particle = engine.getNextAliveParticle();
00386         if (!particle) return;
00387 
00388         Vector velocity;
00389         createDefaultParticle(*particle);
00390 
00391         particle->position_ = position;
00392         particle->renderer_ = ParticleRendererQuads::getInstance();
00393         particle->textureCoord_ = 0;
00394         particle->textureSet_ = set;
00395 }
00396 
00397 void ParticleEmitter::emitExplosion(
00398         Vector &position,
00399         ParticleEngine &engine,
00400         float width,
00401         GLTextureSet *set,
00402         bool animate)
00403 {
00404         for (int i=0; i<int(width) * 4; i++)
00405         {
00406                 Particle *particle = engine.getNextAliveParticle();
00407                 if (!particle) return;
00408 
00409                 float randRotXY = (RAND * TWOPI);
00410                 float randRotXZ = (RAND * TWOPI);
00411                 float cosRandRotXZ = (float) cos(randRotXZ);
00412                 Vector velocity;
00413                 velocity[0] = float(sin(randRotXY) * cosRandRotXZ);
00414                 velocity[1] = float(cos(randRotXY) * cosRandRotXZ);
00415                 velocity[2] = float(sin(randRotXZ));
00416                 velocity *= (width * 2.5f);
00417 
00418                 float size = RAND * width * 2.0f + 2.0f;
00419 
00420                 setEndSize(size, size, size, size);
00421 
00422                 createDefaultParticle(*particle);
00423 
00424                 particle->velocity_ = velocity;
00425                 particle->position_ = position;
00426                 particle->renderer_ = ParticleRendererQuads::getInstance();
00427                 particle->textureCoord_ = int(RAND * 4.0f);
00428                 if (animate)
00429                 {
00430                         particle->textureSet_ = set;
00431                 }
00432                 else
00433                 {
00434                         int index = MIN(int(RAND * (set->getNoTextures() - 1)), set->getNoTextures() - 1);
00435                         particle->texture_ = set->getTexture(index);
00436                 }
00437         }
00438 }
00439 
00440 void ParticleEmitter::emitMushroom(
00441         Vector &position,
00442         ParticleEngine &engine,
00443         int number,
00444         float width)
00445 {
00446         for (int i=0; i<number; i++)
00447         {
00448                 Particle *particle = engine.getNextAliveParticle();
00449                 if (!particle) return;
00450 
00451                 createDefaultParticle(*particle);
00452 
00453                 particle->position_ = position;
00454                 particle->renderer_ = ParticleRendererMushroom::getInstance();
00455                 particle->textureCoord_ = int(RAND * 4.0f);
00456                 particle->texture_ = &ExplosionTextures::instance()->smokeTexture;
00457                 particle->shadow_ = (RAND > 0.80f);
00458                 particle->userData_ = new ExplosionNukeRendererEntry(position, width);
00459         }
00460 }
00461 
00462 void ParticleEmitter::emitPrecipitation(
00463         Vector &position,
00464         ParticleEngine &engine,
00465         int number,
00466         bool rain)
00467 {
00468         for (int i=0; i<number; i++)
00469         {
00470                 Particle *particle = engine.getNextAliveParticle();
00471                 if (!particle) return;
00472 
00473                 createDefaultParticle(*particle);
00474 
00475                 if (rain)
00476                 {
00477                         particle->texture_ = &ExplosionTextures::instance()->rainTexture;
00478                         particle->renderer_ = ParticleRendererRain::getInstance();
00479                 }
00480                 else
00481                 {
00482                         particle->texture_ = &ExplosionTextures::instance()->snowTexture;
00483                         particle->renderer_ = ParticleRendererSnow::getInstance();
00484                 }
00485                 particle->position_[0] = position[0] + RAND * 400.0f - 200.0f;
00486                 particle->position_[1] = position[1] + RAND * 400.0f - 200.0f;
00487                 particle->position_[2] = 180.0f;
00488                 particle->shadow_ = false;
00489         }
00490 }

Generated on Mon Feb 16 15:14:46 2009 for Scorched3D by  doxygen 1.5.3