Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/spaceshipcontrol/src/lib/particles/particle_emitter.cc @ 6722

Last change on this file since 6722 was 6627, checked in by bensch, 19 years ago

trunk: valgrind sweep

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