Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals

/Users/blackie/Documents/myRepository/phobosengine-vc2005/phobosengine/phobosengine/ParticleSystem.cpp

Go to the documentation of this file.
00001 
00002 
00003 #include "ParticleSystem.h"
00004 
00005 #include "MathUtils.h"
00006 #include "Renderer.h"
00007 #include "Texture.h"
00008 #include "TextureDatabase.h"
00009 
00010 
00011 namespace pge {
00012 
00013 
00014         //****************************************************************************
00015         //
00016         //
00017         //
00018         //****************************************************************************
00019         ParticleSystem::ParticleSystem(const std::string &textureFile, Vector3f startPoint, Vector3f direction, int particleNum) {
00020                 m_startPoint = startPoint;
00021                 m_startDirection = direction;
00022                 m_startDirection.normalize();
00023 
00024                 // TODO: what in constructor, what is standard?
00025                 // Initialize with standard values.
00026                 m_particleNum = particleNum;
00027                 m_distribution = 10;
00028                 m_size = 32.0f;
00029                 m_velocity = 0.1f;
00030 
00031                 m_lifeDeg = 0.1f;
00032 
00033                 // Get maxsize for the extension.
00034                 glGetFloatv(GL_POINT_SIZE_MAX_ARB, &m_maxSizeExt);
00035 
00036                 // Blend out.
00037                 m_startFade = Vector3f();
00038                 m_endFade = Vector3f();
00039                 m_fadeEnabled = false;
00040 
00041                 // Set gravity.
00042                 m_gravity = Vector3f(0.0f, -0.98f, 0.0f);
00043 
00044                 // Extensions and billboarding.
00045                 m_billboard = true;
00046                 m_usePointSpriteExt = true;
00047 
00048                 // Loop mode.
00049                 m_loopMode = ParticleLoopForever;
00050 
00051                 m_active = false;
00052 
00053                 // Create the array for the particles.
00054                 m_particleArray = new Particle[m_particleNum];
00055 
00056                 reset();
00057 
00058                 m_texture = TextureDatabase::getInstance()->addTexture(textureFile);
00059         }
00060 
00061 
00062         //****************************************************************************
00063         //
00064         //
00065         //
00066         //****************************************************************************
00067         ParticleSystem::~ParticleSystem(void) {
00068                 if(m_particleArray != NULL) {
00069                         delete [] m_particleArray;
00070                         m_particleArray = NULL;
00071                 }
00072         }
00073 
00074 
00075         //****************************************************************************
00076         //
00077         //
00078         //
00079         //****************************************************************************
00080         void ParticleSystem::setDirection(Vector3f direction) {
00081                 m_startDirection = direction;
00082                 m_startDirection.normalize();
00083                 reset();
00084         }
00085 
00086 
00087         //****************************************************************************
00088         //
00089         //
00090         //
00091         //****************************************************************************
00092         void ParticleSystem::setStartPoint(Vector3f start) {
00093                 m_startPoint = start;
00094                 reset();
00095         }
00096 
00097 
00098         //****************************************************************************
00099         //
00100         //
00101         //
00102         //****************************************************************************
00103         void ParticleSystem::setGravity(Vector3f gravity) {
00104                 m_gravity = gravity;
00105         }
00106 
00107 
00108         //****************************************************************************
00109         //
00110         //
00111         //
00112         //****************************************************************************
00113         void ParticleSystem::setFadeOutStart(Vector3f start) {
00114                 m_startFade = start;
00115         }
00116 
00117 
00118         //****************************************************************************
00119         //
00120         //
00121         //
00122         //****************************************************************************
00123         void ParticleSystem::setFadeOutEnd(Vector3f end) {
00124                 m_endFade = end;
00125         }
00126 
00127 
00128         //****************************************************************************
00129         //
00130         //
00131         //
00132         //****************************************************************************
00133         void ParticleSystem::setFadeOutEnabled(bool enabled) {
00134                 m_fadeEnabled = enabled;
00135         }
00136 
00137 
00138         //****************************************************************************
00139         //
00140         //
00141         //
00142         //****************************************************************************
00143         void ParticleSystem::setLifeDegeneration(float lifeDeg) {
00144                 m_lifeDeg = lifeDeg;
00145         }
00146 
00147 
00148         //****************************************************************************
00149         //
00150         //
00151         //
00152         //****************************************************************************
00153         void ParticleSystem::setLoopMode(ParticleLoopMode mode) {
00154                 m_loopMode = mode;
00155         }
00156 
00157 
00158         //****************************************************************************
00159         //
00160         //
00161         //
00162         //****************************************************************************
00163         void ParticleSystem::setTexture(Texture *texture) {
00164                 m_texture = texture;
00165         }
00166 
00167 
00168         //****************************************************************************
00169         //
00170         //
00171         //
00172         //****************************************************************************
00173         void ParticleSystem::setParticleNum(int num) {
00174                 if(num > 0) {
00175                         m_particleNum = num;
00176 
00177                         if(m_particleArray != NULL) {
00178                                 delete [] m_particleArray;
00179                                 m_particleArray = NULL;
00180                         }
00181 
00182                         m_particleArray = new Particle[m_particleNum];
00183                         reset();
00184                 }
00185         }
00186 
00187 
00188         //****************************************************************************
00189         //
00190         //
00191         //
00192         //****************************************************************************
00193         void ParticleSystem::setParticleSize(float size) {
00194                 // TODO: what todo with size if not using extension?
00195                 if(size <= m_maxSizeExt) {
00196                         m_size = size;
00197                 } else {
00198                         m_size = m_maxSizeExt;
00199                 }
00200         }
00201 
00202 
00203         //****************************************************************************
00204         //
00205         //
00206         //
00207         //****************************************************************************
00208         void ParticleSystem::setDistribution(int dist) {
00209                 if(dist > 0) {
00210                         m_distribution = dist;
00211                         reset();
00212                 }
00213         }
00214 
00215 
00216         //****************************************************************************
00217         //
00218         //
00219         //
00220         //****************************************************************************
00221         void ParticleSystem::setVelocity(float velocity) {
00222                 if(velocity > 0.0f) {
00223                         m_velocity = velocity;
00224                 }
00225         }
00226 
00227 
00228         //****************************************************************************
00229         //
00230         //
00231         //
00232         //****************************************************************************
00233         void ParticleSystem::activate(void) {
00234                 reset();
00235                 m_active = true;
00236         }
00237 
00238 
00239         //****************************************************************************
00240         //
00241         //
00242         //
00243         //****************************************************************************
00244         void ParticleSystem::deactivate(void) {
00245                 m_active = false;
00246         }
00247 
00248 
00249         //****************************************************************************
00250         //
00251         //
00252         //
00253         //****************************************************************************
00254         void ParticleSystem::reset(void) {
00255                 int i;
00256 
00257                 for(i = 0; i < m_particleNum; i++) {
00258                         resetParticle(&m_particleArray[i]);
00259                 }
00260         }
00261 
00262 
00263         //****************************************************************************
00264         //
00265         //
00266         //
00267         //****************************************************************************
00268         bool ParticleSystem::init(void) {
00269                 return true;
00270         }
00271 
00272 
00273         //****************************************************************************
00274         //
00275         //
00276         //
00277         //****************************************************************************
00278         void ParticleSystem::render(void) {
00279                 //
00280                 // Variables
00281                 //
00282                 int i;
00283                 float x;
00284                 float y;
00285                 float z;
00286                 float mat[16];
00287                 Vector3f right;
00288                 Vector3f up;
00289 
00290 
00291                 // If the particle system is active, then render.
00292                 if(m_active) {
00293 
00294                         // TODO: use depth test?
00295                         // glDisable(GL_DEPTH_TEST);
00296 
00297                         renderer::setTextureAlphaBlendEnabled(true);
00298 
00299                         // TODO: Check if texture is set and then set all blending states
00300                         // and so on.
00301                         if(m_texture != NULL) {
00302                                 // Be sure to set the envmode to modulate to enable blending in
00303                                 // and out
00304                                 // of the particles.
00305                                 renderer::setTexture(m_texture, GL_MODULATE);
00306                         }
00307                         // If the extension should be used, set texture unit 0
00308                         // to the point sprite coordinate replace mode
00309                         if(m_usePointSpriteExt) {
00310                                 glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
00311                         }
00312 
00313                         // If the user wants billboarding and not the extension, then
00314                         // calculate
00315                         // necessary values here. We don't need billboarding for the
00316                         // extension.
00317                         if(m_billboard && !m_usePointSpriteExt) {
00318                                 glGetFloatv(GL_MODELVIEW_MATRIX, mat);
00319                                 
00320                                 right = Vector3f(mat[0], mat[4], mat[8]);
00321                                 up = Vector3f(mat[1], mat[5], mat[9]);
00322                         }
00323 
00324                         // Go through all particles and render them.
00325                         for(i = 0; i < m_particleNum; i++) {
00326 
00327                                 // Store position of current particle for easier access.
00328                                 x = m_particleArray[i].m_position.m_v[0];
00329                                 y = m_particleArray[i].m_position.m_v[1];
00330                                 z = m_particleArray[i].m_position.m_v[2];
00331 
00332                                 // Calculate fade out if enabled.
00333                                 if(m_fadeEnabled) {
00334                                         float alpha = 1.0f;
00335                                         float distanceToStart;
00336                                         float distanceToEnd;
00337                                         float distanceStartEnd;
00338 
00339                                         distanceToStart = m_particleArray[i].m_position.sqrDistance(m_startFade);
00340                                         distanceToEnd = m_particleArray[i].m_position.sqrDistance(m_endFade);
00341                                         distanceStartEnd = m_startFade.sqrDistance(m_endFade);
00342 
00343                                         // Check if the particle is inside of the interval of the
00344                                         // startfade and endfade
00345                                         // points.
00346                                         if(distanceToStart <= distanceStartEnd && distanceToEnd <= distanceStartEnd) {
00347                                                 // Calculate alpha value by using the distance to the
00348                                                 // end fade point.
00349                                                 // Also prevent division by zero.
00350                                                 if(distanceStartEnd == 0.0f) {
00351                                                         distanceStartEnd = 1.0f;
00352                                                 }
00353                                                 alpha = distanceToEnd / distanceStartEnd;
00354                                         }
00355 
00356                                         // Check if the particle moved out of the interval between
00357                                         // the starte and the end.
00358                                         // If it did, "kill" it, set alpha to zero and life to zero,
00359                                         // so it will be resetted
00360                                         // next time or the particlesystem can stop.
00361                                         if(distanceToStart > distanceToEnd && distanceToStart > distanceStartEnd
00362                                                 && distanceToEnd <= distanceStartEnd) {
00363                                                         alpha = 0.0f;
00364                                                         m_particleArray[i].m_life = 0.0f;
00365                                         }
00366                                         // Set particle color with alpha.
00367 
00369                                         // TODODOODODDO
00370                                         renderer::color4f(1.0f, 1.0f, 1.0f, alpha);
00371 
00372                                         //Renderer.color(1.0f * DayNightCycle.getInstance().getDayNightCycle(), 1.0f * DayNightCycle
00373                                         //      .getInstance().getDayNightCycle(), 1.0f * DayNightCycle.getInstance().getDayNightCycle(),
00374                                         //      alpha);
00375 
00376                                 } else {
00377                                         // If fadeout is disabled, set alpha to 1.
00378                                         renderer::color4f(1.0f, 1.0f, 1.0f, 1.0f);
00379                                         //renderer::color(1.0f * DayNightCycle.getInstance().getDayNightCycle(), 1.0f * DayNightCycle
00380                                         //      .getInstance().getDayNightCycle(), 1.0f * DayNightCycle.getInstance().getDayNightCycle(),
00381                                         //      1.0f);
00382                                 }
00383 
00384                                 // Render path: no billboarding and no extension.
00385                                 if(!m_billboard && !m_usePointSpriteExt) {
00386                                         // Render the particles with textured triangle strips
00387                                         // without
00388                                         // billboarding.
00389                                         glBegin(GL_TRIANGLE_STRIP);
00390                                         // Top right.
00391                                         renderer::vertex3f(x + (m_size / 2.0f), y + (m_size / 2.0f), z, 1.0f, 1.0f);
00392                                         // Top left.
00393                                         renderer::vertex3f(x - (m_size / 2.0f), y + (m_size / 2.0f), z, 0.0f, 1.0f);
00394                                         // Bottom right.
00395                                         renderer::vertex3f(x + (m_size / 2.0f), y - (m_size / 2.0f), z, 1.0f, 0.0f);
00396                                         // Bottom left.
00397                                         renderer::vertex3f(x - (m_size / 2.0f), y - (m_size / 2.0f), z, 0.0f, 0.0f);
00398                                         glEnd();
00399 
00400                                         // Render path: billboarding but no extension.
00401                                 } else if(m_billboard && !m_usePointSpriteExt) {
00402                                         Vector3f pos = Vector3f(x, y, z);
00403 
00404                                         // Render the particles using textured quads with
00405                                         // billboarding.
00406                                         glBegin(GL_QUADS);
00407                                         // Bottom left.
00408                                         renderer::vertex3f(pos.add(right.add(up).multiply(-m_size)), 0.0f, 0.0f);
00409                                         // Bottom right.
00410                                         renderer::vertex3f(pos.add(right.subtract(up).multiply(m_size)), 1.0f, 0.0f);
00411                                         // Top right.
00412                                         renderer::vertex3f(pos.add(right.add(up).multiply(m_size)), 1.0f, 1.0f);
00413                                         // Top left.
00414                                         renderer::vertex3f(pos.add(up.subtract(right).multiply(m_size)), 0.0f, 1.0f);
00415                                         glEnd();
00416 
00417                                         // Render path: extension.
00418                                 } else if(m_usePointSpriteExt) {
00419 
00420                                         // Set point parameter.
00421                                         // TODO: Where from? What is default?
00422                                         float quadratic[3];
00423                                         quadratic[0] = 1.0f;
00424                                         quadratic[1] = 0.1f;
00425                                         quadratic[2] = 0.01f;
00426 
00427                                         // TODO: Point sprite extension in renderer.
00428                                         glEnable(GL_POINT_SPRITE);
00429                                         glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic);
00430                                         glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, 1.0f);
00431                                         glPointParameterf(GL_POINT_SIZE_MIN, 1.0f);
00432                                         glPointParameterf(GL_POINT_SIZE_MAX, m_maxSizeExt);
00433                                         glPointSize(m_size);
00434 
00435                                         // Render the particles using the point sprite extension.
00436                                         glBegin(GL_POINTS);
00437                                         renderer::vertex3f(x, y, z);
00438                                         glEnd();
00439 
00440                                         glDisable(GL_POINT_SPRITE);
00441                                 }
00442                         } // End for loop.
00443 
00444                         renderer::color4f(1.0f, 1.0f, 1.0f, 1.0f);
00445                         renderer::setTextureAlphaBlendEnabled(false);
00446                         //glEnable(GL_DEPTH_TEST);
00447                 }
00448         }
00449 
00450 
00451         //****************************************************************************
00452         //
00453         //
00454         //
00455         //****************************************************************************
00456         void ParticleSystem::timer(unsigned int delay) {
00457                 bool allDead;
00458                 int i;
00459 
00460                 if(m_active) {
00461 
00462                         allDead = true;
00463 
00464                         // Go through all particles and update them
00465                         for(i = 0; i < m_particleNum; i++) {
00466 
00467                                 // Process particles position.
00468                                 m_particleArray[i].m_position.m_v[0] += m_particleArray[i].m_direction.m_v[0] * m_velocity;
00469                                 m_particleArray[i].m_position.m_v[1] += m_particleArray[i].m_direction.m_v[1] * m_velocity;
00470                                 m_particleArray[i].m_position.m_v[2] += m_particleArray[i].m_direction.m_v[2] * m_velocity;
00471 
00472                                 // Process particles direction.
00473                                 m_particleArray[i].m_direction.m_v[0] += m_gravity.m_v[0];
00474                                 m_particleArray[i].m_direction.m_v[1] += m_gravity.m_v[1];
00475                                 m_particleArray[i].m_direction.m_v[2] += m_gravity.m_v[2];
00476 
00477                                 m_particleArray[i].m_life -= m_lifeDeg;
00478 
00479                                 // If loop mode is set to endless loop, then give particles new
00480                                 // life when they are dead.
00481                                 if(m_loopMode == ParticleLoopForever) {
00482                                         // If particle is "dead".
00483                                         if(m_particleArray[i].m_life <= 0.0f) {
00484                                                 resetParticle(&m_particleArray[i]);
00485                                         }
00486 
00487                                         // Else if loop is set to only once repeat the animation,
00488                                         // then dont give particles new life and wait for one that
00489                                         // still lives.
00490                                         // If so, allDead is false and we continue.
00491                                         // if there is no alive particle, then all dead is true and
00492                                         // we stop the animation.
00493                                 } else if(m_loopMode == ParticlePlayOnce) {
00494                                         if(m_particleArray[i].m_life > 0.0f) {
00495                                                 allDead = false;
00496                                         }
00497                                 }
00498                         } // End for loop.
00499 
00500                         // If we have loop mode repeat once and all particles are dead,
00501                         // stop rendering.
00502                         if(m_loopMode == ParticlePlayOnce && allDead) {
00503                                 m_active = false;
00504                         }
00505                 }
00506         }
00507 
00508 
00509         //****************************************************************************
00510         //
00511         //
00512         //
00513         //****************************************************************************
00514         void ParticleSystem::resetParticle(Particle *particle) {
00515 
00516                 // Set start position of each particle
00517                 particle->m_position.m_v[0] = m_startPoint.m_v[0];
00518                 particle->m_position.m_v[1] = m_startPoint.m_v[1];
00519                 particle->m_position.m_v[2] = m_startPoint.m_v[2];
00520 
00521                 // Set direction of each particle
00522                 particle->m_direction.m_v[0] = m_startDirection.m_v[0] * (float)((rand() % m_distribution) - (m_distribution / 2));
00523                 particle->m_direction.m_v[1] = m_startDirection.m_v[1] * (float)((rand() % m_distribution) - (m_distribution / 2));
00524                 particle->m_direction.m_v[2] = m_startDirection.m_v[2] * (float)((rand() % m_distribution) - (m_distribution / 2));
00525 
00526                 // particle.m_direction.m_v[0] = m_startDirection.m_v[0] *
00527                 // (float)Math.random() * m_distribution;
00528                 // particle.m_direction.m_v[1] = m_startDirection.m_v[1] *
00529                 // (float)Math.random() * m_distribution;
00530                 // particle.m_direction.m_v[2] = m_startDirection.m_v[2] *
00531                 // (float)Math.random() * m_distribution;
00532                 // particle.m_direction.normalize();
00533 
00534                 // Give new life.
00535                 particle->m_life = 1.0f * (mathutils::random() * 2.0f);
00536         }
00537 };

Generated on Mon Oct 16 12:08:10 2006 for Phobosengine by doxygen 1.3.4