Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: ParticleSystem and Emitter get Deleted correctly

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
22#include "load_param.h"
23#include "factory.h"
24#include "debug.h"
25#include "stdlibincl.h"
26
27using namespace std;
28
29
30CREATE_FACTORY(ParticleEmitter, CL_PARTICLE_EMITTER);
31
32/**
33 *  standard constructor
34*/
35ParticleEmitter::ParticleEmitter(const Vector& direction, float angle, float emissionRate,
36                  float velocity)
37{
38  this->init();
39
40  this->direction = direction;
41  this->setSpread(angle);
42  this->setEmissionRate(emissionRate);
43  this->setEmissionVelocity(velocity);
44
45}
46
47/**
48 *  constructs and loads a ParticleEmitter from a XML-element
49 * @param root the XML-element to load from
50*/
51ParticleEmitter::ParticleEmitter(const TiXmlElement* root)
52{
53  this->init();
54
55   if (root != NULL)
56     this->loadParams(root);
57}
58
59/**
60 *  standard destructor
61
62   removes the EmitterSystem from the ParticleEngine
63*/
64ParticleEmitter::~ParticleEmitter ()
65{
66  this->setSystem(NULL);
67}
68
69/**
70  @brief initializes default values of a ParitcleEmitter
71*/
72void ParticleEmitter::init()
73{
74  this->setClassID(CL_PARTICLE_EMITTER, "ParticleEmitter");
75
76  this->type = PARTICLE_EMITTER_DEFAULT_TYPE;
77  this->emitterSize = PARTICLE_EMITTER_DEFAULT_SIZE;
78  this->setInheritSpeed(PARTICLE_EMITTER_DEFAULT_INHERIT_SPEED);
79  this->setEmissionRate(PARTICLE_EMITTER_DEFAULT_EMISSION_RATE);
80  this->setSize(PARTICLE_EMITTER_DEFAULT_SIZE);
81
82  this->system = NULL;
83
84  this->saveTime = 0.0;
85}
86
87/**
88 *  loads a ParticleEmitter from a XML-element
89 * @param root the XML-element to load from
90*/
91void ParticleEmitter::loadParams(const TiXmlElement* root)
92{
93  PNode::loadParams(root);
94
95  LoadParam(root, "type", this, ParticleEmitter, setType)
96    .describe("What type of emitter is this [dot, plane, cube, sphere].");
97
98  LoadParam(root, "size", this, ParticleEmitter, setSize)
99    .describe("How big the emitter is (no effect on dot-emitters)");
100
101  LoadParam(root, "rate", this, ParticleEmitter, setEmissionRate)
102    .describe("How many particles should be emittet from this emitter");
103
104  LoadParam(root, "inherit-speed", this, ParticleEmitter, setInheritSpeed)
105    .describe("the extent, the speed of the emitter has on the particles");
106
107  LoadParam(root, "emission-velocity", this, ParticleEmitter, setEmissionVelocity)
108    .describe("How fast the particles are emittet (their initial speed)");
109
110  LoadParam(root, "emission-momentum", this, ParticleEmitter, setEmissionMomentum)
111      .describe("How fast the particles rotation is at emissiontime (their initial momentum)");
112
113  LoadParam(root, "spread", this, ParticleEmitter, setSpread)
114    .describe("The angle the particles are emitted from (angle, deviation)");
115
116
117  LoadParam(root, "emission-direction", this, ParticleEmitter, setDirection);
118}
119
120void ParticleEmitter::setSystem(ParticleSystem* system)
121{
122  if (system != NULL)
123    system->addEmitter(this);
124  else if (this->system != NULL)
125    this->system->removeEmitter(this);
126}
127
128/**
129 *  this start the emitter
130*/
131void ParticleEmitter::start() {}
132
133
134/**
135 *  this stops the emitter
136*/
137void ParticleEmitter::stop() {}
138
139
140
141
142
143/**
144 * @param type the new Type of this emitter
145*/
146void ParticleEmitter::setType(EMITTER_TYPE type)
147{
148  this->type = type;
149}
150
151/**
152 *  sets the type of emitter
153 * @param type the type as a const char*
154   dot: EMITTER_DOT, plane: EMITTER_PLANE, cube: EMITTER_CUBE, sphere, EMITTER_SPHERE;
155*/
156void ParticleEmitter::setType(const char* type)
157{
158  if (!strcmp(type, "plane"))
159    this->setType(EMITTER_PLANE);
160  else if (!strcmp(type, "cube"))
161    this->setType(EMITTER_CUBE);
162  else if (!strcmp(type, "sphere"))
163    this->setType(EMITTER_SPHERE);
164  else
165    this->setType(EMITTER_DOT);
166}
167
168const char* ParticleEmitter::getTypeC() const
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
180/**
181 *  sets a new size to the emitter
182*/
183void ParticleEmitter::setSize(float emitterSize)
184{
185  if (emitterSize > 0.0)
186    this->emitterSize = emitterSize;
187  else
188    emitterSize = 0.0;
189}
190
191/**
192 *  set the emission rate
193 * @param emissionRate: sets the number of particles emitted per second
194
195   if you want to change the value of this variable during emission time (to make it more dynamic)
196   you may want to use the animation class
197*/
198void ParticleEmitter::setEmissionRate(float emissionRate)
199{
200  if (emissionRate > 0.0)
201    this->emissionRate = emissionRate;
202  else
203    this->emissionRate = 0.0;
204}
205
206/**
207 *  how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
208 * @param value a Value between zero and one
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/**
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
227
228   if you want to change the value of this variable during emission time (to make it more dynamic)
229   you may want to use the animation class
230*/
231void ParticleEmitter::setSpread(float angle, float randomAngle)
232{
233  this->angle = angle;
234  this->randomAngle = randomAngle;
235}
236
237/**
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
241
242   if you want to change the value of this variable during emission time (to make it more dynamic)
243   you may want to use the animation class
244*/
245void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
246{
247  this->velocity = velocity;
248  this->randomVelocity = randomVelocity;
249}
250
251/**
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.
255 */
256void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum)
257{
258  this->momentum = momentum;
259  this->momentumRandom = randomMomentum;
260}
261
262/**
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
266
267   if you want to change the value of this variable during emission time (to make it more dynamic)
268   you may want to use the animation class
269*/
270void ParticleEmitter::tick(float dt)
271{
272  assert (this->system != NULL);
273  if (likely(dt > 0.0 && this->emissionRate > 0.0))
274  {
275    // saving the time (particles only partly emitted in this timestep)
276    float count = (dt+this->saveTime) * this->emissionRate;
277    this->saveTime = modff(count, &count) / this->emissionRate;
278    PRINTF(5)("emitting %f particles, saving %f seconds for the next timestep\n", count, this->saveTime);
279
280    if (likely(count > 0))
281    {
282      Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
283      for (int i = 0; i < (int)count; i++)
284      {
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;
289
290        // this should spread the Particles evenly. if the Emitter is moved around quickly
291        Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
292        Vector extension; // the Vector for different fields.
293
294        if (this->type & EMITTER_PLANE)
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        }
299        else if (this->type & EMITTER_CUBE)
300        {
301          extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
302        }
303
304
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
311        this->system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV, orient, moment);
312      }
313    }
314  }
315}
316
317/**
318 *  outputs some nice debug information
319*/
320void ParticleEmitter::debug() const
321{
322  PRINT(0)(" Emitter %s\n", this->getName());
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());
325}
Note: See TracBrowser for help on using the repository browser.