Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/particles/particle_emitter.cc @ 5587

Last change on this file since 5587 was 5445, checked in by bensch, 19 years ago

orxonox/trunk: Connection-Removing in the Particle-Class

File size: 9.4 KB
RevLine 
[4597]1/*
[3926]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
[3938]12   main-programmer: Benjamin Grauer
[3926]13   co-programmer: Patrick Boenzli
14*/
15
[5357]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
[3926]17
18#include "particle_emitter.h"
19
[3932]20#include "particle_system.h"
[3935]21#include "particle_engine.h"
[3932]22
[4437]23#include "load_param.h"
[4381]24#include "debug.h"
25#include "stdlibincl.h"
26
[3926]27using namespace std;
28
29
[4725]30CREATE_FACTORY(ParticleEmitter);
31
[3926]32/**
[4836]33 *  standard constructor
[3926]34*/
[4597]35ParticleEmitter::ParticleEmitter(const Vector& direction, float angle, float emissionRate,
36                  float velocity)
[3926]37{
[4726]38  this->init();
39
[4439]40  this->direction = direction;
41  this->setSpread(angle);
42  this->setEmissionRate(emissionRate);
43  this->setEmissionVelocity(velocity);
[4639]44
45  ParticleEngine::getInstance()->addEmitter(this);
[4437]46}
47
[4478]48/**
[4836]49 *  constructs and loads a ParticleEmitter from a XML-element
50 * @param root the XML-element to load from
[4478]51*/
[4437]52ParticleEmitter::ParticleEmitter(const TiXmlElement* root)
53{
[4726]54  this->init();
[4338]55
[5445]56   if (root != NULL)
[4437]57     this->loadParams(root);
58
[3935]59   ParticleEngine::getInstance()->addEmitter(this);
[3926]60}
61
62/**
[4836]63 *  standard destructor
[3926]64
[4496]65   removes the EmitterSystem from the ParticleEngine
[3926]66*/
[4597]67ParticleEmitter::~ParticleEmitter ()
[3935]68{
[3944]69  ParticleEngine::getInstance()->removeEmitter(this);
[3935]70}
[3929]71
[4478]72/**
[4726]73  \brief initializes default values of a ParitcleEmitter
74*/
75void ParticleEmitter::init()
76{
77  this->setClassID(CL_PARTICLE_EMITTER, "ParticleEmitter");
78
79  this->type = PARTICLE_EMITTER_DEFAULT_TYPE;
80  this->emitterSize = PARTICLE_EMITTER_DEFAULT_SIZE;
81  this->setInheritSpeed(PARTICLE_EMITTER_DEFAULT_INHERIT_SPEED);
82  this->setEmissionRate(PARTICLE_EMITTER_DEFAULT_EMISSION_RATE);
83  this->setSize(PARTICLE_EMITTER_DEFAULT_SIZE);
84
85  this->saveTime = 0.0;
86}
87
88/**
[4836]89 *  loads a ParticleEmitter from a XML-element
90 * @param root the XML-element to load from
[4478]91*/
[4437]92void ParticleEmitter::loadParams(const TiXmlElement* root)
93{
94  static_cast<PNode*>(this)->loadParams(root);
[3929]95
[4437]96  LoadParam<ParticleEmitter>(root, "type", this, &ParticleEmitter::setType)
97    .describe("What type of emitter is this [dot, plane, cube, sphere].");
98
99  LoadParam<ParticleEmitter>(root, "size", this, &ParticleEmitter::setSize)
100    .describe("How big the emitter is (no effect on dot-emitters)");
101
102  LoadParam<ParticleEmitter>(root, "rate", this, &ParticleEmitter::setEmissionRate)
103    .describe("How many particles should be emittet from this emitter");
104
[4494]105  LoadParam<ParticleEmitter>(root, "inherit-speed", this, &ParticleEmitter::setInheritSpeed)
106    .describe("the extent, the speed of the emitter has on the particles");
107
[4437]108  LoadParam<ParticleEmitter>(root, "emission-velocity", this, &ParticleEmitter::setEmissionVelocity)
109    .describe("How fast the particles are emittet (their initial speed)");
[4597]110
[4725]111  LoadParam<ParticleEmitter>(root, "emission-momentum", this, &ParticleEmitter::setEmissionMomentum)
112      .describe("How fast the particles rotation is at emissiontime (their initial momentum)");
113
[4437]114  LoadParam<ParticleEmitter>(root, "spread", this, &ParticleEmitter::setSpread)
115    .describe("The angle the particles are emitted from (angle, deviation)");
[4726]116
117
118  LoadParam<ParticleEmitter>(root, "emission-direction", this, &ParticleEmitter::setDirection);
[4437]119}
120
[3929]121/**
[4836]122 *  this start the emitter
[3929]123*/
124void ParticleEmitter::start() {}
125
126
127/**
[4836]128 *  this stops the emitter
[3929]129*/
130void ParticleEmitter::stop() {}
131
132
133
134
135
136/**
[4836]137 * @param type the new Type of this emitter
[4338]138*/
139void ParticleEmitter::setType(EMITTER_TYPE type)
140{
141  this->type = type;
142}
143
[4437]144/**
[4836]145 *  sets the type of emitter
146 * @param type the type as a const char*
[4478]147   dot: EMITTER_DOT, plane: EMITTER_PLANE, cube: EMITTER_CUBE, sphere, EMITTER_SPHERE;
[4437]148*/
149void ParticleEmitter::setType(const char* type)
150{
151  if (!strcmp(type, "plane"))
[4639]152    this->setType(EMITTER_PLANE);
[4437]153  else if (!strcmp(type, "cube"))
[4639]154    this->setType(EMITTER_CUBE);
[4437]155  else if (!strcmp(type, "sphere"))
[4639]156    this->setType(EMITTER_SPHERE);
[4437]157  else
[4639]158    this->setType(EMITTER_DOT);
[4437]159}
160
[4746]161const char* ParticleEmitter::getTypeC() const
[4639]162{
163  if (this->type == EMITTER_PLANE)
164    return "EMITTER_PLANE";
165  else if (this->type == EMITTER_CUBE)
166    return "EMITTER_CUBE";
167  else if (this->type == EMITTER_SPHERE)
168    return "EMITTER_SPHERE";
169  else
170    return "EMITTER_DOT";
171}
172
[4478]173/**
[4836]174 *  sets a new size to the emitter
[4478]175*/
[4338]176void ParticleEmitter::setSize(float emitterSize)
177{
178  if (emitterSize > 0.0)
179    this->emitterSize = emitterSize;
180  else
181    emitterSize = 0.0;
182}
183
184/**
[4836]185 *  set the emission rate
186 * @param emissionRate: sets the number of particles emitted per second
[3929]187
188   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]189   you may want to use the animation class
[3929]190*/
[3931]191void ParticleEmitter::setEmissionRate(float emissionRate)
[3933]192{
[4338]193  if (emissionRate > 0.0)
194    this->emissionRate = emissionRate;
195  else
196    this->emissionRate = 0.0;
[3933]197}
[3929]198
199/**
[4836]200 *  how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
201 * @param value a Value between zero and one
[4493]202
203   if you want to change the value of this variable during emission time (to make it more dynamic)
204   you may want to use the animation class
205*/
206void ParticleEmitter::setInheritSpeed(float value)
207{
208  if (unlikely(value > 1.0))
209    this->inheritSpeed = 1;
210  else if (unlikely(value < 0.0))
211    this->inheritSpeed = 0;
212  else
213    this->inheritSpeed = value;
214}
215
216/**
[4836]217 *  set the angle of the emitter
218 * @param angle around the direction in which there are particles to be emitted
219 * @param randomAngle A random spread-angle, the +- randomness of this option
[3929]220
221   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]222   you may want to use the animation class
[3929]223*/
[3931]224void ParticleEmitter::setSpread(float angle, float randomAngle)
[3935]225{
226  this->angle = angle;
227  this->randomAngle = randomAngle;
228}
[3929]229
230/**
[4836]231 *  sets the initial velocity of all particles emitted
232 * @param velocity The starting velocity of the emitted particles
233 * @param randomVelocity A random starting velocity, the +- randomness of this option
[3929]234
235   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]236   you may want to use the animation class
[3929]237*/
[4338]238void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
[3935]239{
240  this->velocity = velocity;
241  this->randomVelocity = randomVelocity;
242}
[3929]243
244/**
[4836]245 *  sets the initial Momentum of all particles emitted
246 * @param momentum the new Momentum (just a float for being not too complicated).
247 * @param randomMomentum variation from the given value.
[4690]248 */
249void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum)
250{
251  this->momentum = momentum;
252  this->momentumRandom = randomMomentum;
253}
254
255/**
[4836]256 *  this set the time to life of a particle, after which it will die
257 * @param dt: the time to live in seconds
258 * @param system: the system into which to emitt
[3929]259
260   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]261   you may want to use the animation class
[3929]262*/
[3932]263void ParticleEmitter::tick(float dt, ParticleSystem* system)
264{
[3950]265  if (likely(dt > 0.0 && this->emissionRate > 0.0))
266  {
[4692]267    // saving the time (particles only partly emitted in this timestep)
[3950]268    float count = (dt+this->saveTime) * this->emissionRate;
[4017]269    this->saveTime = modff(count, &count) / this->emissionRate;
[4692]270    PRINTF(5)("emitting %f particles, saving %f seconds for the next timestep\n", count, this->saveTime);
[4597]271
[4017]272    if (likely(count > 0))
[4690]273    {
274      Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
[4693]275      for (int i = 0; i < (int)count; i++)
[3950]276      {
[4690]277        Vector randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
278        randDir.normalize();
279        randDir = (this->getAbsDir()*Quaternion(angle + randomAngle *((float)rand()/RAND_MAX -.5), randDir)).apply(this->direction);
280        Vector velocityV = randDir.getNormalized()*this->velocity + inheritVelocity;
[4176]281
[4692]282        // this should spread the Particles evenly. if the Emitter is moved around quickly
[4690]283        Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
284        Vector extension; // the Vector for different fields.
[4176]285
[4692]286        if (this->type & EMITTER_PLANE)
[4690]287        {
288          extension = Vector(this->emitterSize * ((float)rand()/RAND_MAX -.5), 0, this->emitterSize * ((float)rand()/RAND_MAX - .5));
289          extension = this->getAbsDir().apply(extension);
290        }
[4692]291        else if (this->type & EMITTER_CUBE)
[4690]292        {
293          extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
294        }
[4338]295
[4597]296
[4690]297        // ROTATIONAL CALCULATION (this must not be done for all types of particles.)
298        randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
299        randDir.normalize();
300        Quaternion orient = Quaternion(M_PI, randDir);
301        Quaternion moment = Quaternion(this->momentum + this->momentumRandom, randDir);
302
303        system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV, orient, moment);
[3950]304      }
[4690]305    }
[3950]306  }
[3932]307}
[3944]308
309/**
[4836]310 *  outputs some nice debug information
[3944]311*/
[4746]312void ParticleEmitter::debug() const
[3944]313{
[4493]314  PRINT(0)(" Emitter %s\n", this->getName());
[4639]315  PRINT(0)("  EmissionRate: %f, Speed: %f, SpreadAngle: %f\n", this->getEmissionRate(), this->getEmissionVelocity(), this->getSpread());
316  PRINT(0)("  Size %f, Type: %s\n", this->getSize(), this->getTypeC());
[3944]317}
Note: See TracBrowser for help on using the repository browser.