/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PARTICLE #include "particle_system.h" #include "particle_emitter.h" #include "particle_engine.h" #include "compiler.h" #include "material.h" using namespace std; /** \brief standard constructor \param count the Count of particles in the System \param type The Type of the ParticleSystem \todo this constructor is not jet implemented - do it */ ParticleSystem::ParticleSystem (unsigned int maxCount, PARTICLE_TYPE type) { this->setClassName ("ParticleSystem"); this->maxCount = maxCount; this->count = 0; this->particleType = type; this->particles = NULL; this->setConserve(.8); this->setLifeSpan(.1); this->setInheritSpeed(0); this->glID = NULL; this->setRadius(1.0, 1.0, 0.0); this->setType(PARTICLE_SPRITE, 1); ParticleEngine::getInstance()->addSystem(this); } /** \brief standard deconstructor */ ParticleSystem::~ParticleSystem() { // delete what has to be deleted here ParticleEngine::getInstance()->removeSystem(this); } void ParticleSystem::setType(PARTICLE_TYPE particleType, int count) { this->particleType = particleType; this->dialectCount = count; if (glID != NULL) delete glID; glID = new GLuint[count]; for (int i = 0; i< count; i++) glID[i] = 0; glID[0] = glGenLists(count); material = new Material("transperencyMap"); material->setDiffuseMap("pictures/radialTransparency.jpg"); glNewList(glID[0], GL_COMPILE); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(1, 1); glVertex3f(0.0, 1.0, 1.0); glTexCoord2f(1, 0); glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(0, 1); glVertex3f(0.0, 0.0, 1.0); glTexCoord2f(0, 0); glVertex3f(0.0, 0.0, 0.0); glEnd(); glEndList(); } // setting properties void ParticleSystem::setMaterial(Material* material) { this->material = material; } /** \brief how much of the speed from the ParticleEmitter should flow onto the ParticleSystem \param value a Value between zero and one if you want to change the value of this variable during emission time (to make it more dynamic) you may want to use the animation class */ void ParticleSystem::setInheritSpeed(float value) { if (unlikely(value > 1.0)) this->inheritSpeed = 1; else if (unlikely(value < 0.0)) this->inheritSpeed = 0; else this->inheritSpeed = value; } void ParticleSystem::setLifeSpan(float lifeSpan, float randomLifeSpan) { this->lifeSpan = lifeSpan; this->randomLifeSpan = randomLifeSpan; } void ParticleSystem::setRadius(float startRadius, float endRadius, float randomStartRadius, float randomEndRadius) { this->startRadius = startRadius; this->endRadius = endRadius; this->randomStartRadius = randomStartRadius; this->randomEndRadius = randomEndRadius; } void ParticleSystem::setConserve(float conserve) { if (conserve > 1.0) this->conserve = 1.0; else if (conserve < 0.0) this->conserve = 0.0; else this->conserve = conserve; } void ParticleSystem::tick(float dt) { Particle* tickPart = particles; // the particle to Tick Particle* prevPart = NULL; // while (likely(tickPart != NULL)) { tickPart->position = tickPart->position + tickPart->velocity; tickPart->radius += tickPart->radiusIt * dt; // many more to come if (this->conserve < 1.0) tickPart->velocity = tickPart->velocity * this->conserve; // find out if we have to delete tickPart if ((tickPart->timeToLive -= dt) <= 0) { // remove the particle from the list if (likely(prevPart != NULL)) { prevPart->next = tickPart->next; delete tickPart; tickPart = prevPart->next; } else { prevPart = NULL; this->particles = tickPart->next; delete tickPart; tickPart = this->particles; } --this->count; } else { prevPart = tickPart; tickPart = tickPart->next; } } } void ParticleSystem::draw(void) { // material->select(); glMatrixMode(GL_MODELVIEW); Particle* drawPart = particles; if (likely(drawPart != NULL)) { glBegin(GL_POINTS); while (likely(drawPart != NULL)) { // draw in DOT mode glPushMatrix(); glTranslatef(drawPart->position.x, drawPart->position.y, drawPart->position.z); glScalef(drawPart->radius, drawPart->radius, drawPart->radius); glCallList(*this->glID); // glVertex3f(drawPart->position.x, drawPart->position.y, drawPart->position.z); drawPart = drawPart->next; glPopMatrix(); } glEnd(); } } void ParticleSystem::addParticle(Vector position, Vector velocity, unsigned int data) { if (this->count <= this->maxCount) { // if it is the first Particle if (unlikely(particles == NULL)) { this->particles = new Particle; this->particles->next = NULL; } // filling the List from the beginning else { Particle* tmpPart = new Particle; tmpPart->next = this->particles; this->particles = tmpPart; } particles->timeToLive = this->lifeSpan + (float)(random()/RAND_MAX)* this->randomLifeSpan; particles->position = position; particles->velocity = velocity; // particle->rotation = ; //! \todo rotation is once again something to be done. particles->mass = this->initialMass + (random()/RAND_MAX -.5)* this->randomInitialMass; particles->radius = this->startRadius + (random()/RAND_MAX-.5)*this->randomStartRadius; particles->radiusIt = (this->endRadius + (random()/RAND_MAX-.5)*this->randomEndRadius - particles->radius) / particles->timeToLive; ++this->count; } else PRINTF(4)("maximum count of particles reached not adding any more\n"); }