]> git.tdb.fi Git - r2c2.git/commitdiff
Add an overlay to display aspects of tracks
authorMikko Rasa <tdb@tdb.fi>
Thu, 25 Feb 2010 18:03:21 +0000 (18:03 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 25 Feb 2010 18:03:21 +0000 (18:03 +0000)
icons/flex.mesh [new file with mode: 0644]
icons/sensor.mesh [new file with mode: 0644]
icons/turnout.mesh [new file with mode: 0644]
source/3d/overlay.cpp [new file with mode: 0644]
source/3d/overlay.h [new file with mode: 0644]
source/3d/track.cpp
source/3d/track.h
source/designer/designer.cpp
source/designer/designer.h

diff --git a/icons/flex.mesh b/icons/flex.mesh
new file mode 100644 (file)
index 0000000..2ad62b1
--- /dev/null
@@ -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 (file)
index 0000000..cea93f2
--- /dev/null
@@ -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 (file)
index 0000000..6eda269
--- /dev/null
@@ -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 (file)
index 0000000..5f07ac8
--- /dev/null
@@ -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 <algorithm>
+#include <cmath>
+#include <msp/fs/path.h>
+#include <msp/gl/matrix.h>
+#include <msp/gl/texture.h>
+#include <msp/io/print.h>
+#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<string, GL::Mesh *>::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<const Track3D *, Icon *>::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 Track3D *, Icon *>::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 GL::Mesh *>::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 (file)
index 0000000..0a9a022
--- /dev/null
@@ -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 <msp/gbase/window.h>
+#include <msp/gl/camera.h>
+#include <msp/gl/font.h>
+#include <msp/gl/mesh.h>
+#include <msp/gl/renderable.h>
+
+namespace Marklin {
+
+class Track3D;
+
+class Overlay3D: public Msp::GL::Renderable
+{
+private:       
+       struct Icon
+       {
+               std::vector<const Msp::GL::Mesh *> 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<std::string, Msp::GL::Mesh *> graphics;
+       std::map<const Track3D *, Icon *> 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
index 32857961d9ecc54134bb4f352c7136783f3098a6..3241852f1ed32c606ad8c0dd07ea6a97e34684db 100644 (file)
@@ -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);
index cf994dd4526fb38a7b902040b130b1567712051a..fb662bf890cfd8fb1f90923bfdcdcda06869fe66 100644 (file)
@@ -29,7 +29,6 @@ private:
        Track &track;
        const TrackType3D &type;
        std::vector<Endpoint3D *> 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;
index f79ef7a9ae8daa4bfdb94a901ba3b6d170412b9c..25289093538f3a2722da62a3991a71aa5641a1a5 100644 (file)
@@ -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<Track3D *> &ltracks = layout_3d->get_tracks();
-               for(list<Track3D *>::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<Track3D *> &tracks = layout_3d->get_tracks();
+       for(list<Track3D *>::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<unsigned>(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();
index a72316e128044aea2e182190a59008f60712950c..c4591abf5f1260991044d2b1839dd11448f161dd 100644 (file)
@@ -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();