From 11229dcfef77baab5a7a3893a7c6281fbc5f7211 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 7 Dec 2008 14:48:54 +0000 Subject: flame particle systems --- src/model/classes.cc | 2 + src/model/classes.h | 14 +++- src/model/map.cc | 6 +- src/render/particles.cc | 214 ++++++++++++++++++++++++++++++++++++++++++++++-- src/render/particles.h | 18 +++- src/render/renderext.cc | 7 +- 6 files changed, 245 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/model/classes.cc b/src/model/classes.cc index 4042c38..06ebda3 100644 --- a/src/model/classes.cc +++ b/src/model/classes.cc @@ -43,6 +43,8 @@ Flare::~Flare() Particles::Particles() : particles_location() { + particles_entity = false; + particles_engine = false; } Particles::Particles(math::Vector3f const & location) : diff --git a/src/model/classes.h b/src/model/classes.h index 175070a..a0e9d1f 100644 --- a/src/model/classes.h +++ b/src/model/classes.h @@ -147,15 +147,21 @@ public: return particles_script; } - inline const float radius() const + inline bool entity() const + { + return particles_entity; + } + + inline bool engine() const { - return particles_radius; + return particles_engine; } - std::string particles_script; math::Vector3f particles_location; math::Axis particles_axis; - float particles_radius; + + bool particles_entity; + bool particles_engine; }; /* ---- class Dock ------------------------------------------------- */ diff --git a/src/model/map.cc b/src/model/map.cc index 618fd51..f2c519f 100644 --- a/src/model/map.cc +++ b/src/model/map.cc @@ -989,7 +989,11 @@ Model * Map::load(std::string const &name) } else if (mapfile.got_key_float("roll", angle)) { particles->particles_axis.change_roll(angle); -/* + + } else if (mapfile.got_key_int("spawnflags", u)) { + particles->particles_entity = spawnflag_isset(u, 2); + particles->particles_engine = spawnflag_isset(u, 4); +/* } else if (mapfile.got_key_float("radius", particles->particles_radius)) { particles->particles_radius *= LIGHTSCALE; */ diff --git a/src/render/particles.cc b/src/render/particles.cc index c232ca1..f9271ab 100644 --- a/src/render/particles.cc +++ b/src/render/particles.cc @@ -112,6 +112,9 @@ void ParticleScript::init() continue; } else if (inifile.got_key_float("speed", script->particles_speed)) { continue; + } else if (inifile.got_key_float("offset", script->particles_offset)) { + math::clamp(script->particles_offset, 0.0f, 1.0f); + continue; } else if (inifile.got_key_float("alpha", script->particles_alpha)) { continue; } else if (inifile.got_key_float("radius", script->particles_radius)) { @@ -159,6 +162,8 @@ ParticleScript::ParticleScript() particles_timeout = 2.0f; particles_eject = 0.25f; + particles_offset = 0.1f; + particles_color.assign(1.0f, 1.0f); } @@ -168,8 +173,7 @@ ParticleScript::~ParticleScript() /* ---- class ParticleSystem --------------------------------------- */ -ParticleSystem::ParticleSystem(ParticleScript *script, core::Entity *entity, const math::Vector3f &location) : - particlesystem_location(location) +ParticleSystem::ParticleSystem(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) { particlesystem_entity = entity; particlesystem_last_eject = 0; // timestamp of the last eject @@ -177,10 +181,24 @@ ParticleSystem::ParticleSystem(ParticleScript *script, core::Entity *entity, con particlesystem_script = script; particlesystem_texture = 0; + particlesystem_modelclass = modelclass; + if (particlesystem_script) { particlesystem_texture = Textures::load("textures/" + particlesystem_script->texture()); + + radius = particlesystem_script->radius(); color.assign(particlesystem_script->color()); } + + if (particlesystem_modelclass) { + particlesystem_location.assign(modelclass->location()); + if (modelclass->entity()) { + color.assign(entity->color()); + } + if (modelclass->engine()) { + color.assign(entity->model()->enginecolor()); + } + } } ParticleSystem::~ParticleSystem() @@ -249,8 +267,8 @@ void ParticleSystem::draw(float elapsed) /* ---- class Jet -------------------------------------------------- */ -Jet::Jet(ParticleScript *script, core::Entity *entity, const math::Vector3f &location) : - ParticleSystem(script, entity, location) { +Jet::Jet(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Jet::~Jet() @@ -309,8 +327,8 @@ void Jet::draw(float elapsed) { /* ---- class Trail ------------------------------------------------ */ -Trail::Trail(ParticleScript *script, core::Entity *entity, const math::Vector3f &location) : - ParticleSystem(script, entity, location) { +Trail::Trail(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Trail::~Trail() @@ -340,6 +358,7 @@ void Trail::draw(float elapsed) { fp = tp / (0.9f * particlesystem_script->timeout()); fp = 1.0 - fp; } + tp = (now - (*first)->time()) / particlesystem_script->timeout(); if (tp > 0) { color.a = 0.0f; @@ -373,6 +392,7 @@ void Trail::draw(float elapsed) { f = t / (0.9f * particlesystem_script->timeout()); f = 1.0 - f; } + t = (now - (*next)->time()) / particlesystem_script->timeout(); color.a = fp * particlesystem_script->alpha(); gl::color(color); @@ -402,4 +422,186 @@ void Trail::draw(float elapsed) { } } +/* ---- class Flame ------------------------------------------------ */ + +Flame::Flame(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { +} + +Flame::~Flame() +{} + +void Flame::draw(float elapsed) { + + if (!particlesystem_script) + return; + + ParticleSystem::draw(elapsed); + + if (particlesystem_stream.size() > 1) { + + Textures::bind(particlesystem_texture); + gl::begin(gl::Quads); + + Stream::iterator first = particlesystem_stream.begin(); + + float tp = now - (*first)->time(); + float fp = 0; + + if (tp < particlesystem_script->timeout() * particlesystem_script->offset()) { + fp = tp / (particlesystem_script->offset() * particlesystem_script->timeout()); + } else { + tp = tp - particlesystem_script->timeout() * particlesystem_script->offset(); + fp = tp / ((1.0f - particlesystem_script->offset()) * particlesystem_script->timeout()); + fp = 1.0 - fp; + } + tp = (now - (*first)->time()) / particlesystem_script->timeout(); + + Stream::iterator next = first; + if (tp > 0) { + color.a = 0; + gl::color(color); + glTexCoord2f(1,0); + gl::vertex(ejector_location); + glTexCoord2f(0,0); + gl::vertex(ejector_location); + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,tp); + gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_script->radius() * fp); + glTexCoord2f(1,tp); + gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_script->radius() * fp); + Stats::quads++; + + color.a = 0; + gl::color(color); + glTexCoord2f(1,0); + gl::vertex(ejector_location); + glTexCoord2f(0,0); + gl::vertex(ejector_location); + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,tp); + gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_script->radius() * fp); + glTexCoord2f(1,tp); + gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_script->radius() * fp); + Stats::quads++; + + color.a = 0; + gl::color(color); + glTexCoord2f(1,0); + gl::vertex(ejector_location); + glTexCoord2f(0,0); + gl::vertex(ejector_location); + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,tp); + gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_script->radius() * fp); + glTexCoord2f(1,tp); + gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_script->radius() * fp); + Stats::quads++; + + color.a = 0; + gl::color(color); + glTexCoord2f(1,0); + gl::vertex(ejector_location); + glTexCoord2f(0,0); + gl::vertex(ejector_location); + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,tp); + gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_script->radius() * fp); + glTexCoord2f(1,tp); + gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_script->radius() * fp); + Stats::quads++; + } + + for (next++; next != particlesystem_stream.end(); next++) { + + float t = now - (*next)->time(); + float f = 0; + + if (t < particlesystem_script->timeout() * particlesystem_script->offset()) { + f = t / (particlesystem_script->offset() * particlesystem_script->timeout()); + } else { + t = t - particlesystem_script->timeout() * particlesystem_script->offset(); + f = t / ((1.0f - particlesystem_script->offset()) * particlesystem_script->timeout()); + f = 1.0 - f; + } + t = (now - (*next)->time()) / particlesystem_script->timeout(); + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(1,tp); + gl::vertex((*first)->location() + (*first)->axis().up() * particlesystem_script->radius() * fp); + glTexCoord2f(0,tp); + gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_script->radius() * fp); + + color.a = f * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,t); + gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_script->radius() * f); + glTexCoord2f(1,t); + gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_script->radius() * f); + Stats::quads++; + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(1,tp); + gl::vertex((*first)->location() - (*first)->axis().left() * particlesystem_script->radius() * fp); + glTexCoord2f(0,tp); + gl::vertex((*first)->location() + (*first)->axis().up() * particlesystem_script->radius() * fp); + + color.a = f * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,t); + gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_script->radius() * f); + glTexCoord2f(1,t); + gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_script->radius() * f); + Stats::quads++; + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(1,tp); + gl::vertex((*first)->location() - (*first)->axis().up() * particlesystem_script->radius() * fp); + glTexCoord2f(0,tp); + gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_script->radius() * fp); + + color.a = f * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,t); + gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_script->radius() * f); + glTexCoord2f(1,t); + gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_script->radius() * f); + Stats::quads++; + + color.a = fp * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(1,tp); + gl::vertex((*first)->location() - (*first)->axis().left() * particlesystem_script->radius() * fp); + glTexCoord2f(0,tp); + gl::vertex((*first)->location() - (*first)->axis().up() * particlesystem_script->radius() * fp); + + color.a = f * particlesystem_script->alpha(); + gl::color(color); + glTexCoord2f(0,t); + gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_script->radius() * f); + glTexCoord2f(1,t); + gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_script->radius() * f); + Stats::quads++; + + first = next; + fp = f; + tp = t; + } + + + gl::end(); + } +} + } // namespace render diff --git a/src/render/particles.h b/src/render/particles.h index 0044832..9c9d44b 100644 --- a/src/render/particles.h +++ b/src/render/particles.h @@ -13,6 +13,7 @@ #include "math/color.h" #include "math/vector3f.h" #include "core/entity.h" +#include "model/classes.h" namespace render { @@ -64,6 +65,8 @@ public: inline float alpha() const { return particles_alpha; } + inline float offset() const { return particles_offset; } + static ParticleScript *find(const std::string &label); static void init(); @@ -84,6 +87,7 @@ private: float particles_eject; float particles_speed; float particles_alpha; + float particles_offset; typedef std::map Registry; @@ -95,7 +99,7 @@ private: /// abstract base class for a particle system attached to an entity class ParticleSystem { public: - ParticleSystem(ParticleScript *script, core::Entity *entity, const math::Vector3f &location); + ParticleSystem(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); virtual ~ParticleSystem(); /// index of the texture to use @@ -136,8 +140,11 @@ protected: math::Vector3f ejector_location; bool ejector_active; + float radius; float now; math::Color color; + + model::Particles *particlesystem_modelclass; }; /* ---- class Flame ------------------------------------------------ */ @@ -145,6 +152,11 @@ protected: /// flame style particles, like engine flames class Flame : public ParticleSystem { +public: + Flame(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + virtual ~Flame(); + + virtual void draw(float elapsed); }; /* ---- class Jet -------------------------------------------------- */ @@ -153,7 +165,7 @@ class Flame : public ParticleSystem class Jet : public ParticleSystem { public: - Jet(ParticleScript *script, core::Entity *entity, const math::Vector3f &location); + Jet(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); virtual ~Jet(); virtual void draw(float elapsed); @@ -165,7 +177,7 @@ public: class Trail : public ParticleSystem { public: - Trail(ParticleScript *script, core::Entity *entity, const math::Vector3f &location); + Trail(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); virtual ~Trail(); virtual void draw(float elapsed); diff --git a/src/render/renderext.cc b/src/render/renderext.cc index 0fa6796..d2d5a71 100644 --- a/src/render/renderext.cc +++ b/src/render/renderext.cc @@ -60,11 +60,14 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re ParticleScript *script = ParticleScript::find(particlesystem->script()); if (script) { if (script->type() == render::ParticleScript::Trail) { - Trail *trail = new Trail(script, entity, particlesystem->location()); + Trail *trail = new Trail(script, entity, particlesystem); state_particles.push_back(trail); } else if (script->type() == render::ParticleScript::Jet) { - Jet *jet = new Jet(script, entity, particlesystem->location()); + Jet *jet = new Jet(script, entity, particlesystem); state_particles.push_back(jet); + } else if (script->type() == render::ParticleScript::Flame) { + Flame *flame = new Flame(script, entity, particlesystem); + state_particles.push_back(flame); } } else { con_warn << "Could not find particle system '" << particlesystem->script() << "'" << std::endl; -- cgit v1.2.3