Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2013-01-20 21:37:11 +0000
committerStijn Buys <ingar@osirion.org>2013-01-20 21:37:11 +0000
commitd4f9da2f3c19511b028da2569d7b6a8d1371e135 (patch)
treee1bba0d8dd3b15169612f865612d3fca6475639a /src/render
parent4feff2411d1b703a3b93d8a342112bd998b1ffed (diff)
Major overhaul of the particle system back-end, support multiple ejectors per particle system.
Diffstat (limited to 'src/render')
-rw-r--r--src/render/Makefile.am12
-rw-r--r--src/render/draw.cc9
-rw-r--r--src/render/particle.cc28
-rw-r--r--src/render/particle.h108
-rw-r--r--src/render/particleejector.cc251
-rw-r--r--src/render/particleejector.h104
-rw-r--r--src/render/particleejectorscript.cc55
-rw-r--r--src/render/particleejectorscript.h367
-rw-r--r--src/render/particles.cc253
-rw-r--r--src/render/particles.h122
-rw-r--r--src/render/particlesystem.cc144
-rw-r--r--src/render/particlesystem.h75
-rw-r--r--src/render/particlesystemscript.cc313
-rw-r--r--src/render/particlesystemscript.h66
-rw-r--r--src/render/render.cc8
-rw-r--r--src/render/renderext.cc37
-rw-r--r--src/render/renderext.h2
17 files changed, 1546 insertions, 408 deletions
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 <deque>
+
+#include "render/particleejectorscript.h"
+#include "render/particle.h"
+
+namespace render {
+
+class ParticleEjector : public ParticleEjectorScript {
+public:
+ typedef std::deque<Particle *> 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<std::string, ParticleScript *> 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<const core::EntityControlable *>(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<const core::EntityControlable *>(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 <list>
+
+#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<ParticleEjector *> 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<ParticleEjectorScript *> 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<std::string, ParticleSystemScript *> 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 <sstream>
#include <iomanip>
+#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 <list>
#include "core/extension.h"
-#include "render/particles.h"
+#include "render/particlesystem.h"
namespace render
{