0ad/source/graphics/ParticleEmitter.cpp
janwas b755ddefda remove all author/modified by tags.
make include guards consistent.

This was SVN commit r5040.
2007-05-07 16:33:24 +00:00

168 lines
4.2 KiB
C++

/**
* =========================================================================
* File : ParticleEmitter.cpp
* Project : 0 A.D.
* Description : Particle and Emitter base classes.
* =========================================================================
*/
#include "precompiled.h"
#include "ParticleEmitter.h"
#include "ParticleEngine.h"
CEmitter::CEmitter(const int MAX_PARTICLES, const int lifetime, int UNUSED(textureID))
{
particleCount = 0;
// declare the pool of nodes
max_particles = MAX_PARTICLES;
heap = new tParticle[max_particles];
emitterLife = lifetime;
decrementLife = true;
decrementAlpha = true;
RenderParticles = true;
isFinished = false;
updateSpeed = 0.02f;
blend_mode = 1;
size = 0.15f;
//texture = textureID;
texture = 0;
// init the used/open list
usedList = NULL;
openList = NULL;
// link all the particles in the heap
// into one large open list
for(int i = 0; i < max_particles - 1; i++)
{
heap[i].next = &(heap[i + 1]);
}
openList = heap;
}
CEmitter::~CEmitter(void)
{
delete [] heap;
}
bool CEmitter::AddParticle()
{
tColor start, end;
float fYaw, fPitch, fSpeed;
if(!openList)
return false;
if(particleCount < max_particles)
{
// get a particle from the open list
tParticle *particle = openList;
// set it's initial position to the emitter's position
particle->pos.X = pos.X;
particle->pos.Y = pos.Y;
particle->pos.Z = pos.Z;
// Calculate the starting direction vector
fYaw = yaw + (yawVar * RandomNum());
fPitch = pitch + (pitchVar * RandomNum());
// Convert the rotations to a vector
RotationToDirection(fPitch,fYaw,&particle->dir);
// Multiply in the speed factor
fSpeed = speed + (speedVar * RandomNum());
particle->dir.X *= fSpeed;
particle->dir.Y *= fSpeed;
particle->dir.Z *= fSpeed;
// Calculate the life span
particle->life = life + (int)((float)lifeVar * RandomNum());
// Calculate the colors
start.r = startColor.r + (startColorVar.r * RandomChar());
start.g = startColor.g + (startColorVar.g * RandomChar());
start.b = startColor.b + (startColorVar.b * RandomChar());
end.r = endColor.r + (endColorVar.r * RandomChar());
end.g = endColor.g + (endColorVar.g * RandomChar());
end.b = endColor.b + (endColorVar.b * RandomChar());
// set the initial color of the particle
particle->color.r = start.r;
particle->color.g = start.g;
particle->color.b = start.b;
// Create the color delta
particle->deltaColor.r = (end.r - start.r) / particle->life;
particle->deltaColor.g = (end.g - start.g) / particle->life;
particle->deltaColor.b = (end.b - start.b) / particle->life;
particle->alpha = 255.0f;
particle->alphaDelta = particle->alpha / particle->life;
particle->inPos = false;
// Now, we pop a node from the open list and put it into the used list
openList = particle->next;
particle->next = usedList;
usedList = particle;
// update the length of the used list (particle Count)
particleCount++;
return true;
}
return false;
}
bool CEmitter::Render()
{
if(RenderParticles)
{
switch(blend_mode)
{
case 1:
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Fire
break;
case 2:
glBlendFunc(GL_SRC_COLOR, GL_ONE); // Crappy Fire
break;
case 3:
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR); // Plain Particles
break;
case 4:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR); // Nice fade out effect
break;
}
// Bind the texture. Use the texture assigned to this emitter.
int unit = 0;
g_Renderer.SetTexture(unit, texture);
glBegin(GL_QUADS);
{
tParticle *tempParticle = usedList;
while(tempParticle)
{
tColor *pColor = &(tempParticle->color);
glColor4ub(pColor->r,pColor->g, pColor->b, (GLubyte)tempParticle->alpha);
glTexCoord2d(0.0, 0.0);
CVector3D *pPos = &(tempParticle->pos);
glVertex3f(pPos->X - size, pPos->Y + size, pPos->Z);
glTexCoord2d(0.0, 1.0);
glVertex3f(pPos->X - size, pPos->Y - size, pPos->Z);
glTexCoord2d(1.0, 1.0);
glVertex3f(pPos->X + size, pPos->Y - size, pPos->Z);
glTexCoord2d(1.0, 0.0);
glVertex3f(pPos->X + size, pPos->Y + size, pPos->Z);
tempParticle = tempParticle->next;
}
}
glEnd();
return true;
}
return false;
}