]> git.tdb.fi Git - r2c2.git/commitdiff
Use raycasting instead of OpenGL selection mode to pick tracks
authorMikko Rasa <tdb@tdb.fi>
Thu, 10 Mar 2011 10:20:57 +0000 (10:20 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 10 Mar 2011 10:20:57 +0000 (10:20 +0000)
16 files changed:
source/3d/layout.cpp
source/3d/layout.h
source/3d/track.cpp
source/3d/track.h
source/designer/designer.cpp
source/designer/designer.h
source/engineer/engineer.cpp
source/engineer/engineer.h
source/libr2c2/layout.cpp
source/libr2c2/layout.h
source/libr2c2/track.cpp
source/libr2c2/track.h
source/libr2c2/trackpart.cpp
source/libr2c2/trackpart.h
source/libr2c2/tracktype.cpp
source/libr2c2/tracktype.h

index 5f015766f6367ad53ae108d379cad9ab0c94861c..0a9ee2d2b4c5362888c7d9996ef965e91f2da3a5 100644 (file)
@@ -1,18 +1,10 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
-#include <algorithm>
-#include <limits>
-#include <msp/gl/clip.h>
-#include <msp/gl/matrix.h>
-#include <msp/gl/rendermode.h>
-#include <msp/gl/select.h>
-#include <msp/gl/texture.h>
-#include <msp/datafile/parser.h>
 #include "layout.h"
 #include "track.h"
 #include "vehicle.h"
@@ -66,42 +58,6 @@ Track3D &Layout3D::get_track(Track &t) const
        return *i->second;
 }
 
-Track3D *Layout3D::pick_track(float x, float y, float size) const
-{
-       vector<GL::SelectRecord> select_buf;
-       GL::select_buffer(select_buf);
-       GL::render_mode(GL::SELECT);
-
-       {
-               GL::PushMatrix push_mat;
-               GL::load_identity();
-
-               GL::ClipPlane(1, 0, x-size, 0).apply_to(0);
-               GL::ClipPlane(-1, 0, -x-size, 0).apply_to(1);
-               GL::ClipPlane(0, 1, y-size, 0).apply_to(2);
-               GL::ClipPlane(0, -1, -y-size, 0).apply_to(3);
-       }
-
-       scene.render(0);
-
-       GL::ClipPlane::disable(0);
-       GL::ClipPlane::disable(1);
-       GL::ClipPlane::disable(2);
-       GL::ClipPlane::disable(3);
-
-       GL::render_mode(GL::RENDER);
-       Track3D *track = 0;
-       unsigned track_depth = numeric_limits<unsigned>::max();
-       for(vector<GL::SelectRecord>::iterator i=select_buf.begin(); i!=select_buf.end(); ++i)
-               if(i->min_depth<track_depth && !i->names.empty())
-               {
-                       track = reinterpret_cast<Track3D *>(i->names.back());
-                       track_depth = i->min_depth;
-               }
-
-       return track;
-}
-
 void Layout3D::add_vehicle(Vehicle3D &v)
 {
        if(vehicles.count(&v.get_vehicle()))
index d1ec7c49f457b472b52adc1359f776ac8a156423..bb9d4277d775babf066c8e3b3ccecf64eaa414ec 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -44,7 +44,6 @@ public:
        void remove_track(Track3D &);
        const TrackMap &get_tracks() const { return tracks; }
        Track3D &get_track(Track &) const;
-       Track3D *pick_track(float, float, float) const;
 
        void add_vehicle(Vehicle3D &);
        void remove_vehicle(Vehicle3D &);
index 8b36b194220c0c3175da4c322e9b846e5112b656..cd17b811a7ea56ba484ee50067c0d513b8f44522 100644 (file)
@@ -7,7 +7,6 @@ Distributed under the GPL
 
 #include <cmath>
 #include <msp/gl/matrix.h>
-#include <msp/gl/misc.h>
 #include <msp/gl/renderer.h>
 #include "libr2c2/tracktype.h"
 #include "endpoint.h"
@@ -107,12 +106,6 @@ GL::Matrix Track3D::get_matrix() const
 void Track3D::setup_render(Msp::GL::Renderer &renderer, const GL::Tag &) const
 {
        renderer.matrix_stack() *= get_matrix();
-       glPushName(reinterpret_cast<unsigned>(this));
-}
-
-void Track3D::finish_render(Msp::GL::Renderer &, const GL::Tag &) const
-{
-       glPopName();
 }
 
 void Track3D::link_changed(unsigned i, Track *trk)
index d0a90f424ee2aed04b73ea0d095a8623f4718e5e..66382bce3794cc91fddcb895e7bbe40072b34ffc 100644 (file)
@@ -47,7 +47,6 @@ public:
 
        Msp::GL::Matrix get_matrix() const;
        virtual void setup_render(Msp::GL::Renderer &, const Msp::GL::Tag &) const;
-       virtual void finish_render(Msp::GL::Renderer &, const Msp::GL::Tag &) const;
 private:
        void link_changed(unsigned, Track *);
 };
