From a861c2729a356173059177a0b800de2b31c9b49c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 25 Feb 2010 18:03:21 +0000 Subject: [PATCH] Add an overlay to display aspects of tracks --- icons/flex.mesh | 19 ++++ icons/sensor.mesh | 13 +++ icons/turnout.mesh | 20 ++++ source/3d/overlay.cpp | 202 +++++++++++++++++++++++++++++++++++ source/3d/overlay.h | 60 +++++++++++ source/3d/track.cpp | 8 +- source/3d/track.h | 4 +- source/designer/designer.cpp | 46 ++++---- source/designer/designer.h | 7 +- 9 files changed, 349 insertions(+), 30 deletions(-) create mode 100644 icons/flex.mesh create mode 100644 icons/sensor.mesh create mode 100644 icons/turnout.mesh create mode 100644 source/3d/overlay.cpp create mode 100644 source/3d/overlay.h diff --git a/icons/flex.mesh b/icons/flex.mesh new file mode 100644 index 0000000..2ad62b1 --- /dev/null +++ b/icons/flex.mesh @@ -0,0 +1,19 @@ +vertices VERTEX2 +{ + vertex2 0.0 0.45; + vertex2 0.4 0.45; + vertex2 0.0 0.65; + vertex2 0.4 0.65; + vertex2 1.0 0.35; + vertex2 0.6 0.35; + vertex2 1.0 0.55; + vertex2 0.6 0.55; +}; +batch LINES +{ + indices 0 1; + indices 2 3; + indices 4 5; + indices 6 7; +}; + diff --git a/icons/sensor.mesh b/icons/sensor.mesh new file mode 100644 index 0000000..cea93f2 --- /dev/null +++ b/icons/sensor.mesh @@ -0,0 +1,13 @@ +vertices VERTEX2 +{ + vertex2 0.0 0.45; + vertex2 0.3 0.45; + vertex2 1.0 0.45; + vertex2 0.7 0.45; + vertex2 0.3 0.65; +}; +batch LINES +{ + indices 0 1; + indices 2 3 3 4; +}; diff --git a/icons/turnout.mesh b/icons/turnout.mesh new file mode 100644 index 0000000..6eda269 --- /dev/null +++ b/icons/turnout.mesh @@ -0,0 +1,20 @@ +vertices VERTEX2 +{ + vertex2 0.0 0.3; + vertex2 1.0 0.3; + vertex2 0.34730 0.33038; + vertex2 0.68404 0.42061; + vertex2 1.0 0.56795; + vertex2 0.0 0.5; + vertex2 1.0 0.5; + vertex2 0.31257 0.52735; + vertex2 0.61564 0.60855; + vertex2 0.9 0.74115; +}; +batch LINES +{ + indices 0 1; + indices 0 2 2 3 3 4; + indices 5 6; + indices 5 7 7 8 8 9; +}; diff --git a/source/3d/overlay.cpp b/source/3d/overlay.cpp new file mode 100644 index 0000000..5f07ac8 --- /dev/null +++ b/source/3d/overlay.cpp @@ -0,0 +1,202 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include +#include +#include +#include +#include +#include "overlay.h" +#include "track.h" +#include "tracktype.h" + +using namespace std; +using namespace Msp; + +namespace Marklin { + +Overlay3D::Overlay3D(const Graphics::Window &w, const GL::Camera &c, const GL::Font &f): + window(w), + camera(c), + font(f) +{ } + +Overlay3D::~Overlay3D() +{ + for(map::iterator i=graphics.begin(); i!=graphics.end(); ++i) + delete i->second; +} + +void Overlay3D::set_label(const Track3D &track, const string &label) +{ + get_icon(track).label = label; + update_icon(get_icon(track)); +} + +void Overlay3D::add_graphic(const Track3D &track, const string &grf_name) +{ + const GL::Mesh *grf = get_graphic(grf_name); + if(!grf) + return; + + Icon &icon = get_icon(track); + if(find(icon.graphics.begin(), icon.graphics.end(), grf)==icon.graphics.end()) + icon.graphics.push_back(grf); + + update_icon(icon); +} + +void Overlay3D::remove_graphic(const Track3D &track, const string &grf_name) +{ + const GL::Mesh *grf = get_graphic(grf_name); + Icon &icon = get_icon(track); + icon.graphics.erase(remove(icon.graphics.begin(), icon.graphics.end(), grf), icon.graphics.end()); + + update_icon(icon); +} + +void Overlay3D::clear_graphics(const Track3D &track) +{ + get_icon(track).graphics.clear(); + update_icon(get_icon(track)); +} + +void Overlay3D::clear(const Track3D &track) +{ + map::iterator i = icons.find(&track); + if(i!=icons.end()) + { + delete i->second; + icons.erase(i); + } +} + +void Overlay3D::render(const GL::Tag &tag) const +{ + if(tag==0) + { + GL::matrix_mode(GL::PROJECTION); + GL::push_matrix(); + GL::load_identity(); + GL::scale(2.0/window.get_width(), 2.0/window.get_height(), 1.0); + GL::matrix_mode(GL::MODELVIEW); + GL::push_matrix(); + GL::load_identity(); + + glLineWidth(1); + + int size = int(font.get_default_size()+0.5); + float spacing = round(size*1.1)/size; + float baseline = round((0.5-font.get_ascent()*0.5-font.get_descent()*0.5)*size)/size; + + for(map::const_iterator i=icons.begin(); i!=icons.end(); ++i) + { + const Icon &icon = *i->second; + + const Point &pos = i->first->get_track().get_position(); + Point minp; + Point maxp; + i->first->get_type().get_bounds(0, minp, maxp); + float rot = i->first->get_track().get_rotation(); + float c = cos(rot); + float s = sin(rot); + + GL::Vector3 p((minp.x+maxp.x)/2, (minp.y+maxp.y)/2, 0); + p = GL::Vector3(pos.x+c*p.x-s*p.y, pos.y+s*p.x+c*p.y, pos.z+0.02); + p = camera.project(p); + + GL::PushMatrix push_mat; + p.x = int(p.x*0.5*window.get_width()-icon.width*size/2); + p.y = int(p.y*0.5*window.get_height()); + GL::translate(p.x, p.y, p.z); + GL::scale_uniform(size); + + icon.background.draw(); + + glColor3f(0.0, 1.0, 0.0); + for(vector::const_iterator j=icon.graphics.begin(); j!=icon.graphics.end(); ++j) + { + (*j)->draw(); + GL::translate(spacing, 0, 0); + } + + GL::translate(0, baseline, 0); + font.draw_string(icon.label); + GL::Texture::unbind(); + } + + GL::matrix_mode(GL::PROJECTION); + GL::pop_matrix(); + GL::matrix_mode(GL::MODELVIEW); + GL::pop_matrix(); + } +} + +Overlay3D::Icon &Overlay3D::get_icon(const Track3D &track) +{ + Icon *&icon = icons[&track]; + if(!icon) + icon = new Icon; + + return *icon; +} + +const GL::Mesh *Overlay3D::get_graphic(const string &name) +{ + GL::Mesh *&grf = graphics[name]; + if(!grf) + { + grf = new GL::Mesh; + try + { + DataFile::load(*grf, (FS::Path("icons")/(name+".mesh")).str()); + } + catch(const Exception &e) + { + IO::print("Error loading overlay graphic '%s': %s\n", name, e.what()); + delete grf; + grf = 0; + } + } + + return grf; +} + +void Overlay3D::update_icon(Icon &icon) +{ + icon.background.clear(); + + icon.width = max(icon.graphics.size()*1.1+font.get_string_width(icon.label), 1.0); + + GL::MeshBuilder bld(icon.background); + bld.color(0.2f, 0.2f, 0.2f, 0.7f); + + bld.begin(GL::TRIANGLE_FAN); + bld.vertex(0.4, 0.5); + bld.vertex(icon.width-0.4, 0.5); + bld.vertex(icon.width-0.4, 1.2); + for(int i=4; i<=12; ++i) + bld.vertex(0.4+cos(i*M_PI/8)*0.7, 0.5+sin(i*M_PI/8)*0.7); + bld.end(); + + bld.begin(GL::TRIANGLE_FAN); + bld.vertex(icon.width-0.4, 0.5); + bld.vertex(0.4, 0.5); + bld.vertex(0.4, -0.2); + for(int i=-4; i<=4; ++i) + bld.vertex(icon.width-0.4+cos(i*M_PI/8)*0.7, 0.5+sin(i*M_PI/8)*0.7); + bld.end(); +} + + +Overlay3D::Icon::Icon(): + width(1.0), + background((GL::COLOR4_UBYTE, GL::VERTEX2)) +{ } + +} // namespace Marklin diff --git a/source/3d/overlay.h b/source/3d/overlay.h new file mode 100644 index 0000000..0a9a022 --- /dev/null +++ b/source/3d/overlay.h @@ -0,0 +1,60 @@ +/* $Id$ + +This file is part of the MSP Märklin suite +Copyright © 2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#ifndef MARKLIN3D_OVERLAY_H_ +#define MARKLIN3D_OVERLAY_H_ + +#include +#include +#include +#include +#include + +namespace Marklin { + +class Track3D; + +class Overlay3D: public Msp::GL::Renderable +{ +private: + struct Icon + { + std::vector graphics; + std::string label; + float width; + Msp::GL::Mesh background; + + Icon(); + }; + + const Msp::Graphics::Window &window; + const Msp::GL::Camera &camera; + const Msp::GL::Font &font; + std::map graphics; + std::map icons; + +public: + Overlay3D(const Msp::Graphics::Window &, const Msp::GL::Camera &, const Msp::GL::Font &); + ~Overlay3D(); + + void set_label(const Track3D &, const std::string &); + void add_graphic(const Track3D &, const std::string &); + void remove_graphic(const Track3D &, const std::string &); + void clear_graphics(const Track3D &); + void clear(const Track3D &); + + virtual void render(const Msp::GL::Tag &) const; + +private: + Icon &get_icon(const Track3D &); + const Msp::GL::Mesh *get_graphic(const std::string &); + void update_icon(Icon &); +}; + +} // namespace Marklin + +#endif diff --git a/source/3d/track.cpp b/source/3d/track.cpp index 3285796..3241852 100644 --- a/source/3d/track.cpp +++ b/source/3d/track.cpp @@ -22,8 +22,7 @@ namespace Marklin { Track3D::Track3D(Layout3D &l, Track &t): layout(l), track(t), - type(layout.get_catalogue().get_track(track.get_type())), - color(1, 1, 1) + type(layout.get_catalogue().get_track(track.get_type())) { layout.add_track(*this); layout.get_scene().add(*this); @@ -42,11 +41,6 @@ Track3D::~Track3D() delete *i; } -void Track3D::set_color(const Msp::GL::Color &c) -{ - color = c; -} - void Track3D::get_bounds(float angle, Point &minp, Point &maxp) const { type.get_bounds(angle-track.get_rotation(), minp, maxp); diff --git a/source/3d/track.h b/source/3d/track.h index cf994dd..fb662bf 100644 --- a/source/3d/track.h +++ b/source/3d/track.h @@ -29,7 +29,6 @@ private: Track &track; const TrackType3D &type; std::vector endpoints; - Msp::GL::Color color; public: Track3D(Layout3D &, Track &); @@ -37,7 +36,8 @@ public: Layout3D &get_layout() const { return layout; } Track &get_track() const { return track; } - void set_color(const Msp::GL::Color &); + const TrackType3D &get_type() const { return type; } + void set_color(const Msp::GL::Color &) { } void get_bounds(float, Point &, Point &) const; virtual void render(const Msp::GL::Tag &) const; diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index f79ef7a..2528909 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -74,9 +74,6 @@ Designer::Designer(int argc, char **argv): { filename = argv[1]; DataFile::load(*layout, argv[1]); - const list <racks = layout_3d->get_tracks(); - for(list::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) - update_track_color(**i); if(!layout->get_base().empty()) { @@ -119,6 +116,12 @@ Designer::Designer(int argc, char **argv): root->add(*toolbar); toolbar->set_position(0, window.get_height()-toolbar->get_geometry().h); toolbar->set_visible(true); + + overlay = new Overlay3D(window, camera, ui_res.get_default_font()); + + const list &tracks = layout_3d->get_tracks(); + for(list::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + update_track_icon(**i); } Designer::~Designer() @@ -309,7 +312,7 @@ void Designer::key_press(unsigned code, unsigned mod, wchar_t) if(*j!=*i) (*i)->snap_to(**j, true); - update_track_color(layout_3d->get_track(**i)); + update_track_icon(layout_3d->get_track(**i)); } } else if(key==Msp::Input::KEY_F) @@ -465,6 +468,9 @@ void Designer::render() pipeline->render_all(); layout_3d->get_endpoint_scene().render(); GL::enable(GL_CULL_FACE); + GL::disable(GL::DEPTH_TEST); + overlay->render(0); + GL::enable(GL::DEPTH_TEST); /*if(cur_route) { glColor4f(0.5, 0.8, 1.0, 1.0); @@ -514,21 +520,23 @@ Track3D *Designer::pick_track(int x, int y) return l->pick_track(xx, yy, size); } -void Designer::update_track_color(Track3D &track) +void Designer::update_track_icon(Track3D &track) { - if(track.get_track().get_sensor_id()) + overlay->clear(track); + + if(track.get_track().get_flex()) + overlay->add_graphic(track, "flex"); + + if(unsigned sid = track.get_track().get_sensor_id()) { - if(track.get_track().get_flex()) - track.set_color(GL::Color(1, 0.6, 1)); - else - track.set_color(GL::Color(0.7, 0.7, 1)); + overlay->add_graphic(track, "sensor"); + overlay->set_label(track, lexical_cast(sid)); + } + else if(unsigned tid = track.get_track().get_turnout_id()) + { + overlay->add_graphic(track, "turnout"); + overlay->set_label(track, lexical_cast(tid)); } - else if(track.get_track().get_turnout_id()) - track.set_color(GL::Color(0.8, 1, 0.8)); - else if(track.get_track().get_flex()) - track.set_color(GL::Color(1, 0.8, 0.8)); - else - track.set_color(GL::Color(1, 1, 1)); } void Designer::manipulation_status(const string &status) @@ -586,7 +594,7 @@ void Designer::turnout_id_accept() unsigned id = lexical_cast(input->get_text()); track->set_turnout_id(id); - update_track_color(layout_3d->get_track(*track)); + update_track_icon(layout_3d->get_track(*track)); input_dismiss(); } @@ -599,7 +607,7 @@ void Designer::sensor_id_accept() { (*i)->set_sensor_id(id); - update_track_color(layout_3d->get_track(**i)); + update_track_icon(layout_3d->get_track(**i)); } input_dismiss(); diff --git a/source/designer/designer.h b/source/designer/designer.h index a72316e..c4591ab 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -24,6 +24,7 @@ Distributed under the GPL #include "libmarklin/catalogue.h" #include "libmarklin/layout.h" #include "3d/layout.h" +#include "3d/overlay.h" #include "3d/track.h" #include "cameracontroller.h" #include "manipulator.h" @@ -58,6 +59,7 @@ private: std::string filename; Marklin::Layout *layout; Marklin::Layout3D *layout_3d; + Marklin::Overlay3D *overlay; Msp::GL::Object *base_object; Marklin::Route *cur_route; Msp::GL::Pipeline *pipeline; @@ -90,6 +92,7 @@ public: Marklin::Layout *get_layout() { return layout; } Marklin::Layout3D *get_layout_3d() { return layout_3d; } + const Msp::GL::Camera &get_camera() const { return camera; } const Msp::GLtk::Resources &get_ui_resources() const { return ui_res; } Msp::GLtk::Root &get_root() const { return *root; } void edit_route(Marklin::Route &); @@ -106,7 +109,7 @@ private: void apply_camera(); void render(); Marklin::Track3D *pick_track(int, int); - void update_track_color(Marklin::Track3D &); + void update_track_icon(Marklin::Track3D &); void manipulation_status(const std::string &); void manipulation_done(bool); void measure_changed(); -- 2.43.0