📄 particlesystem.h
字号:
#define PARTICLES_PER_MILLISECOND 0.1f
#define MAX_PARTICLES 2000
#define RANDOM_NUMBER ((static_cast<float>(rand())*2.0f)/(static_cast<float>(RAND_MAX))-1.0f)
float ParticleFraction=1.0f;
struct fRGBColor
{
float r, g, b;
};
struct Particle
{
Vector3d Pos, Speed;
float fAge;
float fLifetime;
float fInitialAlpha;
float fFinalAlpha;
float fInitialSize;
float fFinalSize;
fRGBColor InitialColor;
fRGBColor FinalColor;
};
class ParticleSystem
{
public:
bool Solid, Enabled, IndividualAcceleration, BumpAtYPlane, BumpAtXPlane, BumpAtMinusXPlane;
float YPlane, XPlane, AccelFraction;
Particle Particles[MAX_PARTICLES];
Uint16 NumberOfParticles, ParticlesReleased;
Particle InitialParticle, Chaos; /* the initial particle setings will come from
InitialParticle, and every possible variation
from those are simply Chaos ]:D */
Vector3d InitialAccel, FinalAccel, aPos; // initial and final grav vectors (no chaos ;=)
// also the position vector to move the particles
// to when IndividualAcceleration is enabled
Uint16 Texture; // Texture for the particles
void AccelerateTo(Vector3d Position)
{
aPos=Position;
}
ParticleSystem()
{
NumberOfParticles = ParticlesReleased = 0;
}
~ParticleSystem()
{}
}
;
class ParticleGod // diferent from a particle system: this handles EVERY particle in EVERY system in the scene :)
{
public:
int NewSystem (int NumberOfParticles, string TextureFile, int Threshold, bool Solid, float AccelFraction_ForIndividualAcceleration);
inline void Update(float MillisecondsEllapsed);
inline void Draw();
Uint16 Size()
{
return Systems.size();
}
~ParticleGod()
{
Systems.clear();
}
void Clear ()
{
Systems.clear();
}
ParticleSystem *operator[](Uint16 Index)
{
return &Systems[Index];
}
protected:
vector<ParticleSystem> Systems;
}
PGod;
int ParticleGod::NewSystem(int NumberOfParticles, string TextureFile, int Threshold, bool Solid, float AccelFraction_ForIndividualAcceleration=0.0f)
{
if (ParticleFraction==0.0f)
return -1;
if ((int)((float)NumberOfParticles*ParticleFraction)<=0 || (int)((float)NumberOfParticles*ParticleFraction)>=MAX_PARTICLES)
return -1;
int ret;
ParticleSystem System;
Systems.push_back(System);
ret = Systems.size() - 1;
Systems[ret].Texture = LoadAlphaBitmap(TextureFile,CT_LINEAR,Threshold);
Systems[ret].NumberOfParticles = (int)((float)NumberOfParticles*ParticleFraction);
Systems[ret].ParticlesReleased=0;
Systems[ret].Solid=Solid;
Systems[ret].Enabled=true;
Systems[ret].IndividualAcceleration=false;
Systems[ret].BumpAtYPlane=false;
Systems[ret].BumpAtXPlane=false;
Systems[ret].BumpAtMinusXPlane=false;
Systems[ret].AccelFraction=AccelFraction_ForIndividualAcceleration;
return ret;
}
inline void ParticleGod::Update (float MillisecondsEllapsed)
{
Uint16 ParticlesAfterRelease,t;
float fLifeFraction;
for (Uint16 i=0;i<Systems.size();i++)
{
if (Systems[i].Enabled)
{
t=Systems[i].ParticlesReleased;
t=Systems[i].NumberOfParticles;
if (Systems[i].ParticlesReleased<Systems[i].NumberOfParticles)
{
ParticlesAfterRelease = Systems[i].ParticlesReleased+(PARTICLES_PER_MILLISECOND * MillisecondsEllapsed);
if (ParticlesAfterRelease>Systems[i].NumberOfParticles)
ParticlesAfterRelease=Systems[i].NumberOfParticles;
if (ParticlesAfterRelease<Systems[i].NumberOfParticles)
{
for (Uint16 j=Systems[i].ParticlesReleased+1;j<=ParticlesAfterRelease;j++)
{
Systems[i].Particles[j].Pos.Coords[0] = Systems[i].InitialParticle.Pos.Coords[0]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[0]);
Systems[i].Particles[j].Pos.Coords[1] = Systems[i].InitialParticle.Pos.Coords[1]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[1]);
Systems[i].Particles[j].Pos.Coords[2] = Systems[i].InitialParticle.Pos.Coords[2]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[2]);
Systems[i].Particles[j].Speed.Coords[0] = Systems[i].InitialParticle.Speed.Coords[0]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[0]);
Systems[i].Particles[j].Speed.Coords[1] = Systems[i].InitialParticle.Speed.Coords[1]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[1]);
Systems[i].Particles[j].Speed.Coords[2] = Systems[i].InitialParticle.Speed.Coords[2]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[2]);
Systems[i].Particles[j].fAge = 0.0f;
Systems[i].Particles[j].fLifetime = Systems[i].InitialParticle.fLifetime+(RANDOM_NUMBER * Systems[i].Chaos.fLifetime);
Systems[i].Particles[j].fInitialAlpha = Systems[i].InitialParticle.fInitialAlpha+(RANDOM_NUMBER * Systems[i].Chaos.fInitialAlpha);
Systems[i].Particles[j].fFinalAlpha = Systems[i].InitialParticle.fFinalAlpha+(RANDOM_NUMBER * Systems[i].Chaos.fFinalAlpha);
Systems[i].Particles[j].fInitialSize = Systems[i].InitialParticle.fInitialSize+(RANDOM_NUMBER * Systems[i].Chaos.fInitialSize);
Systems[i].Particles[j].fFinalSize = Systems[i].InitialParticle.fFinalSize+(RANDOM_NUMBER * Systems[i].Chaos.fFinalSize);
Systems[i].Particles[j].InitialColor.r = Systems[i].InitialParticle.InitialColor.r+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.r);
Systems[i].Particles[j].InitialColor.g = Systems[i].InitialParticle.InitialColor.g+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.g);
Systems[i].Particles[j].InitialColor.b = Systems[i].InitialParticle.InitialColor.b+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.b);
Systems[i].Particles[j].FinalColor.r = Systems[i].InitialParticle.FinalColor.r+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.r);
Systems[i].Particles[j].FinalColor.g = Systems[i].InitialParticle.FinalColor.g+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.g);
Systems[i].Particles[j].FinalColor.b = Systems[i].InitialParticle.FinalColor.b+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.b);
}
Systems[i].ParticlesReleased=ParticlesAfterRelease;
}
else
{
Systems[i].ParticlesReleased=Systems[i].NumberOfParticles;
}
}
for (Uint16 j=0;j<=Systems[i].ParticlesReleased;j++)
{
Systems[i].Particles[j].fAge += MillisecondsEllapsed;
if (Systems[i].Particles[j].fAge>=Systems[i].Particles[j].fLifetime)
{
Systems[i].Particles[j].Pos.Coords[0] = Systems[i].InitialParticle.Pos.Coords[0]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[0]);
Systems[i].Particles[j].Pos.Coords[1] = Systems[i].InitialParticle.Pos.Coords[1]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[1]);
Systems[i].Particles[j].Pos.Coords[2] = Systems[i].InitialParticle.Pos.Coords[2]+(RANDOM_NUMBER * Systems[i].Chaos.Pos.Coords[2]);
Systems[i].Particles[j].Speed.Coords[0] = Systems[i].InitialParticle.Speed.Coords[0]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[0]);
Systems[i].Particles[j].Speed.Coords[1] = Systems[i].InitialParticle.Speed.Coords[1]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[1]);
Systems[i].Particles[j].Speed.Coords[2] = Systems[i].InitialParticle.Speed.Coords[2]+(RANDOM_NUMBER * Systems[i].Chaos.Speed.Coords[2]);
Systems[i].Particles[j].fAge = 0.0f;
Systems[i].Particles[j].fLifetime = Systems[i].InitialParticle.fLifetime+(RANDOM_NUMBER * Systems[i].Chaos.fLifetime);
Systems[i].Particles[j].fInitialAlpha = Systems[i].InitialParticle.fInitialAlpha+(RANDOM_NUMBER * Systems[i].Chaos.fInitialAlpha);
Systems[i].Particles[j].fFinalAlpha = Systems[i].InitialParticle.fFinalAlpha+(RANDOM_NUMBER * Systems[i].Chaos.fFinalAlpha);
Systems[i].Particles[j].fInitialSize = Systems[i].InitialParticle.fInitialSize+(RANDOM_NUMBER * Systems[i].Chaos.fInitialSize);
Systems[i].Particles[j].fFinalSize = Systems[i].InitialParticle.fFinalSize+(RANDOM_NUMBER * Systems[i].Chaos.fFinalSize);
Systems[i].Particles[j].InitialColor.r = Systems[i].InitialParticle.InitialColor.r+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.r);
Systems[i].Particles[j].InitialColor.g = Systems[i].InitialParticle.InitialColor.g+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.g);
Systems[i].Particles[j].InitialColor.b = Systems[i].InitialParticle.InitialColor.b+(RANDOM_NUMBER * Systems[i].Chaos.InitialColor.b);
Systems[i].Particles[j].FinalColor.r = Systems[i].InitialParticle.FinalColor.r+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.r);
Systems[i].Particles[j].FinalColor.g = Systems[i].InitialParticle.FinalColor.g+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.g);
Systems[i].Particles[j].FinalColor.b = Systems[i].InitialParticle.FinalColor.b+(RANDOM_NUMBER * Systems[i].Chaos.FinalColor.b);
}
fLifeFraction = Systems[i].Particles[j].fAge / Systems[i].Particles[j].fLifetime;
Systems[i].Particles[j].Pos += Systems[i].Particles[j].Speed*MillisecondsEllapsed;
if (Systems[i].BumpAtYPlane)
if (Systems[i].Particles[j].Pos.Coords[1]<Systems[i].YPlane)
{
Systems[i].Particles[j].Speed.Coords[1]=-Systems[i].Particles[j].Speed.Coords[1];
Systems[i].Particles[j].Pos.Coords[1] +=Systems[i].Particles[j].Speed.Coords[1] * MillisecondsEllapsed * 2.0f;
}
if (Systems[i].BumpAtXPlane)
if (Systems[i].Particles[j].Pos.Coords[0]<Systems[i].XPlane)
{
Systems[i].Particles[j].Speed.Coords[0]=-Systems[i].Particles[j].Speed.Coords[0];
Systems[i].Particles[j].Pos.Coords[0] +=Systems[i].Particles[j].Speed.Coords[0] * MillisecondsEllapsed * 2.0f;
}
if (Systems[i].BumpAtMinusXPlane)
if (Systems[i].Particles[j].Pos.Coords[0]>Systems[i].XPlane)
{
Systems[i].Particles[j].Speed.Coords[0]=-Systems[i].Particles[j].Speed.Coords[0];
Systems[i].Particles[j].Pos.Coords[0] +=Systems[i].Particles[j].Speed.Coords[0] * MillisecondsEllapsed * 2.0f;
}
if (Systems[i].IndividualAcceleration)
{
Systems[i].Particles[j].Speed += (Systems[i].aPos-Systems[i].Particles[j].Pos)*Systems[i].AccelFraction;
Systems[i].Particles[j].Pos += (Systems[i].aPos-Systems[i].Particles[j].Pos)*Systems[i].AccelFraction;
}
else
{
if (Systems[i].InitialAccel!=Systems[i].FinalAccel)
Systems[i].Particles[j].Speed += (Systems[i].InitialAccel + ((Systems[i].FinalAccel-Systems[i].InitialAccel)*fLifeFraction))*MillisecondsEllapsed;
else
Systems[i].Particles[j].Speed +=Systems[i].InitialAccel*MillisecondsEllapsed;
}
}
}
}
}
inline void ParticleGod::Draw()
{
glDisable(GL_CULL_FACE);
//glDisable(GL_ALPHA_TEST);
glDepthMask(false);
float fLifeFraction, fSize;
float modelview[16];
for (Uint16 i=0;i<Systems.size();i++)
{
if (Systems[i].Enabled)
{
Bind(Systems[i].Texture);
if (!Systems[i].Solid)
{
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
}
for (Uint16 j=0;j<=Systems[i].ParticlesReleased;j++)
{
//Calculate The Fraction of life remaining
fLifeFraction = Systems[i].Particles[j].fAge / Systems[i].Particles[j].fLifetime;
// Calculate the fraction of Size acoording to inital and final size, and fLifeFraction
fSize = Systems[i].Particles[j].fInitialSize + ((Systems[i].Particles[j].fFinalSize - Systems[i].Particles[j].fInitialSize)*fLifeFraction);
// Calculate the color and alpha
glColor4f(Systems[i].Particles[j].InitialColor.r + ((Systems[i].Particles[j].FinalColor.r - Systems[i].Particles[j].InitialColor.r)*fLifeFraction),
Systems[i].Particles[j].InitialColor.g + ((Systems[i].Particles[j].FinalColor.g - Systems[i].Particles[j].InitialColor.g)*fLifeFraction),
Systems[i].Particles[j].InitialColor.b + ((Systems[i].Particles[j].FinalColor.b - Systems[i].Particles[j].InitialColor.b)*fLifeFraction),
Systems[i].Particles[j].fInitialAlpha + ((Systems[i].Particles[j].fFinalAlpha - Systems[i].Particles[j].fInitialAlpha)*fLifeFraction));
//save current modelview matrix
glPushMatrix();
// Goto the particle position
glTranslatef(Systems[i].Particles[j].Pos.Coords[0],Systems[i].Particles[j].Pos.Coords[1],Systems[i].Particles[j].Pos.Coords[2]);
// Get The Matrix!
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
for(int k=0; k<3; k++ ) //Undo all cam rotation, so particle will allways be turned this way
for(int l=0; l<3; l++ )
{
if ( k==l )
modelview[k*4+l] = 1.0;
else
modelview[k*4+l] = 0.0;
}
// set the modelview to our own!
glLoadMatrixf(modelview);
//draw the quad around the particle pos, considering fSize
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.998f,0.998f);
glVertex3f (fSize,fSize,0.0f);
glTexCoord2f(0.0f,0.998f);
glVertex3f (-fSize,fSize,0.0f);
glTexCoord2f(0.998f,0.0f);
glVertex3f (fSize,-fSize,0.0f);
glTexCoord2f(0.0f,0.0f);
glVertex3f (-fSize,-fSize,0.0f);
glEnd();
// restore the previous matrix
glPopMatrix();
}
}
}
//glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
//glEnable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDepthMask(true);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -