src/particles.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *            particle.cpp
00003  *
00004  *  Sun Apr  3 11:02:01 2005
00005  *  Copyright  2005  Joe Venzon
00006  *  joe@venzon.net
00007  ****************************************************************************/
00008 
00009 /*
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024  
00025 #include "particles.h"
00026 
00027 PARTICLE::PARTICLE()
00028 {
00029         drawlist = 0;
00030         /*int i;
00031         for (i = 0; i < PARTICLE_TEXTURES; i++)
00032                 texture[i] = 0;*/
00033         slotguess = 0;
00034         
00035         VERTEX direction;
00036         direction.y = 1.0;
00037         
00038         params[0].transparency = 1.0;
00039         params[0].longevity = 2.0;
00040         params[0].speed = 0.5;
00041         params[0].direction = direction;
00042         params[0].size = 1.0;
00043         
00044         params[1].transparency = 1.0;
00045         params[1].longevity = 2.0;
00046         params[1].speed = 0.5;
00047         params[1].direction = direction;
00048         params[1].size = 1.0;
00049         
00050         srand(1337);
00051         
00052         curtime = 0;
00053         curtex = 0;
00054         
00055         loaded = false;
00056 }
00057 
00058 extern bool verbose_output;
00059 PARTICLE::~PARTICLE()
00060 {
00061         if (verbose_output)
00062                 cout << "particle deinit" << endl;
00063         
00064         if (loaded)
00065         {
00066                 //glDeleteTextures( PARTICLE_TEXTURES, texture );
00067                 glDeleteLists(drawlist, 1);
00068                 drawlist = 0;
00069                 
00070                 for (int i = 0; i < PARTICLE_TEXTURES; i++)
00071                 {
00072                         char fname[128];
00073                         sprintf(fname, "smoke/particle%i.png", i);
00074                         //textures.Delete(fname);
00075                         texture[i].Unload();
00076                 }
00077         }
00078 }
00079 
00080 void PARTICLE::Load()
00081 {
00082         int i;
00083         
00084         if (loaded)
00085         {
00086                 //glDeleteTextures( PARTICLE_TEXTURES, texture );
00087                 
00088                 for (i = 0; i < PARTICLE_TEXTURES; i++)
00089                 {
00090                         //glDeleteTextures( 1, &(texture[i]) );
00091                         char fname[128];
00092                         sprintf(fname, "smoke/particle%i.png", i);
00093                         //textures.Delete(fname);
00094                         texture[i].Unload();
00095                 }
00096                 glDeleteLists(drawlist, 1);
00097                 drawlist = 0;
00098         }
00099         
00100         for (i = 0; i < MAX_PARTICLES; i++)
00101         {
00102                 particle[i].active = false;
00103         }
00104         
00105         //load textures
00106         char fname[128];
00107         for (i = 0; i < PARTICLE_TEXTURES; i++)
00108         {
00109                 sprintf(fname, "smoke/particle%i.png", i);
00110                 //if (!texture[i])
00111                         //texture[i] = textures.Load(fname, false);
00112                 texture[i].Load(fname, false);
00113 
00114                 //cout << fname << ": " << texture[i] << endl;
00115         }
00116         
00117         //create display list
00118         if (!drawlist)
00119         {
00120                 drawlist = glGenLists(1);
00121                 glNewList (drawlist, GL_COMPILE);
00122                 
00123                 for (i = 0; i <= NUM_ROTATIONS; i++)
00124                 {
00125                         float thisrot = 90.0 / (float) NUM_ROTATIONS;
00126                         thisrot *= i;
00127                         
00128                         glPushMatrix();
00129                         glRotatef(thisrot,0,1,0);
00130                         //glRotatef(p.rotation,0,0,1);
00131                         init_draw();
00132                         glPopMatrix();
00133                         
00134                         //cout << thisrot << " ";
00135                         
00136                         /*glPushMatrix();
00137                         glRotatef(90,1,0,0);
00138                         glRotatef(p.rotation,0,0,1);
00139                         glCallList(drawlist);
00140                         glPopMatrix();*/
00141                 }
00142                 
00143                 glEndList ();
00144         }
00145         
00146         curtime = 0;
00147         
00148         loaded = true;
00149 }
00150 
00151 void PARTICLE::init_draw()
00152 {
00153         float x1 = .5;
00154         float x2 = -.5;
00155         float y1 = .5;
00156         float y2 = -.5;
00157         
00158         pheight = y1 - y2;
00159         if (pheight < 0)
00160                 pheight = -pheight;
00161         
00162         glBegin(GL_QUADS);
00163                 glTexCoord2d(0,0);
00164                 glVertex3f(x1, y1, 0);
00165         
00166                 glTexCoord2d(0,1);
00167                 glVertex3f(x1, y2, 0);
00168         
00169                 glTexCoord2d(1,1);
00170                 glVertex3f(x2, y2, 0);
00171         
00172                 glTexCoord2d(1,0);
00173                 glVertex3f(x2, y1, 0);
00174         glEnd();
00175 }
00176 
00177 void PARTICLE::SetParams(float transmin, float transmax, float longmin, float longmax,
00178                                         float speedmin, float speedmax, VERTEX direction, float sizemin,
00179                                         float sizemax)
00180 {
00181         params[0].transparency = transmin;
00182         params[0].longevity = longmin;
00183         params[0].speed = speedmin;
00184         params[0].direction = direction;
00185         params[0].size = sizemin;
00186         
00187         params[1].transparency = transmax;
00188         params[1].longevity = longmax;
00189         params[1].speed = speedmax;
00190         params[1].direction = direction;
00191         params[1].size = sizemax;
00192 }
00193 
00194 void PARTICLE::AddParticle(VERTEX pos)
00195 {
00196         int idx = slotguess;
00197         int i;
00198         for (i = 0; i < MAX_PARTICLES; i++)
00199         {
00200                 if (!particle[idx].active)
00201                 {
00202                         particle[idx].active = true;
00203                         particle[idx].start_position = pos;
00204                         VERTEX noise;
00205                         float noisemag = 0.1;
00206                         noise.x = randf(-noisemag, noisemag);
00207                         noise.y = randf(-noisemag, noisemag);
00208                         noise.z = randf(-noisemag, noisemag);
00209                         particle[idx].direction = (params[0].direction + noise + wind).normalize();
00210                         particle[idx].timestamp = curtime;
00211                         
00212                         particle[idx].speed = randf(params[0].speed, params[1].speed);
00213                         particle[idx].transparency = randf(params[0].transparency, params[1].transparency);
00214                         particle[idx].longevity = randf(params[0].longevity, params[1].longevity);
00215                         particle[idx].size = randf(params[0].size, params[1].size);
00216                         
00217                         particle[idx].rotation = randf(0,360);
00218                         particle[idx].texture = curtex;
00219                         curtex++;
00220                         if (curtex >= PARTICLE_TEXTURES)
00221                                 curtex -= PARTICLE_TEXTURES;
00222                         
00223                         slotguess = idx+1;
00224                         if (slotguess >= MAX_PARTICLES)
00225                                 slotguess = 0;
00226                         
00227                         i = MAX_PARTICLES; //break
00228                 }
00229                 else
00230                 {
00231                         idx++;
00232                         if (idx >= MAX_PARTICLES)
00233                                 idx -= MAX_PARTICLES;
00234                 }
00235         }
00236 }
00237 
00238 float PARTICLE::randf(float min, float max)
00239 {
00240         if (min > max)
00241         {
00242                 float temp = min;
00243                 min = max;
00244                 max = temp;
00245         }
00246         
00247         float r = (float) rand() / (float) RAND_MAX;
00248 //float r = 0;
00249         r *= max-min;
00250         r += min;
00251         return r;
00252 }
00253 
00254 void PARTICLE::Update(float timefactor, float fps)
00255 {
00256         curtime += timefactor/fps;
00257 }
00258 
00259 void PARTICLE::Draw()
00260 {
00261         glPushAttrib(GL_ALL_ATTRIB_BITS);
00262         glDisable(GL_LIGHTING);
00263         glEnable(GL_BLEND);
00264         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00265         glDepthMask(0);
00266         int i;
00267         for (i = 0; i < MAX_PARTICLES; i++)
00268         {       
00269                 if (particle[i].active)
00270                 {
00271                         if (curtime - particle[i].timestamp > particle[i].longevity)
00272                                 particle[i].active = false;
00273                         else
00274                                 DrawParticle(particle[i]);
00275                 }
00276         }
00277         glDepthMask(1);
00278         glPopAttrib();
00279 }
00280 
00281 void PARTICLE::DrawParticle(struct SINGLE_PARTICLE & p)
00282 {
00283         VERTEX drawpos;
00284         drawpos = p.start_position;
00285         float age = curtime - p.timestamp;
00286         VERTEX offset = p.direction.ScaleR(age*p.speed);
00287         drawpos = drawpos + offset;
00288         
00289         glPushMatrix();
00290         glTranslatef(drawpos.x, drawpos.y, drawpos.z);
00291         
00292         float trans = 0.5;
00293         float sizescale = 1.0;
00294         if (p.longevity > 0)
00295         {
00296                 trans = p.transparency*pow((double)(1.0f-age/p.longevity),4.0)*1.0f/((float)NUM_ROTATIONS+1.0f);
00297                 float transmax = 0.5/(NUM_ROTATIONS+1.0f);
00298                 if (trans > transmax)
00299                         trans = transmax;
00300                 if (trans < 0.0)
00301                         trans = 0.0;
00302                 
00303                 sizescale = 15.0*(age/p.longevity)+1.0;
00304         }
00305         glColor4f(1,1,1,trans);
00306         //glBindTexture(GL_TEXTURE_2D, texture[p.texture]);
00307         texture[p.texture].Activate();
00308         //cout << texture[p.texture] << endl;
00309         
00310         glScalef(p.size*sizescale, p.size*sizescale, p.size*sizescale);
00311         
00312         //glRotatef(p.rotation,0,0,1);
00313         
00314         glCallList(drawlist);
00315         
00316         glPopMatrix();
00317 }
00318 
00319 void PARTICLE::ProbAddParticle(VERTEX pos, float probability)
00320 {
00321         float roll = randf(0,1);
00322         if (probability > roll)
00323         {
00324                 AddParticle(pos);
00325         }
00326 }
00327 
00328 float PARTICLE::ParticleHeight()
00329 {
00330         return pheight;
00331 }
00332 
00333 void PARTICLE::ClipParticles(VERTEX * rect)
00334 {
00335         //return;
00336         
00337         float height = 0;
00338         int j;
00339         for (j = 0; j < 4; j++)
00340         {
00341                 height += rect[j].y;
00342         }
00343         height /= 4.0f;
00344         
00345         height += 0.2f;
00346         
00347         int i;
00348         for (i = 0; i < MAX_PARTICLES; i++)
00349         {       
00350                 if (particle[i].active)
00351                 {
00352                         VERTEX drawpos;
00353                         drawpos = particle[i].start_position;
00354                         float age = curtime - particle[i].timestamp;
00355                         VERTEX offset = particle[i].direction.ScaleR(age*particle[i].speed);
00356                         drawpos = drawpos + offset;
00357                         
00358                         float dimension = 0.5f;
00359                         VERTEX dprect[4];
00360                         dprect[0] = drawpos;
00361                         dprect[0].x -= dimension;
00362                         dprect[0].z -= dimension;
00363                         dprect[1] = drawpos;
00364                         dprect[1].x -= dimension;
00365                         dprect[1].z += dimension;
00366                         dprect[2] = drawpos;
00367                         dprect[2].x += dimension;
00368                         dprect[2].z += dimension;
00369                         dprect[3] = drawpos;
00370                         dprect[3].x += dimension;
00371                         dprect[3].z -= dimension;
00372                         
00373                         //if (inrect(rect, drawpos))// && drawpos.y > height)
00374                         if (overlap(rect, dprect) && drawpos.y > height)
00375                         {
00376                                 if (drawpos.y - height <= 0.2)
00377                                 {
00378                                         float age = (curtime - particle[i].timestamp);
00379                                         particle[i].start_position = drawpos;
00380                                         particle[i].start_position.y = height;
00381                                         particle[i].longevity = particle[i].longevity - age;
00382                                         particle[i].timestamp = curtime;
00383                                         particle[i].transparency = particle[i].transparency*(1.0f-age/particle[i].longevity)*1.0f/((float)NUM_ROTATIONS+1.0f);
00384                                 }
00385                                 else
00386                                         particle[i].active = false;
00387                         }
00388                 }
00389         }
00390 }
00391 
00392 bool PARTICLE::inrect (VERTEX * rect, VERTEX p)
00393 {
00394         int i;
00395         
00396         int positive = 0;
00397         
00398         float x0, x1, x2, y0, y1, y2;
00399         
00400         for (i = 0; i < 4; i++)
00401         {
00402                 x2 = p.x;
00403                 y2 = p.z;
00404                 
00405                 x0 = rect[i].x;
00406                 y0 = rect[i].z;
00407                 
00408                 int nexti = i+1;
00409                 if (nexti >= 4)
00410                         nexti = 0;
00411                 x1 = rect[nexti].x;
00412                 y1 = rect[nexti].z;
00413                 
00414                 if ((.5)*(x1*y2 - y1*x2 -x0*y2 + y0*x2 + x0*y1 - y0*x1) < 0)
00415                         positive ++;
00416         }
00417         
00418         if (positive == 4)
00419                 return true;
00420         
00421         //cout << positive << endl;
00422         
00423         return false;
00424 }
00425 
00426 bool PARTICLE::inrange(float x1, float x2, float val)
00427 {
00428         if (x1 >= x2 && val >= x2 && val <= x1)
00429                 return true;
00430         if (x2 > x1 && val <= x2 && val >= x1)
00431                 return true;
00432         
00433         return false;
00434 }
00435 
00436 bool PARTICLE::overlap (VERTEX * rect1, VERTEX * rect2)
00437 {
00438         return (inrect(rect1, rect2[0]) || inrect(rect1, rect2[1]) 
00439                         || inrect(rect1, rect2[2]) || inrect(rect1, rect2[3]));
00440 }
00441 
00442 void PARTICLE::Clear()
00443 {
00444         int i;
00445         for (i = 0; i < MAX_PARTICLES; i++)
00446         {
00447                 particle[i].active = false;
00448         }
00449 }

Generated on Thu Oct 19 04:05:54 2006 by  doxygen 1.4.6