Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more momentum implementation in particles

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