www.pudn.com > 32709.zip > particle.cpp
/*************************************************** * Developer: Clinton Jon Selke * * Version: Totally FreeWare (Do what you will) * * Section: Particle Implementation * ***************************************************/ #include "particle.h" #include "resource.h" #include#include #include "image.h" // RANDOM_FLOAT_0_1 returns a random number from 0.f to 1.f #define RANDOM_FLOAT_0_1 ((float)rand() / (float)RAND_MAX) // RANDOM_FLOAT(min, max) returns a random number from min to max #define RANDOM_FLOAT(min, max) (((max) - (min)) * RANDOM_FLOAT_0_1 + (min)) struct Particle { float age, // current age in seconds dying_age, // dying age in seconds size, // current size inc_size, // increase in size per second alpha, // current alpha (transparency) inc_alpha; // increase in alpha per second Vector3 colour, // current colour inc_colour, // increase in colour per second position, // current position velocity; // current velocity }; GLuint ParticleSystem::_particle_texture = 0; ParticleSystem::ParticleSystem( const Vector3& position, const Vector3& velocity, float min_dying_age, float max_dying_age, float start_size, float end_size, float start_alpha, float end_alpha, float min_speed, float max_speed, float create_delay, const Vector3& start_colour, const Vector3& end_colour, const Vector3& gravity, unsigned int max_particles ): _position(position), _velocity(velocity), MIN_DYING_AGE(min_dying_age), MAX_DYING_AGE(max_dying_age), START_SIZE(start_size), END_SIZE(end_size), START_ALPHA(start_alpha), END_ALPHA(end_alpha), MIN_SPEED(min_speed), MAX_SPEED(max_speed), CREATE_DELAY(create_delay), START_COLOUR(start_colour), END_COLOUR(end_colour), GRAVITY(gravity), MAX_PARTICLES(max_particles), _number_of_particles(0), _creation_timer(create_delay) { // Allocate array of null particles _particle_array = new Particle *[MAX_PARTICLES]; for (int i = 0; i < MAX_PARTICLES; i++) { _particle_array[i] = 0; } } ParticleSystem::~ParticleSystem() { // Free particle array for (unsigned int i = 0; i < _number_of_particles; i++) { if (_particle_array[i]) { delete _particle_array[i]; _particle_array[i] = 0; } } if (_particle_array) { delete [] _particle_array; _particle_array = 0; } _number_of_particles = 0; } void ParticleSystem::loadTexture() { Image texture("particle.bmp"); // Create OpenGL Texture from bitmap glGenTextures(1, &_particle_texture); glBindTexture(GL_TEXTURE_2D, _particle_texture); glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.sizeX(), texture.sizeY(), 0, GL_RGB, GL_UNSIGNED_BYTE, texture.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void ParticleSystem::calculate(float dt) { // For all particles for (unsigned int i = 0; i < _number_of_particles; i++) { // Grab particle from array Particle &p = *_particle_array[i]; // Calculate new age p.age += dt; // If the particle has reach its dying age, then its dead so destroy it if (p.age >= p.dying_age) { delete _particle_array[i]; _number_of_particles--; if (_number_of_particles) { _particle_array[i] = _particle_array[_number_of_particles]; _particle_array[_number_of_particles] = 0; continue; } else { break; } } // Calculate other particles stats p.size += p.inc_size * dt; p.alpha += p.inc_alpha * dt; p.colour += p.inc_colour * dt; p.position += p.velocity * dt; p.velocity += GRAVITY * 0.5f * dt * dt; } // Check for creation of particle if (_number_of_particles < MAX_PARTICLES) { if ((_creation_timer -= dt) <= 0.f) { // Setup new particle Particle p; p.age = 0; p.dying_age = RANDOM_FLOAT(MIN_DYING_AGE, MAX_DYING_AGE); float one_over_dying_age = 1.f / p.dying_age; // speed purposes p.size = START_SIZE; p.inc_size = (END_SIZE - START_SIZE) * one_over_dying_age; p.alpha = START_ALPHA; p.inc_alpha = (END_ALPHA - START_ALPHA) * one_over_dying_age; p.colour = START_COLOUR; p.inc_colour = (END_COLOUR - START_COLOUR) * one_over_dying_age; p.position = _position; { float speed = RANDOM_FLOAT(MIN_SPEED, MAX_SPEED); float theta = RANDOM_FLOAT(-M_PI, M_PI); float phi = RANDOM_FLOAT(-M_PI*0.5f, M_PI*0.5f); p.velocity.x = sin(phi) * speed; p.velocity.y = cos(phi) * cos(theta) * speed; p.velocity.z = cos(phi) * sin(theta) * speed; } // Store new particle in array _particle_array[_number_of_particles++] = new Particle(p); // Reset creation timer _creation_timer = CREATE_DELAY; } } } void ParticleSystem::draw() { // Select our texture glBindTexture(GL_TEXTURE_2D, _particle_texture); // For all particles that exist for (unsigned int i = 0; i < _number_of_particles; i++) { // Grab particle the from array Particle &p = *_particle_array[i]; // Set colour of particle glColor4f(p.colour.x, p.colour.y, p.colour.z, p.alpha); // Set texture of particle glBindTexture(GL_TEXTURE_2D, _particle_texture); // Draw particle float half_size = p.size * 0.5f; glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1.f, 1.f); glVertex3f(p.position.x + half_size, p.position.y + half_size, p.position.z); glTexCoord2d(0.f, 1.f); glVertex3f(p.position.x - half_size, p.position.y + half_size, p.position.z); glTexCoord2d(1.f, 0.f); glVertex3f(p.position.x + half_size, p.position.y - half_size, p.position.z); glTexCoord2d(0.f, 0.f); glVertex3f(p.position.x - half_size, p.position.y - half_size, p.position.z); glEnd(); } }