Commit code circa 2006
This commit is contained in:
280
particle.h
Executable file
280
particle.h
Executable file
@@ -0,0 +1,280 @@
|
||||
#ifndef __PARTICLE_H__
|
||||
#define __PARTICLE_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* max particles per emitter */
|
||||
#define MAX_PARTICLES 256
|
||||
|
||||
typedef struct {
|
||||
GLint aliveTime; /* time the particle's been alive */
|
||||
GLint lifetime; /* how long this particle should stay alive (in ms) */
|
||||
GLfloat alpha;
|
||||
Vector speed;
|
||||
Vector pos;
|
||||
Vector iGrav;
|
||||
} Particle;
|
||||
|
||||
typedef struct {
|
||||
GLboolean active; /* emitter active? */
|
||||
GLint lifetime; /* base lifetime of particles from this emitter */
|
||||
GLint lifeEdge; /* the random adjustment to each particle's lifetime
|
||||
(between lifeEdge and lifeEdge*2) */
|
||||
GLfloat alphaFade; /* a floating point value between 0.0 and 1.0 that tells
|
||||
how much transparency should be added to the particle each frame */
|
||||
|
||||
Vector pos; /* base position of particles from this emitter */
|
||||
Vector speed; /* base speed (direction) of particles from this emitter */
|
||||
Vector pGrav; /* the base x, y, and z gravity acting on
|
||||
particles from this emitter*/
|
||||
|
||||
Vector rSpeed; /* the random speed adjustment applied to particles */
|
||||
Vector rGrav; /* the random gravity adjustment applied to particles */
|
||||
Vector rPos; /* the random position adjustment applied to particles */
|
||||
|
||||
Particle particles[MAX_PARTICLES]; /* the actual particles */
|
||||
GLfloat texCoords[4][2]; // the texture coordinates for all quad or triangle particles
|
||||
GLuint texHandle; /* the texture handle for all particles from this emitter*/
|
||||
GLuint pType; /* GL_POINTS, GL_TRIANGLES, or GL_QUADS.*/
|
||||
GLfloat color[3]; /* color of particles in this emitter */
|
||||
|
||||
GLfloat size[2]; /* the size in X and Y of all particles from this emitter */
|
||||
|
||||
} PEmitter;
|
||||
|
||||
|
||||
void DrawParticle(Particle *particle, PEmitter *emitter)
|
||||
{
|
||||
|
||||
/* set up the texturing if we're not doing points */
|
||||
if ( emitter->pType != GL_POINTS ) {
|
||||
glBindTexture(GL_TEXTURE_2D, emitter->texHandle);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
glBegin(emitter->pType);
|
||||
|
||||
if ( emitter->pType == GL_TRIANGLES ) {
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[0][0],
|
||||
emitter->texCoords[0][1]);
|
||||
glVertex3f(particle->pos.x - ( emitter->size[0] / 2),
|
||||
particle->pos.y - ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[1][0],
|
||||
emitter->texCoords[1][1]);
|
||||
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||
particle->pos.y - ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[2][0],
|
||||
emitter->texCoords[2][1]);
|
||||
glVertex3f(particle->pos.x,
|
||||
particle->pos.y + ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
}
|
||||
|
||||
else if ( emitter->pType == GL_QUADS ) {
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[0][0],
|
||||
emitter->texCoords[0][1]);
|
||||
glVertex3f(particle->pos.x - ( emitter->size[0] / 2),
|
||||
particle->pos.y + ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[1][0],
|
||||
emitter->texCoords[1][1]);
|
||||
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||
particle->pos.y - ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[2][0],
|
||||
emitter->texCoords[2][1]);
|
||||
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||
particle->pos.y - ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
|
||||
glColor3f(emitter->color[0],
|
||||
emitter->color[1],
|
||||
emitter->color[2]);
|
||||
glTexCoord2f(emitter->texCoords[3][0],
|
||||
emitter->texCoords[3][1]);
|
||||
glVertex3f(particle->pos.x + ( emitter->size[0] / 2),
|
||||
particle->pos.y + ( emitter->size[1] / 2),
|
||||
particle->pos.z);
|
||||
}
|
||||
else {
|
||||
glColor4f(emitter->color[0], emitter->color[1], emitter->color[2], particle->alpha);
|
||||
glVertex3f(particle->pos.x, particle->pos.y, particle->pos.z);
|
||||
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
GLuint DrawEmitter(PEmitter *emitter)
|
||||
{
|
||||
/* this function assumes the viewport and etc has already been setup
|
||||
* (e.g., call this from within your main GL drawing function) */
|
||||
|
||||
int i = 0;
|
||||
Particle *currParticle;
|
||||
|
||||
if ( !emitter ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( emitter->active != GL_TRUE ) {
|
||||
return 0; // emitter not active, but this isn't an error
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < MAX_PARTICLES ; i++ ) {
|
||||
currParticle = &emitter->particles[i];
|
||||
|
||||
/* draw the particle given its type */
|
||||
DrawParticle(currParticle, emitter);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ResetParticle(Particle *particle, PEmitter *emitter)
|
||||
{
|
||||
particle->aliveTime = 0;
|
||||
|
||||
/* get a new lifetime for the particle based on the base from the emitter + random adj */
|
||||
particle->lifetime = emitter->lifetime + (rand() % (emitter->lifeEdge*2)) - emitter->lifeEdge;
|
||||
particle->alpha = 1.0F;
|
||||
|
||||
/* reset the particle's x, y, z position from the emitter base */
|
||||
vectorCopy(&particle->pos, &emitter->pos);
|
||||
if ( emitter->rPos.x != 0.0f)
|
||||
particle->pos.x += frand( emitter->rPos.x);
|
||||
if ( emitter->rPos.y != 0.0f )
|
||||
particle->pos.y += frand( emitter->rPos.y );
|
||||
if ( emitter->rPos.z != 0.0f )
|
||||
particle->pos.z += frand( emitter->rPos.z );
|
||||
|
||||
/* reset the particle's gravity from the base gravity of the emitter + rand adjust */
|
||||
vectorCopy(&particle->iGrav, &emitter->pGrav);
|
||||
if ( emitter->rGrav.x != 0.0f )
|
||||
particle->iGrav.x += frand( emitter->rGrav.x );
|
||||
if ( emitter->rGrav.y != 0.0f )
|
||||
particle->iGrav.y += frand( emitter->rGrav.y );
|
||||
if ( emitter->rGrav.z != 0.0f )
|
||||
particle->iGrav.z += frand( emitter->rGrav.z );
|
||||
|
||||
/* reset the particle's speed from the base gravity of the emitter + rand adjust */
|
||||
vectorCopy(&particle->speed, &emitter->speed);
|
||||
if ( emitter->rSpeed.x != 0.0f )
|
||||
particle->speed.x += frand( emitter->rSpeed.x);
|
||||
if ( emitter->rSpeed.y != 0.0f )
|
||||
particle->speed.y += frand( emitter->rSpeed.y);
|
||||
if ( emitter->rSpeed.z != 0.0f )
|
||||
particle->speed.z += frand( emitter->rSpeed.z);
|
||||
}
|
||||
|
||||
void UpdateEmitter(PEmitter *emitter, GLuint timePassed)
|
||||
{
|
||||
/* here's where we do the emitter's logic. It's assumed
|
||||
* we're being called once per frame, so we don't do any
|
||||
* time calculations, other than updating the lifetimes
|
||||
* ... timePassed is the number of ms passed since the last call */
|
||||
|
||||
int i = 0;
|
||||
Particle *currParticle;
|
||||
|
||||
for ( i = 0 ; i < MAX_PARTICLES ; i++ ) {
|
||||
currParticle = &emitter->particles[i];
|
||||
|
||||
currParticle->aliveTime += timePassed;
|
||||
|
||||
if ( currParticle->aliveTime >= currParticle->lifetime ) {
|
||||
/* this particle has died; set it to inactive and reset its lifetime/pos/dir */
|
||||
ResetParticle(currParticle,emitter);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* apply gravity and such to the particle */
|
||||
|
||||
currParticle->speed.x += currParticle->iGrav.x;
|
||||
currParticle->speed.y += currParticle->iGrav.y;
|
||||
currParticle->speed.z += currParticle->iGrav.z;
|
||||
|
||||
currParticle->pos.x += (currParticle->speed.x);
|
||||
currParticle->pos.y += (currParticle->speed.y);
|
||||
currParticle->pos.z += (currParticle->speed.z);
|
||||
|
||||
/* the alpha is a constant drop over the lifetime of the particle */
|
||||
currParticle->alpha -= emitter->alphaFade;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint PopulateEmitter(PEmitter *emitter,
|
||||
GLboolean active,
|
||||
GLfloat color[],
|
||||
GLfloat alphaFade,
|
||||
GLint lifetime,
|
||||
Vector *pGrav,
|
||||
Vector *pos,
|
||||
Vector *speed,
|
||||
Vector *rgrav,
|
||||
Vector *rpos,
|
||||
Vector *rspeed,
|
||||
GLint lifeEdge,
|
||||
GLuint pType,
|
||||
GLuint texHandle)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if ( !emitter ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
emitter->active = active;
|
||||
|
||||
emitter->color[0] = color[0];
|
||||
emitter->color[1] = color[1];
|
||||
emitter->color[2] = color[2];
|
||||
|
||||
emitter->lifetime = lifetime;
|
||||
emitter->lifeEdge = lifeEdge;
|
||||
emitter->alphaFade = alphaFade;
|
||||
|
||||
vectorCopy(&emitter->pGrav, pGrav);
|
||||
vectorCopy(&emitter->pos, pos);
|
||||
vectorCopy(&emitter->speed, speed);
|
||||
vectorCopy(&emitter->rSpeed, rspeed);
|
||||
vectorCopy(&emitter->rPos, rpos);
|
||||
vectorCopy(&emitter->rGrav, rgrav);
|
||||
|
||||
|
||||
emitter->pType = pType;
|
||||
emitter->texHandle = texHandle;
|
||||
|
||||
for ( i = 0; i < MAX_PARTICLES; i++ ) {
|
||||
ResetParticle(&emitter->particles[i],emitter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // __PARTICLE_H__
|
||||
Reference in New Issue
Block a user