From ee017172af06f4b247038510e5ef7f8ac3596f66 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 17 Nov 2010 22:49:18 +0000 Subject: Cleaned up model::Mapfile axis related keys in the map reader, added warning messages where approriate. Support for multiple particle systems in render::ParticleScript. Cleaned up render::ParticleScript member variable names. Added support for axis related keys and scale key in particle scripts. --- src/model/mapfile.cc | 250 ++++++++++++--------------------- src/model/mapfile.h | 9 ++ src/model/tags.cc | 32 +++-- src/model/tags.h | 61 ++++++-- src/render/draw.cc | 1 + src/render/particles.cc | 361 ++++++++++++++++++++++++++++++------------------ src/render/particles.h | 114 ++++++++------- src/render/renderext.cc | 14 +- 8 files changed, 466 insertions(+), 376 deletions(-) diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 1dbf0df..560bbc1 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -789,6 +789,58 @@ bool MapFile::got_key_color(const char * keylabel, math::Color & color) } } +bool MapFile::got_key_axis(math::Axis &axis) +{ + float pitch, yaw, roll = 0.0f; + + if (got_key_float("angle", yaw)) { + + if (yaw == ANGLEUP) { + axis.change_pitch(-90.0f); + } else if (yaw == ANGLEDOWN) { + axis.change_pitch(90.0f); + } else { + axis.change_direction(yaw); + } + return true; + + } else if (got_key("angles")) { + + std::istringstream str(value()); + if (str >> pitch >> yaw >> roll) { + axis.clear(); + axis.change_pitch(-pitch); + axis.change_direction(yaw); + axis.change_roll(-roll); + } else { + unknown_value(); + } + + return true; + + } else if (got_key_float("pitch", pitch)) { + // TODO this warning should eventually disappear + unknown_error("'" + classname() + ":" + key() + "' has changed polarity"); + axis.change_pitch(-pitch); + + return true; + + } else if (got_key_float("yaw", yaw)) { + axis.change_direction(yaw); + + return true; + + } else if (got_key_float("roll", roll)) { + // TODO this warning should eventually disappear + unknown_error("'" + classname() + ":" + key() + "' has changed polarity"); + axis.change_roll(-roll); + + return true; + } + + return false; +} + void MapFile::close() { mapfile_ifs.close(); @@ -938,6 +990,17 @@ void MapFile::warn_depricated() const con_warn << name() << " depricated key '" << key() << "' for '" << classname() << "' at line " << line() << std::endl; } +void MapFile::unknown_error(const char *text) const +{ + con_warn << name() << " " << (text && text[0] ? text : "unknown error") << " at line " << line() << std::endl; +} + +void MapFile::unknown_error(const std::string &text) const +{ + con_warn << name() << " " << text << " at line " << line() << std::endl; +} + + Model * MapFile::load(std::string const &name) { // open the .map file @@ -965,7 +1028,6 @@ Model * MapFile::load(std::string const &name) SubModelList submodel_list; unsigned int u; - float angle; float r, s; std::string str; @@ -1026,42 +1088,9 @@ Model * MapFile::load(std::string const &name) } else if (mapfile.in_class("func_rotate")) { - if (mapfile.got_key_float("angle", angle)) { - - if (angle == ANGLEUP) { - mapfile.class_axis.change_pitch(90.0f); - } else if (angle == ANGLEDOWN) { - mapfile.class_axis.change_pitch(-90.0f); - } else { - mapfile.class_axis.change_direction(angle); - } - - } else if (mapfile.got_key("angles")) { - - std::istringstream str(mapfile.value()); - float yaw, pitch,roll = 0.0f; - - if (str >> yaw >> pitch >> roll) { - mapfile.class_axis.clear(); - mapfile.class_axis.change_direction(yaw); - mapfile.class_axis.change_pitch(pitch); - mapfile.class_axis.change_roll(roll); - } else { - mapfile.unknown_value(); - } - - } else if (mapfile.got_key_float("direction", angle)) { - mapfile.class_axis.change_direction(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("pitch", angle)) { - mapfile.class_axis.change_pitch(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("roll", angle)) { - mapfile.class_axis.change_roll(angle); - mapfile.warn_depricated(); - + if (mapfile.got_key_axis(mapfile.class_axis)) { + continue; + } else if (mapfile.got_key_int("spawnflags", u)) { mapfile.class_engine = spawnflag_isset(u, 4); continue; @@ -1140,7 +1169,10 @@ Model * MapFile::load(std::string const &name) } else if (mapfile.classname().compare("fx_flare") == 0) { // flare attributes - if (mapfile.got_key_vector3f("origin", location)) { + if (mapfile.got_key_axis(tag_flare->get_axis())) { + continue; + + } else if (mapfile.got_key_vector3f("origin", location)) { tag_flare->get_location().assign(location * SCALE); continue; @@ -1177,42 +1209,6 @@ Model * MapFile::load(std::string const &name) tag_flare->set_flare(u); continue; - } else if (mapfile.got_key_float("angle", angle)) { - - if (angle == ANGLEUP) { - tag_flare->get_axis().change_pitch(90.0f); - } else if (angle == ANGLEDOWN) { - tag_flare->get_axis().change_pitch(-90.0f); - } else { - tag_flare->get_axis().change_direction(angle); - } - - } else if (mapfile.got_key("angles")) { - - std::istringstream str(mapfile.value()); - float yaw, pitch,roll = 0.0f; - - if (str >> yaw >> pitch >> roll) { - tag_flare->get_axis().clear(); - tag_flare->get_axis().change_direction(yaw); - tag_flare->get_axis().change_pitch(pitch); - tag_flare->get_axis().change_roll(roll); - } else { - mapfile.unknown_value(); - } - - } else if (mapfile.got_key_float("direction", angle)) { - tag_flare->get_axis().change_direction(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("pitch", angle)) { - tag_flare->get_axis().change_pitch(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("roll", angle)) { - tag_flare->get_axis().change_roll(angle); - mapfile.warn_depricated(); - } else if (mapfile.got_key_string("cull", str)) { aux::to_lowercase(str); @@ -1239,7 +1235,10 @@ Model * MapFile::load(std::string const &name) } else if (mapfile.classname().compare("fx_particles") == 0) { // particle system attributes - if (mapfile.got_key_vector3f("origin", location)) { + if (mapfile.got_key_axis(tag_particles->get_axis())) { + continue; + + } else if (mapfile.got_key_vector3f("origin", location)) { tag_particles->get_location().assign(location * SCALE); continue; @@ -1247,59 +1246,12 @@ Model * MapFile::load(std::string const &name) tag_particles->set_script(str); continue; - } else if (mapfile.got_key_float("angle", angle)) { - if (angle == ANGLEUP) { - tag_particles->get_axis().change_pitch(90.0f); - } else if (angle == ANGLEDOWN) { - tag_particles->get_axis().change_pitch(-90.0f); - } else { - tag_particles->get_axis().change_direction(angle); - } - - } else if (mapfile.got_key("angles")) { - - std::istringstream str(mapfile.value()); - float yaw, pitch,roll = 0.0f; - - if (str >> yaw >> pitch >> roll) { - tag_particles->get_axis().clear(); - tag_particles->get_axis().change_direction(yaw); - tag_particles->get_axis().change_pitch(pitch); - tag_particles->get_axis().change_roll(roll); - } else { - mapfile.unknown_value(); - } - - } else if (mapfile.got_key_float("direction", angle)) { - tag_particles->get_axis().change_direction(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("pitch", angle)) { - tag_particles->get_axis().change_pitch(angle); - mapfile.warn_depricated(); - - } else if (mapfile.got_key_float("roll", angle)) { - tag_particles->get_axis().change_roll(angle); - mapfile.warn_depricated(); - } else if (mapfile.got_key_int("spawnflags", u)) { tag_particles->set_entity(spawnflag_isset(u, 2)); tag_particles->set_engine(spawnflag_isset(u, 4)); - } else if (mapfile.got_key_float("radius", r)) { - tag_particles->set_radius(r * LIGHTSCALE); - - } else if (mapfile.got_key_string("cull", str)) { - aux::to_lowercase(str); - if (str.compare("none") == 0) { - tag_particles->set_cull(CullNone); - } else if (str.compare("back") == 0) { - tag_particles->set_cull(CullBack); - } else if (str.compare("front") == 0) { - tag_particles->set_cull(CullFront); - } else { - mapfile.unknown_value(); - } + } else if (mapfile.got_key_float("scale", s)) { + tag_particles->set_scale(s); } else if (mapfile.got_key()) { mapfile.unknown_key(); @@ -1345,7 +1297,6 @@ Model * MapFile::load(std::string const &name) } - } else if (mapfile.got_classname("misc_model")) { // new submodel tag @@ -1354,7 +1305,11 @@ Model * MapFile::load(std::string const &name) } else if (mapfile.classname().compare("misc_model") == 0) { - if (mapfile.got_key_vector3f("origin", location)) { + // submodel attributes + if (mapfile.got_key_axis(tag_submodel->get_axis())) { + continue; + + } else if (mapfile.got_key_vector3f("origin", location)) { tag_submodel->get_location().assign(location * SCALE); continue; @@ -1365,30 +1320,7 @@ Model * MapFile::load(std::string const &name) } tag_submodel->set_name(modelname); continue; - - } else if (mapfile.got_key_float("angle", angle)) { - if (angle == ANGLEUP) { - tag_submodel->get_axis().change_pitch(90.0f); - } else if (angle == ANGLEDOWN) { - tag_submodel->get_axis().change_pitch(-90.0f); - } else { - tag_submodel->get_axis().change_direction(angle); - } - } else if (mapfile.got_key("angles")) { - - std::istringstream str(mapfile.value()); - float yaw, pitch,roll = 0.0f; - - if (str >> yaw >> pitch >> roll) { - tag_submodel->get_axis().clear(); - tag_submodel->get_axis().change_direction(yaw); - tag_submodel->get_axis().change_pitch(pitch); - tag_submodel->get_axis().change_roll(roll); - } else { - mapfile.unknown_value(); - } - } else if (mapfile.got_key_float("modelscale", s)) { if (s) { tag_submodel->set_scale(s); @@ -1401,7 +1333,6 @@ Model * MapFile::load(std::string const &name) } - } else if (mapfile.got_classname("location_dock")) { // new docking location @@ -1411,20 +1342,15 @@ Model * MapFile::load(std::string const &name) } else if (mapfile.classname().compare("location_dock") == 0) { // dock attributes - if (mapfile.got_key_vector3f("origin", location)) { + if (mapfile.got_key_axis(tag_dock->get_axis())) { + continue; + + } else if (mapfile.got_key_vector3f("origin", location)) { tag_dock->get_location().assign(location * SCALE); continue; } else if (mapfile.got_key_float("radius", r)) { - tag_dock->set_radius(r); - continue; - - } else if (mapfile.got_key("angle")) { - // TODO - continue; - - } else if (mapfile.got_key("angles")) { - // TODO + tag_dock->set_radius(r * SCALE); continue; } else if (mapfile.got_key()) { @@ -1539,7 +1465,7 @@ Model * MapFile::load(std::string const &name) for (Model::ParticleSystems::const_iterator pit = submodel_model->particles().begin(); pit != submodel_model->particles().end(); pit++) { tag_particles = new Particles(*(*pit)); tag_particles->get_location().assign(tag_submodel->location() + tag_particles->location() * tag_submodel->scale()); - tag_particles->set_radius(tag_particles->radius() * tag_submodel->scale()); + tag_particles->set_scale(tag_particles->scale() * tag_submodel->scale()); model->add_particles(tag_particles); } @@ -1576,7 +1502,7 @@ Model * MapFile::load(std::string const &name) fragmentgroup->set_location(fragmentgroup->location() - map_center); } - // translate tags + // translate tags for (Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); lit++) { (*lit)->get_location() -= map_center; } diff --git a/src/model/mapfile.h b/src/model/mapfile.h index 7ee47d3..a12e295 100644 --- a/src/model/mapfile.h +++ b/src/model/mapfile.h @@ -105,6 +105,9 @@ private: bool got_key_angle(const char * keylabel, float & f); bool got_key_vector3f(const char * keylabel, math::Vector3f & v); + + /// check if the last read key is one of the axis related keys (angle, angles, pitch, yaw, roll) + bool got_key_axis(math::Axis &axis); /// return the number of lines read so far @@ -152,6 +155,12 @@ private: /// print 'depricated key' warning message to the console void warn_depricated() const; + + /// print a generic error message + void unknown_error(const char *text = 0) const; + + /// print a generic error message + void unknown_error(const std::string &text) const; /// list of planes for the current brush std::vector planes; diff --git a/src/model/tags.cc b/src/model/tags.cc index a47a16c..c1467a1 100644 --- a/src/model/tags.cc +++ b/src/model/tags.cc @@ -19,10 +19,6 @@ Tag::Tag(const Tag& other) : tag_location(other.location()) { } -Tag::Tag(const math::Vector3f& location) : tag_location(location) -{ -} - Tag::~Tag() { } @@ -71,12 +67,16 @@ Light::~Light() /* ---- class Flare ------------------------------------------------ */ -Flare::Flare() : Light() +Flare::Flare() : + Light(), + flare_axis() { flare_cull = CullBack; } -Flare::Flare(const Flare& other) : Light(other) +Flare::Flare(const Flare& other) : + Light(other), + flare_axis(other.axis()) { flare_cull = other.cull(); } @@ -86,17 +86,26 @@ Flare::~Flare() /* ---- class Particles -------------------------------------------- */ -Particles::Particles() : Tag() +Particles::Particles() : + Tag(), + particles_axis(), + particles_script() { particles_entity = false; particles_engine = false; - particles_radius = 0.0f; + particles_scale = 1.0f; particles_cull = CullNone; } -Particles::Particles(const math::Vector3f& location) : - Tag(location) +Particles::Particles(const Particles & other) : + Tag(other), + particles_axis(other.axis()), + particles_script(other.script()) { + particles_entity = other.entity(); + particles_engine = other.engine(); + particles_scale = other.scale(); + particles_cull = other.cull(); } Particles::~Particles() @@ -113,6 +122,7 @@ Dock::Dock() : Tag() Dock::Dock(const Dock& other) : Tag(other) { dock_radius = other.radius(); + dock_axis.assign(other.axis()); } Dock::~Dock() @@ -126,7 +136,7 @@ Sound::Sound() : Tag() } Sound::Sound(const Sound& other) : Tag(other), - sound_name(other.name()) + sound_name(other.name()) { } diff --git a/src/model/tags.h b/src/model/tags.h index 881b914..af1bc27 100644 --- a/src/model/tags.h +++ b/src/model/tags.h @@ -46,12 +46,6 @@ public: */ Tag(const Tag& other); - /** - * @brief constructor with location - * @param location location of this part within the parent model - */ - Tag(const math::Vector3f& location); - /** * @brief default destructor */ @@ -311,16 +305,28 @@ private: class Particles : public Tag { public: + /** + * @brief default constructor + */ Particles(); - Particles(const math::Vector3f & location); + /** + * @brief copy constructor + */ + Particles(const Particles & other); + /** + * @brief destructor + */ ~Particles(); inline const math::Axis &axis() const { return particles_axis; } + /** + * @brief name of the script to load + */ inline const std::string& script() const { return particles_script; } @@ -333,8 +339,8 @@ public: return particles_engine; } - inline float radius() const { - return particles_radius; + inline float scale() const { + return particles_scale; } inline Cull cull() const { @@ -357,10 +363,6 @@ public: particles_engine = engine; } - inline void set_radius(const float radius) { - particles_radius = radius; - } - inline void set_cull(const Cull cull) { particles_cull = cull; } @@ -368,6 +370,10 @@ public: inline void set_script(const std::string& script) { particles_script.assign(script); } + + inline void set_scale(const float scale) { + particles_scale = scale; + } /* ---- actors --------------------------------------------- */ @@ -384,8 +390,8 @@ private: Cull particles_cull; - float particles_radius; - + float particles_scale; + math::Axis particles_axis; std::string particles_script; }; @@ -396,6 +402,9 @@ private: class Dock : public Tag { public: + /** + * @brief default constructor + */ Dock(); /** @@ -403,8 +412,15 @@ public: */ Dock(const Dock& other); + /** + * @brief destructor + */ ~Dock(); + inline const math::Axis &axis() const { + return dock_axis; + } + /// dock radius, default is 0.01f inline float radius() const { return dock_radius; @@ -415,8 +431,23 @@ public: dock_radius = radius; } + /// set dock axis + inline void set_axis(const math::Axis& axis) { + dock_axis.assign(axis); + } + + /* ---- actors --------------------------------------------- */ + + /** + * @brief mutable reference to the axis + */ + inline math::Axis& get_axis() { + return dock_axis; + } + private: float dock_radius; + math::Axis dock_axis; }; /* ---- class Sound ------------------------------------------------ */ diff --git a/src/render/draw.cc b/src/render/draw.cc index 780c77e..af5cf41 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -591,6 +591,7 @@ void draw_model_fragments(model::Model *model, const float rotation_angle = math::degrees360f((group->engine() ? enginetime : core::application()->time()) * group->speed()); gl::rotate(-rotation_angle, group->axis().forward()); } else { + // FIXME group origin is lost gl::multmatrix(group->axis()); } diff --git a/src/render/particles.cc b/src/render/particles.cc index 610c49a..86847c3 100644 --- a/src/render/particles.cc +++ b/src/render/particles.cc @@ -30,47 +30,56 @@ Particle::Particle(const math::Vector3f &location, const math::Axis &axis, float /* ---- static ParticleScript registry ---------------------------------- */ -ParticleScript::Registry ParticleScript::particles_registry; +ParticleScript::Registry ParticleScript::particlescript_registry; void ParticleScript::list() { - std::string str; - for (Registry::iterator it = particles_registry.begin(); it != particles_registry.end(); it++) { + + for (Registry::const_iterator it = particlescript_registry.begin(); it != particlescript_registry.end(); it++) { - ParticleScript *script = (*it).second; - switch (script->type()) { - case Flame: - str.assign("flame"); - break; - case Jet: - str.assign("jet"); - break; - case Spray: - str.assign("spray"); - break; - case Trail: - str.assign("trail"); - break; + 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 << " " << script->label() << " " << str << std::endl; - con_print << particles_registry.size() << " particle scripts" << std::endl; + 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 = particles_registry.begin(); it != particles_registry.end(); it++) { + for (Registry::iterator it = particlescript_registry.begin(); it != particlescript_registry.end(); it++) { delete(*it).second; (*it).second = 0; } - particles_registry.clear(); + particlescript_registry.clear(); } ParticleScript *ParticleScript::find(const std::string &label) { - Registry::iterator it = particles_registry.find(label); + Registry::iterator it = particlescript_registry.find(label); - if (it != particles_registry.end()) { + if (it != particlescript_registry.end()) { return (*it).second; } else { return 0; @@ -79,9 +88,9 @@ ParticleScript *ParticleScript::find(const std::string &label) ParticleScript *ParticleScript::load(const std::string &label) { - ParticleScript *script = find(label); - if (script) - return script; + ParticleScript *parent_script = find(label); + if (parent_script) + return parent_script; filesystem::IniFile inifile; @@ -92,15 +101,23 @@ ParticleScript *ParticleScript::load(const std::string &label) return 0; } - script = new ParticleScript(label); - con_debug << " " << inifile.name() << std::endl; - + ParticleScript *script = 0; std::string strval; + float pitch, yaw, roll = 0.0f; 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(); @@ -113,34 +130,85 @@ ParticleScript *ParticleScript::load(const std::string &label) if (inifile.got_key_string("type", strval)) { aux::to_label(strval); if (strval.compare("flame") == 0) { - script->particles_type = ParticleScript::Flame; + script->particlescript_type = ParticleScript::Flame; } else if (strval.compare("jet") == 0) { - script->particles_type = ParticleScript::Jet; + script->particlescript_type = ParticleScript::Jet; } else if (strval.compare("trail") == 0) { - script->particles_type = ParticleScript::Trail; + script->particlescript_type = ParticleScript::Trail; } else { inifile.unknown_value(); } continue; - } else if (inifile.got_key_string("texture", script->particles_texture)) { + + } 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->particles_speed)) { + } 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("offset", script->particles_offset)) { - math::clamp(script->particles_offset, 0.0f, 1.0f); + } else if (inifile.got_key_float("alpha", script->particlescript_alpha)) { continue; - } else if (inifile.got_key_float("alpha", script->particles_alpha)) { + } else if (inifile.got_key_float("radius", script->particlescript_radius)) { + script->particlescript_radius *= model::SCALE; continue; - } else if (inifile.got_key_float("radius", script->particles_radius)) { - script->particles_radius *= model::SCALE; + } else if (inifile.got_key_float("eject", script->particlescript_eject)) { continue; - } else if (inifile.got_key_float("eject", script->particles_eject)) { + } else if (inifile.got_key_float("timeout", script->particlescript_timeout)) { continue; - } else if (inifile.got_key_float("timeout", script->particles_timeout)) { + } else if (inifile.got_key_color("color", script->particlescript_color)) { continue; - } else if (inifile.got_key_color("color", script->particles_color)) { + + } 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.clear(); + script->particlescript_axis.change_pitch(-pitch); + script->particlescript_axis.change_direction(yaw); + script->particlescript_axis.change_roll(-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.unkown_key(); } @@ -149,67 +217,92 @@ ParticleScript *ParticleScript::load(const std::string &label) } 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; - particles_registry[script->label()] = script; - - return script; + return parent_script; } /* ---- class ParticleScript --------------------------------------- */ -ParticleScript::ParticleScript(const std::string label) : particles_label(label) +ParticleScript::ParticleScript(const std::string & label) : particlescript_label(label) { - particles_radius = 1.0f; - particles_alpha = 1.0f; + particlescript_radius = 1.0f; + particlescript_alpha = 1.0f; - particles_speed = 0.0f; - particles_timeout = 2.0f; - particles_eject = 0.25f; + particlescript_speed = 0.0f; + particlescript_timeout = 2.0f; + particlescript_eject = 0.25f; - particles_offset = 0.1f; + particlescript_offset = 0.1f; - particles_color.assign(1.0f, 1.0f); + particlescript_color.assign(1.0f, 1.0f); + + particlescript_next = 0; + + particlescript_cull = model::CullNone; } ParticleScript::~ParticleScript() { + if (particlescript_next) { + delete particlescript_next; + } } /* ---- class ParticleSystem --------------------------------------- */ -ParticleSystem::ParticleSystem(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) +ParticleSystem::ParticleSystem(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass) { + particlesystem_script = script; particlesystem_entity = entity; + particlesystem_modelclass = modelclass; + particlesystem_last_eject = 0; // timestamp of the last eject - - particlesystem_script = script; - particlesystem_texture = 0; particlesystem_cull = model::CullNone; - - particlesystem_modelclass = modelclass; - + particlesystem_texture = 0; + particlesystem_radius = 1.0f; + if (particlesystem_script) { particlesystem_texture = Textures::load("textures/" + particlesystem_script->texture()); - - // map entity radius overrules script value - if (modelclass->radius()) - particlesystem_radius = modelclass->radius(); - else - particlesystem_radius = particlesystem_script->radius(); - - color.assign(particlesystem_script->color()); + particlesystem_radius = particlesystem_script->radius(); + particlesystem_cull = particlesystem_script->cull(); + particlesystem_color.assign(particlesystem_script->color()); + particlesystem_axis.assign(particlesystem_script->axis()); } if (particlesystem_modelclass) { particlesystem_location.assign(modelclass->location()); + if (modelclass->entity()) { - color.assign(entity->color()); + particlesystem_color.assign(entity->color()); } if (modelclass->engine()) { - color.assign(entity->model()->enginecolor()); + // FIXME if not modelclass->has_color(); + particlesystem_color.assign(entity->model()->enginecolor()); } - particlesystem_axis.assign(modelclass->axis()); -// particlesystem_cull = particlesystem_modelclass->cull(); + particlesystem_axis.assign(modelclass->axis() * particlesystem_axis); + particlesystem_radius *= particlesystem_modelclass->scale(); } @@ -234,11 +327,11 @@ void ParticleSystem::clear() particlesystem_stream.clear(); } -void ParticleSystem::draw(float elapsed) +void ParticleSystem::draw(const float elapsed) { if (particlesystem_entity->type() == core::Entity::Controlable) { - core::EntityControlable *ec = static_cast(particlesystem_entity); - if (ec->state() == core::Entity::Docked) { + const core::EntityControlable *controlable = static_cast(particlesystem_entity); + if (controlable->state() == core::Entity::Docked) { if (particlesystem_stream.size()) clear(); return; @@ -266,13 +359,13 @@ void ParticleSystem::draw(float elapsed) ejector_active = true; } else { if (particlesystem_entity->type() == core::Entity::Dynamic) { - core::EntityDynamic *ed = static_cast(particlesystem_entity); + const core::EntityDynamic *ed = static_cast(particlesystem_entity); if (ed->speed()) { ejector_active = true; } } else if (particlesystem_entity->type() == core::Entity::Controlable) { - core::EntityControlable *ec = static_cast(particlesystem_entity); - if ((ec->thrust() > 0.0f) || (ec->state() == core::Entity::ImpulseInitiate) || (ec->state() == core::Entity::Impulse)) { + const core::EntityControlable *controlable = static_cast(particlesystem_entity); + if ((controlable->thrust() > 0.0f) || (controlable->state() == core::Entity::ImpulseInitiate) || (controlable->state() == core::Entity::Impulse)) { ejector_active = true; } } @@ -287,15 +380,15 @@ void ParticleSystem::draw(float elapsed) /* ---- class Jet -------------------------------------------------- */ -Jet::Jet(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : - ParticleSystem(script, entity, modelclass) +Jet::Jet(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Jet::~Jet() {} -void Jet::draw(float elapsed) +void Jet::draw(const float elapsed) { if (!particlesystem_script) return; @@ -329,8 +422,8 @@ void Jet::draw(float elapsed) f *= f; float radius = particlesystem_radius * f; - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, 1); gl::vertex(particle->location() + quad[0] * radius); @@ -348,15 +441,15 @@ void Jet::draw(float elapsed) } /* ---- class Spray ------------------------------------------------ */ -Spray::Spray(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : - ParticleSystem(script, entity, modelclass) +Spray::Spray(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Spray::~Spray() {} -void Spray::draw(float elapsed) +void Spray::draw(const float elapsed) { if (!particlesystem_script) return; @@ -390,8 +483,8 @@ void Spray::draw(float elapsed) f *= f; float radius = particlesystem_radius * f; - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, 1); gl::vertex(particle->location() + quad[0] * radius); @@ -411,15 +504,15 @@ void Spray::draw(float elapsed) /* ---- class Trail ------------------------------------------------ */ -Trail::Trail(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : - ParticleSystem(script, entity, modelclass) +Trail::Trail(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Trail::~Trail() {} -void Trail::draw(float elapsed) +void Trail::draw(const float elapsed) { if (!particlesystem_script) @@ -447,16 +540,16 @@ void Trail::draw(float elapsed) tp = (now - (*first)->time()) / particlesystem_script->timeout(); if (tp > 0) { - color.a = 0.0f; - gl::color(color); + particlesystem_color.a = 0.0f; + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex(ejector_location); glTexCoord2f(0, 0); gl::vertex(ejector_location); - color.a = fp; - gl::color(color); + particlesystem_color.a = fp; + gl::color(particlesystem_color); glTexCoord2f(0, 1); gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_radius * fp); @@ -480,16 +573,16 @@ void Trail::draw(float elapsed) } t = (now - (*next)->time()) / particlesystem_script->timeout(); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex((*first)->location() - (*first)->axis().left() * particlesystem_radius * fp); glTexCoord2f(0, 0); gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_radius * fp); - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, 1); gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_radius * f); @@ -510,15 +603,15 @@ void Trail::draw(float elapsed) /* ---- class Flame ------------------------------------------------ */ -Flame::Flame(ParticleScript *script, core::Entity *entity, model::Particles *modelclass) : - ParticleSystem(script, entity, modelclass) +Flame::Flame(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass) : + ParticleSystem(script, entity, modelclass) { } Flame::~Flame() {} -void Flame::draw(float elapsed) +void Flame::draw(const float elapsed) { if (!particlesystem_script) @@ -547,60 +640,60 @@ void Flame::draw(float elapsed) Stream::iterator next = first; if (tp > 0) { - color.a = 0; - gl::color(color); + particlesystem_color.a = 0; + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex(ejector_location); glTexCoord2f(0, 0); gl::vertex(ejector_location); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, tp); gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_radius * fp); glTexCoord2f(1, tp); gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_radius * fp); Stats::quads++; - color.a = 0; - gl::color(color); + particlesystem_color.a = 0; + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex(ejector_location); glTexCoord2f(0, 0); gl::vertex(ejector_location); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, tp); gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_radius * fp); glTexCoord2f(1, tp); gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_radius * fp); Stats::quads++; - color.a = 0; - gl::color(color); + particlesystem_color.a = 0; + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex(ejector_location); glTexCoord2f(0, 0); gl::vertex(ejector_location); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, tp); gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_radius * fp); glTexCoord2f(1, tp); gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_radius * fp); Stats::quads++; - color.a = 0; - gl::color(color); + particlesystem_color.a = 0; + gl::color(particlesystem_color); glTexCoord2f(1, 0); gl::vertex(ejector_location); glTexCoord2f(0, 0); gl::vertex(ejector_location); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, tp); gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_radius * fp); glTexCoord2f(1, tp); @@ -622,60 +715,60 @@ void Flame::draw(float elapsed) } t = (now - (*next)->time()) / particlesystem_script->timeout(); - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(1, tp); gl::vertex((*first)->location() + (*first)->axis().up() * particlesystem_radius * fp); glTexCoord2f(0, tp); gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_radius * fp); - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, t); gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_radius * f); glTexCoord2f(1, t); gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_radius * f); Stats::quads++; - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(1, tp); gl::vertex((*first)->location() - (*first)->axis().left() * particlesystem_radius * fp); glTexCoord2f(0, tp); gl::vertex((*first)->location() + (*first)->axis().up() * particlesystem_radius * fp); - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, t); gl::vertex((*next)->location() + (*next)->axis().up() * particlesystem_radius * f); glTexCoord2f(1, t); gl::vertex((*next)->location() - (*next)->axis().left() * particlesystem_radius * f); Stats::quads++; - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(1, tp); gl::vertex((*first)->location() - (*first)->axis().up() * particlesystem_radius * fp); glTexCoord2f(0, tp); gl::vertex((*first)->location() + (*first)->axis().left() * particlesystem_radius * fp); - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, t); gl::vertex((*next)->location() + (*next)->axis().left() * particlesystem_radius * f); glTexCoord2f(1, t); gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_radius * f); Stats::quads++; - color.a = fp * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = fp * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(1, tp); gl::vertex((*first)->location() - (*first)->axis().left() * particlesystem_radius * fp); glTexCoord2f(0, tp); gl::vertex((*first)->location() - (*first)->axis().up() * particlesystem_radius * fp); - color.a = f * particlesystem_script->alpha(); - gl::color(color); + particlesystem_color.a = f * particlesystem_script->alpha(); + gl::color(particlesystem_color); glTexCoord2f(0, t); gl::vertex((*next)->location() - (*next)->axis().up() * particlesystem_radius * f); glTexCoord2f(1, t); diff --git a/src/render/particles.h b/src/render/particles.h index 5b159da..909d027 100644 --- a/src/render/particles.h +++ b/src/render/particles.h @@ -57,45 +57,58 @@ public: enum Type {Jet = 0, Trail = 1, Flame = 2, Spray = 3 }; inline const Type type() const { - return particles_type; + return particlescript_type; } inline const std::string &label() const { - return particles_label; + return particlescript_label; } inline const std::string &texture() const { - return particles_texture; + return particlescript_texture; } inline const math::Color &color() const { - return particles_color; + return particlescript_color; + } + + /// axis transformation relative to the ejector + inline const math::Axis &axis() const { + return particlescript_axis; } inline float radius() const { - return particles_radius; + return particlescript_radius; } inline float timeout() const { - return particles_timeout; + return particlescript_timeout; } inline float eject() const { - return particles_eject; + return particlescript_eject; } inline float speed() const { - return particles_speed; + return particlescript_speed; } inline float alpha() const { - return particles_alpha; + return particlescript_alpha; } inline float offset() const { - return particles_offset; + 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(); @@ -104,24 +117,29 @@ public: private: static ParticleScript *find(const std::string &label); - ParticleScript(const std::string label); + ParticleScript(const std::string & label); ~ParticleScript(); - std::string particles_label; - std::string particles_texture; - Type particles_type; - math::Color particles_color; - - float particles_radius; - float particles_timeout; - float particles_eject; - float particles_speed; - float particles_alpha; - float particles_offset; + std::string particlescript_label; + std::string particlescript_texture; + Type particlescript_type; + math::Color particlescript_color; + math::Axis particlescript_axis; + + 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 particles_registry; + static Registry particlescript_registry; }; /* ---- class ParticleSystem --------------------------------------- */ @@ -130,7 +148,7 @@ private: class ParticleSystem { public: - ParticleSystem(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + ParticleSystem(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass); virtual ~ParticleSystem(); /// index of the texture to use @@ -151,8 +169,13 @@ public: inline const model::Cull cull() const { return particlesystem_cull; } + + /// color of the particles + inline const math::Color & color() const { + return particlesystem_color; + } - virtual void draw(float elapsed); + virtual void draw(const float elapsed); void set_timeout(float timeout); @@ -162,33 +185,30 @@ public: void clear(); protected: - core::Entity *particlesystem_entity; - typedef std::deque Stream; inline Stream & stream() { return particlesystem_stream; } - - size_t particlesystem_texture; - + Stream particlesystem_stream; + math::Axis particlesystem_axis; math::Vector3f particlesystem_location; - - float particlesystem_last_eject; - - ParticleScript *particlesystem_script; - - Stream particlesystem_stream; - math::Vector3f ejector_location; + math::Color particlesystem_color; + model::Cull particlesystem_cull; + + bool ejector_active; + float particlesystem_last_eject; float particlesystem_radius; float now; - math::Color color; - model::Particles *particlesystem_modelclass; - model::Cull particlesystem_cull; + size_t particlesystem_texture; + + const model::Particles *particlesystem_modelclass; + const ParticleScript *particlesystem_script; + const core::Entity *particlesystem_entity; }; /* ---- class Flame ------------------------------------------------ */ @@ -197,10 +217,10 @@ protected: class Flame : public ParticleSystem { public: - Flame(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + Flame(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass); virtual ~Flame(); - virtual void draw(float elapsed); + virtual void draw(const float elapsed); }; /* ---- class Jet -------------------------------------------------- */ @@ -209,10 +229,10 @@ public: class Jet : public ParticleSystem { public: - Jet(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + Jet(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass); virtual ~Jet(); - virtual void draw(float elapsed); + virtual void draw(const float elapsed); }; /* ---- class Spray ----------------------------------------------- */ @@ -221,10 +241,10 @@ public: class Spray : public ParticleSystem { public: - Spray(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + Spray(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass); virtual ~Spray(); - virtual void draw(float elapsed); + virtual void draw(const float elapsed); }; /* ---- class Trail ------------------------------------------------ */ @@ -233,7 +253,7 @@ public: class Trail : public ParticleSystem { public: - Trail(ParticleScript *script, core::Entity *entity, model::Particles *modelclass); + Trail(const ParticleScript *script, const core::Entity *entity, const model::Particles *modelclass); virtual ~Trail(); virtual void draw(float elapsed); diff --git a/src/render/renderext.cc b/src/render/renderext.cc index 5f24e85..049b3de 100644 --- a/src/render/renderext.cc +++ b/src/render/renderext.cc @@ -54,15 +54,14 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re flare->set_texture(Textures::load(flarename.str())); } - for (model::Model::ParticleSystems::iterator pit = model->particles().begin(); pit != model->particles().end(); pit++) { - model::Particles *particlesystem = (*pit); + for (model::Model::ParticleSystems::const_iterator pit = model->particles().begin(); pit != model->particles().end(); pit++) { + // model attachment location tag + const model::Particles *particlesystem = (*pit); - // TODO multiple particlesystems per script - // load particle systems - ParticleScript *script = ParticleScript::load(particlesystem->script()); - if (script) { - if (script->type() == render::ParticleScript::Trail) { + 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) { @@ -75,6 +74,7 @@ RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Re Flame *flame = new Flame(script, entity, particlesystem); state_particles.push_back(flame); } + script = script->next(); } } -- cgit v1.2.3