std::list<Train3D *> trains;
Msp::GL::Scene scene;
Msp::GL::Scene ep_scene;
+ Msp::GL::Scene path_scene;
public:
Layout3D(Layout &);
Msp::GL::Scene &get_scene() { return scene; }
Msp::GL::Scene &get_endpoint_scene() { return ep_scene; }
+ Msp::GL::Scene &get_path_scene() { return path_scene; }
private:
void track_added(Track &);
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <msp/gl/matrix.h>
+#include "libmarklin/tracktype.h"
+#include "layout.h"
+#include "path.h"
+#include "track.h"
+#include "tracktype.h"
+
+using namespace Msp;
+
+namespace Marklin {
+
+Path3D::Path3D(const Track3D &t):
+ track(t),
+ paths(0),
+ automatic(true)
+{
+ track.get_layout().get_path_scene().add(*this);
+}
+
+Path3D::~Path3D()
+{
+ track.get_layout().get_path_scene().remove(*this);
+}
+
+void Path3D::set_automatic()
+{
+ automatic = true;
+}
+
+void Path3D::set_path(unsigned p)
+{
+ if(!(track.get_track().get_type().get_paths()&(1<<p)))
+ throw InvalidParameterValue("Invalid path");
+ automatic = false;
+ paths = 1<<p;
+}
+
+void Path3D::set_mask(unsigned p)
+{
+ if(p&~track.get_track().get_type().get_paths())
+ throw InvalidParameterValue("Invalid path mask");
+ automatic = false;
+ paths = p;
+}
+
+void Path3D::set_color(const GL::Color &c)
+{
+ color = c;
+}
+
+void Path3D::render(const GL::Tag &tag) const
+{
+ if(tag==0)
+ {
+ unsigned mask = (automatic ? 1<<track.get_track().get_active_path() : paths);
+ mask &= track.get_track().get_type().get_paths();
+ if(!mask)
+ return;
+
+ GL::PushMatrix push_mat;
+ track.apply_matrix();
+
+ glColor4f(color.r, color.g, color.b, color.a);
+ for(unsigned i=0; mask; ++i, mask>>=1)
+ if(mask&1)
+ track.get_type().get_path_mesh(i).draw();
+ }
+}
+
+} // namespace Marklin
--- /dev/null
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef MARKLIN3D_PATH_H_
+#define MARKLIN3D_PATH_H_
+
+#include <msp/gl/color.h>
+#include <msp/gl/mesh.h>
+#include <msp/gl/renderable.h>
+
+namespace Marklin {
+
+class Track3D;
+
+class Path3D: public Msp::GL::Renderable
+{
+private:
+ const Track3D &track;
+ unsigned paths;
+ bool automatic;
+ Msp::GL::Color color;
+
+public:
+ Path3D(const Track3D &);
+ ~Path3D();
+
+ void set_automatic();
+ void set_path(unsigned);
+ void set_mask(unsigned);
+ void set_color(const Msp::GL::Color &);
+
+ virtual void render(const Msp::GL::Tag &) const;
+};
+
+} // namespace Marklin
+
+#endif
#include "libmarklin/tracktype.h"
#include "endpoint.h"
#include "layout.h"
+#include "path.h"
#include "track.h"
#include "tracktype.h"
Track3D::Track3D(Layout3D &l, Track &t):
layout(l),
track(t),
- type(layout.get_catalogue().get_track(track.get_type()))
+ type(layout.get_catalogue().get_track(track.get_type())),
+ path(new Path3D(*this))
{
layout.add_track(*this);
layout.get_scene().add(*this);
return Point(pos.x+c*center.x-s*center.y, pos.y+s*center.x+c*center.y, pos.z+0.02);
}
-void Track3D::render(const GL::Tag &tag) const
+void Track3D::apply_matrix() const
{
- GL::PushMatrix push_mat;
-
const Point &pos = track.get_position();
float rot = track.get_rotation();
glTranslatef(pos.x, pos.y, pos.z);
glRotatef(rot*180/M_PI, 0, 0, 1);
glRotatef(track.get_slope()/track.get_type().get_total_length()*180/M_PI, 0, -1, 0);
+}
+
+void Track3D::render(const GL::Tag &tag) const
+{
+ GL::PushMatrix push_mat;
+
+ apply_matrix();
glPushName(reinterpret_cast<unsigned>(this));
class Endpoint3D;
class Layout3D;
+class Path3D;
class TrackType3D;
class Track3D: public Object3D, public Msp::GL::Renderable
Track &track;
const TrackType3D &type;
std::vector<Endpoint3D *> endpoints;
+ Path3D *path;
public:
Track3D(Layout3D &, Track &);
Track &get_track() const { return track; }
const TrackType3D &get_type() const { return type; }
void get_bounds(float, Point &, Point &) const;
+ Path3D &get_path() { return *path; }
virtual Point get_node() const;
+ void apply_matrix() const;
virtual void render(const Msp::GL::Tag &) const;
};
const Profile &ballast_profile = cat.get_ballast_profile();
const Point &ballast_min = ballast_profile.get_min_coords();
const Point &ballast_max = ballast_profile.get_max_coords();
+ float ballast_h = ballast_max.y-ballast_min.y;
const Profile &rail_profile = cat.get_rail_profile();
const Point &rail_min = rail_profile.get_min_coords();
const Point &rail_max = rail_profile.get_max_coords();
+ float rail_h = rail_max.y-rail_min.y;
float gauge = cat.get_gauge();
unsigned index = 0;
GL::MeshBuilder bld(rail_mesh);
bld.color(0.85f, 0.85f, 0.85f);
- float y = ballast_max.y-ballast_min.y-rail_min.y;
+ float y = ballast_h-rail_min.y;
for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
build_part(*i, rail_profile, Point(-gauge/2-rail_max.x, y), bld, index);
for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
build_part(*i, rail_profile, Point(gauge/2-rail_min.x, y), bld, index);
}
+
+ unsigned paths = tt.get_paths();
+ for(unsigned i=0; paths; ++i, paths>>=1)
+ {
+ GL::Mesh *mesh = 0;
+ if(paths&1)
+ {
+ mesh = new GL::Mesh(GL::VERTEX3);
+ GL::MeshBuilder bld(*mesh);
+ unsigned index = 0;
+ for(vector<TrackPart>::const_iterator j=parts.begin(); j!=parts.end(); ++j)
+ if(j->get_path()==i)
+ build_part(*j, cat.get_path_profile(), Point(0, ballast_h+1.5*rail_h), bld, index);
+ }
+ path_meshes.push_back(mesh);
+ }
min_z = max_z = border.front().z;
for(vector<Point>::iterator i=border.begin(); i!=border.end(); ++i)
}
}
+const GL::Mesh &TrackType3D::get_path_mesh(unsigned p) const
+{
+ if(p>=path_meshes.size() || !path_meshes[p])
+ throw InvalidParameterValue("Invalid path");
+ return *path_meshes[p];
+}
+
void TrackType3D::render(const GL::Tag &tag) const
{
if(tag==0)
const Catalogue3D &catalogue;
Msp::GL::Mesh ballast_mesh;
Msp::GL::Mesh rail_mesh;
+ std::vector<Msp::GL::Mesh *> path_meshes;
std::vector<Point> border;
float min_z;
float max_z;
TrackType3D(const Catalogue3D &, const TrackType &);
void get_bounds(float, Point &, Point &) const;
+ const Msp::GL::Mesh &get_path_mesh(unsigned) const;
virtual void render(const Msp::GL::Tag &) const;
private:
void build_part(const TrackPart &, const Profile &, const Point &, Msp::GL::MeshBuilder &, unsigned &);
- //void optimize_border();
};
} // namespace Marklin
#include <msp/time/utils.h>
#include "libmarklin/route.h"
#include "libmarklin/tracktype.h"
+#include "3d/path.h"
#include "designer.h"
#include "input.h"
#include "manipulator.h"
void Designer::edit_route(Route &r)
{
cur_route = &r;
+ show_route(r);
}
void Designer::add_selection_to_route()
{
IO::print("%s\n", e.what());
}
+
+ show_route(*cur_route);
}
Point Designer::map_pointer_coords(int x, int y)
{
pipeline->render_all();
layout_3d->get_endpoint_scene().render();
+ if(cur_route)
+ layout_3d->get_path_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);
- const set<const Track *> &rtracks = cur_route->get_tracks();
- const map<unsigned, int> &turnouts = cur_route->get_turnouts();
- for(set<const Track *>::const_iterator i=rtracks.begin(); i!=rtracks.end(); ++i)
- {
- unsigned path = 0;
- if(unsigned tid=(*i)->get_turnout_id())
- {
- map<unsigned, int>::const_iterator j = turnouts.find(tid);
- if(j!=turnouts.end())
- path = j->second;
- }
- layout_3d->get_track(**i).render_path(path);
- }
- }*/
manipulator.render();
if(mode==MEASURE)
return string();
}
+
+void Designer::show_route(const Route &route)
+{
+ const set<Track *> <racks = layout->get_tracks();
+ const set<const Track *> &rtracks = route.get_tracks();
+ for(set<Track *>::iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
+ {
+ Track3D &t3d = layout_3d->get_track(**i);
+ if(rtracks.count(*i))
+ {
+ t3d.get_path().set_color(GL::Color(0.5, 0.8, 1.0));
+ if((*i)->get_type().is_turnout())
+ {
+ unsigned tid = (*i)->get_turnout_id();
+ int path = (tid ? route.get_turnout(tid) : -1);
+ if(path>=0)
+ t3d.get_path().set_path(path);
+ else
+ t3d.get_path().set_mask((*i)->get_type().get_paths());
+ }
+ else
+ t3d.get_path().set_path(0);
+ }
+ else
+ t3d.get_path().set_mask(0);
+ }
+}
void sensor_id_accept(const std::string &);
void view_all();
std::string tooltip(int, int);
+ void show_route(const Marklin::Route &);
};
#endif
#include <msp/time/units.h>
#include "libmarklin/driver.h"
#include "libmarklin/tracktype.h"
+#include "3d/path.h"
#include "engineer.h"
#include "mainpanel.h"
#include "trainpanel.h"
GL::clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
pipeline.render_all();
+ layout_3d.get_path_scene().render();
{
GL::Bind blend(GL::Blend::alpha());
overlay->render(0);
void Engineer::set_block_color(const Block &block, const GL::Color &color)
{
- (void)block; (void)color;
+ const set<Track *> &tracks = block.get_tracks();
+ for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ layout_3d.get_track(**i).get_path().set_color(color);
}
void Engineer::reset_block_color(const Block &block)
void Catalogue::Loader::gauge(float g)
{
obj.gauge = g/1000;
+ obj.path_profile = Profile();
+ obj.path_profile.append_point(Point(0.1*obj.gauge, 0));
+ obj.path_profile.append_point(Point(-0.1*obj.gauge, 0));
}
void Catalogue::Loader::layout()
float gauge;
Profile rail_profile;
Profile ballast_profile;
+ Profile path_profile;
std::map<unsigned, TrackType *> tracks;
std::map<unsigned, LocoType *> locos;
Layout layout;
float get_gauge() const { return gauge; }
const Profile &get_rail_profile() const { return rail_profile; }
const Profile &get_ballast_profile() const { return ballast_profile; }
+ const Profile &get_path_profile() const { return path_profile; }
void add_track(TrackType &);
const TrackType &get_track(unsigned) const;
namespace Marklin {
+void Profile::append_point(const Point &p)
+{
+ points.push_back(p);
+ if(points.size()==1)
+ {
+ min_coords = p;
+ max_coords = p;
+ }
+ else
+ {
+ min_coords.x = min(min_coords.x, p.x);
+ min_coords.y = min(min_coords.y, p.y);
+ max_coords.x = max(max_coords.x, p.x);
+ max_coords.y = max(max_coords.y, p.y);
+ }
+}
+
const Point &Profile::get_point(unsigned i) const
{
if(i>=points.size())
add("point", &Loader::point);
}
-void Profile::Loader::finish()
-{
- obj.min_coords = obj.points[0];
- obj.max_coords = obj.points[0];
- for(unsigned i=1; i<obj.points.size(); ++i)
- {
- obj.min_coords.x = min(obj.min_coords.x, obj.points[i].x);
- obj.min_coords.y = min(obj.min_coords.y, obj.points[i].y);
- obj.max_coords.x = max(obj.max_coords.x, obj.points[i].x);
- obj.max_coords.y = max(obj.max_coords.y, obj.points[i].y);
- }
-}
-
void Profile::Loader::point(float x, float y)
{
- obj.points.push_back(Point(x/1000, y/1000));
+ obj.append_point(Point(x/1000, y/1000));
}
} // namespace Marklin
public:
Loader(Profile &);
private:
- virtual void finish();
void point(float, float);
};
Point max_coords;
public:
+ void append_point(const Point &);
unsigned get_n_points() const { return points.size(); }
const Point &get_point(unsigned) const;
const Point &get_min_coords() const { return min_coords; }
if(layout.has_driver())
layout.get_driver().signal_turnout.connect(sigc::mem_fun(this, &Track::turnout_event));
+
+ for(unsigned paths = type.get_paths(); !(paths&1); ++active_path, paths>>=1) ;
}
Track::~Track()
using namespace std;
using namespace Msp;
-#include <msp/io/print.h>
-
namespace Marklin {
TrackPart::TrackPart():
if(dx*dx+dy*dy<1e-6 && da>=-0.01 && da<=0.01)
{
- IO::print("TrackParts linked!\n");
links[i] = &other;
other.links[j] = this;
return;