Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/graphics/particles/particle_system.cc @ 4336

Last change on this file since 4336 was 4320, checked in by patrick, 20 years ago

orxonox/trunk: now string name of a class works parallel to the int id representation and is only used for documentation purposes

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