From 2c8331414db790824df9e9e2ea6e25ad7aa39b99 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 16 Apr 2013 21:06:49 +0000 Subject: Support for 'colorsecond' in particle scripts, have trail style particles use a single texture for the entire length instead of repeating it. --- src/render/particle.cc | 2 - src/render/particle.h | 24 ++++++++---- src/render/particleejector.cc | 76 +++++++++++++++++++++---------------- src/render/particleejectorscript.cc | 4 ++ src/render/particleejectorscript.h | 54 ++++++++++++++++++++++++-- src/render/particlesystemscript.cc | 6 ++- 6 files changed, 118 insertions(+), 48 deletions(-) diff --git a/src/render/particle.cc b/src/render/particle.cc index 5925ba5..6774cde 100644 --- a/src/render/particle.cc +++ b/src/render/particle.cc @@ -19,7 +19,6 @@ Particle::Particle(const math::Vector3f &location, const unsigned long timestamp particle_speed = 0.0f; particle_radius = 0.0f; - particle_alpha = 0.0f; } @@ -31,7 +30,6 @@ Particle::Particle(const math::Vector3f &location, const math::Axis &axis, const particle_speed = 0.0f; particle_radius = 0.0f; - particle_alpha = 0.0f; } } //namespace render diff --git a/src/render/particle.h b/src/render/particle.h index c259dbc..742a03a 100644 --- a/src/render/particle.h +++ b/src/render/particle.h @@ -59,11 +59,11 @@ public: } /** - * @brief alpha value of the particle + * @brief color of the particle * */ - const float alpha() const + const math::Color color() const { - return particle_alpha; + return particle_color; } /** @@ -130,11 +130,19 @@ public: } /** - * @brief set the alpha value of the particle + * @brief set the color of the particle * */ - inline void set_alpha(const float alpha) + inline void set_color(const math::Color color) { - particle_alpha = alpha; + particle_color.assign(color); + } + + /** + * @brief return a reference to the color of the particle + * */ + math::Color & get_color() + { + return particle_color; } /** @@ -148,9 +156,9 @@ public: protected: math::Vector3f particle_location; + math::Color particle_color; math::Axis particle_axis; - float particle_radius; - float particle_alpha; + float particle_radius; float particle_rotation; float particle_speed; unsigned long particle_timestamp; diff --git a/src/render/particleejector.cc b/src/render/particleejector.cc index 29a255d..5fae7d1 100644 --- a/src/render/particleejector.cc +++ b/src/render/particleejector.cc @@ -82,7 +82,10 @@ void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_locat Particle *particle = new Particle(particle_location, particle_axis, now); particle->set_radius(radius_vec()[0]); - particle->set_alpha(alpha_vec()[0]); + + particle->set_color(color()); + particle->get_color().a = alpha_vec()[0]; + particle->set_rotation(math::randomf(2.0f * M_PI)); particle->set_speed(math::randomf(speed_vec()[0], speed_vec()[1])); particles().push_front(particle); @@ -90,7 +93,8 @@ void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_locat if (type() == Streak) { Particle *tail = new Particle(particle_location, particle_axis, now); tail->set_radius(radius_vec()[0]); - tail->set_alpha(alpha_vec()[0]); + tail->set_color(color()); + tail->get_color().a = alpha_vec()[0]; tail->set_rotation(particle->rotation()); tail->set_speed(math::randomf(tailspeed_vec()[0], tailspeed_vec()[1])); particles().push_front(tail); @@ -115,20 +119,32 @@ void ParticleEjector::frame(const float seconds, const math::Vector3f & ps_locat // apply velocity particle->get_location() += (particle->axis().forward() * particle->speed() * seconds); - // set particle radius_vec and alpha_vec + // interpolate particle radius, color and alpha const float age = (float) (now - particle->timestamp()); const float halflife = offset() * (float) lifespan(); + float t; if (age < halflife) { - const float t = age / halflife; + 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]); + particle->get_color().a = ((1.0f - t) * alpha_vec()[0] + t * alpha_vec()[1]); + + t *= 0.5f; + } else { - const float t = (age - halflife) / ((float) lifespan() - halflife); + 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]); + particle->get_color().a = ((1.0f - t) * alpha_vec()[1] + t * alpha_vec()[2]); + + t = 0.5f + t * 0.5f; + } + + if (color_interpolated()) { + particle->get_color().r = color().r * (1.0f - t) + color_second().r * t; + particle->get_color().g = color().g * (1.0f - t) + color_second().g * t; + particle->get_color().b = color().b * (1.0f - t) + color_second().b * t; } } @@ -183,8 +199,6 @@ void ParticleEjectorSprite::draw(const math::Vector3f & ps_location, const math: 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); @@ -194,8 +208,7 @@ void ParticleEjectorSprite::draw(const math::Vector3f & ps_location, const math: math::Vector3f l(attached() ? ps_location + ps_axis * particle->location() : particle->location()); const float r = particle->radius(); - c.a = particle->alpha(); - gl::color(c); + gl::color(particle->color()); glTexCoord2f(0, 1); gl::vertex(l + rotation * quad[0] * r); @@ -226,7 +239,7 @@ void ParticleEjectorFlare::draw(const math::Vector3f & ps_location, const math:: { Textures::bind(texture()); gl::begin(gl::Quads); - math::Color c(color()); + for (Particles::iterator it = particles().begin(); it != particles().end(); it++) { Particle *particle = (*it); @@ -234,8 +247,7 @@ void ParticleEjectorFlare::draw(const math::Vector3f & ps_location, const math:: math::Axis particle_axis(attached() ? ps_axis * particle->axis() : particle->axis()); const float r = particle->radius(); - c.a = particle->alpha(); - gl::color(c); + gl::color(particle->color()); glTexCoord2f(0, 1); gl::vertex(particle_location + (particle_axis.up() - particle_axis.left()) * r); @@ -268,7 +280,7 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: return; } - (*particles().rbegin())->set_alpha(0.0f); + (*particles().rbegin())->get_color().a = (0.0f); Particles::iterator first = particles().begin(); Particles::iterator next = first; @@ -277,9 +289,7 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: Textures::bind(texture()); gl::begin(gl::Quads); - math::Color c(color()); - c.a = (*first)->alpha(); - gl::color(c); + gl::color((*first)->color()); //math::Vector3f first_location(attached() ? ps_location + ps_axis * (*first)->location() : (*first)->location()); math::Vector3f first_normal(math::crossproduct(((*first)->location() - ps_location), ((*first)->location() - Camera::eye()))); @@ -287,14 +297,17 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: math::Vector3f next_normal(first_normal); + const float length = (float) particles().size(); + float position = 1.0f; + 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); + glTexCoord2f(0, position / length); gl::vertex((*first)->location() + next_normal * (*first)->radius()); - glTexCoord2f(1, 1); + glTexCoord2f(1, position / length); gl::vertex((*first)->location() - next_normal * (*first)->radius()); Stats::quads++; @@ -302,20 +315,20 @@ void ParticleEjectorTrail::draw(const math::Vector3f & ps_location, const math:: next_normal.assign(math::crossproduct(((*next)->location() - (*first)->location()), ((*next)->location() - Camera::eye()))); next_normal.normalize(); - c.a = (*first)->alpha(); - gl::color(c); + gl::color((*first)->color()); - glTexCoord2f(1, 0); + glTexCoord2f(1, position / length); gl::vertex((*first)->location() - first_normal * (*first)->radius()); - glTexCoord2f(0, 0); + glTexCoord2f(0, position / length); gl::vertex((*first)->location() + first_normal * (*first)->radius()); - c.a = (*next)->alpha(); - gl::color(c); + gl::color((*next)->color()); - glTexCoord2f(0, 1); + position += 1.0f; + + glTexCoord2f(0, position / length); gl::vertex((*next)->location() + next_normal * (*next)->radius()); - glTexCoord2f(1, 1); + glTexCoord2f(1, position / length); gl::vertex((*next)->location() - next_normal * (*next)->radius()); Stats::quads++; @@ -352,7 +365,6 @@ void ParticleEjectorStreak::draw(const math::Vector3f & ps_location, const math: Particles::iterator next = first; math::Vector3f normal; - math::Color c(color()); Textures::bind(texture()); gl::begin(gl::Quads); @@ -368,16 +380,14 @@ void ParticleEjectorStreak::draw(const math::Vector3f & ps_location, const math: normal.assign(math::crossproduct((first_location - Camera::eye()), (next_location - Camera::eye()))); normal.normalize(); - c.a = (*first)->alpha(); - gl::color(c); + gl::color((*first)->color()); glTexCoord2f(1, 0); gl::vertex(first_location - normal * (*first)->radius()); glTexCoord2f(0, 0); gl::vertex(first_location + normal * (*first)->radius()); - c.a = (*next)->alpha(); - gl::color(c); + gl::color((*next)->color()); glTexCoord2f(0, 1); gl::vertex(next_location + normal * (*next)->radius()); diff --git a/src/render/particleejectorscript.cc b/src/render/particleejectorscript.cc index b2c84bc..250eb20 100644 --- a/src/render/particleejectorscript.cc +++ b/src/render/particleejectorscript.cc @@ -28,6 +28,8 @@ ParticleEjectorScript::ParticleEjectorScript() script_spawn_radius = 0.0f; script_attached = false; script_scaled = false; + + script_color_interpolated = false; } ParticleEjectorScript::ParticleEjectorScript(const ParticleEjectorScript &other) @@ -48,6 +50,7 @@ ParticleEjectorScript::ParticleEjectorScript(const ParticleEjectorScript &other) script_cull = other.cull(); script_attached = other.attached(); script_scaled = other.scaled(); + script_color_interpolated = other.color_interpolated(); script_texture.assign(other.texture()); script_axis.assign(other.axis()); @@ -56,6 +59,7 @@ ParticleEjectorScript::ParticleEjectorScript(const ParticleEjectorScript &other) script_speed_vec.assign(other.speed_vec()); script_tailspeed_vec.assign(other.tailspeed_vec()); script_color.assign(other.color()); + script_color_second.assign(other.color_second()); } ParticleEjectorScript::~ParticleEjectorScript() diff --git a/src/render/particleejectorscript.h b/src/render/particleejectorscript.h index 535458e..ef2be4c 100644 --- a/src/render/particleejectorscript.h +++ b/src/render/particleejectorscript.h @@ -125,6 +125,14 @@ public: return script_attached; } + /** + * @brief true if particle color is interpolated between color() and color_second() + * */ + inline const bool color_interpolated() const + { + return script_color_interpolated; + } + /** * @brief ejector particles and speed are scaled according to modelscale * */ @@ -155,6 +163,14 @@ public: return script_color; } + /** + * @brief secondary color used to render ejected particles + * */ + inline const math::Color &color_second() const + { + return script_color_second; + } + /** * @brief radius vector for ejected particles, start, middle, end * The radius is interpolated depending on the age and lifespan of the particle @@ -249,13 +265,21 @@ public: } /** - * @brief return a reference to particle color + * @brief return a reference to primary particle color * */ inline math::Color &get_color() { return script_color; } + /** + * @brief return a reference to secondary particle color + * */ + inline math::Color &get_color_second() + { + return script_color_second; + } + /** * @brief set the ejector type * */ @@ -408,19 +432,35 @@ public: script_attached = attached; } + /** + * @brief set to true to interpolate particle color between color() and color_second() + * */ + inline void set_color_interpolated(const bool color_interpolated) + { + script_color_interpolated = color_interpolated; + } + inline void set_scaled(const bool scaled) { script_scaled = scaled; } /** - * @brief set the particle color + * @brief set the particle color at the begin of lifespan * */ inline void set_color(const math::Color &color) { script_color.assign(color); } + /** + * @brief set the particle color at the end of lifespane + * */ + inline void set_color_second(const math::Color &color_second) + { + script_color_second.assign(color_second); + } + private: /// type of ejector Type script_type; @@ -450,9 +490,15 @@ private: /// spawn radius float script_spawn_radius; - /// color of ejected particles + /// color of ejected particles at start of lifespan math::Color script_color; - + + /// color of ejected particles at end of lifespan + math::Color script_color_second; + + /// true of the particle color has to be interpolated betwoon color and color_second + bool script_color_interpolated; + /// particles have entity primary color bool script_entity; /// particles have entity secondary color diff --git a/src/render/particlesystemscript.cc b/src/render/particlesystemscript.cc index f78fa88..03ce86e 100644 --- a/src/render/particlesystemscript.cc +++ b/src/render/particlesystemscript.cc @@ -214,11 +214,15 @@ ParticleSystemScript *ParticleSystemScript::load(const std::string &label) } else if (inifile.got_key_long("timeout", l)) { ejector->set_timeout((unsigned long) l); - continue; + continue; } else if (inifile.got_key_color("color", ejector->get_color())) { continue; + } else if (inifile.got_key_color("colorsecond", ejector->get_color_second())) { + ejector->set_color_interpolated(true); + continue; + } else if (inifile.got_key_bool("engine", b)) { ejector->set_engine(b); continue; -- cgit v1.2.3