Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6429 was 5750, checked in by bensch, 19 years ago

orxonox/trunk: merged the WorldEntities into the Trunk.
Merged with command:
svn merge branches/world_entities/ trunk/ -r5516:HEAD

conflics from world_entities changed in favor of branches/world_entity
all other conflict in favor of the trunk

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