From d4f9da2f3c19511b028da2569d7b6a8d1371e135 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 20 Jan 2013 21:37:11 +0000 Subject: Major overhaul of the particle system back-end, support multiple ejectors per particle system. --- src/render/Makefile.am | 12 +- src/render/draw.cc | 9 +- src/render/particle.cc | 28 +++ src/render/particle.h | 108 +++++++++++ src/render/particleejector.cc | 251 ++++++++++++++++++++++++ src/render/particleejector.h | 104 ++++++++++ src/render/particleejectorscript.cc | 55 ++++++ src/render/particleejectorscript.h | 367 ++++++++++++++++++++++++++++++++++++ src/render/particles.cc | 253 ------------------------- src/render/particles.h | 122 +----------- src/render/particlesystem.cc | 144 ++++++++++++++ src/render/particlesystem.h | 75 ++++++++ src/render/particlesystemscript.cc | 313 ++++++++++++++++++++++++++++++ src/render/particlesystemscript.h | 66 +++++++ src/render/render.cc | 8 +- src/render/renderext.cc | 37 +--- src/render/renderext.h | 2 +- 17 files changed, 1546 insertions(+), 408 deletions(-) create mode 100644 src/render/particle.cc create mode 100644 src/render/particle.h create mode 100644 src/render/particleejector.cc create mode 100644 src/render/particleejector.h create mode 100644 src/render/particleejectorscript.cc create mode 100644 src/render/particleejectorscript.h create mode 100644 src/render/particlesystem.cc create mode 100644 src/render/particlesystem.h create mode 100644 src/render/particlesystemscript.cc create mode 100644 src/render/particlesystemscript.h (limited to 'src/render') diff --git a/src/render/Makefile.am b/src/render/Makefile.am index 7993036..b5acde1 100644 --- a/src/render/Makefile.am +++ b/src/render/Makefile.am @@ -17,7 +17,11 @@ noinst_HEADERS = \ jpgfile.h \ light.h \ lightenvironment.h \ - particles.h \ + particle.h \ + particleejector.h \ + particlesystem.h \ + particleejectorscript.h \ + particlesystemscript.h \ pngfile.h \ render.h \ renderext.h \ @@ -38,7 +42,11 @@ librender_la_SOURCES = \ jpgfile.cc \ light.cc \ lightenvironment.cc \ - particles.cc \ + particle.cc \ + particleejector.cc \ + particlesystem.cc \ + particleejectorscript.cc \ + particlesystemscript.cc \ pngfile.cc \ render.cc \ renderext.cc \ diff --git a/src/render/draw.cc b/src/render/draw.cc index a49b017..0d77c7b 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -322,6 +322,8 @@ void draw_globe_rings(const math::Color & color, const size_t rings_id) //gl::enable(GL_CULL_FACE); gl::disable(GL_BLEND); + + Stats::quads += 2; } void draw_pass_globes() @@ -1085,7 +1087,9 @@ void draw_pass_model_fx(float elapsed) // draw particle systems if (draw_particles && ext_render(entity)->particles().size()) { + /* gl::disable(GL_CULL_FACE); + model::Cull current_cull = model::CullNone; for (RenderExt::ParticleSystems::iterator it = ext_render(entity)->particles().begin(); it != ext_render(entity)->particles().end(); it++) { @@ -1112,7 +1116,10 @@ void draw_pass_model_fx(float elapsed) particlesystem->draw(elapsed); } - + */ + for (RenderExt::ParticleSystems::iterator it = ext_render(entity)->particles().begin(); it != ext_render(entity)->particles().end(); ++it) { + (*it)->draw(elapsed); + } } } diff --git a/src/render/particle.cc b/src/render/particle.cc new file mode 100644 index 0000000..ddd8abd --- /dev/null +++ b/src/render/particle.cc @@ -0,0 +1,28 @@ +/* + render/particle.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/particle.h" + + +namespace render +{ + +/* ---- class Particle --------------------------------------------- */ + +Particle::Particle(const math::Vector3f &location, const unsigned long timestamp) : + particle_location(location) +{ + particle_timestamp = timestamp; +} + +Particle::Particle(const math::Vector3f &location, const math::Vector3f &velocity, const unsigned long timestamp) : + particle_location(location), + particle_velocity(velocity) +{ + particle_timestamp = timestamp; +} + +} //namespace render diff --git a/src/render/particle.h b/src/render/particle.h new file mode 100644 index 0000000..f2b1788 --- /dev/null +++ b/src/render/particle.h @@ -0,0 +1,108 @@ +/* + render/particle.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_PARTICLE_H__ +#define __INCLUDED_RENDER_PARTICLE_H__ + +#include "math/axis.h" +#include "math/color.h" +#include "math/vector3f.h" + +namespace render { + +/* ---- class Particle --------------------------------------------- */ + +/** + * @brief One particle + * */ +class Particle +{ +public: + Particle(const math::Vector3f &location, const unsigned long timestamp); + Particle(const math::Vector3f &location, const math::Vector3f &velocity, const unsigned long timestamp); + + /** + * @brief location of the particle + * */ + inline const math::Vector3f &location() const { + return particle_location; + } + + /** + * @brief velocity vector of the particle + * */ + inline const math::Vector3f &velocity() const { + return particle_velocity; + } + + const float radius() const + { + return particle_radius; + } + + const float alpha() const + { + return particle_alpha; + } + + /** + * @brief creation timestamp + * */ + inline const unsigned long timestamp() const { + return particle_timestamp; + } + + /** + * @brief reference to the location of the particle + * */ + inline math::Vector3f &get_location() { + return particle_location; + } + + /** + * @brief reference velocity vector of the particle + * */ + inline math::Vector3f &get_velocity() { + return particle_velocity; + } + + /** + * @brief set the location of the particle + * */ + inline void set_location(const math::Vector3f &location) + { + particle_location.assign(location); + } + + /** + * @brief set the velocity of the particle + * */ + inline void set_velocity(const math::Vector3f &velocity) + { + particle_velocity.assign(velocity); + } + + inline void set_radius(const float radius) + { + particle_radius = radius; + } + + inline void set_alpha(const float alpha) + { + particle_alpha = alpha; + } + +protected: + math::Vector3f particle_location; + math::Vector3f particle_velocity; + float particle_radius; + float particle_alpha; + unsigned long particle_timestamp; +}; + +} // namespace + +#endif // __INCLUDED_RENDER_PARTICLE_H__ diff --git a/src/render/particleejector.cc b/src/render/particleejector.cc new file mode 100644 index 0000000..5b26d59 --- /dev/null +++ b/src/render/particleejector.cc @@ -0,0 +1,251 @@ +/* + render/particleejector.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "core/application.h" +#include "render/particleejector.h" +#include "render/camera.h" +#include "render/gl.h" +#include "render/textures.h" +#include "render/draw.h" + +namespace render { + +/* ---- class ParticleEjector -------------------------------------- */ + +ParticleEjector::ParticleEjector(const ParticleEjectorScript &script) : ParticleEjectorScript(script) +{ + ejector_last_eject = 0; + ejector_enabled = true; +} + +ParticleEjector::~ParticleEjector() +{ + clear(); +} + +void ParticleEjector::clear() +{ + for (Particles::iterator it = particles().begin(); it != particles().end(); ++it) { + delete (*it); + (*it) = 0; + } + ejector_last_eject = 0; +} + +void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_location, const math::Axis & ps_axis) +{ + unsigned long now = core::application()->timestamp(); + + // remove dead particles + Particles::reverse_iterator it = particles().rbegin(); + while ((it != particles().rend()) && ((*it)->timestamp() + lifespan() <= now)) { + delete(*particles().rbegin()); + particles().pop_back(); + it = particles().rbegin(); + } + + // add new particles + if ( (ejector_enabled) && (ejector_last_eject + interval() <= now) ) + { + math::Vector3f particle_location(ps_location); + math::Axis particle_axis(ps_axis * axis()); + + if (cone() > 0) { + particle_axis.change_roll(math::randomf(360.0f)); + particle_axis.change_pitch(math::randomf(cone()) - (cone() * 0.5f) ); + } + if (spawn_radius() > 0) { + // FIXME find a faster formula + math::Axis random_axis(ps_axis); + random_axis.change_roll(math::randomf(360.0f)); + random_axis.change_pitch(math::randomf(180.0f)); + particle_location += random_axis.forward() * spawn_radius(); + } + + Particle *particle = new Particle(particle_location, particle_axis.forward() * speed(), now); + particle->set_radius(radius_vec()[0]); + particle->set_alpha(alpha_vec()[0]); + + particles().push_front(particle); + ejector_last_eject = now; + } + + for (Particles::iterator it = particles().begin(); it != particles().end(); ++it) { + Particle *particle = (*it); + if (particle->timestamp() < now) { + // apply velocity + particle->get_location() += (particle->velocity() * seconds); + + // set particle radius_vec and alpha_vec + const float age = (float) (now - particle->timestamp()); + const float halflife = offset() * (float) lifespan(); + + if (age < halflife) { + const float t = age / halflife; + + particle->set_radius((1.0f - t) * radius_vec()[0] + t * radius_vec()[1]); + particle->set_alpha((1.0f - t) * alpha_vec()[0] + t * alpha_vec()[1]); + } else { + const float t = (age - halflife) / ((float) lifespan() - halflife); + + particle->set_radius((1.0f - t) * radius_vec()[1] + t * radius_vec()[2]); + particle->set_alpha((1.0f - t) * alpha_vec()[1] + t * alpha_vec()[2]); + } + + } + } + + switch(cull()) { + case model::CullNone: + gl::disable(GL_CULL_FACE); + break; + + case model::CullBack: + gl::enable(GL_CULL_FACE); + gl::cullface(GL_BACK); + break; + + case model::CullFront: + gl::enable(GL_CULL_FACE); + gl::cullface(GL_FRONT); + break; + } + + if (particles().size()) { + draw(ps_location); + } +} + +void ParticleEjector::draw(const math::Vector3f & ps_location) +{ + +} + +/* ---- class ParticleEjectorSpray --------------------------------- */ + +ParticleEjectorSpray::ParticleEjectorSpray(const ParticleEjectorScript &script) : ParticleEjector(script) +{ + +} + +ParticleEjectorSpray::~ParticleEjectorSpray() +{ + +} + +void ParticleEjectorSpray::draw(const math::Vector3f & ps_location) +{ + math::Vector3f quad[4]; + Textures::bind(texture()); + gl::begin(gl::Quads); + + 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())); + + math::Color c(color()); + + for (Particles::iterator it = particles().begin(); it != particles().end(); it++) { + Particle *particle = (*it); + + const float r = particle->radius(); + + c.a = particle->alpha(); + gl::color(c); + + glTexCoord2f(0, 1); + gl::vertex(particle->location() + quad[0] * r); + glTexCoord2f(0, 0); + gl::vertex(particle->location() + quad[1] * r); + glTexCoord2f(1, 0); + gl::vertex(particle->location() + quad[2] * r); + glTexCoord2f(1, 1); + gl::vertex(particle->location() + quad[3] * r); + Stats::quads++; + } + gl::end(); +} + +/* ---- class ParticleEjectorTrail --------------------------------- */ + +ParticleEjectorTrail::ParticleEjectorTrail(const ParticleEjectorScript &script) : ParticleEjector(script) +{ + +} + +ParticleEjectorTrail::~ParticleEjectorTrail() +{ + +} + +void ParticleEjectorTrail::draw(const math::Vector3f & ps_location) +{ + if (!particles().size()) { + return; + } + + (*particles().rbegin())->set_alpha(0.0f); + + Particles::iterator first = particles().begin(); + Particles::iterator next = first; + ++next; + + Textures::bind(texture()); + gl::begin(gl::Quads); + + math::Color c(color()); + c.a = (*first)->alpha(); + gl::color(c); + + math::Vector3f first_normal(math::crossproduct(((*first)->location() - ps_location), ((*first)->location() - Camera::eye()))); + first_normal.normalize(); + + math::Vector3f next_normal(first_normal); + + glTexCoord2f(1, 0); + gl::vertex(ps_location - first_normal * (*first)->radius()); + glTexCoord2f(0, 0); + gl::vertex(ps_location + first_normal * (*first)->radius()); + + glTexCoord2f(0, 1); + gl::vertex((*first)->location() + next_normal * (*first)->radius()); + glTexCoord2f(1, 1); + gl::vertex((*first)->location() - next_normal * (*first)->radius()); + Stats::quads++; + + while (next != particles().end()) { + next_normal.assign(math::crossproduct(((*next)->location() - (*first)->location()), ((*next)->location() - Camera::eye()))); + next_normal.normalize(); + + c.a = (*first)->alpha(); + gl::color(c); + + glTexCoord2f(1, 0); + gl::vertex((*first)->location() - first_normal * (*first)->radius()); + glTexCoord2f(0, 0); + gl::vertex((*first)->location() + first_normal * (*first)->radius()); + + c.a = (*next)->alpha(); + gl::color(c); + + glTexCoord2f(0, 1); + gl::vertex((*next)->location() + next_normal * (*next)->radius()); + glTexCoord2f(1, 1); + gl::vertex((*next)->location() - next_normal * (*next)->radius()); + + Stats::quads++; + + first_normal = next_normal; + first = next; + ++next; + } + + gl::end(); +} + +} // namespace render + diff --git a/src/render/particleejector.h b/src/render/particleejector.h new file mode 100644 index 0000000..f626f26 --- /dev/null +++ b/src/render/particleejector.h @@ -0,0 +1,104 @@ +/* + render/particleejector.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_PARTICLEEJECTOR_H__ +#define __INCLUDED_RENDER_PARTICLEEJECTOR_H__ + +#include + +#include "render/particleejectorscript.h" +#include "render/particle.h" + +namespace render { + +class ParticleEjector : public ParticleEjectorScript { +public: + typedef std::deque Particles; + + /** + * @brief initialize an ejector from a ParticleEjectorScript + * */ + ParticleEjector(const ParticleEjectorScript &script); + virtual ~ParticleEjector(); + + /** + * @brief if false, no new particles are created + * */ + inline const bool enabled() + { + return ejector_enabled; + } + + /* ---- mutators ------------------------------------------- */ + + /** + * @brief enable or disable particle ejection + * */ + inline void enable(const bool enabled = true) + { + ejector_enabled = enabled; + } + + /** + * @brief disable or enable particle ejection + * */ + inline void disable(const bool disabled = true) + { + ejector_enabled = !disabled; + } + + /** + * @brief updated the particles attached to the ejector, and drawn them + * */ + void frame(const float seconds, const math::Vector3f & ps_location, const math::Axis & ps_axis); + + /** + * @brief remove all particles + * */ + void clear(); + +protected: + inline Particles &particles() + { + return ejector_particles; + } + + virtual void draw(const math::Vector3f & ps_location); + +private: + unsigned long ejector_last_eject; + Particles ejector_particles; + bool ejector_enabled; +}; + +/** + * @brief Spray particles + * */ +class ParticleEjectorSpray : public ParticleEjector { +public: + ParticleEjectorSpray(const ParticleEjectorScript &script); + virtual ~ParticleEjectorSpray(); + +protected: + virtual void draw(const math::Vector3f & ps_location); +}; + +/** + * @brief Trail particles + * */ +class ParticleEjectorTrail : public ParticleEjector { +public: + ParticleEjectorTrail(const ParticleEjectorScript &script); + virtual ~ParticleEjectorTrail(); + +protected: + virtual void draw(const math::Vector3f & ps_location); +}; + +} // namespace render + +#endif // __INCLUDED_RENDER_PARTICLEEJECTOR_H__ + diff --git a/src/render/particleejectorscript.cc b/src/render/particleejectorscript.cc new file mode 100644 index 0000000..4c9b6c9 --- /dev/null +++ b/src/render/particleejectorscript.cc @@ -0,0 +1,55 @@ +/* + render/particleejectorscript.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/particleejectorscript.h" +#include "model/model.h" + +namespace render +{ + +ParticleEjectorScript::ParticleEjectorScript() +{ + script_type = Spray; + script_interval = 100; + script_cone = 0.0f; + script_offset = 0.5f; + script_lifespan = 1000; + script_speed = 0; + script_entity = false; + script_entity_second = false; + script_engine = false; + script_thrust = false; + script_cull = model::CullNone; + script_spawn_radius = 0.0f; +} + +ParticleEjectorScript::ParticleEjectorScript(const ParticleEjectorScript &other) +{ + script_type = other.type(); + script_interval = other.interval(); + script_cone = other.cone(); + script_offset = other.offset(); + script_lifespan = other.lifespan(); + script_speed = other.speed(); + script_entity = other.entity(); + script_entity_second = other.entity_second(); + script_engine = other.engine(); + script_thrust = other.thrust(); + script_cull = other.cull(); + script_spawn_radius = other.spawn_radius(); + + script_texture.assign(other.texture()); + script_axis.assign(other.axis()); + script_radius_vec.assign(other.radius_vec()); + script_alpha_vec.assign(other.alpha_vec()); + script_color.assign(other.color()); +} + +ParticleEjectorScript::~ParticleEjectorScript() +{ +} + +} \ No newline at end of file diff --git a/src/render/particleejectorscript.h b/src/render/particleejectorscript.h new file mode 100644 index 0000000..a538bb5 --- /dev/null +++ b/src/render/particleejectorscript.h @@ -0,0 +1,367 @@ +/* + render/particleejectorscript.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_PARTICLEEJECTORSCRIPT_H__ +#define __INCLUDED_RENDER_PARTICLEEJECTORSCRIPT_H__ + +#include "math/axis.h" +#include "math/color.h" +#include "math/vector3f.h" +#include "model/model.h" + +namespace render { + +class ParticleEjectorScript { +public: + + /** + * @brief definition for type of ejector + * */ + enum Type {Jet = 0, Trail = 1, Flame = 2, Spray = 3, Flare = 4 }; + + ParticleEjectorScript(); + ParticleEjectorScript(const ParticleEjectorScript & other); + + ~ParticleEjectorScript(); + + /* ---- inspectors ----------------------------------------- */ + + /** + * @brief the tytpe of ejector + * */ + inline const Type type() const + { + return script_type; + } + + /** + * @brief ejector axis relative to the particle system + * */ + inline const math::Axis &axis() const + { + return script_axis; + } + + /** + * @brief true of the ejector reacts on thrust + * */ + inline bool thrust() const { + return script_thrust; + } + + inline const unsigned int interval() const + { + return script_interval; + } + + /** + * @brief angle of the cone through which to randomly spread ejected particles + * */ + inline const float cone() const + { + return script_cone; + } + + /** + * @brief offset defines the interpolation midpoint for alpha and radius ranges, default 0.5f + * */ + inline float offset() const { + return script_offset; + } + + /** + * @brief lifespan of ejected particles, in milliseconds + * */ + inline unsigned long lifespan() const { + return script_lifespan; + } + + /** + * @brief true if engine color is to be applied to ejected particles + * */ + inline bool engine() const { + return script_engine; + } + + /** + * @brief true if entity primary color is to be applied to ejected particles + * */ + inline bool entity() const + { + return script_entity; + } + + /** + * @brief true if entity secondary color is to be applied to ejected particles + * */ + inline bool entity_second() const + { + return script_entity_second; + } + + /** + * @brief name of the texture used to render ejected particles + * */ + inline const std::string &texture() const { + return script_texture; + } + + + inline const model::Cull cull() const + { + return script_cull; + } + + /** + * @brief color used to render ejected particles + * */ + inline const math::Color &color() const + { + return script_color; + } + + /** + * @brief radius vector for ejected particles, start, middle, end + * The radius is interpolated depending on the age and lifespan of the particle + * */ + inline const math::Vector3f &radius_vec() const + { + return script_radius_vec; + } + + /** + * @brief alpha vector for ejected particles, start, middle, end + * The alpha value is interpolated depending on the age and lifespan of the particle + * */ + inline const math::Vector3f & alpha_vec() const + { + return script_alpha_vec; + } + + /** + * @brief speed of ejected particles, in gameunits per second + * */ + inline const float speed() const + { + return script_speed; + } + + /** + * @brief spawn radius + * radius within wich particles are spawn + * */ + inline const float spawn_radius() const + { + return script_spawn_radius; + } + + /* ---- mutators ------------------------------------------- */ + + /** + * @brief return a reference to the ejector axis + * */ + inline math::Axis &get_axis() + { + return script_axis; + } + + /** + * @brief return a reference to the radius vector + * */ + inline math::Vector3f &get_radius_vec() + { + return script_radius_vec; + } + + /** + * @brief return a reference to the alpha vector + * */ + inline math::Vector3f &get_alpha_vec() + { + return script_alpha_vec; + } + + /** + * @brief return a reference to particle color + * */ + inline math::Color &get_color() + { + return script_color; + } + + /** + * @brief set the ejector type + * */ + inline void set_type(const Type type) + { + script_type = type; + } + + /** + * @brief set the radius within which particles are spawned + * */ + void set_spawn_radius(const float spawn_radius) + { + script_spawn_radius = spawn_radius; + } + + /** + * @brief set the speed of ejected particles, in gameunits per second + * */ + inline void set_speed(const float speed) + { + script_speed = speed; + } + + /** + * @brief set ejector cone, in degrees + * */ + inline void set_cone(const float cone) + { + script_cone = cone; + } + + /** + * @brief set ejector interval, in milliseconds + * */ + inline void set_interval(const unsigned long interval) + { + script_interval = interval; + } + + /** + * @brief set particle lifespan, in milliseconds + * */ + inline void set_lifespan(const unsigned long lifespan) + { + script_lifespan = lifespan; + } + + /** + * @brief set polygon cull rule + * */ + inline void set_cull(const model::Cull cull) + { + script_cull = cull; + } + + /** + * @brief set texture name + * */ + inline void set_texture(const std::string &texture) + { + script_texture.assign(texture); + } + + /** + * @brief temporal interpolation midpoint, default 0.5f + * */ + inline void set_offset(const float offset) + { + script_offset = offset; + } + + /** + * @brief set the radius vector + * */ + inline void set_radius_vec(const math::Vector3f radius_vec) + { + script_radius_vec.assign(radius_vec); + } + + /** + * @brief set the alpha vector + * */ + inline void set_alpha_vec(const math::Vector3f alpha_vec) + { + script_alpha_vec.assign(alpha_vec); + } + + /** + * @brief set particle entity primary color + * */ + inline void set_entity(const bool use_color_entity) + { + script_entity = use_color_entity; + } + + /** + * @brief set particle entity secondary color + * */ + inline void set_entity_second(const bool use_color_entity_second) + { + script_entity_second = use_color_entity_second; + } + + /** + * @brief set particle engine color + * */ + inline void set_engine(const bool use_color_engine) + { + script_engine = use_color_engine; + } + + /** + * @brief make ejector react on thruster setting + * */ + inline void set_thrust(const bool use_thrust) + { + script_thrust = use_thrust; + } + + /** + * @brief set the particle color + * */ + inline void set_color(const math::Color &color) + { + script_color.assign(color); + } + +private: + /// type of ejector + Type script_type; + /// ejector axis, relative to the particle system axis + math::Axis script_axis; + /// interval between to ejects, in milliseconds + unsigned long script_interval; + /// lifespan of a particle, in milliseconds + unsigned long script_lifespan; + /// ejector cone, in default 360 degrees + float script_cone; + /// offset defines the 'middle' point for radius and alpha, range 0.0f-1.0f, default 0.5f. + float script_offset; + /// particle alpha vector: 0.0 - middle - 1.0 + math::Vector3f script_alpha_vec; + /// particle radius vector: 0.0 - middle - 1.0 + math::Vector3f script_radius_vec; + + /// speed of ejected particles, in gameunits per second + float script_speed; + + /// spawn radius + float script_spawn_radius; + + /// color of ejected particles + math::Color script_color; + + /// particles have entity primary color + bool script_entity; + /// particles have entity secondary color + bool script_entity_second; + /// particles jave engine color + bool script_engine; + /// ejector reacts on engine thrust + bool script_thrust; + + /// texture to render particles with + std::string script_texture; + /// texture cull + model::Cull script_cull; +}; + +} // namespace render + +#endif // __INCLUDED_RENDER_PARTICLEEJECTORSCRIPT_H__ diff --git a/src/render/particles.cc b/src/render/particles.cc index fc27234..5e41316 100644 --- a/src/render/particles.cc +++ b/src/render/particles.cc @@ -28,259 +28,6 @@ Particle::Particle(const math::Vector3f &location, const math::Axis &axis, float } -/* ---- static ParticleScript registry ---------------------------------- */ - -ParticleScript::Registry ParticleScript::particlescript_registry; - -void ParticleScript::list() -{ - - for (Registry::const_iterator it = particlescript_registry.begin(); it != particlescript_registry.end(); it++) { - - const ParticleScript *script = (*it).second; - - std::string strval; - size_t count = 0; - while (script) { - - switch (script->type()) { - case Flame: - strval.append(" flame"); - break; - case Jet: - strval.append(" jet"); - break; - case Spray: - strval.append(" spray"); - break; - case Trail: - strval.append(" trail"); - break; - } - - count++; - script = script->next(); - } - con_print << " " << (*it).second->label() << strval << " " << count << " " << aux::plural("ejector", count) << std::endl; - } - con_print << particlescript_registry.size() << " particle scripts" << std::endl; -} - -void ParticleScript::clear() -{ - for (Registry::iterator it = particlescript_registry.begin(); it != particlescript_registry.end(); it++) { - delete(*it).second; - (*it).second = 0; - } - particlescript_registry.clear(); -} - -ParticleScript *ParticleScript::find(const std::string &label) -{ - Registry::iterator it = particlescript_registry.find(label); - - if (it != particlescript_registry.end()) { - return (*it).second; - } else { - return 0; - } -} - -ParticleScript *ParticleScript::load(const std::string &label) -{ - ParticleScript *parent_script = find(label); - if (parent_script) - return parent_script; - - filesystem::IniFile inifile; - - inifile.open("particles/" + label); - - if (!inifile.is_open()) { - con_warn << "Could not open " << inifile.name() << std::endl; - return 0; - } - - ParticleScript *script = 0; - std::string strval; - float pitch, yaw, roll = 0.0f; - bool b; - - while (inifile.getline()) { - - if (inifile.got_section()) { - - if (inifile.got_section("particles")) { - if (script) { - script->particlescript_next = new ParticleScript(std::string()); - script = script->particlescript_next; - } else { - script = new ParticleScript(label); - particlescript_registry[script->label()] = script; - parent_script = script; - } - continue; - } else { - inifile.unknown_section(); - } - - } else if (inifile.got_key()) { - - if (inifile.in_section("particles")) { - - if (inifile.got_key_string("type", strval)) { - aux::to_label(strval); - if (strval.compare("flame") == 0) { - script->particlescript_type = ParticleScript::Flame; - } else if (strval.compare("jet") == 0) { - script->particlescript_type = ParticleScript::Jet; - } else if (strval.compare("trail") == 0) { - script->particlescript_type = ParticleScript::Trail; - } else if (strval.compare("spray") == 0) { - script->particlescript_type = ParticleScript::Spray; - } else { - inifile.unknown_value(); - } - continue; - - } else if (inifile.got_key_string("cull", strval)) { - aux::to_label(strval); - if (strval.compare("none") == 0) { - script->particlescript_cull = model::CullNone; - } else if (strval.compare("back") == 0) { - script->particlescript_cull = model::CullBack; - } else if (strval.compare("front") == 0) { - script->particlescript_cull = model::CullFront; - } else { - inifile.unknown_value(); - } - continue; - - } else if (inifile.got_key_string("texture", script->particlescript_texture)) { - Textures::load("textures/" + script->texture()); - continue; - } else if (inifile.got_key_float("speed", script->particlescript_speed)) { - continue; - } else if (inifile.got_key_float("offset", script->particlescript_offset)) { - math::clamp(script->particlescript_offset, 0.0f, 1.0f); - continue; - } else if (inifile.got_key_float("alpha", script->particlescript_alpha)) { - continue; - } else if (inifile.got_key_float("radius", script->particlescript_radius)) { - script->particlescript_radius *= model::SCALE; - continue; - } else if (inifile.got_key_float("eject", script->particlescript_eject)) { - continue; - } else if (inifile.got_key_float("timeout", script->particlescript_timeout)) { - continue; - } else if (inifile.got_key_color("color", script->particlescript_color)) { - continue; - } else if (inifile.got_key_bool("engine", script->particlescript_engine)) { - continue; - } else if (inifile.got_key_bool("entity", script->particlescript_entity)) { - continue; - } else if (inifile.got_key_bool("entitysecond", script->particlescript_entity_second)) { - continue; - } else if (inifile.got_key_bool("entitythird", b)) { - if (b) { - script->particlescript_entity = true; - script->particlescript_entity_second = true; - } - continue; - } else if (inifile.got_key_float("angle", yaw)) { - - if (yaw == model::ANGLEUP) { - script->particlescript_axis.change_pitch(-90.0f); - } else if (yaw == model::ANGLEDOWN) { - script->particlescript_axis.change_pitch(90.0f); - } else { - script->particlescript_axis.change_direction(yaw); - } - continue; - - } else if (inifile.got_key("angles")) { - - std::istringstream str(inifile.value()); - if (str >> pitch >> yaw >> roll) { - script->particlescript_axis.assign(yaw, pitch, roll); - } else { - inifile.unknown_value(); - } - continue; - - } else if (inifile.got_key_float("pitch", pitch)) { - script->particlescript_axis.change_pitch(-pitch); - continue; - - } else if (inifile.got_key_float("yaw", yaw)) { - script->particlescript_axis.change_direction(yaw); - continue; - - } else if (inifile.got_key_float("roll", roll)) { - script->particlescript_axis.change_roll(-roll); - continue; - - } else { - inifile.unknown_key(); - } - } - } - } - - inifile.close(); - - strval.clear(); - - size_t count = 0; - for (script = parent_script; script != 0; script = script->particlescript_next) { - switch (script->type()) { - case Flame: - strval.append(" flame"); - break; - case Jet: - strval.append(" jet"); - break; - case Spray: - strval.append(" spray"); - break; - case Trail: - strval.append(" trail"); - break; - } - count++; - } - con_debug << " " << inifile.name() << strval << " " << count << " " << aux::plural("ejector", count) << std::endl; - - return parent_script; -} - -/* ---- class ParticleScript --------------------------------------- */ - -ParticleScript::ParticleScript(const std::string & label) : particlescript_label(label) -{ - particlescript_entity = false; - particlescript_entity_second = false; - particlescript_engine = false; - particlescript_radius = 1.0f; - particlescript_alpha = 1.0f; - - particlescript_speed = 0.0f; - particlescript_timeout = 2.0f; - particlescript_eject = 0.25f; - particlescript_offset = 0.1f; - - particlescript_color.assign(1.0f, 1.0f); - particlescript_cull = model::CullNone; - - particlescript_next = 0; -} - -ParticleScript::~ParticleScript() -{ - if (particlescript_next) { - delete particlescript_next; - } -} /* ---- class ParticleSystem --------------------------------------- */ diff --git a/src/render/particles.h b/src/render/particles.h index 4c3de0e..b329b7f 100644 --- a/src/render/particles.h +++ b/src/render/particles.h @@ -4,6 +4,8 @@ the terms of the GNU General Public License version 2 */ +#error do not include this header + #ifndef __INCLUDED_RENDER_PARTICLES_H__ #define __INCLUDED_RENDER_PARTICLES_H__ @@ -47,126 +49,6 @@ protected: float particle_time; }; -/* ---- class ParticleScript --------------------------------------- */ - -/// class to hold particle scripts -class ParticleScript -{ -public: - - enum Type {Jet = 0, Trail = 1, Flame = 2, Spray = 3 }; - - inline const Type type() const { - return particlescript_type; - } - - inline const std::string &label() const { - return particlescript_label; - } - - inline const std::string &texture() const { - return particlescript_texture; - } - - inline const math::Color &color() const { - return particlescript_color; - } - - /// axis transformation relative to the ejector - inline const math::Axis &axis() const { - return particlescript_axis; - } - - /// true if entity color is to be applied - inline bool engine() const { - return particlescript_engine; - } - - /** - * @brief true if entity primary color is to be applied - * */ - inline bool entity() const - { - return particlescript_entity; - } - - /** - * @brief true if entity secondary color is to be applied - * */ - inline bool entity_second() const - { - return particlescript_entity_second; - } - - inline float radius() const { - return particlescript_radius; - } - - inline float timeout() const { - return particlescript_timeout; - } - - inline float eject() const { - return particlescript_eject; - } - - inline float speed() const { - return particlescript_speed; - } - - inline float alpha() const { - return particlescript_alpha; - } - - inline float offset() const { - return particlescript_offset; - } - - inline const model::Cull cull() const { - return particlescript_cull; - } - - inline const ParticleScript *next() const { - return particlescript_next; - } - - static ParticleScript *load(const std::string &label); - - static void clear(); - - static void list(); - -private: - static ParticleScript *find(const std::string &label); - - ParticleScript(const std::string & label); - ~ParticleScript(); - - std::string particlescript_label; - std::string particlescript_texture; - Type particlescript_type; - math::Color particlescript_color; - math::Axis particlescript_axis; - - bool particlescript_entity; - bool particlescript_entity_second; - bool particlescript_engine; - - float particlescript_radius; - float particlescript_timeout; - float particlescript_eject; - float particlescript_speed; - float particlescript_alpha; - float particlescript_offset; - - model::Cull particlescript_cull; - - ParticleScript *particlescript_next; - - typedef std::map Registry; - - static Registry particlescript_registry; -}; /* ---- class ParticleSystem --------------------------------------- */ diff --git a/src/render/particlesystem.cc b/src/render/particlesystem.cc new file mode 100644 index 0000000..ff9c720 --- /dev/null +++ b/src/render/particlesystem.cc @@ -0,0 +1,144 @@ +/* + render/particlesystem.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/particlesystem.h" + +namespace render { + +ParticleSystem::ParticleSystem(const ParticleSystemScript *script, const core::Entity *entity, const model::Particles *modelclass) +{ + // constructor asserts that modelclass->parent == entity->model + + particlesystem_modelscale = 1.0f; + + particlesystem_entity = entity; + + if (modelclass) { + particlesystem_location.assign(modelclass->location()); + particlesystem_axis.assign(modelclass->axis()); + } + + if (entity && entity->model() && entity->model()->radius()) { + particlesystem_modelscale = entity->radius() / entity->model()->radius(); + particlesystem_location *= particlesystem_modelscale; + + } + + // add ParticleEjectors as defined by the ParticleSystemScript + for (ParticleSystemScript::Ejectors::const_iterator it = script->ejectors().begin(); it != script->ejectors().end(); ++it) { + ParticleEjector *ejector = 0; + switch ((*it)->type()) { + case ParticleEjector::Spray: + ejector = new ParticleEjectorSpray(*(*it)); + break; + + case ParticleEjector::Trail: + ejector = new ParticleEjectorTrail(*(*it)); + break; + default: + break; + } + + if (ejector) { + ejectors().push_back(ejector); + + if (entity) { + if (ejector->entity()) { + if (ejector->entity_second()) { + for (size_t i = 0; i < 3; i++) { + ejector->get_color()[i] = (entity->color()[i] + entity->color_second()[i]) * 0.5f; + } + } else { + ejector->set_color(entity->color()); + } + } else if (ejector->entity_second()) { + ejector->set_color(entity->color_second()); + } else if (ejector->engine()) { + if (entity->model()) { + ejector->set_color(entity->model()->enginecolor()); + } + } + } + + if (modelclass) { + // modelclass overrides script parameters + if (modelclass->has_color()) { + ejector->set_color(modelclass->color()); + } + if (entity) { + if (modelclass->entity()) { + if (modelclass->entity_second()) { + for (size_t i = 0; i < 3; i++) { + ejector->get_color()[i] = (entity->color()[i] + entity->color_second()[i]) * 0.5f; + } + } else { + ejector->set_color(entity->color()); + } + } else if (modelclass->entity_second()) { + ejector->set_color(entity->color_second()); + } else if (modelclass->engine()) { + if (entity->model()) { + ejector->set_color(entity->model()->enginecolor()); + } + } + } + } + } + } +} + +ParticleSystem::~ParticleSystem() +{ + for (Ejectors::iterator it = ejectors().begin(); it != ejectors().end(); ++it) { + delete (*it); + (*it) = 0; + } + ejectors().clear(); + +} + +void ParticleSystem::clear() +{ + for (Ejectors::iterator it = ejectors().begin(); it != ejectors().end(); ++it) { + (*it)->clear(); + } +} +void ParticleSystem::draw(const float seconds) +{ + // clear particles for docked entities + if ( entity() && (entity()->type() == core::Entity::Controlable)) { + const core::EntityControlable *controlable = static_cast(entity()); + if (controlable->state() == core::Entity::Docked) { + clear(); + return; + } + } + + math::Vector3f current_location(entity() ? entity()->location() + (entity()->axis() * location()) : location()); + math::Axis current_axis(entity() ? entity()->axis() * axis() : axis()); + + for (Ejectors::iterator it = ejectors().begin(); it != ejectors().end(); ++it) { + + if (entity()) { + bool ejector_active = true; + if (entity()->type() == core::Entity::Controlable) { + + if ((*it)->thrust()) { + // thrust activated + const core::EntityControlable *controlable = static_cast(entity()); + if ( controlable->thrust() == 0.0f ) { + ejector_active = false; + } + (*it)->enable(ejector_active); + } + } + } + + (*it)->frame(seconds, current_location, current_axis); + } +} + +} \ No newline at end of file diff --git a/src/render/particlesystem.h b/src/render/particlesystem.h new file mode 100644 index 0000000..b3edce4 --- /dev/null +++ b/src/render/particlesystem.h @@ -0,0 +1,75 @@ +/* + render/particlesystem.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_PARTICLESYSTEM_H__ +#define __INCLUDED_RENDER_PARTICLESYSTEM_H__ + +#include + +#include "core/entity.h" + +#include "render/particlesystemscript.h" +#include "render/particleejector.h" + + +namespace render { + +/* ---- class ParticleSystem --------------------------------------- */ + +/** + * @brief abstract base class for a particle system attached to an entity + * */ +class ParticleSystem +{ +public: + typedef std::list Ejectors; + + ParticleSystem(const ParticleSystemScript *script, const core::Entity *entity, const model::Particles *modelclass); + ~ParticleSystem(); + + void draw(const float seconds); + + /** + * @brief clear all particles from all ejectors + * */ + void clear(); + + inline const core::Entity *entity() + { + return particlesystem_entity; + } + + /** + * @brief location of the particlesystem + * */ + inline const math::Vector3f &location() const { + return particlesystem_location; + } + + /** + * @brief axisof the particlesystem + * */ + inline const math::Axis &axis() const { + return particlesystem_axis; + } + +private: + inline Ejectors & ejectors() + { + return particlesystem_ejectors; + } + + float particlesystem_modelscale; + math::Vector3f particlesystem_location; + math::Axis particlesystem_axis; + const core::Entity *particlesystem_entity; + Ejectors particlesystem_ejectors; + +}; + +} // namespace + +#endif // __INCLUDED_RENDER_PARTICLESYSTEM_H__ diff --git a/src/render/particlesystemscript.cc b/src/render/particlesystemscript.cc new file mode 100644 index 0000000..98c0a2d --- /dev/null +++ b/src/render/particlesystemscript.cc @@ -0,0 +1,313 @@ +/* + render/particlesystemscript.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/particlesystemscript.h" +#include "render/textures.h" + +namespace render +{ + +/* ---- static ParticleSystemScript registry ---------------------------------- */ + +ParticleSystemScript::Registry ParticleSystemScript::script_registry; + +void ParticleSystemScript::list() +{ + + for (Registry::const_iterator it = script_registry.begin(); it != script_registry.end(); ++it) { + + const ParticleSystemScript *script = (*it).second; + std::string strval; + + for (Ejectors::const_iterator eit = script->script_ejectors.begin(); eit != script->script_ejectors.end(); ++eit) { + const ParticleEjectorScript *ejector = (*eit); + + switch (ejector->type()) { + case ParticleEjectorScript::Flame: + strval.append(" flame"); + break; + case ParticleEjectorScript::Flare: + strval.append(" flare"); + break; + case ParticleEjectorScript::Jet: + strval.append(" jet"); + break; + case ParticleEjectorScript::Spray: + strval.append(" spray"); + break; + case ParticleEjectorScript::Trail: + strval.append(" trail"); + break; + } + } + con_print << " " << script->label() << strval << " " << script->script_ejectors.size() << " " << aux::plural("ejector", script->script_ejectors.size()) << std::endl; + } + con_print << script_registry.size() << " particle scripts" << std::endl; +} + +void ParticleSystemScript::clear() +{ + for (Registry::iterator it = script_registry.begin(); it != script_registry.end(); it++) { + delete(*it).second; + (*it).second = 0; + } + script_registry.clear(); +} + +ParticleSystemScript *ParticleSystemScript::find(const std::string &label) +{ + Registry::iterator it = script_registry.find(label); + + if (it != script_registry.end()) { + return (*it).second; + } else { + return 0; + } +} + +ParticleSystemScript *ParticleSystemScript::load(const std::string &label) +{ + ParticleSystemScript *script = find(label); + if (script) { + return script; + } + + filesystem::IniFile inifile; + inifile.open("particles/" + label); + if (!inifile.is_open()) { + con_warn << "Could not open " << inifile.name() << std::endl; + return 0; + } + + ParticleEjectorScript *ejector = 0; + std::string strval; + float pitch, yaw, roll = 0.0f; + float f; + bool b; + long l; + + while (inifile.getline()) { + + if (inifile.got_section()) { + + if (inifile.got_section("particles")) { + if (!script) { + script = new ParticleSystemScript(label); + script_registry[script->label()] = script; + } + ejector = 0; + continue; + } else if (inifile.got_section("ejector")) { + if (script) { + ejector = script->add_ejector(); + } else { + inifile.unknown_error("ejector section without particles section"); + } + } else { + inifile.unknown_section(); + } + + } else if (inifile.got_key()) { + + if (inifile.in_section("particles")) { + inifile.unknown_key(); + + } else if (inifile.in_section("ejector") && ejector) { + + if (inifile.got_key_string("type", strval)) { + aux::to_label(strval); + if (strval.compare("jet") == 0) { + ejector->set_type(ParticleEjectorScript::Jet); + } else if (strval.compare("trail") == 0) { + ejector->set_type(ParticleEjectorScript::Trail); + } else if (strval.compare("flame") == 0) { + ejector->set_type(ParticleEjectorScript::Flame); + } else if (strval.compare("spray") == 0) { + ejector->set_type(ParticleEjectorScript::Spray); + } else if (strval.compare("flare") == 0) { + ejector->set_type(ParticleEjectorScript::Flare); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_string("cull", strval)) { + aux::to_label(strval); + if (strval.compare("none") == 0) { + ejector->set_cull(model::CullNone); + } else if (strval.compare("back") == 0) { + ejector->set_cull(model::CullBack); + } else if (strval.compare("front") == 0) { + ejector->set_cull(model::CullFront); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_string("texture", strval)) { + ejector->set_texture("textures/" + strval); + Textures::load(ejector->texture()); + continue; + + } else if (inifile.got_key_float("speed", f)) { + // convert speed from meters/second to game units/second + ejector->set_speed(f * 0.01f); + continue; + + } else if (inifile.got_key_float("offset", f)) { + math::clamp(f, 0.0f, 1.0f); + ejector->set_offset(f); + continue; + + } else if (inifile.got_key_vector3f_opt("alpha", ejector->get_alpha_vec())) { + math::clamp(ejector->get_alpha_vec()[0], 0.0f, 1.0f); + math::clamp(ejector->get_alpha_vec()[1], 0.0f, 1.0f); + math::clamp(ejector->get_alpha_vec()[2], 0.0f, 1.0f); + continue; + + } else if (inifile.got_key_vector3f_opt("radius", ejector->get_radius_vec())) { + ejector->get_radius_vec() *= model::SCALE; + continue; + + } else if (inifile.got_key_float("spawnradius", f)) { + ejector->set_spawn_radius(f * model::SCALE); + continue; + + } else if (inifile.got_key_float("cone", f)) { + ejector->set_cone(f); + continue; + + } else if (inifile.got_key_long("interval", l)) { + ejector->set_interval((unsigned long) l); + continue; + + } else if (inifile.got_key_long("lifespan", l)) { + ejector->set_lifespan((unsigned long) l); + continue; + + } else if (inifile.got_key_color("color", ejector->get_color())) { + continue; + + } else if (inifile.got_key_bool("engine", b)) { + ejector->set_engine(b); + continue; + + } else if (inifile.got_key_bool("thrust", b)) { + ejector->set_thrust(b); + continue; + + } else if (inifile.got_key_bool("entity", b)) { + ejector->set_entity(b); + continue; + + } else if (inifile.got_key_bool("entitysecond", b)) { + ejector->set_entity_second(b); + continue; + + } else if (inifile.got_key_bool("entitythird", b)) { + if (b) { + ejector->set_entity(true); + ejector->set_entity_second(true); + } + continue; + + } else if (inifile.got_key_float("angle", yaw)) { + + if (yaw == model::ANGLEUP) { + ejector->get_axis().change_pitch(-90.0f); + } else if (yaw == model::ANGLEDOWN) { + ejector->get_axis().change_pitch(90.0f); + } else { + ejector->get_axis().change_direction(yaw); + } + continue; + + } else if (inifile.got_key("angles")) { + + std::istringstream str(inifile.value()); + if (str >> pitch >> yaw >> roll) { + ejector->get_axis().assign(yaw, pitch, roll); + } else { + inifile.unknown_value(); + } + continue; + + } else if (inifile.got_key_float("pitch", pitch)) { + ejector->get_axis().change_pitch(-pitch); + continue; + + } else if (inifile.got_key_float("yaw", yaw)) { + ejector->get_axis().change_direction(yaw); + continue; + + } else if (inifile.got_key_float("roll", roll)) { + ejector->get_axis().change_roll(-roll); + continue; + + } else { + inifile.unknown_key(); + } + } + } + } + + inifile.close(); + +#ifdef HAVE_DEBUG_MESSAGES + if (script) { + strval.clear(); + for (Ejectors::const_iterator eit = script->script_ejectors.begin(); eit != script->script_ejectors.end(); ++eit) { + const ParticleEjectorScript *ejector = (*eit); + + switch (ejector->type()) { + case ParticleEjectorScript::Flame: + strval.append(" flame"); + break; + case ParticleEjectorScript::Flare: + strval.append(" flare"); + break; + case ParticleEjectorScript::Jet: + strval.append(" jet"); + break; + case ParticleEjectorScript::Spray: + strval.append(" spray"); + break; + case ParticleEjectorScript::Trail: + strval.append(" trail"); + break; + } + } + con_debug << " " << script->label() << strval << " " << script->script_ejectors.size() << " " << aux::plural("ejector", script->script_ejectors.size()) << std::endl; + } +#endif + return script; +} + +/* ---- class ParticleSystemScript --------------------------------------- */ + +ParticleSystemScript::ParticleSystemScript(const std::string & label) : script_label(label) +{ + +} + +ParticleSystemScript::~ParticleSystemScript() +{ + for (Ejectors::iterator it = script_ejectors.begin(); it != script_ejectors.end(); ++it) + { + delete (*it); + (*it) = 0; + } + script_ejectors.clear(); +} + +ParticleEjectorScript *ParticleSystemScript::add_ejector() +{ + ParticleEjectorScript *ejector = new ParticleEjectorScript(); + script_ejectors.push_back(ejector); + return ejector; +} + +} \ No newline at end of file diff --git a/src/render/particlesystemscript.h b/src/render/particlesystemscript.h new file mode 100644 index 0000000..d4a7d9b --- /dev/null +++ b/src/render/particlesystemscript.h @@ -0,0 +1,66 @@ +/* + render/particlesystemscript.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_RENDER_PARTICLESYSTEMSCRIPT_H__ +#define __INCLUDED_RENDER_PARTICLESYSTEMSCRIPT_H__ + +#include "math/axis.h" +#include "math/color.h" +#include "math/vector3f.h" +#include "core/entity.h" +#include "model/tags.h" +#include "render/particleejectorscript.h" + +namespace render +{ + +/* ---- class ParticleSystemScript --------------------------------------- */ + +/** + * @brief a ParticleSystemScript holds the definition for a complete particle system. + * A script can hold the one ore more ejector definitions, and + * all required parameters are read from a .ini file. + * */ +class ParticleSystemScript +{ +public: + typedef std::list Ejectors; + + inline const std::string &label() const { + return script_label; + } + + ParticleEjectorScript *add_ejector(); + + inline const Ejectors &ejectors() const { + return script_ejectors; + } + + static ParticleSystemScript *load(const std::string &label); + + static ParticleSystemScript *find(const std::string &label); + + static void clear(); + + static void list(); + +private: + + ParticleSystemScript(const std::string & label); + + ~ParticleSystemScript(); + + std::string script_label; + Ejectors script_ejectors; + + typedef std::map Registry; + + static Registry script_registry; +}; + +} // namespace render + +#endif // __INCLUDED_RENDER_PARTICLESYSTEMSCRIPT_H__ diff --git a/src/render/render.cc b/src/render/render.cc index bf14e7d..d6c8817 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -21,7 +21,7 @@ #include "render/gl.h" #include "render/state.h" #include "render/dust.h" -#include "render/particles.h" +#include "render/particlesystemscript.h" #include "render/render.h" #include "render/screenshot.h" #include "render/textures.h" @@ -51,7 +51,7 @@ void func_list_textures(std::string const &args) void func_list_particles(std::string const &args) { - ParticleScript::list(); + ParticleSystemScript::list(); } void func_load_info_models(std::string const &args) @@ -201,7 +201,7 @@ void clear() } // clear particle system scripts - ParticleScript::clear(); + ParticleSystemScript::clear(); } // load assets @@ -235,7 +235,7 @@ void load_info_models() for (model::Model::ParticleSystems::iterator pit = (*it).second->particles().begin(); pit != (*it).second->particles().end(); pit++) { model::Particles *particles = (*pit); if (particles->script().size()) { - ParticleScript::load(particles->script()); + ParticleSystemScript::load(particles->script()); } } } diff --git a/src/render/renderext.cc b/src/render/renderext.cc index 1dc82f8..25e0cab 100644 --- a/src/render/renderext.cc +++ b/src/render/renderext.cc @@ -7,6 +7,7 @@ #include #include +#include "render/particlesystemscript.h" #include "math/functions.h" #include "core/application.h" #include "core/entity.h" @@ -39,7 +40,7 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re if (entity->model()) { model::Model *model = entity->model(); - for (model::Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) { + for (model::Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); ++lit) { model::Light *light = (*lit); // load light texture @@ -48,7 +49,7 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re light->set_texture(Textures::load(flarename.str())); } - for (model::Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); flit++) { + for (model::Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); ++flit) { model::Flare *flare = (*flit); // load flare texture @@ -57,30 +58,12 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re flare->set_texture(Textures::load(flarename.str())); } - for (model::Model::ParticleSystems::const_iterator pit = model->particles().begin(); pit != model->particles().end(); pit++) { - // model attachment location tag - const model::Particles *particlesystem = (*pit); - + for (model::Model::ParticleSystems::const_iterator pit = model->particles().begin(); pit != model->particles().end(); ++pit) { // load particle systems - const ParticleScript *script = ParticleScript::load(particlesystem->script()); - while (script) { - if ( script->type() == render::ParticleScript::Trail) { - 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); - state_particles.push_back(jet); - - } else if (script->type() == render::ParticleScript::Spray) { - Spray *spray = new Spray(script, entity, particlesystem); - state_particles.push_back(spray); - - } else if (script->type() == render::ParticleScript::Flame) { - Flame *flame = new Flame(script, entity, particlesystem); - state_particles.push_back(flame); - } - script = script->next(); + const ParticleSystemScript *script = ParticleSystemScript::load((*pit)->script()); + if (script) { + ParticleSystem *ps = new ParticleSystem(script, entity, (*pit)); + state_particles.push_back(ps); } } @@ -181,9 +164,9 @@ void RenderExt::frame(float elapsed) if (!state_explosion) { // add explosion - const ParticleScript *script = ParticleScript::load("explosion"); + const ParticleSystemScript *script = ParticleSystemScript::load("explosion"); if (script) { - state_explosion = (ParticleSystem *) new Spray(script, entity(), 0); + state_explosion = new ParticleSystem(script, entity(), 0); state_particles.push_back(state_explosion); } } diff --git a/src/render/renderext.h b/src/render/renderext.h index 14dbaa3..d140bbe 100644 --- a/src/render/renderext.h +++ b/src/render/renderext.h @@ -10,7 +10,7 @@ #include #include "core/extension.h" -#include "render/particles.h" +#include "render/particlesystem.h" namespace render { -- cgit v1.2.3