1
0
forked from 0ad/0ad
0ad/source/graphics/ParticleEmitter.cpp

168 lines
4.2 KiB
C++

/////////////////////////////////////////////////////
// File Name: ParticleEmitter.cpp
// Date: 6/29/05
// Author: Will Dull
// Purpose: The base particle and emitter
// classes implementations.
/////////////////////////////////////////////////////
#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::renderEmitter()
{
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);
tVector *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;
}