1
0
forked from 0ad/0ad

First commit of CSprite, CParticle and CParticleEmitter classes

This was SVN commit r173.
This commit is contained in:
Ben 2004-03-05 06:37:44 +00:00
parent bc223f487b
commit fa34a13f44
6 changed files with 683 additions and 0 deletions

64
source/terrain/Particle.cpp Executable file
View File

@ -0,0 +1,64 @@
//***********************************************************
//
// Name: Particle.cpp
// Last Update: 03/04/04
// Author: Ben Vinegar
//
// Description: Particle class implementation
//
//***********************************************************
#include "Particle.h"
#include "time.h"
#include "ogl.h"
#include <assert.h>
CParticle::CParticle() :
m_duration(0.0f),
m_timeElapsedTotal(0.0f),
m_position(0.0f, 0.0f, 0.0f),
m_velocity(0.0f, 0.0f, 0.0f),
m_gravity(0.0f, 0.0f, 0.0f) {
m_timeOfLastFrame = get_time();
// default white colour
m_colour[0] = m_colour[1] = m_colour[2] = m_colour[3] = 1.0f;
}
CParticle::~CParticle() {
}
void CParticle::Init() {
// calculate colour increment per second in order to fade to black
m_colourInc[0] = - (m_colour[0] / m_duration);
m_colourInc[1] = - (m_colour[1] / m_duration);
m_colourInc[2] = - (m_colour[2] / m_duration);
}
void CParticle::Frame() {
Update();
Render();
}
void CParticle::Render() {
assert(m_sprite);
m_sprite->SetColour(m_colour);
m_sprite->SetTranslation(m_position);
m_sprite->Render();
}
void CParticle::Update() {
float timeElapsed = float(get_time() - m_timeOfLastFrame);
m_velocity += m_gravity * timeElapsed;
m_position += m_velocity * timeElapsed;
// fade colour
m_colour[0] += m_colourInc[0] * timeElapsed;
m_colour[1] += m_colourInc[1] * timeElapsed;
m_colour[2] += m_colourInc[2] * timeElapsed;
m_timeOfLastFrame = get_time();
m_timeElapsedTotal += timeElapsed;
}

46
source/terrain/Particle.h Executable file
View File

@ -0,0 +1,46 @@
//***********************************************************
//
// Name: Particle.h
// Last Update: 03/04/04
// Author: Ben Vinegar
//
// Description: Particle class header
//
//***********************************************************
#ifndef PARTICLE_H
#define PARTICLE_H
#include "Vector3D.h"
#include "Sprite.h"
class CParticle {
public:
CParticle();
~CParticle();
// necessary pre-processing immediately before first update call
void Init();
void Frame();
void Update();
void Render();
void SetColour(float r, float g, float b, float a);
CSprite * m_sprite;
float m_duration;
double m_timeOfLastFrame;
double m_timeElapsedTotal;
CVector3D m_position;
CVector3D m_velocity;
CVector3D m_gravity;
float m_colour[4];
float m_colourInc[3];
};
#endif // PARTICLE_H

View File

