/* $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"
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()))
/* $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
*/
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 &);
#include <cmath>
#include <msp/gl/matrix.h>
-#include <msp/gl/misc.h>
#include <msp/gl/renderer.h>
#include "libr2c2/tracktype.h"
#include "endpoint.h"
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)
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 *);
};
/* $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
*/
{
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();
{
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);
}
}
}
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)
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;
}
/* $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
*/
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 &);
/* $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
*/
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
}
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))
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));
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)
/* $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
*/
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);
/* $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
*/
}
}
+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;
/* $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
*/
class Route;
class Track;
class Train;
+class Vector;
class Vehicle;
class Zone;
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();
/* $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
*/
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));
/* $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
*/
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);
/* $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
*/
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)
/* $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
*/
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
/* $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
*/
}
}
+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();
/* $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
*/
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();