Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

particle.cpp

Go to the documentation of this file.
00001 // Particle Classes    by Alan Baylis 2001
00002 
00003 // Inspired by the work by
00004 // John van der Burg
00005 // Mystic Game Development
00006 // john@mysticgd.com
00007 
00008 #include "particle.h"
00009 #include "matrix.h"
00010 #include "texture.h"
00011 #include "listnode.h"
00012 #include "collision.h"
00013 #include "general.h"
00014 #include "bsp.h"
00015 #include "locmath.h"
00016 #include "mmgr.h"
00017 
00018 extern BSP_node* root;
00019 extern ParticleManager PManager;
00020 extern TEXTURE* texture;
00021 extern LinkedList<BSP_node> LeafList;
00022 extern LinkedList<BSP_node> PartitionList;
00023 extern BSP_node* listnode;
00024 
00025 int PARTICLE::Compare(const PARTICLE& Particle)
00026 {
00027     if (linkPosition < Particle.linkPosition)
00028         return smaller;
00029     if (linkPosition > Particle.linkPosition)
00030         return bigger;
00031     else
00032         return same;
00033 }
00034 
00035 // ParticleSystem Methods
00036 void ParticleSystem::Render(int nodeid)
00037 {
00038    // Add a default method
00039 }
00040 
00041 void ParticleSystem::Update()
00042 {
00043    // Add a default method
00044 }
00045 
00046 void ParticleSystem::SetDefaults(PARTICLE* Particle)
00047 {
00048    // Add a default method
00049 }
00050 
00051 void ParticleSystem::SetShape(PARTICLE* Particle)
00052 {
00053    // Add a default method
00054 }
00055 
00056 int ParticleSystem::GetNumAlive()
00057 {
00058     int numParticles = 0;
00059     PARTICLE* tempParticle;
00060     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00061     {
00062         tempParticle = ParticleList.Get(loop);
00063         if (tempParticle->PartInfo.Alive)
00064             numParticles++;
00065     }
00066     return numParticles;
00067 }
00068 
00069 // Add initial particles to the empty list
00070 void ParticleSystem::SetupParticles()
00071 {
00072     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00073     {
00074         PARTICLE* newParticle = new PARTICLE;
00075         SetDefaults(newParticle);
00076         SetShape(newParticle);
00077         newParticle->linkPosition = loop;
00078         ParticleList.Insert(newParticle);
00079     }
00080 }
00081 
00082 void ParticleSystem::Remove()
00083 {
00084     if (SysInfo.numParticles > 0)
00085     {
00086         ParticleList.Delete(1);
00087         --SysInfo.numParticles;
00088     }
00089 }
00090 
00091 PARTICLE* ParticleSystem::Add()
00092 {
00093     PARTICLE* newParticle = new PARTICLE;
00094     SetDefaults(newParticle);
00095     SetShape(newParticle);
00096     newParticle->linkPosition = ++SysInfo.numParticles;
00097     ParticleList.Insert(newParticle);
00098     return newParticle;
00099 }
00100 
00101 int ParticleSystem::Compare(const ParticleSystem& ParticleSys)
00102 {
00103   if (linkPosition < ParticleSys.linkPosition)
00104     return smaller;
00105   if (linkPosition > ParticleSys.linkPosition)
00106     return bigger;
00107   else
00108     return same;
00109 }
00110 
00111 // Particle Manager Methods
00112 void ParticleManager::Update()
00113 {
00114     int loop, innerloop;
00115     ParticleSystem* PartSys;
00116     PARTICLE* tempParticle;
00117     for (loop = 1; loop <= numSystems; loop++)
00118     {
00119         PartSys = SystemList.Get(loop);
00120 
00121         if (!PartSys->GetNumAlive())
00122         {
00123             SystemList.Delete(PartSys->linkPosition);
00124             numSystems--;
00125         }
00126         else
00127         {
00128             PartSys->Update();
00129             for (innerloop = 1; innerloop < PartSys->SysInfo.numParticles; innerloop++)
00130             {
00131                 tempParticle = PartSys->ParticleList.Get(innerloop);
00132                 tempParticle->PartInfo.Leaf = FindCurrentLeaf(tempParticle->PartInfo.Pos, root);
00133             }
00134         }
00135     }
00136 }
00137 
00138 void ParticleManager::Render(int nodeid)
00139 {
00140     for (int loop = 1; loop <= numSystems; loop++)
00141     {
00142         ParticleSystem* PartSys = SystemList.Get(loop);
00143         PartSys->Render(nodeid);
00144     }
00145 }
00146 
00147 void ParticleManager::SetId(int Id, int newId)
00148 {
00149     for (int loop = 1; loop <= numSystems; loop++)
00150     {
00151         ParticleSystem* PartSys = SystemList.Get(loop);
00152         if (Id == PartSys->SysInfo.Id)
00153             PartSys->SysInfo.Id = newId;
00154     }
00155 }
00156 
00157 void ParticleManager::SetTextureId(int Id, unsigned int TexID)
00158 {
00159     for (int loop = 1; loop <= numSystems; loop++)
00160     {
00161         ParticleSystem* PartSys = SystemList.Get(loop);
00162         if (Id == PartSys->SysInfo.Id)
00163             PartSys->SysInfo.TexID = TexID;
00164     }
00165 }
00166 
00167 void ParticleManager::SetBlendMode(int Id, int BlendMode)
00168 {
00169     for (int loop = 1; loop <= numSystems; loop++)
00170     {
00171         ParticleSystem* PartSys = SystemList.Get(loop);
00172         if (Id == PartSys->SysInfo.Id)
00173             PartSys->SysInfo.BlendMode = BlendMode;
00174     }
00175 }
00176 
00177 void ParticleManager::SetType(int Id, ParticleType Type)
00178 {
00179     for (int loop = 1; loop <= numSystems; loop++)
00180     {
00181         ParticleSystem* PartSys = SystemList.Get(loop);
00182         if (Id == PartSys->SysInfo.Id)
00183             PartSys->SysInfo.Type = Type;
00184     }
00185 }
00186 
00187 void ParticleManager::SetVisibility(int Id, bool State)
00188 {
00189     for (int loop = 1; loop <= numSystems; loop++)
00190     {
00191         ParticleSystem* PartSys = SystemList.Get(loop);
00192         if (Id == PartSys->SysInfo.Id)
00193             PartSys->SysInfo.Visibility = State;
00194     }
00195 }
00196 
00197 void ParticleManager::ToggleVisibility(int Id)
00198 {
00199     for (int loop = 1; loop <= numSystems; loop++)
00200     {
00201         ParticleSystem* PartSys = SystemList.Get(loop);
00202         if (Id == PartSys->SysInfo.Id)
00203             PartSys->SysInfo.Visibility = !PartSys->SysInfo.Visibility;
00204     }
00205 }
00206 
00207 ParticleSystem* ParticleManager::Add(ParticleSystem* PartSys)
00208 {
00209     PartSys->SetupParticles();
00210     PartSys->linkPosition = ++numSystems;
00211     SystemList.Insert(PartSys);
00212     return PartSys;
00213 }
00214 
00215 void ParticleManager::Remove(int Id)
00216 {
00217     for (int loop = 1; loop <= numSystems; loop++)
00218     {
00219         ParticleSystem* PartSys = SystemList.Get(loop);
00220         if (Id == PartSys->SysInfo.Id)
00221         {
00222             SystemList.Delete(PartSys->linkPosition);
00223             --numSystems;
00224         }
00225     }
00226 }
00227 
00228 void ParticleManager::RemoveType(ParticleType Type)
00229 {
00230     for (int loop = 1; loop <= numSystems; loop++)
00231     {
00232         ParticleSystem* PartSys = SystemList.Get(loop);
00233         if (Type == PartSys->SysInfo.Type)
00234         {
00235             SystemList.Delete(PartSys->linkPosition);
00236             --numSystems;
00237         }
00238     }
00239 }
00240 
00241 // Derived Particle Systems
00242 
00243 // spark type
00244 void Spark::Update()
00245 {
00246     bool CollisionFlag;
00247     VECTOR VelocityVector, normal, pos, oldpos, temppos;
00248     PARTICLE* tempParticle;
00249     // Loop through all the particles of this system
00250     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00251     {
00252         // Get the particle from the list
00253         tempParticle = ParticleList.Get(loop);
00254         // Set the old position
00255         tempParticle->PartInfo.OldPos = tempParticle->PartInfo.Pos;
00256         // Apply gravity
00257         tempParticle->PartInfo.Velocity.x += 0.0;
00258         tempParticle->PartInfo.Velocity.y += -0.002;
00259         tempParticle->PartInfo.Velocity.z += 0.0;
00260 
00261         if (tempParticle->PartInfo.Energy > 0.0)
00262         {
00263             // Set the alpha channel to the energy value
00264             tempParticle->PartInfo.Color[3] = tempParticle->PartInfo.Energy;
00265             // Decrease the energy
00266             tempParticle->PartInfo.Energy -= 0.002;
00267             // Update the position
00268             oldpos = tempParticle->PartInfo.Pos;
00269             pos = tempParticle->PartInfo.Pos + tempParticle->PartInfo.Velocity;
00270             temppos = pos;
00271             // Check for a collision and get the normal of the collision polygon
00272             CollisionFlag = CheckForParticleCollision(tempParticle, oldpos, &temppos, &normal);
00273             // If there was a collision then reflect the velocity vector
00274             if (CollisionFlag)
00275             {
00276                 VECTOR vectn = normal * (normal.DotProduct(tempParticle->PartInfo.Velocity));
00277                 VECTOR vectt = tempParticle->PartInfo.Velocity - vectn;
00278                 VECTOR vel = (vectt - vectn);
00279                 tempParticle->PartInfo.Pos.x += vel.x;
00280                 tempParticle->PartInfo.Pos.y += vel.y;
00281                 tempParticle->PartInfo.Pos.z += vel.z;
00282                 // Decrease the velocity
00283                 tempParticle->PartInfo.Velocity.x = vel.x / 3.0;
00284                 tempParticle->PartInfo.Velocity.y = vel.y / 3.0;
00285                 tempParticle->PartInfo.Velocity.z = vel.z / 3.0;
00286                 // Reduce the particles energy due to the collision
00287                 tempParticle->PartInfo.Energy -= 0.2;
00288             }
00289             else // Update the position as normal
00290             {
00291                 tempParticle->PartInfo.Pos.x += tempParticle->PartInfo.Velocity.x;
00292                 tempParticle->PartInfo.Pos.y += tempParticle->PartInfo.Velocity.y;
00293                 tempParticle->PartInfo.Pos.z += tempParticle->PartInfo.Velocity.z;
00294             }
00295         }
00296         else // The particles energy has reduced to zero
00297         {
00298             tempParticle->PartInfo.Alive = false;
00299         }
00300     }
00301 }
00302 
00303 void Spark::Render(int nodeid)
00304 {
00305     MATRIX mat;
00306     VECTOR up;
00307     VECTOR right;
00308     PARTICLE* tempParticle;
00309     // Get the current modelview matrix
00310     glGetFloatv(GL_MODELVIEW_MATRIX, mat.Element);
00311     // Set texture states
00312     glEnable(GL_BLEND);
00313     glDepthMask(0);
00314     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00315     glDisable(GL_LIGHTING);
00316     glBindTexture(GL_TEXTURE_2D, SysInfo.TexID);
00317     // Loop through all the particles in this system
00318     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00319     {
00320         // Get the particle from the list
00321         tempParticle = ParticleList.Get(loop);
00322         // If the particle is in the current bsp node
00323         if (tempParticle->PartInfo.Leaf == nodeid)
00324         {
00325             // If the particle is still alive
00326             if (tempParticle->PartInfo.Alive)
00327             {
00328                 // Set the shape, should really be performed in Spark::SetShape()
00329                 right.x = mat.Element[0];
00330                 right.y = mat.Element[4];
00331                 right.z = mat.Element[8];
00332                 right.Normalize();
00333                 right.x *= tempParticle->PartInfo.SizeX / 2;
00334                 right.y *= tempParticle->PartInfo.SizeX / 2;
00335                 right.z *= tempParticle->PartInfo.SizeX / 2;
00336 
00337                 up.x = mat.Element[1];
00338                 up.y = mat.Element[5];
00339                 up.z = mat.Element[9];
00340                 up.Normalize();
00341                 up.x *= tempParticle->PartInfo.SizeY / 2;
00342                 up.y *= tempParticle->PartInfo.SizeY / 2;
00343                 up.z *= tempParticle->PartInfo.SizeY / 2;
00344                 // Set the color to the default values
00345                 glColor4f(tempParticle->PartInfo.Color[0],
00346                             tempParticle->PartInfo.Color[1],
00347                             tempParticle->PartInfo.Color[2],
00348                             tempParticle->PartInfo.Color[3]);
00349                 // Render the billboarded particle
00350                 glBegin(GL_QUADS);
00351                     glTexCoord2f(0.0f, 0.0f);
00352                     glVertex3f(tempParticle->PartInfo.Pos.x + (-right.x - up.x),
00353                                 tempParticle->PartInfo.Pos.y + (-right.y - up.y),
00354                                 tempParticle->PartInfo.Pos.z + (-right.z - up.z));
00355                     glTexCoord2f(1.0f, 0.0f);
00356                     glVertex3f(tempParticle->PartInfo.Pos.x + (right.x - up.x),
00357                                 tempParticle->PartInfo.Pos.y + (right.y - up.y),
00358                                 tempParticle->PartInfo.Pos.z + (right.z - up.z));
00359                     glTexCoord2f(1.0f, 1.0f);
00360                     glVertex3f(tempParticle->PartInfo.Pos.x + (right.x + up.x),
00361                                 tempParticle->PartInfo.Pos.y + (right.y + up.y),
00362                                 tempParticle->PartInfo.Pos.z + (right.z + up.z));
00363                     glTexCoord2f(0.0f, 1.0f);
00364                     glVertex3f(tempParticle->PartInfo.Pos.x + (up.x - right.x),
00365                                 tempParticle->PartInfo.Pos.y + (up.y - right.y),
00366                                 tempParticle->PartInfo.Pos.z + (up.z - right.z));
00367                 glEnd();
00368             }
00369         }
00370     }
00371     // Reset texture states
00372     glEnable(GL_LIGHTING);
00373     glDepthMask(1);
00374     glDisable(GL_BLEND);
00375 }
00376 
00377 void Spark::SetDefaults(PARTICLE* Particle)
00378 {
00379     // Set this particle systems properties
00380     Particle->PartInfo.Alive = true;
00381     Particle->PartInfo.Pos = SysInfo.Pos;
00382     Particle->PartInfo.OldPos = SysInfo.Pos;
00383     Particle->PartInfo.OrigPos = SysInfo.Pos;
00384     // Reflect the initial velocity
00385     VECTOR Velocity = SysInfo.InitialVelocity;
00386     VECTOR vectn = SysInfo.Normal * (SysInfo.Normal.DotProduct(Velocity));
00387     VECTOR vectt = Velocity - vectn;
00388     VECTOR vel = (vectt - vectn);
00389     Velocity.normalize();
00390     // Create a random spread for each particle
00391     float x;
00392     x = (float)rand()/(float)RAND_MAX;
00393     Particle->PartInfo.Velocity.x = Velocity.x + (x - 0.5);
00394     Particle->PartInfo.Velocity.x /= 2.0;
00395     x = (float)rand()/(float)RAND_MAX;
00396     Particle->PartInfo.Velocity.y = Velocity.y + (x - 0.5);
00397     Particle->PartInfo.Velocity.y /= 2.0;
00398     x = (float)rand()/(float)RAND_MAX;
00399     Particle->PartInfo.Velocity.z = Velocity.z + (x - 0.5);
00400     Particle->PartInfo.Velocity.z /= 2.0;
00401     // Set the color
00402     Particle->PartInfo.Color[0] = 1.0;
00403     Particle->PartInfo.Color[1] = 1.0;
00404     Particle->PartInfo.Color[2] = 1.0;
00405     Particle->PartInfo.Color[3] = 1.0;
00406     // Create a random energy value between 0.5 and 1.0
00407     x = (float)rand()/(float)RAND_MAX;
00408     Particle->PartInfo.Energy = x + 0.5;
00409     if (Particle->PartInfo.Energy > 1.0)
00410         Particle->PartInfo.Energy = 1.0;
00411     // Set the size of the particle
00412     Particle->PartInfo.SizeX = 0.8;
00413     Particle->PartInfo.SizeY = 0.8;
00414 }
00415 
00416 void Spark::SetShape(PARTICLE* Particle)
00417 {
00418     // Unused for now
00419 }
00420 
00421 // Roman candle type
00422 void Roman::Update()
00423 {
00424     VECTOR normal, pos, oldpos, temppos;
00425     PARTICLE* tempParticle;
00426 
00427     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00428     {
00429         tempParticle = ParticleList.Get(loop);
00430         tempParticle->PartInfo.OldPos = tempParticle->PartInfo.Pos;
00431         tempParticle->PartInfo.Velocity.x += 0.0;
00432         tempParticle->PartInfo.Velocity.y += -0.003;
00433         tempParticle->PartInfo.Velocity.z += 0.0;
00434         if (tempParticle->PartInfo.Energy > 0.0)
00435         {
00436             tempParticle->PartInfo.Color[3] = tempParticle->PartInfo.Energy;
00437             tempParticle->PartInfo.Energy -= 0.003;
00438             oldpos = tempParticle->PartInfo.Pos;
00439             pos = tempParticle->PartInfo.Pos + tempParticle->PartInfo.Velocity;
00440             temppos = pos;
00441             bool CollisionFlag = CheckForParticleCollision(tempParticle, oldpos, &temppos, &normal);
00442 
00443             VECTOR VelocityVector;
00444 
00445             if (CollisionFlag)
00446             {
00447                 VECTOR vn = normal * (normal.DotProduct(tempParticle->PartInfo.Velocity));
00448                 VECTOR vt = tempParticle->PartInfo.Velocity - vn;
00449                 VECTOR vel = (vt - vn);
00450                 tempParticle->PartInfo.Pos.x += vel.x;
00451                 tempParticle->PartInfo.Pos.y += vel.y;
00452                 tempParticle->PartInfo.Pos.z += vel.z;
00453                 tempParticle->PartInfo.Velocity.x = vel.x / 3.0;
00454                 tempParticle->PartInfo.Velocity.y = vel.y / 3.0;
00455                 tempParticle->PartInfo.Velocity.z = vel.z / 3.0;
00456                 tempParticle->PartInfo.Energy -= 0.3;
00457             }
00458             else
00459             {
00460                 tempParticle->PartInfo.Pos.x += tempParticle->PartInfo.Velocity.x;
00461                 tempParticle->PartInfo.Pos.y += tempParticle->PartInfo.Velocity.y;
00462                 tempParticle->PartInfo.Pos.z += tempParticle->PartInfo.Velocity.z;
00463             }
00464         }
00465         else
00466         {
00467             SetDefaults(tempParticle);
00468         }
00469 
00470         tempParticle->PartInfo.Color[0] += 0.006;
00471         if (tempParticle->PartInfo.Color[0] > 1.0)
00472             tempParticle->PartInfo.Color[0] = 1.0;
00473         tempParticle->PartInfo.Color[1] += 0.006;
00474         if (tempParticle->PartInfo.Color[1] > 1.0)
00475             tempParticle->PartInfo.Color[1] = 1.0;
00476         tempParticle->PartInfo.Color[2] += 0.006;
00477         if (tempParticle->PartInfo.Color[2] > 1.0)
00478             tempParticle->PartInfo.Color[2] = 1.0;
00479     }
00480 }
00481 
00482 void Roman::Render(int nodeid)
00483 {
00484     MATRIX mat;
00485     VECTOR up;
00486     VECTOR right;
00487     PARTICLE* tempParticle;
00488 
00489     glGetFloatv(GL_MODELVIEW_MATRIX, mat.Element);
00490 
00491     glEnable(GL_BLEND);
00492     glDepthMask(0);
00493     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00494     glDisable(GL_LIGHTING);
00495     glBindTexture(GL_TEXTURE_2D, SysInfo.TexID);
00496 
00497     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00498     {
00499         tempParticle = ParticleList.Get(loop);
00500 
00501         if (tempParticle->PartInfo.Leaf == nodeid)
00502         {
00503             if (tempParticle->PartInfo.Alive)
00504             {
00505                 right.x = mat.Element[0];
00506                 right.y = mat.Element[4];
00507                 right.z = mat.Element[8];
00508                 right.Normalize();
00509                 right.x *= tempParticle->PartInfo.SizeX / 2;
00510                 right.y *= tempParticle->PartInfo.SizeX / 2;
00511                 right.z *= tempParticle->PartInfo.SizeX / 2;
00512 
00513                 up.x = mat.Element[1];
00514                 up.y = mat.Element[5];
00515                 up.z = mat.Element[9];
00516                 up.Normalize();
00517                 up.x *= tempParticle->PartInfo.SizeY / 2;
00518                 up.y *= tempParticle->PartInfo.SizeY / 2;
00519                 up.z *= tempParticle->PartInfo.SizeY / 2;
00520 
00521                 glColor4f(tempParticle->PartInfo.Color[0], tempParticle->PartInfo.Color[1], tempParticle->PartInfo.Color[2], tempParticle->PartInfo.Color[3]);
00522                 glBegin(GL_QUADS);
00523                     glTexCoord2f(0.0f, 0.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (-right.x - up.x), tempParticle->PartInfo.Pos.y + (-right.y - up.y), tempParticle->PartInfo.Pos.z + (-right.z - up.z));
00524                     glTexCoord2f(1.0f, 0.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (right.x - up.x), tempParticle->PartInfo.Pos.y + (right.y - up.y), tempParticle->PartInfo.Pos.z + (right.z - up.z));
00525                     glTexCoord2f(1.0f, 1.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (right.x + up.x), tempParticle->PartInfo.Pos.y + (right.y + up.y), tempParticle->PartInfo.Pos.z + (right.z + up.z));
00526                     glTexCoord2f(0.0f, 1.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (up.x - right.x), tempParticle->PartInfo.Pos.y + (up.y - right.y), tempParticle->PartInfo.Pos.z + (up.z - right.z));
00527                 glEnd();
00528             }
00529         }
00530     }
00531 
00532     glEnable(GL_LIGHTING);
00533     glDepthMask(1);
00534     glDisable(GL_BLEND);
00535 }
00536 
00537 void Roman::SetDefaults(PARTICLE* Particle)
00538 {
00539     Particle->PartInfo.Alive = true;
00540     Particle->PartInfo.Pos = SysInfo.Pos;
00541     Particle->PartInfo.OldPos = SysInfo.Pos;
00542     Particle->PartInfo.OrigPos = SysInfo.Pos;
00543 
00544     VECTOR Velocity = SysInfo.Normal;
00545 
00546     float x;
00547     x = (float)rand()/(float)RAND_MAX;
00548     Particle->PartInfo.Velocity.x = Velocity.x + (x - 0.5) / 5;
00549     Particle->PartInfo.Velocity.x /= 4.0;
00550     x = (float)rand()/(float)RAND_MAX;
00551     Particle->PartInfo.Velocity.y = Velocity.y + (x - 0.5);
00552     Particle->PartInfo.Velocity.y /= 4.0;
00553     x = (float)rand()/(float)RAND_MAX;
00554     Particle->PartInfo.Velocity.z = Velocity.z + (x - 0.5) / 5;
00555     Particle->PartInfo.Velocity.z /= 4.0;
00556 
00557     Particle->PartInfo.Color[0] = SysInfo.Color[0];
00558     Particle->PartInfo.Color[1] = SysInfo.Color[1];
00559     Particle->PartInfo.Color[2] = SysInfo.Color[2];
00560     Particle->PartInfo.Color[3] = 1.0;
00561 
00562     Particle->PartInfo.Energy = 1.0;
00563     Particle->PartInfo.SizeX = 3.0;
00564     Particle->PartInfo.SizeY = 3.0;
00565 }
00566 
00567 void Roman::SetShape(PARTICLE* Particle)
00568 {
00569 }
00570 
00571 // Bouncing type
00572 void Bouncy::Update()
00573 {
00574     bool CollisionFlag;
00575     VECTOR VelocityVector, normal, pos, oldpos, temppos;
00576     PARTICLE* tempParticle;
00577 
00578     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00579     {
00580         tempParticle = ParticleList.Get(loop);
00581         tempParticle->PartInfo.OldPos = tempParticle->PartInfo.Pos;
00582         oldpos = tempParticle->PartInfo.Pos;
00583         pos = tempParticle->PartInfo.Pos + tempParticle->PartInfo.Velocity;
00584         temppos = pos;
00585         CollisionFlag = CheckForParticleCollision(tempParticle, oldpos, &temppos, &normal);
00586 
00587         if (CollisionFlag)
00588         {
00589             VECTOR vn = normal * (normal.DotProduct(tempParticle->PartInfo.Velocity));
00590             VECTOR vt = tempParticle->PartInfo.Velocity - vn;
00591             VECTOR vel = (vt - vn);
00592             tempParticle->PartInfo.Pos.x += vel.x;
00593             tempParticle->PartInfo.Pos.y += vel.y;
00594             tempParticle->PartInfo.Pos.z += vel.z;
00595             tempParticle->PartInfo.Velocity.x = vel.x;
00596             tempParticle->PartInfo.Velocity.y = vel.y;
00597             tempParticle->PartInfo.Velocity.z = vel.z;
00598         }
00599         else
00600         {
00601             tempParticle->PartInfo.Pos.x += tempParticle->PartInfo.Velocity.x;
00602             tempParticle->PartInfo.Pos.y += tempParticle->PartInfo.Velocity.y;
00603             tempParticle->PartInfo.Pos.z += tempParticle->PartInfo.Velocity.z;
00604         }
00605     }
00606 }
00607 
00608 void Bouncy::Render(int nodeid)
00609 {
00610     MATRIX mat;
00611     VECTOR up;
00612     VECTOR right;
00613     PARTICLE* tempParticle;
00614 
00615     glGetFloatv(GL_MODELVIEW_MATRIX, mat.Element);
00616 
00617     glEnable(GL_BLEND);
00618     glDepthMask(0);
00619     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00620     glDisable(GL_LIGHTING);
00621     glBindTexture(GL_TEXTURE_2D, SysInfo.TexID);
00622 
00623     for (int loop = 1; loop <= SysInfo.numParticles; loop++)
00624     {
00625         tempParticle = ParticleList.Get(loop);
00626 
00627         if (tempParticle->PartInfo.Leaf == nodeid)
00628         {
00629             if (tempParticle->PartInfo.Alive)
00630             {
00631                 right.x = mat.Element[0];
00632                 right.y = mat.Element[4];
00633                 right.z = mat.Element[8];
00634                 right.Normalize();
00635                 right.x *= tempParticle->PartInfo.SizeX / 2;
00636                 right.y *= tempParticle->PartInfo.SizeX / 2;
00637                 right.z *= tempParticle->PartInfo.SizeX / 2;
00638 
00639                 up.x = mat.Element[1];
00640                 up.y = mat.Element[5];
00641                 up.z = mat.Element[9];
00642                 up.Normalize();
00643                 up.x *= tempParticle->PartInfo.SizeY / 2;
00644                 up.y *= tempParticle->PartInfo.SizeY / 2;
00645                 up.z *= tempParticle->PartInfo.SizeY / 2;
00646 
00647                 glColor4f(0.0, 1.0, 0.0, 1.0);
00648                 glBegin(GL_QUADS);
00649                     glTexCoord2f(0.0f, 0.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (-right.x - up.x), tempParticle->PartInfo.Pos.y + (-right.y - up.y), tempParticle->PartInfo.Pos.z + (-right.z - up.z));
00650                     glTexCoord2f(1.0f, 0.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (right.x - up.x), tempParticle->PartInfo.Pos.y + (right.y - up.y), tempParticle->PartInfo.Pos.z + (right.z - up.z));
00651                     glTexCoord2f(1.0f, 1.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (right.x + up.x), tempParticle->PartInfo.Pos.y + (right.y + up.y), tempParticle->PartInfo.Pos.z + (right.z + up.z));
00652                     glTexCoord2f(0.0f, 1.0f); glVertex3f(tempParticle->PartInfo.Pos.x + (up.x - right.x), tempParticle->PartInfo.Pos.y + (up.y - right.y), tempParticle->PartInfo.Pos.z + (up.z - right.z));
00653                 glEnd();
00654             }
00655         }
00656     }
00657 
00658     glEnable(GL_LIGHTING);
00659     glDepthMask(1);
00660     glDisable(GL_BLEND);
00661 }
00662 
00663 void Bouncy::SetDefaults(PARTICLE* Particle)
00664 {
00665     Particle->PartInfo.Alive = true;
00666     Particle->PartInfo.Pos = SysInfo.Pos;
00667     Particle->PartInfo.OldPos = SysInfo.Pos;
00668     Particle->PartInfo.OrigPos = SysInfo.Pos;
00669 
00670     VECTOR Velocity = SysInfo.Normal;
00671 
00672     float x;
00673     x = (float)rand()/(float)RAND_MAX;
00674     Particle->PartInfo.Velocity.x = Velocity.x + (x - 0.5) / 5;
00675     Particle->PartInfo.Velocity.x /= 4.0;
00676     x = (float)rand()/(float)RAND_MAX;
00677     Particle->PartInfo.Velocity.y = Velocity.y + (x - 0.5);
00678     Particle->PartInfo.Velocity.y /= 4.0;
00679     x = (float)rand()/(float)RAND_MAX;
00680     Particle->PartInfo.Velocity.z = Velocity.z + (x - 0.5) / 5;
00681     Particle->PartInfo.Velocity.z /= 4.0;
00682 
00683     Particle->PartInfo.Energy = 1.0;
00684     Particle->PartInfo.SizeX = 3.0;
00685     Particle->PartInfo.SizeY = 3.0;
00686 }
00687 
00688 void Bouncy::SetShape(PARTICLE* Particle)
00689 {
00690 }
00691 
00692 void RenderParticles(int nodeid)
00693 {
00694     PManager.Render(nodeid);
00695 }
00696 
00697 void CreateSparks(VECTOR OldPos, VECTOR Pos, VECTOR Normal)
00698 {
00699 
00700     SystemInfo SI;
00701     ZeroMemory(&SI, sizeof(SI));
00702     SI.Visibility = true;
00703     SI.numParticles = rand()%6 + 2;
00704     SI.Type = spark;
00705     SI.TexID = texture[8].TexID;
00706     SI.Id = 1;
00707     SI.Pos = Pos;
00708     SI.Normal = Normal;
00709     SI.InitialVelocity = Pos - OldPos;
00710 
00711     ParticleSystem* sparky = new Spark;
00712     sparky->SysInfo = SI;
00713     PManager.Add(sparky);
00714 }
00715 
00716 void CreateRomanCandle(VECTOR Pos)
00717 {
00718 
00719     SystemInfo SI;
00720     ZeroMemory(&SI, sizeof(SI));
00721     SI.Visibility = true;
00722     SI.numParticles = 80;
00723     SI.Type = roman;
00724     SI.TexID = texture[9].TexID;
00725     SI.Id = 2;
00726     SI.Pos = Pos;
00727     SI.Normal.Set(0.0, 1.0, 0.0);
00728 
00729     SI.Color[0] = 1.0;
00730     SI.Color[1] = 0.0;
00731     SI.Color[2] = 0.0;
00732     SI.Color[3] = 1.0;
00733 
00734     ParticleSystem* romancandle = new Roman;
00735     romancandle->SysInfo = SI;
00736     PManager.Add(romancandle);
00737 }
00738 
00739 void CreateBouncy(VECTOR Pos)
00740 {
00741 
00742     SystemInfo SI;
00743     ZeroMemory(&SI, sizeof(SI));
00744     SI.Visibility = true;
00745     SI.numParticles = 20;
00746     SI.Type = roman;
00747     SI.TexID = texture[9].TexID;
00748     SI.Id = 2;
00749     SI.Pos = Pos;
00750     SI.Normal.Set(0.0, 1.0, 0.0);
00751 
00752     ParticleSystem* bouncy = new Bouncy;
00753     bouncy->SysInfo = SI;
00754     PManager.Add(bouncy);
00755 }
00756 
00757 // finds the collision point and normal of the collision polygon
00758 bool CheckForParticleCollision(PARTICLE* Particle, VECTOR OldPos, VECTOR* Pos, VECTOR* Norm)
00759 {
00760     int CollisionPoly, ParticleLeaf;
00761     POLYGON tempPolygon;
00762     BSP_node* tempnode;
00763     VECTOR CollisionPoint, p0, pN, a, b, c;
00764     bool CollisionFlag = false;
00765 
00766     ParticleLeaf = FindCurrentLeaf(OldPos, root);
00767     tempnode = LeafList.Get(ParticleLeaf);
00768 
00769     // Loop through all polygons in leaf
00770     for (CollisionPoly = 0; CollisionPoly < tempnode->numpolys; CollisionPoly++)
00771     {
00772         tempPolygon = tempnode->nodepolylist[CollisionPoly];
00773         // Get a point on the polygon
00774         p0 = tempPolygon.Vertex[0].coords;
00775         // Get the polygons normal
00776         pN = tempPolygon.Vertex[0].normal;
00777         // If the position isn't in front of or on the polygon then continue
00778         if (ClassifyPoint(*Pos, p0, pN) == 1 || ClassifyPoint(*Pos, p0, pN) == 0)
00779             continue;
00780         // Find collision point on the plane
00781         CollisionPoint = line_plane_collision(&OldPos, Pos, &tempPolygon);
00782         // If collision point is within the polygon
00783         a = tempPolygon.Vertex[0].coords;
00784         b = tempPolygon.Vertex[1].coords;
00785         c = tempPolygon.Vertex[2].coords;
00786         if (CheckPointInTriangle(CollisionPoint, a, b, c))
00787         {
00788             CollisionFlag = true;
00789             VECTOR Normal = tempPolygon.GetNormal();
00790             *Pos = CollisionPoint;
00791 
00792             Normal.normalize();
00793             *Norm = Normal;
00794             break;
00795         }
00796     }
00797     return CollisionFlag;
00798 }
00799 
00800 

Generated on Fri Dec 23 05:15:47 2005 for Constructive Solid Geometry by doxygen1.2.15