From 315a8c2dff9b76ac5e1ebbef265f13ac19d65e3d Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 16 Nov 2008 13:53:44 +0000 Subject: engine trails --- src/render/particles.cc | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/render/particles.cc (limited to 'src/render/particles.cc') diff --git a/src/render/particles.cc b/src/render/particles.cc new file mode 100644 index 0000000..94a3a07 --- /dev/null +++ b/src/render/particles.cc @@ -0,0 +1,144 @@ +/* + render/particles.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "render/particles.h" +#include "render/camera.h" +#include "render/gl.h" +#include "render/draw.h" +#include "render/textures.h" + +#include "core/application.h" +namespace render { + +/* ---- class Particle --------------------------------------------- */ + +Particle::Particle(const math::Vector3f &location, float time) : particle_location(location) +{ + particle_time = time; +} + +Particle::Particle(const math::Vector3f &location, const math::Vector3f &up, const math::Vector3f &left, float time) : particle_location(location), particle_up(up), particle_left(left) +{ + particle_time = time; +} + +/* ---- class ParticleStream --------------------------------------- */ + +ParticleStream::ParticleStream(const math::Vector3f &location, const math::Color &color, float radius, size_t texture, core::EntityControlable *entity, bool oriented) : particles_location(location), particles_color(color) +{ + particles_texture = texture; + particles_entity = entity; + if (!entity) { + particles_oriented = false; + } else { + particles_oriented = oriented; + } + + particles_radius = radius; + + particles_timeout = 1.5f; // a particles lives for 3 seconds + particles_eject = 0.02f; // a particle is ejected every 0.2 seconds + + particles_last_eject = 0; // timestamp of the last eject +} + +ParticleStream::~ParticleStream() +{ + for (Particles::iterator it = particles_stream.begin(); it != particles_stream.end(); it++) { + delete (*it); + } + particles_stream.clear(); +} + +void ParticleStream::draw() { + float now = core::application()->time(); + + // remove dead particles + Particles::iterator it = particles_stream.begin(); + while ((it != particles_stream.end()) && ((*it)->time() + particles_timeout <= now)) { + delete (*it); + particles_stream.erase(it); + it = particles_stream.begin(); + } + + // add new particles + if (particles_last_eject + particles_eject <= now) { + if (particles_entity) { + float u = 0; + if ((particles_entity->eventstate() == core::Entity::ImpulseInitiate ) || (particles_entity->eventstate() == core::Entity::Impulse)) { + u = 1.0f; + } else if(particles_entity->eventstate() == core::Entity::Normal) { + u = particles_entity->thrust(); + } + if (u > 0.0f) { + math::Vector3f l(particles_entity->location() + (particles_entity->axis() * location())); + Particle *p = 0; + if (particles_oriented) { + p = new Particle(l, particles_entity->axis().up(), particles_entity->axis().left(), now); + } else { + p = new Particle(l, now); + } + particles_stream.push_back(p); + } + } else { + particles_stream.push_back(new Particle(location(), now)); + } + particles_last_eject = now; + } + + math::Vector3f quad[4]; + + if (particles_stream.size()) { + Textures::bind(particles_texture); + gl::begin(gl::Quads); + + for (Particles::reverse_iterator rit = particles_stream.rbegin(); rit != particles_stream.rend(); rit++) { + Particle *particle = (*rit); + + if (particles_oriented) { + quad[0].assign(particle->up() - particle->left()); + quad[1].assign(particle->up() + particle->left()); + quad[2].assign(particle->up() * -1 + particle->left()); + quad[3].assign(particle->up() * -1 - particle->left()); + } else { + quad[0].assign(Camera::axis().up() - Camera::axis().left()); + quad[1].assign(Camera::axis().up() + Camera::axis().left()); + quad[2].assign(Camera::axis().up() * -1 + Camera::axis().left()); + quad[3].assign(Camera::axis().up() * -1 - Camera::axis().left()); + } + + float t = now - particle->time(); + float f = 0; + + if (t < particles_timeout * 0.1f) { + f = t / (0.1f * particles_timeout); + } else { + t = t - particles_timeout * 0.1f; + f = t / (0.9f * particles_timeout); + f = 1.0 - f; + } + + f *= f; + float radius = particles_radius * f; + particles_color.a = f; + gl::color(particles_color); + + glTexCoord2f(0,1); + gl::vertex(particle->location() + quad[0] * radius); + glTexCoord2f(0,0); + gl::vertex(particle->location() + quad[1] * radius); + glTexCoord2f(1,0); + gl::vertex(particle->location() + quad[2] * radius); + glTexCoord2f(1,1); + gl::vertex(particle->location() + quad[3] * radius); + Stats::quads++; + } + + gl::end(); + } +} + +} // namespace render -- cgit v1.2.3