Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: momentum works correct now (i think)

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   \brief sets a new size to the emitter
155*/
156void ParticleEmitter::setSize(float emitterSize)
157{
158  if (emitterSize > 0.0)
159    this->emitterSize = emitterSize;
160  else
161    emitterSize = 0.0;
162}
163
164/**
165   \brief set the emission rate
166   \param emissionRate: sets the number of particles emitted per second
167
168   if you want to change the value of this variable during emission time (to make it more dynamic)
169   you may want to use the animation class
170*/
171void ParticleEmitter::setEmissionRate(float emissionRate)
172{
173  if (emissionRate > 0.0)
174    this->emissionRate = emissionRate;
175  else
176    this->emissionRate = 0.0;
177}
178
179/**
180   \brief how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
181   \param value a Value between zero and one
182
183   if you want to change the value of this variable during emission time (to make it more dynamic)
184   you may want to use the animation class
185*/
186void ParticleEmitter::setInheritSpeed(float value)
187{
188  if (unlikely(value > 1.0))
189    this->inheritSpeed = 1;
190  else if (unlikely(value < 0.0))
191    this->inheritSpeed = 0;
192  else
193    this->inheritSpeed = value;
194}
195
196/**
197   \brief set the angle of the emitter
198   \param angle around the direction in which there are particles to be emitted
199   \param randomAngle A random spread-angle, the +- randomness of this option
200
201   if you want to change the value of this variable during emission time (to make it more dynamic)
202   you may want to use the animation class
203*/
204void ParticleEmitter::setSpread(float angle, float randomAngle)
205{
206  this->angle = angle;
207  this->randomAngle = randomAngle;
208}
209
210/**
211   \brief sets the initial velocity of all particles emitted
212   \param velocity The starting velocity of the emitted particles
213   \param randomVelocity A random starting velocity, the +- randomness of this option
214
215   if you want to change the value of this variable during emission time (to make it more dynamic)
216   you may want to use the animation class
217*/
218void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
219{
220  this->velocity = velocity;
221  this->randomVelocity = randomVelocity;
222}
223
224/**
225   \brief sets the initial Momentum of all particles emitted
226   \param momentum the new Momentum (just a float for being not too complicated).
227   \param randomMomentum variation from the given value.
228 */
229void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum)
230{
231  this->momentum = momentum;
232  this->momentumRandom = randomMomentum;
233}
234
235/**
236   \brief this set the time to life of a particle, after which it will die
237   \param dt: the time to live in seconds
238   \param system: the system into which to emitt
239
240   if you want to change the value of this variable during emission time (to make it more dynamic)
241   you may want to use the animation class
242*/
243void ParticleEmitter::tick(float dt, ParticleSystem* system)
244{
245  if (likely(dt > 0.0 && this->emissionRate > 0.0))
246  {
247    // saving the time
248    float count = (dt+this->saveTime) * this->emissionRate;
249    this->saveTime = modff(count, &count) / this->emissionRate;
250    PRINTF(5)("emitting %f particles, saving %f seconds for the next round\n", count, this->saveTime);
251
252    if (likely(count > 0))
253    {
254      Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
255      for (int i = 0; i < count; i++)
256          // emmits from EMITTER_DOT,
257      {
258        Vector randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
259        randDir.normalize();
260        randDir = (this->getAbsDir()*Quaternion(angle + randomAngle *((float)rand()/RAND_MAX -.5), randDir)).apply(this->direction);
261        Vector velocityV = randDir.getNormalized()*this->velocity + inheritVelocity;
262
263            // this should spread the Particles evenly. if the Emitter is moved around quickly
264        Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
265        Vector extension; // the Vector for different fields.
266
267        if (this->type & 2)
268        {
269          extension = Vector(this->emitterSize * ((float)rand()/RAND_MAX -.5), 0, this->emitterSize * ((float)rand()/RAND_MAX - .5));
270          extension = this->getAbsDir().apply(extension);
271        }
272        else if (this->type & 8)
273        {
274          extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
275        }
276
277
278        // ROTATIONAL CALCULATION (this must not be done for all types of particles.)
279        randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
280        randDir.normalize();
281        Quaternion orient = Quaternion(M_PI, randDir);
282        Quaternion moment = Quaternion(this->momentum + this->momentumRandom, randDir);
283
284        system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV, orient, moment);
285
286      }
287    }
288  }
289}
290
291/**
292   \brief outputs some nice debug information
293*/
294void ParticleEmitter::debug(void) const
295{
296  PRINT(0)(" Emitter %s\n", this->getName());
297  PRINT(0)("  EmissionRate: %f, Speed: %f, SpreadAngle: %f\n", this->getEmissionRate(), this->getEmissionVelocity(), this->getSpread());
298  PRINT(0)("  Size %f, Type: %s\n", this->getSize(), this->getTypeC());
299}
Note: See TracBrowser for help on using the repository browser.