Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6620 was 6620, checked in by bensch, 18 years ago

trunk: particle-optimisation

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