Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: particleFun draws some Particles again

File size: 8.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_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/* these are Animation interfaces: so you can change spec values as you want */
116
117/**
118   \param type the new Type of this emitter
119*/
120void ParticleEmitter::setType(EMITTER_TYPE type)
121{
122  this->type = type;
123}
124
125/**
126   \brief sets the type of emitter
127   \param type the type as a const char*
128   dot: EMITTER_DOT, plane: EMITTER_PLANE, cube: EMITTER_CUBE, sphere, EMITTER_SPHERE;
129*/
130void ParticleEmitter::setType(const char* type)
131{
132  if (!strcmp(type, "plane"))
133    this->setType(EMITTER_PLANE);
134  else if (!strcmp(type, "cube"))
135    this->setType(EMITTER_CUBE);
136  else if (!strcmp(type, "sphere"))
137    this->setType(EMITTER_SPHERE);
138  else
139    this->setType(EMITTER_DOT);
140}
141
142const char* ParticleEmitter::getTypeC(void) const
143{
144  if (this->type == EMITTER_PLANE)
145    return "EMITTER_PLANE";
146  else if (this->type == EMITTER_CUBE)
147    return "EMITTER_CUBE";
148  else if (this->type == EMITTER_SPHERE)
149    return "EMITTER_SPHERE";
150  else
151    return "EMITTER_DOT";
152
153
154}
155
156/**
157   \brief sets a new size to the emitter
158*/
159void ParticleEmitter::setSize(float emitterSize)
160{
161  if (emitterSize > 0.0)
162    this->emitterSize = emitterSize;
163  else
164    emitterSize = 0.0;
165}
166
167/**
168   \brief set the emission rate
169   \param emissionRate: sets the number of particles emitted per second
170
171   if you want to change the value of this variable during emission time (to make it more dynamic)
172   you may want to use the animation class
173*/
174void ParticleEmitter::setEmissionRate(float emissionRate)
175{
176  if (emissionRate > 0.0)
177    this->emissionRate = emissionRate;
178  else
179    this->emissionRate = 0.0;
180}
181
182/**
183   \brief how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
184   \param value a Value between zero and one
185
186   if you want to change the value of this variable during emission time (to make it more dynamic)
187   you may want to use the animation class
188*/
189void ParticleEmitter::setInheritSpeed(float value)
190{
191  if (unlikely(value > 1.0))
192    this->inheritSpeed = 1;
193  else if (unlikely(value < 0.0))
194    this->inheritSpeed = 0;
195  else
196    this->inheritSpeed = value;
197}
198
199/**
200   \brief set the angle of the emitter
201   \param angle around the direction in which there are particles to be emitted
202   \param randomAngle A random spread-angle, the +- randomness of this option
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::setSpread(float angle, float randomAngle)
208{
209  this->angle = angle;
210  this->randomAngle = randomAngle;
211}
212
213/**
214   \brief sets the velocity of all particles emitted
215   \param velocity The starting velocity of the emitted particles
216   \param randomVelocity A random starting velocity, the +- randomness of this option
217
218   if you want to change the value of this variable during emission time (to make it more dynamic)
219   you may want to use the animation class
220*/
221void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
222{
223  this->velocity = velocity;
224  this->randomVelocity = randomVelocity;
225}
226
227/**
228   \brief this set the time to life of a particle, after which it will die
229   \param dt: the time to live in seconds
230   \param system: the system into which to emitt
231
232   if you want to change the value of this variable during emission time (to make it more dynamic)
233   you may want to use the animation class
234*/
235
236void ParticleEmitter::tick(float dt, ParticleSystem* system)
237{
238  if (likely(dt > 0.0 && this->emissionRate > 0.0))
239  {
240    // saving the time
241    float count = (dt+this->saveTime) * this->emissionRate;
242    this->saveTime = modff(count, &count) / this->emissionRate;
243    PRINTF(5)("emitting %f particles, saving %f seconds for the next round\n", count, this->saveTime);
244
245    if (likely(count > 0))
246      {
247        Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
248        for (int i = 0; i < count; i++)
249          // emmits from EMITTER_DOT,
250          {
251            Vector randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
252            randDir.normalize();
253            randDir = (this->getAbsDir()*Quaternion(angle + randomAngle *((float)rand()/RAND_MAX -.5), randDir)).apply(this->direction);
254            Vector velocityV = randDir.getNormalized()*this->velocity + inheritVelocity;
255
256            // this should spread the Particles evenly. if the Emitter is moved around quickly
257            Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
258            Vector extension; // the Vector for different fields.
259
260            if (this->type & 2)
261              {
262                extension = Vector(this->emitterSize * ((float)rand()/RAND_MAX -.5), 0, this->emitterSize * ((float)rand()/RAND_MAX - .5));
263                extension = this->getAbsDir().apply(extension);
264              }
265            else if (this->type & 8)
266              {
267                extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
268              }
269
270            system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV);
271
272          }
273      }
274  }
275}
276
277/**
278   \brief outputs some nice debug information
279*/
280void ParticleEmitter::debug(void) const
281{
282  PRINT(0)(" Emitter %s\n", this->getName());
283  PRINT(0)("  EmissionRate: %f, Speed: %f, SpreadAngle: %f\n", this->getEmissionRate(), this->getEmissionVelocity(), this->getSpread());
284  PRINT(0)("  Size %f, Type: %s\n", this->getSize(), this->getTypeC());
285}
Note: See TracBrowser for help on using the repository browser.