Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: further cleanup

File size: 9.3 KB
Line 
1/*
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:
12   main-programmer: Benjamin Grauer
13   co-programmer: Patrick Boenzli
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
17
18#include "particle_emitter.h"
19
20#include "particle_system.h"
21#include "particle_engine.h"
22
23#include "load_param.h"
24#include "factory.h"
25#include "debug.h"
26#include "stdlibincl.h"
27
28using namespace std;
29
30
31CREATE_FACTORY(ParticleEmitter);
32
33/**
34 *  standard constructor
35*/
36ParticleEmitter::ParticleEmitter(const Vector& direction, float angle, float emissionRate,
37                  float velocity)
38{
39  this->init();
40
41  this->direction = direction;
42  this->setSpread(angle);
43  this->setEmissionRate(emissionRate);
44  this->setEmissionVelocity(velocity);
45
46  ParticleEngine::getInstance()->addEmitter(this);
47}
48
49/**
50 *  constructs and loads a ParticleEmitter from a XML-element
51 * @param root the XML-element to load from
52*/
53ParticleEmitter::ParticleEmitter(const TiXmlElement* root)
54{
55  this->init();
56
57   if (root != NULL)
58     this->loadParams(root);
59
60   ParticleEngine::getInstance()->addEmitter(this);
61}
62
63/**
64 *  standard destructor
65
66   removes the EmitterSystem from the ParticleEngine
67*/
68ParticleEmitter::~ParticleEmitter ()
69{
70  ParticleEngine::getInstance()->removeEmitter(this);
71}
72
73/**
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/**
90 *  loads a ParticleEmitter from a XML-element
91 * @param root the XML-element to load from
92*/
93void ParticleEmitter::loadParams(const TiXmlElement* root)
94{
95  static_cast<PNode*>(this)->loadParams(root);
96
97  LoadParamNEW(root, "type", this, ParticleEmitter, setType)
98    .describe("What type of emitter is this [dot, plane, cube, sphere].");
99
100  LoadParamNEW(root, "size", this, ParticleEmitter, setSize)
101    .describe("How big the emitter is (no effect on dot-emitters)");
102
103  LoadParamNEW(root, "rate", this, ParticleEmitter, setEmissionRate)
104    .describe("How many particles should be emittet from this emitter");
105
106  LoadParamNEW(root, "inherit-speed", this, ParticleEmitter, setInheritSpeed)
107    .describe("the extent, the speed of the emitter has on the particles");
108
109  LoadParamNEW(root, "emission-velocity", this, ParticleEmitter, setEmissionVelocity)
110    .describe("How fast the particles are emittet (their initial speed)");
111
112  LoadParamNEW(root, "emission-momentum", this, ParticleEmitter, setEmissionMomentum)
113      .describe("How fast the particles rotation is at emissiontime (their initial momentum)");
114
115  LoadParamNEW(root, "spread", this, ParticleEmitter, setSpread)
116    .describe("The angle the particles are emitted from (angle, deviation)");
117
118
119  LoadParamNEW(root, "emission-direction", this, ParticleEmitter, setDirection);
120}
121
122/**
123 *  this start the emitter
124*/
125void ParticleEmitter::start() {}
126
127
128/**
129 *  this stops the emitter
130*/
131void ParticleEmitter::stop() {}
132
133
134
135
136
137/**
138 * @param type the new Type of this emitter
139*/
140void ParticleEmitter::setType(EMITTER_TYPE type)
141{
142  this->type = type;
143}
144
145/**
146 *  sets the type of emitter
147 * @param type the type as a const char*
148   dot: EMITTER_DOT, plane: EMITTER_PLANE, cube: EMITTER_CUBE, sphere, EMITTER_SPHERE;
149*/
150void ParticleEmitter::setType(const char* type)
151{
152  if (!strcmp(type, "plane"))
153    this->setType(EMITTER_PLANE);
154  else if (!strcmp(type, "cube"))
155    this->setType(EMITTER_CUBE);
156  else if (!strcmp(type, "sphere"))
157    this->setType(EMITTER_SPHERE);
158  else
159    this->setType(EMITTER_DOT);
160}
161
162const char* ParticleEmitter::getTypeC() const
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
174/**
175 *  sets a new size to the emitter
176*/
177void ParticleEmitter::setSize(float emitterSize)
178{
179  if (emitterSize > 0.0)
180    this->emitterSize = emitterSize;
181  else
182    emitterSize = 0.0;
183}
184
185/**
186 *  set the emission rate
187 * @param emissionRate: sets the number of particles emitted per second
188
189   if you want to change the value of this variable during emission time (to make it more dynamic)
190   you may want to use the animation class
191*/
192void ParticleEmitter::setEmissionRate(float emissionRate)
193{
194  if (emissionRate > 0.0)
195    this->emissionRate = emissionRate;
196  else
197    this->emissionRate = 0.0;
198}
199
200/**
201 *  how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
202 * @param value a Value between zero and one
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/**
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
221
222   if you want to change the value of this variable during emission time (to make it more dynamic)
223   you may want to use the animation class
224*/
225void ParticleEmitter::setSpread(float angle, float randomAngle)
226{
227  this->angle = angle;
228  this->randomAngle = randomAngle;
229}
230
231/**
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
235
236   if you want to change the value of this variable during emission time (to make it more dynamic)
237   you may want to use the animation class
238*/
239void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
240{
241  this->velocity = velocity;
242  this->randomVelocity = randomVelocity;
243}
244
245/**
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.
249 */
250void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum)
251{
252  this->momentum = momentum;
253  this->momentumRandom = randomMomentum;
254}
255
256/**
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
260
261   if you want to change the value of this variable during emission time (to make it more dynamic)
262   you may want to use the animation class
263*/
264void ParticleEmitter::tick(float dt, ParticleSystem* system)
265{
266  if (likely(dt > 0.0 && this->emissionRate > 0.0))
267  {
268    // saving the time (particles only partly emitted in this timestep)
269    float count = (dt+this->saveTime) * this->emissionRate;
270    this->saveTime = modff(count, &count) / this->emissionRate;
271    PRINTF(5)("emitting %f particles, saving %f seconds for the next timestep\n", count, this->saveTime);
272
273    if (likely(count > 0))
274    {
275      Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
276      for (int i = 0; i < (int)count; i++)
277      {
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;
282
283        // this should spread the Particles evenly. if the Emitter is moved around quickly
284        Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
285        Vector extension; // the Vector for different fields.
286
287        if (this->type & EMITTER_PLANE)
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        }
292        else if (this->type & EMITTER_CUBE)
293        {
294          extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
295        }
296
297
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);
305      }
306    }
307  }
308}
309
310/**
311 *  outputs some nice debug information
312*/
313void ParticleEmitter::debug() const
314{
315  PRINT(0)(" Emitter %s\n", this->getName());
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());
318}
Note: See TracBrowser for help on using the repository browser.