index 3b43efd11ff5226b64cfa0cc9478a72adca90fde..a64c8eb931c9a2d37cf970533bd0627f0a8e65f2 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -468,10 +468,10 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned mod)
        {
                if(btn==1)
                {
-                       Track3D *ctrack = pick_track(x, y);
+                       Track *ctrack = pick_track(x, y);
                        if(ctrack)
                        {
-                               Track *track = new Track(*layout, ctrack->get_track().get_type());
+                               Track *track = new Track(*layout, ctrack->get_type());
                                track->set_position(ground);
 
                                selection.clear();
@@ -487,12 +487,12 @@ void Designer::button_press(int x, int y, unsigned btn, unsigned mod)
        {
                if(btn==1)
                {
-                       Track3D *track = pick_track(x, y);
+                       Track *track = pick_track(x, y);
                        if(track)
                        {
                                if(!(mod&Input::MOD_SHIFT))
                                        selection.clear();
-                               selection.toggle_track(&track->get_track());
+                               selection.toggle_track(track);
                        }
                }
        }
@@ -573,19 +573,18 @@ void Designer::track_removed(Track &trk)
                new_tracks.erase(i);
 }
 
-Track3D *Designer::pick_track(int x, int y)
+Track *Designer::pick_track(int x, int y)
 {
-       Layout3D *l = layout_3d;
+       float xx = x*2.0/window.get_width()-1.0;
+       float yy = y*2.0/window.get_height()-1.0;
        if(mode==CATALOGUE)
-               l = cat_layout_3d;
-
-       float xx = ((float(x)-window.get_width()/2)/window.get_height())*0.82843;
-       float yy = (float(y)/window.get_height()-0.5)*0.82843;
-       float size = 4.0/window.get_height()*0.82843;
-
-       apply_camera();
-
-       return l->pick_track(xx, yy, size);
+               return catalogue.get_layout().pick_track(Vector(0, 0, 1), Vector(xx*0.05523, yy*0.042421, -0.1));
+       else
+       {
+               const GL::Vector3 &cpos = camera.get_position();
+               GL::Vector4 cray = camera.unproject(GL::Vector4(xx, yy, 0, 0));
+               return layout->pick_track(Vector(cpos.x, cpos.y, cpos.z), Vector(cray.x, cray.y, cray.z));
+       }
 }
 
 void Designer::update_track_icon(Track3D &track)
@@ -683,17 +682,16 @@ void Designer::svg_export_accept(const string &text)
 
 string Designer::tooltip(int x, int y)
 {
-       if(Track3D *t3d = pick_track(x, y))
+       if(Track *track = pick_track(x, y))
        {
-               const Track &track = t3d->get_track();
-               const TrackType &ttype = track.get_type();
+               const TrackType &ttype = track->get_type();
                string info = format("%d %s", ttype.get_article_number(), ttype.get_description());
-               if(mode!=CATALOGUE && abs(track.get_slope())>1e-4)
-                       info += format(" (slope %.1f%%)", abs(track.get_slope()/ttype.get_total_length()*100));
-               if(track.get_turnout_id())
-                       info += format(" (turnout %d)", track.get_turnout_id());
-               else if(track.get_sensor_id())
-                       info += format(" (sensor %d)", track.get_sensor_id());
+               if(mode!=CATALOGUE && abs(track->get_slope())>1e-4)
+                       info += format(" (slope %.1f%%)", abs(track->get_slope()/ttype.get_total_length()*100));
+               if(track->get_turnout_id())
+                       info += format(" (turnout %d)", track->get_turnout_id());
+               else if(track->get_sensor_id())
+                       info += format(" (sensor %d)", track->get_sensor_id());
 
                return info;
        }
index da6cb0e4b4ba76fd33bba808d119149e498e96f5..49d4283da2bbf9f026362c875f10239b35d8dd05 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -122,7 +122,7 @@ private:
        void render();
        void track_added(R2C2::Track &);
        void track_removed(R2C2::Track &);
-       R2C2::Track3D *pick_track(int, int);
+       R2C2::Track *pick_track(int, int);
        void update_track_icon(R2C2::Track3D &);
        void selection_changed();
        void manipulation_status(const std::string &);
index fad61693aef66161e1822dc18f7e8a209f7d33af..32b23ab900aa16ea6ab7009081d911ec8801a73a 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -213,15 +213,15 @@ void Engineer::tick()
 
                if(picking)
                {
-                       Track3D *track = pick_track(pointer_x, window.get_height()-pointer_y-1);
-                       if(track && &track->get_track()!=picking_track)
+                       Track *track = pick_track(pointer_x, window.get_height()-pointer_y-1);
+                       if(track && track!=picking_track)
                        {
-                               picking_track = &track->get_track();
+                               picking_track = track;
                                if(picking_entry>=0)
                                        picking_entry = 0;
 
                                delete picking_path;
-                               picking_path = new Path3D(*track);
+                               picking_path = new Path3D(layout_3d.get_track(*track));
                                if(picking_entry>=0)
                                        picking_path->set_mask(picking_track->get_type().get_endpoint(picking_entry).paths);
                                else
@@ -280,19 +280,18 @@ void Engineer::button_press(int x, int y, unsigned btn, unsigned)
        }
        else
        {
-               Track3D *t3d = pick_track(x, window.get_height()-y-1);
-               if(t3d)
+               Track *track = pick_track(x, window.get_height()-y-1);
+               if(track)
                {
-                       Track &track = t3d->get_track();
-                       if(track.get_turnout_id())
+                       if(track->get_turnout_id())
                        {
-                               Block &block = track.get_block();
+                               Block &block = track->get_block();
                                if(block.get_train() && !block.get_train()->free_block(block))
                                        set_status("Turnout is busy");
                                else
                                {
-                                       unsigned paths = track.get_type().get_paths();
-                                       unsigned i = track.get_active_path()+1;
+                                       unsigned paths = track->get_type().get_paths();
+                                       unsigned i = track->get_active_path()+1;
                                        while(!(paths&(1<<i)))
                                        {
                                                if(!(paths>>i))
@@ -300,11 +299,11 @@ void Engineer::button_press(int x, int y, unsigned btn, unsigned)
                                                else
                                                        ++i;
                                        }
-                                       track.set_active_path(i);
-                                       set_status(format("Turnout %d", track.get_turnout_id()));
+                                       track->set_active_path(i);
+                                       set_status(format("Turnout %d", track->get_turnout_id()));
                                }
                        }
-                       if(unsigned sid = track.get_sensor_id())
+                       if(unsigned sid = track->get_sensor_id())
                        {
                                if(options.simulate)
                                        layout.get_driver().set_sensor(sid, !layout.get_driver().get_sensor(sid));
@@ -418,16 +417,14 @@ void Engineer::block_reserved(const Block &block, const Train *)
        reset_block_color(block);
 }
 
-Track3D *Engineer::pick_track(int x, int y)
+Track *Engineer::pick_track(int x, int y)
 {
-       float view_height = tan(camera.get_field_of_view()/2)*2;
-       float xx = ((float(x)-window.get_width()/2)/window.get_height())*view_height;
-       float yy = (float(y)/window.get_height()-0.5)*view_height;
-       float size = 4.0/window.get_height()*view_height;
-
-       camera.apply();
+       const GL::Vector3 &start = camera.get_position();
+       float xx = x*2.0/window.get_width()-1.0;
+       float yy = y*2.0/window.get_height()-1.0;
+       GL::Vector4 ray = camera.unproject(GL::Vector4(xx, yy, 0, 0));
 
-       return layout_3d.pick_track(xx, yy, size);
+       return layout.pick_track(Vector(start.x, start.y, start.z), Vector(ray.x, ray.y, ray.z));
 }
 
 void Engineer::train_added(Train &train)
index 4ca753e949f230b864acf266f3e07b2403c86294..944c39047a967ae0344b13bb3d216871e427b082 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -92,7 +92,7 @@ private:
        void reset_block_color(const R2C2::Block &);
        void sensor_event(unsigned, bool);
        void block_reserved(const R2C2::Block &, const R2C2::Train *);
-       R2C2::Track3D *pick_track(int, int);
+       R2C2::Track *pick_track(int, int);
        void train_added(R2C2::Train &);
        virtual void sighandler(int);
 
index d6bd9ee909dee6f11c7016559ccdd24acbf7386a..5c4cf9e1d82d26f604fbb4f5a20736cf944937d6 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -86,6 +86,15 @@ void Layout::remove_track(Track &t)
        }
 }
 
+Track *Layout::pick_track(const Vector &start, const Vector &ray)
+{
+       for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+               if((*i)->collide_ray(start, ray))
+                       return *i;
+
+       return 0;
+}
+
 unsigned Layout::allocate_turnout_id()
 {
        set<unsigned> used_ids;
index 8c143ac3d79b0a6508ce8fbba5ed50cda37eb4bd..f0a292f580e9847507a57f3acb49c64d175b54eb 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -22,6 +22,7 @@ class Driver;
 class Route;
 class Track;
 class Train;
+class Vector;
 class Vehicle;
 class Zone;
 
@@ -87,6 +88,7 @@ public:
 
        void add_track(Track &);
        const std::set<Track *> &get_tracks() const { return tracks; }
+       Track *pick_track(const Vector &, const Vector &);
        void remove_track(Track &);
        unsigned allocate_turnout_id();
 
index 0d4052ea999a83b6394bb79f7d03f9216604fc39..b2d3e63af703031446d86e5fe5986b1f7e8664fd 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -333,6 +333,19 @@ TrackPoint Track::get_point(unsigned epi, float d) const
        return get_point(epi, active_path, d);
 }
 
+bool Track::collide_ray(const Vector &start, const Vector &ray)
+{
+       Vector local_start(start.x-pos.x, start.y-pos.y, start.z-pos.z);
+       float c = cos(rot);
+       float s = sin(rot);
+       local_start = Vector(c*local_start.x+s*local_start.y, c*local_start.y-s*local_start.x, local_start.z);
+       Vector local_ray(c*ray.x+s*ray.y, c*ray.y-s*ray.x, ray.z);
+
+       float width = layout.get_catalogue().get_ballast_profile().get_width();
+
+       return type.collide_ray(local_start, local_ray, width);
+}
+
 void Track::save(list<DataFile::Statement> &st) const
 {
        st.push_back((DataFile::Statement("position"), pos.x, pos.y, pos.z));
index 8f75f78fc1c093f94e83f74e70a5518b1f378aa3..df4032567a8dbe84991d53b4a09e9a43f73e910a 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -89,6 +89,8 @@ public:
        TrackPoint get_point(unsigned, unsigned, float) const;
        TrackPoint get_point(unsigned, float) const;
 
+       bool collide_ray(const Vector &, const Vector &);
+
        void save(std::list<Msp::DataFile::Statement> &) const;
 private:
        void turnout_event(unsigned, unsigned);
index f677c703ee5a7e89f7ffa9d241fbaa69754f433c..d60d374091556b2f89441e9febfc4ddda4ebd7fa 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -92,6 +92,33 @@ TrackPart *TrackPart::get_link(unsigned i) const
        return links[i];
 }
 
+bool TrackPart::collide_ray(const Vector &start, const Vector &ray, float width) const
+{
+       Vector local_start(start.x-pos.x, start.y-pos.y, start.z);
+       float c = cos(dir);
+       float s = sin(dir);
+       local_start = Vector(c*local_start.x+s*local_start.y, c*local_start.y-s*local_start.x, local_start.z);
+       Vector local_ray(c*ray.x+s*ray.y, c*ray.y-s*ray.x, ray.z);
+
+       float d = -local_start.z/local_ray.z;
+       if(d<0)
+               return false;
+
+       Vector base(local_start.x+d*local_ray.x, local_start.y+d*local_ray.y);
+
+       if(radius)
+       {
+               base.y -= radius;
+               if(radius<0)
+                       base.y = -base.y;
+               float r = sqrt(base.x*base.x+base.y*base.y)-abs(radius);
+               float a = atan2(base.x, -base.y);
+               return (a>=0 && a<=length && r>=-width/2 && r<=width/2);
+       }
+       else
+               return (base.x>=0 && base.x<=length && base.y>=-width/2 && base.y<=width/2);
+}
+
 
 TrackPart::Loader::Loader(TrackPart &p):
        Msp::DataFile::BasicLoader<TrackPart>(p)
index 42945845add5aa8d58d17ddd82f6c498f3d4f100..ebe353c34cfde4022586fbd9f2b3922f40a479ef 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -44,6 +44,7 @@ public:
        bool is_dead_end() const { return dead_end; }
        void check_link(TrackPart &);
        TrackPart *get_link(unsigned) const;
+       bool collide_ray(const Vector &, const Vector &, float) const;
 };
 
 } // namespace R2C2
index 35d220821500e1621dbb19bc732587398154507b..5b41e1f5f26f58ade0d2f13eb197d9adae5b6987 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -120,6 +120,15 @@ TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const
        }
 }
 
+bool TrackType::collide_ray(const Vector &start, const Vector &dir, float width) const
+{
+       for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+               if(i->collide_ray(start, dir, width))
+                       return true;
+
+       return false;
+}
+
 void TrackType::collect_endpoints()
 {
        endpoints.clear();
index f285036f905b236c8ac894e6022d1961e195ca5f..7eb2bdc64d15bcfb4cbc853f14b23374583e1c1c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of R²C²
-Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -68,6 +68,7 @@ public:
        const std::vector<Endpoint> &get_endpoints() const { return endpoints; }
        const Endpoint &get_endpoint(unsigned) const;
        TrackPoint get_point(unsigned, unsigned, float) const;
+       bool collide_ray(const Vector &, const Vector &, float) const;
 
 private:
        void collect_endpoints();