From 277e8e7e4230aa8867f507ace62476afe575cff1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 10 Mar 2011 10:20:57 +0000 Subject: [PATCH] Use raycasting instead of OpenGL selection mode to pick tracks --- source/3d/layout.cpp | 46 +--------------------------------- source/3d/layout.h | 3 +-- source/3d/track.cpp | 7 ------ source/3d/track.h | 1 - source/designer/designer.cpp | 48 +++++++++++++++++------------------- source/designer/designer.h | 4 +-- source/engineer/engineer.cpp | 43 +++++++++++++++----------------- source/engineer/engineer.h | 4 +-- source/libr2c2/layout.cpp | 11 ++++++++- source/libr2c2/layout.h | 4 ++- source/libr2c2/track.cpp | 15 ++++++++++- source/libr2c2/track.h | 4 ++- source/libr2c2/trackpart.cpp | 29 +++++++++++++++++++++- source/libr2c2/trackpart.h | 3 ++- source/libr2c2/tracktype.cpp | 11 ++++++++- source/libr2c2/tracktype.h | 3 ++- 16 files changed, 121 insertions(+), 115 deletions(-) diff --git a/source/3d/layout.cpp b/source/3d/layout.cpp index 5f01576..0a9ee2d 100644 --- a/source/3d/layout.cpp +++ b/source/3d/layout.cpp @@ -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 -#include -#include -#include -#include -#include -#include -#include #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 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::max(); - for(vector::iterator i=select_buf.begin(); i!=select_buf.end(); ++i) - if(i->min_depthnames.empty()) - { - track = reinterpret_cast(i->names.back()); - track_depth = i->min_depth; - } - - return track; -} - void Layout3D::add_vehicle(Vehicle3D &v) { if(vehicles.count(&v.get_vehicle())) diff --git a/source/3d/layout.h b/source/3d/layout.h index d1ec7c4..bb9d427 100644 --- a/source/3d/layout.h +++ b/source/3d/layout.h @@ -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 &); diff --git a/source/3d/track.cpp b/source/3d/track.cpp index 8b36b19..cd17b81 100644 --- a/source/3d/track.cpp +++ b/source/3d/track.cpp @@ -7,7 +7,6 @@ Distributed under the GPL #include #include -#include #include #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(this)); -} - -void Track3D::finish_render(Msp::GL::Renderer &, const GL::Tag &) const -{ - glPopName(); } void Track3D::link_changed(unsigned i, Track *trk) diff --git a/source/3d/track.h b/source/3d/track.h index d0a90f4..66382bc 100644 --- a/source/3d/track.h +++ b/source/3d/track.h @@ -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 *); }; diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index 3b43efd..a64c8eb 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -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; } diff --git a/source/designer/designer.h b/source/designer/designer.h index da6cb0e..49d4283 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -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 &); diff --git a/source/engineer/engineer.cpp b/source/engineer/engineer.cpp index fad6169..32b23ab 100644 --- a/source/engineer/engineer.cpp +++ b/source/engineer/engineer.cpp @@ -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)) @@ -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) diff --git a/source/engineer/engineer.h b/source/engineer/engineer.h index 4ca753e..944c390 100644 --- a/source/engineer/engineer.h +++ b/source/engineer/engineer.h @@ -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); diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index d6bd9ee..5c4cf9e 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -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::iterator i=tracks.begin(); i!=tracks.end(); ++i) + if((*i)->collide_ray(start, ray)) + return *i; + + return 0; +} + unsigned Layout::allocate_turnout_id() { set used_ids; diff --git a/source/libr2c2/layout.h b/source/libr2c2/layout.h index 8c143ac..f0a292f 100644 --- a/source/libr2c2/layout.h +++ b/source/libr2c2/layout.h @@ -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 &get_tracks() const { return tracks; } + Track *pick_track(const Vector &, const Vector &); void remove_track(Track &); unsigned allocate_turnout_id(); diff --git a/source/libr2c2/track.cpp b/source/libr2c2/track.cpp index 0d4052e..b2d3e63 100644 --- a/source/libr2c2/track.cpp +++ b/source/libr2c2/track.cpp @@ -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 &st) const { st.push_back((DataFile::Statement("position"), pos.x, pos.y, pos.z)); diff --git a/source/libr2c2/track.h b/source/libr2c2/track.h index 8f75f78..df40325 100644 --- a/source/libr2c2/track.h +++ b/source/libr2c2/track.h @@ -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 &) const; private: void turnout_event(unsigned, unsigned); diff --git a/source/libr2c2/trackpart.cpp b/source/libr2c2/trackpart.cpp index f677c70..d60d374 100644 --- a/source/libr2c2/trackpart.cpp +++ b/source/libr2c2/trackpart.cpp @@ -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(p) diff --git a/source/libr2c2/trackpart.h b/source/libr2c2/trackpart.h index 4294584..ebe353c 100644 --- a/source/libr2c2/trackpart.h +++ b/source/libr2c2/trackpart.h @@ -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 diff --git a/source/libr2c2/tracktype.cpp b/source/libr2c2/tracktype.cpp index 35d2208..5b41e1f 100644 --- a/source/libr2c2/tracktype.cpp +++ b/source/libr2c2/tracktype.cpp @@ -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::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(); diff --git a/source/libr2c2/tracktype.h b/source/libr2c2/tracktype.h index f285036..7eb2bdc 100644 --- a/source/libr2c2/tracktype.h +++ b/source/libr2c2/tracktype.h @@ -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 &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(); -- 2.43.0