00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 ¤t,
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 }