@ -0,0 +1,236 @@
//***********************************************************
//
// Name: ParticleEmitter.cpp
// Last Update: 03/02/04
// Author: Ben Vinegar
//
// Description: Particle class header
//
//
// To-do: - estimate particles to release / second
// - randomness, range still needs to be implemented
// - colour issues
//***********************************************************
#include "ParticleEmitter.h"
#include "time.h"
#include "ogl.h"
#include <stdlib.h>
CParticleEmitter::CParticleEmitter() :
m_particles(NULL),
m_origin(0.0f, 0.0f, 0.0f),
m_originSpread(0.0f, 0.0f, 0.0f),
m_velocity(0.0f, 0.0f, 0.0f),
m_velocitySpread(0.0f, 0.0f, 0.0f),
m_gravity(0.0f, 0.0f, 0.0f),
m_maxParticles(0),
m_minParticles(0),
m_numParticles(0),
m_maxLifetime(0),
m_minLifetime(0),
m_timeOfLastFrame(0.0f),
m_timeSinceLastEmit(0.0f) {
m_particles.clear();
}
CParticleEmitter::~CParticleEmitter() {
}
void CParticleEmitter::Frame() {
Update();
Render();
}
void CParticleEmitter::Render() {
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
vector<CParticle *>::iterator itor = m_particles.begin();
while (itor != m_particles.end()) {
CParticle * curParticle = (*itor);
curParticle->Frame();
++itor;
}
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
void CParticleEmitter::Update() {
float timeElapsed = get_time() - m_timeOfLastFrame;
// update existing particles
vector<CParticle *>::iterator itor = m_particles.begin();
while (itor != m_particles.end()) {
CParticle * curParticle = (*itor);
curParticle->Update();
// destroy particle if it has lived beyond its duration
if (curParticle->m_timeElapsedTotal >= curParticle->m_duration) {
m_particles.erase(itor);
delete curParticle;
--m_numParticles;
}
++itor;
}
float secondsPerEmit = 1 / (m_minParticles / m_minLifetime);
if (m_timeSinceLastEmit > secondsPerEmit) {
int duration;
CVector3D position, velocity;
float colour[4];
bool moreParticlesToEmit = true;
while (moreParticlesToEmit) {
CParticle * newParticle = new CParticle();
// calculate particle duration
duration = m_minLifetime;
duration += (rand() % (int)((m_maxLifetime - m_minLifetime) * 1000.0f + 1)) / 1000.0f;
newParticle->m_duration = duration;
// calculate particle start position from spread
position = m_origin;
position.X += (rand() % (int)(m_originSpread.X * 2000.0f + 1)) / 1000.0f - m_originSpread.X;
position.Y += (rand() % (int)(m_originSpread.Y * 2000.0f + 1)) / 1000.0f - m_originSpread.Y;
position.Z += (rand() % (int)(m_originSpread.Z * 2000.0f + 1)) / 1000.0f - m_originSpread.Z;
newParticle->m_position = position;
// calculate particle velocity from spread
velocity = m_velocity;
velocity.X += (rand() % (int)(m_velocitySpread.X * 2000.0f + 1)) / 1000.0f - m_velocitySpread.X;
velocity.Y += (rand() % (int)(m_velocitySpread.Y * 2000.0f + 1)) / 1000.0f - m_velocitySpread.Y;
velocity.Z += (rand() % (int)(m_velocitySpread.Z * 2000.0f + 1)) / 1000.0f - m_velocitySpread.Z;
newParticle->m_velocity = velocity;
newParticle->m_gravity = m_gravity;
// calculate and assign colour
memcpy(colour, m_startColour, sizeof(float) * 4);
colour[0] += (rand() % (int)((m_endColour[0] - m_startColour[0]) * 1000.0f + 1)) / 1000.0f;
colour[1] += (rand() % (int)((m_endColour[1] - m_startColour[1]) * 1000.0f + 1)) / 1000.0f;
colour[2] += (rand() % (int)((m_endColour[2] - m_startColour[2]) * 1000.0f + 1)) / 1000.0f;
colour[3] += (rand() % (int)((m_endColour[3] - m_startColour[3]) * 1000.0f + 1)) / 1000.0f;
memcpy(newParticle->m_colour, colour, sizeof(float) * 4);
// assign sprite
newParticle->m_sprite = m_sprite;
// final pre-processing init call
newParticle->Init();
// add to vector of particles
m_particles.push_back(newParticle);
timeElapsed -= secondsPerEmit;
if (timeElapsed < secondsPerEmit) {
moreParticlesToEmit = false;
}
++m_numParticles;
}
m_timeSinceLastEmit = 0.0f;
}
else
m_timeSinceLastEmit += timeElapsed;
m_timeOfLastFrame = get_time();
}
void CParticleEmitter::SetSprite(CSprite * sprite) {
m_sprite = sprite;
}
void CParticleEmitter::SetOrigin(CVector3D origin) {
m_origin = origin;
}
void CParticleEmitter::SetOrigin(float x, float y, float z) {
m_origin.X = x;
m_origin.Y = y;
m_origin.Z = z;
}
void CParticleEmitter::SetOriginSpread(CVector3D spread) {
m_originSpread = spread;
}
void CParticleEmitter::SetOriginSpread(float x, float y, float z) {
m_originSpread.X = x;
m_originSpread.Y = y;
m_originSpread.Z = z;
}
void CParticleEmitter::SetGravity(CVector3D gravity) {
m_gravity = gravity;
}
void CParticleEmitter::SetGravity(float x, float y, float z) {
m_gravity.X = x;
m_gravity.Y = y;
m_gravity.Z = z;
}
void CParticleEmitter::SetVelocity(CVector3D velocity) {
m_velocity = velocity;
}
void CParticleEmitter::SetVelocity(float x, float y, float z) {
m_velocity.X = x;
m_velocity.Y = y;
m_velocity.Z = z;
}
void CParticleEmitter::SetVelocitySpread(CVector3D spread) {
m_velocitySpread = spread;
}
void CParticleEmitter::SetVelocitySpread(float x, float y, float z) {
m_velocitySpread.X = x;
m_velocitySpread.Y = y;
m_velocitySpread.Z = z;
}
void CParticleEmitter::SetStartColour(float r, float g, float b, float a) {
m_startColour[0] = r;
m_startColour[1] = g;
m_startColour[2] = b;
m_startColour[3] = a;
}
void CParticleEmitter::SetEndColour(float r, float g, float b, float a) {
m_endColour[0] = r;
m_endColour[1] = g;
m_endColour[2] = b;
m_endColour[3] = a;
}
void CParticleEmitter::SetMaxLifetime(double maxLife) {
m_maxLifetime = maxLife;
}
void CParticleEmitter::SetMinLifetime(double minLife) {
m_minLifetime = minLife;
}
void CParticleEmitter::SetMaxParticles(int maxParticles) {
m_maxParticles = maxParticles;
}
void CParticleEmitter::SetMinParticles(int minParticles) {
m_minParticles = minParticles;
}

View File

@ -0,0 +1,92 @@
//***********************************************************
//
// Name: ParticleEmitter.h
// Last Update: 03/01/04
// Author: Ben Vinegar
//
// Description: Particle class header
//
//***********************************************************
#ifndef PARTICLE_EMITTER_H
#define PARTICLE_EMITTER_H
#include "Particle.h"
#include "Sprite.h"
#include "Vector3D.h"
#include <vector>
class CParticleEmitter {
public:
CParticleEmitter();
~CParticleEmitter();
// must be performed before first frame/render/update call
bool Init();
// renders and updates particles
void Frame();
// renders without updating particles
void Render();
void Update();
void SetSprite(CSprite * sprite);
void SetOrigin(CVector3D origin);
void SetOrigin(float x, float y, float z);
void SetOriginSpread(CVector3D spread);
void SetOriginSpread(float x, float y, float z);
void SetGravity(CVector3D gravity);
void SetGravity(float x, float y, float z);
void SetVelocity(CVector3D direction);
void SetVelocity(float x, float y, float z);
void SetVelocitySpread(CVector3D spread);
void SetVelocitySpread(float x, float y, float z);
void SetStartColour(float r, float g, float b, float a);
void SetEndColour(float r, float g, float b, float a);
// in milliseconds
void SetMaxLifetime(double maxLife);
// in milliseconds
void SetMinLifetime(double minLife);
void SetMaxParticles(int maxParticles);
void SetMinParticles(int minParticles);
private:
CSprite * m_sprite;
std::vector<CParticle *> m_particles;
CVector3D m_origin;
CVector3D m_originSpread;
CVector3D m_velocity;
CVector3D m_velocitySpread;
CVector3D m_gravity;
float m_startColour[4];
float m_endColour[4];
int m_maxParticles;
int m_minParticles;
int m_numParticles;
double m_maxLifetime;
double m_minLifetime;
double m_timeOfLastFrame;
float m_timeSinceLastEmit;
};
#endif // PARTICLE_EMITTER_H

182
source/terrain/Sprite.cpp Executable file
View File

@ -0,0 +1,182 @@
//***********************************************************
//
// Name: Sprite.cpp
// Last Update: 26/02/04
// Author: Ben Vinegar
//
// Description: 3D Sprite class implementation.
//
// To-do:
//
//***********************************************************
#include "Sprite.h"
#include "ogl.h"
#include "tex.h"
CSprite::CSprite() :
m_texture(NULL) {
// default scale 1:1
m_scale.X = m_scale.Y = m_scale.Z = 1.0f;
// default position (0.0f, 0.0f, 0.0f)
m_translation.X = m_translation.Y = m_translation.Z = 0.0f;
// default size 1.0 x 1.0
SetSize(1.0f, 1.0f);
// default colour, white
m_colour[0] = m_colour[1] = m_colour[2] = m_colour[3] = 1.0f;
}
CSprite::~CSprite() {
}
void CSprite::Render() {
BeginBillboard();
glDisable(GL_CULL_FACE);
glTranslatef(m_translation.X, m_translation.Y, m_translation.Z);
glScalef(m_scale.X, m_scale.Y, m_scale.Z);
tex_bind(m_texture->GetHandle());
glColor4fv(m_colour);
glBegin(GL_TRIANGLE_STRIP);
// bottom left
glTexCoord2f(0.0f, 0.0f);
glVertex3fv((GLfloat *) &m_coords[0]);
// top left
glTexCoord2f(0.0f, 1.0f);
glVertex3fv((GLfloat *) &m_coords[1]);
// bottom right
glTexCoord2f(1.0f, 0.0f);
glVertex3fv((GLfloat *) &m_coords[2]);
// top left
glTexCoord2f(1.0f, 1.0f);
glVertex3fv((GLfloat *) &m_coords[3]);
glEnd();
glEnable(GL_CULL_FACE);
EndBillboard();
}
int CSprite::SetTexture(CTexture *texture) {
if (texture == NULL) return -1;
m_texture = texture;
return 0;
}
void CSprite::SetSize(float width, float height) {
m_width = width;
m_height = height;
float xOffset = m_width / 2;
float yOffset = m_height / 2;
// bottom left
m_coords[0].X = - (xOffset);
m_coords[0].Y = - (yOffset);
m_coords[0].Z = 0.0f;
// top left
m_coords[1].X = - (xOffset);
m_coords[1].Y = yOffset;
m_coords[1].Z = 0.0f;
// bottom right
m_coords[2].X = xOffset;
m_coords[2].Y = - (yOffset);
m_coords[2].Z = 0.0f;
// top right
m_coords[3].X = xOffset;
m_coords[3].Y = yOffset;
m_coords[3].Z = 0.0f;
}
float CSprite::GetWidth() {
return m_width;
}
void CSprite::SetWidth(float width) {
SetSize(width, m_height);
}
float CSprite::GetHeight() {
return m_height;
}
void CSprite::SetHeight(float height) {
SetSize(m_width, height);
}
CVector3D CSprite::GetTranslation() {
return m_translation;
}
void CSprite::SetTranslation(CVector3D trans) {
m_translation = trans;
}
void CSprite::SetTranslation(float x, float y, float z) {
m_translation.X = x;
m_translation.Y = y;
m_translation.Z = z;
}
CVector3D CSprite::GetScale() {
return m_scale;
}
void CSprite::SetScale(CVector3D scale) {
m_scale = scale;
}
void CSprite::SetScale(float x, float y, float z) {
m_scale.X = x;
m_scale.Y = y;
m_scale.Z = z;
}
void CSprite::SetColour(float * colour) {
m_colour[0] = colour[0];
m_colour[1] = colour[1];
m_colour[2] = colour[2];
m_colour[3] = colour[3];
}
// should be called before any other gl calls
void CSprite::BeginBillboard() {
float newMatrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
float currentMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, currentMatrix);
newMatrix[0] = currentMatrix[0];
newMatrix[1] = currentMatrix[4];
newMatrix[2] = currentMatrix[8];
newMatrix[4] = currentMatrix[1];
newMatrix[5] = currentMatrix[5];
newMatrix[6] = currentMatrix[9];
newMatrix[8] = currentMatrix[2];
newMatrix[9] = currentMatrix[6];
newMatrix[10] = currentMatrix[10];
glPushMatrix();
glMultMatrixf(newMatrix);
}
void CSprite::EndBillboard() {
glPopMatrix();
}

63
source/terrain/Sprite.h Executable file
View File

@ -0,0 +1,63 @@
//***********************************************************
//
// Name: Sprite.h
// Last Update: 22/02/04
// Author: Ben Vinegar
//
// Description: 3D Sprite class header.
//
//***********************************************************
#ifndef SPRITE_H
#define SPRITE_H
#include "Vector3D.h"
#include "Texture.h"
class CSprite {
public:
CSprite();
~CSprite();
void Render();
int SetTexture(CTexture *texture);
void SetSize(float width, float height);
float GetWidth();
void SetWidth(float width);
float GetHeight();
void SetHeight(float height);
CVector3D GetTranslation();
void SetTranslation(CVector3D pos);
void SetTranslation(float x, float y, float z);
CVector3D GetScale();
void SetScale(CVector3D scale);
void SetScale(float x, float y, float z);
void SetColour(float * colour);
void SetColour(float r, float g, float b, float a = 1.0f);
private:
void BeginBillboard();
void EndBillboard();
CTexture *m_texture;
CVector3D m_coords[4];
float m_width;
float m_height;
CVector3D m_translation;
CVector3D m_scale;
float m_colour[4];
};
#endif // SPRITE_H