Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/physics/src/lib/graphics/particles/particle_system.cc @ 4186

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

orxonox/branches/physics: forces now time dependant

File size: 9.8 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: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PARTICLE
17
18#include "particle_system.h"
19
20#include "particle_emitter.h"
21#include "particle_engine.h"
22#include "compiler.h"
23#include "material.h"
24
25#include "field.h"
26
27using namespace std;
28
29/**
30   \brief standard constructor
31   \param count the Count of particles in the System
32   \param type The Type of the ParticleSystem
33
34   \todo this constructor is not jet implemented - do it
35*/
36ParticleSystem::ParticleSystem (unsigned int maxCount, PARTICLE_TYPE type)
37{
38  this->setClassName ("ParticleSystem");
39  this->material = NULL;
40  this->name = NULL;
41  this->maxCount = maxCount;
42  this->count = 0;
43  this->particles = NULL;
44  this->deadList = NULL;
45  this->setConserve(1);
46  this->setLifeSpan(1);
47  this->setInheritSpeed(0);
48  this->glID = NULL;
49  this->setRadius(1.0, 1.0, 0.0);
50  this->setType(type, 1);
51  ParticleEngine::getInstance()->addSystem(this);
52}
53
54
55/**
56   \brief standard deconstructor
57*/
58ParticleSystem::~ParticleSystem()
59{
60  // delete what has to be deleted here
61   ParticleEngine::getInstance()->removeSystem(this);
62
63   // deleting all the living Particles
64   while (this->particles)
65     {
66       Particle* tmpDelPart = this->particles;
67       this->particles = this->particles->next;
68       delete tmpDelPart;
69     }
70
71   // deleting all the dead particles
72   while (this->deadList)
73     {
74       Particle* tmpDelPart = this->deadList;
75       this->deadList = this->deadList->next;
76       delete tmpDelPart;
77     }
78
79   if (this->material)
80     delete this->material;
81}
82
83/**
84   \brief sets the Name of the Particle System
85   \param name the Name of the System
86*/
87void ParticleSystem::setName(const char* name)
88{
89  if (this->name)
90    delete this->name;
91  this->name = new char[strlen(name)+1];
92  strcpy(this->name, name);
93}
94
95/**
96   \returns the Name of the ParticleSystem
97*/
98const char* ParticleSystem::getName(void) const
99{
100  return this->name;
101}
102
103/**
104   \todo this will be different
105*/
106void ParticleSystem::setType(PARTICLE_TYPE particleType, int count)
107{
108  this->particleType = particleType;
109  this->dialectCount = count;
110  if (glID != NULL)
111    delete glID;
112
113  glID = new GLuint[count];
114  for (int i = 0; i< count; i++)
115    glID[i] = 0;
116
117  glID[0] = glGenLists(count);
118 
119  material = new Material("transperencyMap");
120  material->setDiffuseMap("pictures/radialTransparency.png");
121  //  material->setTransparency(.5);
122
123  glNewList(glID[0], GL_COMPILE);
124  glBegin(GL_TRIANGLE_STRIP);
125  glTexCoord2f(1, 1);
126  glVertex3f(0.0, .5, .5);
127  glTexCoord2f(1, 0);
128  glVertex3f(0.0, -.5, .5);
129  glTexCoord2f(0, 1);
130  glVertex3f(0.0, .5, -.5);
131  glTexCoord2f(0, 0);
132  glVertex3f(0.0, -.5, -.5);
133  glEnd();
134  glEndList();
135}
136
137// setting properties
138void ParticleSystem::setMaterial(Material* material)
139{
140  this->material = material;
141}
142
143
144
145/**
146   \brief how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
147   \param value a Value between zero and one
148
149   
150   if you want to change the value of this variable during emission time (to make it more dynamic)
151   you may want to use the animation class
152*/
153void ParticleSystem::setInheritSpeed(float value)
154{
155  if (unlikely(value > 1.0))
156    this->inheritSpeed = 1;
157  else if (unlikely(value < 0.0))
158    this->inheritSpeed = 0;
159  else
160    this->inheritSpeed = value;
161}
162
163/**
164   \brief Sets the lifespan of newly created particles
165*/   
166void ParticleSystem::setLifeSpan(float lifeSpan, float randomLifeSpan)
167{
168  this->lifeSpan = lifeSpan;
169  this->randomLifeSpan = randomLifeSpan;
170}
171
172/**
173   \brief sets the radius of newly created particles
174*/
175void ParticleSystem::setRadius(float startRadius, float endRadius, float randomStartRadius, float randomEndRadius)
176{
177  this->startRadius = startRadius;
178  this->endRadius = endRadius;
179  this->randomStartRadius = randomStartRadius;
180  this->randomEndRadius = randomEndRadius;
181}
182
183/**
184   \brief sets the conserve Factor of newly created particles
185*/
186void ParticleSystem::setConserve(float conserve)
187{
188  if (conserve > 1.0)
189    this->conserve = 1.0;
190  else if (conserve < 0.0)
191    this->conserve = 0.0;
192  else
193    this->conserve = conserve;
194}
195
196/**
197   \brief ticks the system.
198   \param dt the time to tick all the Particles of the System
199
200   this is used to get all the particles some motion
201*/
202void ParticleSystem::tick(float dt)
203{
204  Particle* tickPart = particles;  // the particle to Tick
205  Particle* prevPart = NULL;       //
206  while (likely(tickPart != NULL))
207    {
208      tickPart->position = tickPart->position + tickPart->velocity;
209      tickPart->radius += tickPart->radiusIt * dt;
210
211      // applying force to the System.
212      tickPart->velocity += tickPart->extForce * tickPart->mass;
213      tickPart->extForce = Vector(0,0,0);
214
215      // many more to come
216
217      if (this->conserve < 1.0)
218        tickPart->velocity = tickPart->velocity * this->conserve;
219      // find out if we have to delete tickPart
220      if ((tickPart->timeToLive -= dt) <= 0)
221        {
222          // remove the particle from the list
223          if (likely(prevPart != NULL))
224            {
225              prevPart->next = tickPart->next;
226              tickPart->next = this->deadList;
227              this->deadList = tickPart;
228              tickPart = prevPart->next;
229            }
230          else
231            {
232              prevPart = NULL;
233              this->particles = tickPart->next;
234              tickPart->next = this->deadList;
235              this->deadList = tickPart;
236              tickPart = this->particles;
237            }
238          --this->count;
239        }
240      else
241        {     
242          prevPart = tickPart;
243          tickPart = tickPart->next;
244        }
245    }
246}
247
248/**
249    \brief applies some force to a Particle.
250 */
251void ParticleSystem::applyField(float dt, Field* field)
252{
253  Particle* tickPart = particles;
254  while (tickPart)
255    {
256      tickPart->extForce += field->calcForce(dt, tickPart->position);
257      tickPart = tickPart->next;
258    }
259}
260
261
262/**
263   \brief draws all the Particles of this System
264   \param the time passed in seconds (since the last draw)
265*/
266void ParticleSystem::draw(float dt)
267{
268  glPushAttrib(GL_ENABLE_BIT);
269  //  material->select();
270  Particle* drawPart = particles;
271
272  switch (this->particleType)
273    {
274    case PARTICLE_SPRITE:
275      glMatrixMode(GL_MODELVIEW);
276      //  glDisable(GL_LIGHTING);
277      material->select(); 
278      glDisable(GL_DEPTH_TEST);
279      while (likely(drawPart != NULL))
280        {
281          glPushMatrix();
282          glTranslatef(drawPart->position.x, drawPart->position.y, drawPart->position.z);
283          glScalef(drawPart->radius, drawPart->radius, drawPart->radius);
284          glCallList(*this->glID);
285         
286          //glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z);
287          drawPart = drawPart->next;
288          glPopMatrix();
289        }
290      //      glEnd();
291     
292      //  glEnable(GL_LIGHTING);
293     
294      glEnable(GL_DEPTH_TEST);
295      break;
296    default:
297
298    case PARTICLE_SPARK:
299      glEnable(GL_LINE_SMOOTH);
300      glBegin(GL_LINES);
301      while (likely(drawPart != NULL))
302        {
303          glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z);
304          glVertex3f(drawPart->position.x - drawPart->velocity.x,
305                     drawPart->position.y - drawPart->velocity.y,
306                     drawPart->position.z - drawPart->velocity.z);
307          drawPart = drawPart->next;
308        }
309      glEnd();
310      break;
311     
312    case PARTICLE_DOT:
313      glBegin(GL_POINTS);
314      while (likely(drawPart != NULL))
315        {
316          glLineWidth(drawPart->radius);
317
318          glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z);
319          drawPart = drawPart->next;
320        }
321      glEnd();
322      break;
323    }
324  glPopAttrib();
325}
326
327/**
328   \brief adds a new Particle to the System
329   \param position the position where the particle gets emitted.
330   \param velocity the Starting velocity of the particle.
331   \param data some more data given by the emitter
332*/
333void ParticleSystem::addParticle(const Vector& position, const Vector& velocity, unsigned int data)
334{
335  if (this->count <= this->maxCount)
336    {
337      // if it is the first Particle
338      if (unlikely(particles == NULL))
339        {
340          if (likely(deadList != NULL))
341            {
342              this->particles = this->deadList;
343              deadList = deadList->next;
344            }
345          else
346            {
347              PRINTF(5)("Generating new Particle\n");
348              this->particles = new Particle;
349            }
350          this->particles->next = NULL;
351        }
352      // filling the List from the beginning
353      else
354        {
355          Particle* tmpPart;
356          if (likely(deadList != NULL))
357            {
358              tmpPart = this->deadList;
359              deadList = deadList->next;
360            }
361          else
362            {
363              PRINTF(5)("Generating new Particle\n");
364              tmpPart = new Particle;
365            }
366          tmpPart->next = this->particles;
367          this->particles = tmpPart;
368        }
369     
370      particles->timeToLive = this->lifeSpan + (float)(rand()/RAND_MAX)* this->randomLifeSpan;
371      particles->position = position;
372      particles->velocity = velocity;
373
374      //  particle->rotation = ; //! \todo rotation is once again something to be done.
375      particles->mass = this->initialMass + (rand()/RAND_MAX -.5)* this->randomInitialMass;
376      particles->radius = this->startRadius + (rand()/RAND_MAX-.5)*this->randomStartRadius;
377     
378      particles->radiusIt = (this->endRadius + (rand()/RAND_MAX-.5)*this->randomEndRadius - particles->radius) / particles->timeToLive;
379
380      ++this->count;
381    }
382  else
383    PRINTF(5)("maximum count of particles reached not adding any more\n");
384}
385
386/**
387   \brief outputs some nice debug information
388*/
389void ParticleSystem::debug(void)
390{
391  PRINT(0)("  ParticleSystem %s\n", this->name);
392  PRINT(0)("  ParticleCount: %d, maximumCount: %d :: filled %d%%\n", this->count, this->maxCount, 100*this->count/this->maxCount);
393  if (deadList)
394    {
395      PRINT(0)("  - ParticleDeadList is used: ");
396      int i = 1;
397      Particle* tmpPart = this->deadList;
398      while (tmpPart = tmpPart->next) ++i;
399      PRINT(0)("count: %d\n", i);
400    }
401}
Note: See TracBrowser for help on using the repository browser.