From ca499a03e46e4d828102e789453a23c44badbf15 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 14 May 2011 19:36:22 +0100 Subject: [PATCH] Remove old CurvedTrack and SBend now replaced with SplineTrack --- include/ITrackSegment.hpp | 3 - maps/coal_mine/coal_mine.xml | 32 +-- maps/demo/demo.xml | 38 ++-- maps/goods_demo/goods_demo.xml | 32 +-- maps/long_map/long_map.xml | 84 ++++---- maps/points/points.xml | 52 ++--- maps/sbends/sbends.xml | 24 +-- maps/uphill/uphill.xml | 32 +-- maps/villages/villages.xml | 24 +-- schemas/map.xsd | 20 ++ src/CurvedTrack.cpp | 350 --------------------------------- src/Map.cpp | 86 +------- src/SBend.cpp | 309 ----------------------------- 13 files changed, 184 insertions(+), 902 deletions(-) delete mode 100644 src/CurvedTrack.cpp delete mode 100644 src/SBend.cpp diff --git a/include/ITrackSegment.hpp b/include/ITrackSegment.hpp index d8f88d2..715fe23 100644 --- a/include/ITrackSegment.hpp +++ b/include/ITrackSegment.hpp @@ -161,13 +161,10 @@ struct ITrackSegment : IXMLSerialisable { }; ITrackSegmentPtr make_straight_track(const track::Direction& a_direction); -ITrackSegmentPtr make_curved_track(track::Angle a_start_angle, - track::Angle a_finish_angle, int a_radius); ITrackSegmentPtr make_crossover_track(); ITrackSegmentPtr make_points(track::Direction a_direction, bool reflect); ITrackSegmentPtr make_slope_track(track::Direction axis, Vector slope, Vector slope_before, Vector slope_after); -ITrackSegmentPtr make_s_bend(track::Direction dir, int straight, int off); ITrackSegmentPtr make_spline_track(Vector delta, track::Direction entry_dir, track::Direction exit_dir); diff --git a/maps/coal_mine/coal_mine.xml b/maps/coal_mine/coal_mine.xml index 4e697f3..5198d74 100644 --- a/maps/coal_mine/coal_mine.xml +++ b/maps/coal_mine/coal_mine.xml @@ -60,11 +60,11 @@ - + - + @@ -80,7 +80,7 @@ - + @@ -164,7 +164,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -312,7 +312,7 @@ - + @@ -324,11 +324,11 @@ - + - + @@ -420,7 +420,7 @@ - + @@ -502,7 +502,7 @@ - + @@ -736,11 +736,11 @@ - + - + @@ -904,7 +904,7 @@ - + @@ -944,7 +944,7 @@ - + @@ -1008,11 +1008,11 @@ - + - + diff --git a/maps/demo/demo.xml b/maps/demo/demo.xml index e7016ce..22d212d 100644 --- a/maps/demo/demo.xml +++ b/maps/demo/demo.xml @@ -24,7 +24,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -134,7 +134,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -398,7 +398,7 @@ - + @@ -430,7 +430,7 @@ - + @@ -450,7 +450,7 @@ - + @@ -506,7 +506,7 @@ - + @@ -626,7 +626,7 @@ - + @@ -882,7 +882,7 @@ - + @@ -1086,11 +1086,11 @@ - + - + @@ -1106,7 +1106,7 @@ - + @@ -1118,7 +1118,7 @@ - + @@ -1350,7 +1350,7 @@ - + @@ -1398,7 +1398,7 @@ - + diff --git a/maps/goods_demo/goods_demo.xml b/maps/goods_demo/goods_demo.xml index 3bf7b71..7642ce8 100644 --- a/maps/goods_demo/goods_demo.xml +++ b/maps/goods_demo/goods_demo.xml @@ -172,7 +172,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -280,7 +280,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -350,7 +350,7 @@ - + @@ -460,7 +460,7 @@ - + @@ -468,7 +468,7 @@ - + @@ -512,7 +512,7 @@ - + @@ -558,7 +558,7 @@ - + @@ -618,7 +618,7 @@ - + @@ -714,7 +714,7 @@ - + @@ -722,7 +722,7 @@ - + @@ -814,7 +814,7 @@ - + @@ -922,7 +922,7 @@ - + @@ -942,7 +942,7 @@ - + @@ -970,7 +970,7 @@ - + diff --git a/maps/long_map/long_map.xml b/maps/long_map/long_map.xml index b5585e7..a7e2bcb 100644 --- a/maps/long_map/long_map.xml +++ b/maps/long_map/long_map.xml @@ -12,11 +12,11 @@ - + - + @@ -40,7 +40,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -88,7 +88,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -300,11 +300,11 @@ - + - + @@ -360,7 +360,7 @@ - + @@ -372,7 +372,7 @@ - + @@ -524,11 +524,11 @@ - + - + @@ -1104,7 +1104,7 @@ - + @@ -1120,7 +1120,7 @@ - + @@ -1192,11 +1192,11 @@ - + - + @@ -1564,11 +1564,11 @@ - + - + @@ -1636,11 +1636,11 @@ - + - + @@ -1756,11 +1756,11 @@ - + - + @@ -3348,11 +3348,11 @@ - + - + @@ -3744,11 +3744,11 @@ - + - + @@ -3864,11 +3864,11 @@ - + - + @@ -4240,11 +4240,11 @@ - + - + @@ -4268,7 +4268,7 @@ - + @@ -4276,7 +4276,7 @@ - + @@ -5844,7 +5844,7 @@ - + @@ -5856,11 +5856,11 @@ - + - + @@ -5872,7 +5872,7 @@ - + @@ -5900,7 +5900,7 @@ - + @@ -5912,7 +5912,7 @@ - + @@ -6028,7 +6028,7 @@ - + @@ -6040,7 +6040,7 @@ - + @@ -6340,11 +6340,11 @@ - + - + diff --git a/maps/points/points.xml b/maps/points/points.xml index 30fbd9a..395feb7 100644 --- a/maps/points/points.xml +++ b/maps/points/points.xml @@ -48,11 +48,11 @@ - + - + @@ -64,7 +64,7 @@ - + @@ -116,7 +116,7 @@ - + @@ -156,15 +156,15 @@ - + - + - + @@ -176,7 +176,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -224,11 +224,11 @@ - + - + @@ -268,7 +268,7 @@ - + @@ -284,7 +284,7 @@ - + @@ -452,11 +452,11 @@ - + - + @@ -492,11 +492,11 @@ - + - + @@ -564,11 +564,11 @@ - + - + @@ -656,15 +656,15 @@ - + - + - + @@ -672,7 +672,7 @@ - + @@ -704,7 +704,7 @@ - + @@ -716,11 +716,11 @@ - + - + diff --git a/maps/sbends/sbends.xml b/maps/sbends/sbends.xml index 000c581..c4df358 100644 --- a/maps/sbends/sbends.xml +++ b/maps/sbends/sbends.xml @@ -8,7 +8,7 @@ - + @@ -24,7 +24,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -52,15 +52,15 @@ - + - + - + @@ -92,11 +92,11 @@ - + - + @@ -104,7 +104,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -164,7 +164,7 @@ - + diff --git a/maps/uphill/uphill.xml b/maps/uphill/uphill.xml index f20a8aa..e6382e3 100644 --- a/maps/uphill/uphill.xml +++ b/maps/uphill/uphill.xml @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -156,7 +156,7 @@ - + @@ -220,7 +220,7 @@ - + @@ -232,7 +232,7 @@ - + @@ -252,7 +252,7 @@ - + @@ -288,7 +288,7 @@ - + @@ -332,7 +332,7 @@ - + @@ -468,7 +468,7 @@ - + @@ -532,7 +532,7 @@ - + @@ -604,7 +604,7 @@ - + @@ -668,11 +668,11 @@ - + - + @@ -692,7 +692,7 @@ - + @@ -720,7 +720,7 @@ - + @@ -736,7 +736,7 @@ - + diff --git a/maps/villages/villages.xml b/maps/villages/villages.xml index 862903b..651cf71 100644 --- a/maps/villages/villages.xml +++ b/maps/villages/villages.xml @@ -144,7 +144,7 @@ - + @@ -156,7 +156,7 @@ - + @@ -184,7 +184,7 @@ - + @@ -192,11 +192,11 @@ - + - + @@ -204,15 +204,15 @@ - + - + - + @@ -228,7 +228,7 @@ - + @@ -236,7 +236,7 @@ - + @@ -532,7 +532,7 @@ - + @@ -602,7 +602,7 @@ - + diff --git a/schemas/map.xsd b/schemas/map.xsd index 84e9092..7ec8939 100644 --- a/schemas/map.xsd +++ b/schemas/map.xsd @@ -80,6 +80,7 @@ + + + + + + + + + + + + + + diff --git a/src/CurvedTrack.cpp b/src/CurvedTrack.cpp deleted file mode 100644 index 8ae053b..0000000 --- a/src/CurvedTrack.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// -// Copyright (C) 2009-2010 Nick Gasson -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "ITrackSegment.hpp" -#include "TrackCommon.hpp" -#include "ILogger.hpp" -#include "XMLBuilder.hpp" - -#include -#include -#include -#include - -#include -#include - -using namespace placeholders; -using namespace track; -using namespace boost; - -// Concrete implementation of curved pieces of track -class CurvedTrack : public ITrackSegment, - public enable_shared_from_this, - private CurvedTrackHelper { -public: - CurvedTrack(track::Angle a_start_angle, track::Angle a_finish_angle, - int a_radius); - ~CurvedTrack(); - - void render() const {} - void merge(IMeshBufferPtr buf) const; - - void set_origin(int x, int y, float h); - float segment_length(const track::TravelToken& a_token) const; - - Connection next_position(const track::TravelToken& a_token) const; - bool is_valid_direction(const Direction& a_direction) const; - void get_endpoints(vector >& a_list) const; - void get_covers(vector >& output) const; - void get_height_locked(vector >& output) const; - - ITrackSegmentPtr merge_exit(Point where, track::Direction dir); - - xml::element to_xml() const; - track::TravelToken get_travel_token(track::Position a_position, - track::Direction a_direction) const; - - bool has_multiple_states() const { return false; } - void next_state() {} - void prev_state() {} - void set_state_render_hint() {} - -private: - void transform(const track::TravelToken& a_token, float delta) const; - void glTransform_toOrigin() const; - Vector cw_entry_vector() const; - Vector ccw_entry_vector() const; - void ensure_valid_direction(const Direction& a_direction) const; - - Point origin; - int base_radius; - track::Angle start_angle, finish_angle; - float height; -}; - -CurvedTrack::CurvedTrack(track::Angle a_start_angle, - track::Angle a_finish_angle, - int a_radius) - : origin(make_point(0, 0)), base_radius(a_radius), - start_angle(a_start_angle), finish_angle(a_finish_angle), - height(0.0f) -{ - -} - -CurvedTrack::~CurvedTrack() -{ - -} - -void CurvedTrack::set_origin(int x, int y, float h) -{ - origin = make_point(x, y); - height = h; -} - -track::TravelToken -CurvedTrack::get_travel_token(track::Position a_position, - track::Direction a_direction) const -{ - ensure_valid_direction(a_direction); - - track::TravelToken tok = { - a_direction, - a_position, - bind(&CurvedTrack::transform, this, _1, _2), - track::flat_gradient_func, - 1 - }; - return tok; -} - -void CurvedTrack::glTransform_toOrigin() const -{ - glTranslatef((base_radius-1)*-sin(deg_to_rad(start_angle)) - 0.5f, 0.0f, - (base_radius-1)*-cos(deg_to_rad(start_angle)) - 0.5f); - - // There *must* be a way to incorporate this in the above translation - // as a neat formula, but I really can't think of it - // This is a complete a hack, but whatever... - if (start_angle >= 90 && start_angle <= 180) - glTranslatef(0.0f, 0.0f, 1.0f); - - if (start_angle >= 180 && start_angle <= 270) - glTranslatef(1.0f, 0.0f, 0.0f); -} - -void CurvedTrack::transform(const track::TravelToken& a_token, float delta) const -{ - assert(delta < segment_length(a_token)); - - glTranslated(static_cast(origin.x), - height, - static_cast(origin.y)); - - glTransform_toOrigin(); - - bool backwards = a_token.direction == cw_entry_vector(); - - double ratio = delta / segment_length(a_token); - if (backwards) - ratio = 1.0 - ratio; - - double angle = start_angle + (90.0 * ratio); - - glRotated(angle, 0.0, 1.0, 0.0); - glTranslated(0.0, 0.0, static_cast(base_radius - 0.5)); - - if (backwards) - glRotatef(180.0, 0, 1, 0); -} - -float CurvedTrack::segment_length(const track::TravelToken& a_token) const -{ - // Assume curve is only through 90 degrees - return M_PI * (static_cast(base_radius) - 0.5f) / 2.0f; -} - -// -// Imagine the train is travelling in a circle like this: -// -// (0, 0) -// 180 -// [-1 0] -// <-------------^ -// | | -// | | -// [0 1] | | [0 -1] 90 -// 270 | | -// | | -// V------------>| -// [1 0] -// 0 -// -// Above are the vectors for /counter/-clockwise movement -// - -// The vector the train is moving on if it enters clockwise -Vector CurvedTrack::cw_entry_vector() const -{ - return make_vector(-cos(deg_to_rad(finish_angle)), 0, - sin(deg_to_rad(finish_angle))); -} - -// The vector the train is moving on if it enters counter-clockwise -Vector CurvedTrack::ccw_entry_vector() const -{ - return make_vector(cos(deg_to_rad(start_angle)), 0.0, - -sin(deg_to_rad(start_angle))); -} - -void CurvedTrack::ensure_valid_direction(const Direction& a_direction) const -{ - if (!is_valid_direction(a_direction)) - throw runtime_error - ("Invalid direction on curved track from " - + lexical_cast(start_angle) + " to " - + lexical_cast(finish_angle) + " degrees: " - + lexical_cast(a_direction) - + " (should be " - + lexical_cast(cw_entry_vector()) + " or " - + lexical_cast(ccw_entry_vector()) + ")"); -} - -bool CurvedTrack::is_valid_direction(const Direction& a_direction) const -{ - return a_direction == cw_entry_vector() || a_direction == ccw_entry_vector(); -} - -Connection CurvedTrack::next_position(const track::TravelToken& a_token) const -{ - bool backwards; - Vector next_dir; - if (a_token.direction == cw_entry_vector()) { - next_dir = -ccw_entry_vector(); - backwards = true; - } - else if (a_token.direction == ccw_entry_vector()) { - next_dir = -cw_entry_vector(); - backwards = false; - } - else - assert(false); - - // Assuming 90 degree curves again - const int cos_end = static_cast(cos(deg_to_rad(finish_angle))); - const int cos_start = static_cast(cos(deg_to_rad(start_angle))); - const int sin_end = static_cast(sin(deg_to_rad(finish_angle))); - const int sin_start = static_cast(sin(deg_to_rad(start_angle))); - - int x_delta, y_delta; - - if (backwards) - x_delta = y_delta = 0; - else { - x_delta = (base_radius - 1) * (sin_end - sin_start); - y_delta = (base_radius - 1) * (cos_end - cos_start); - } - - return make_pair(make_point(origin.x + x_delta + next_dir.x, - origin.y + y_delta + next_dir.z), - next_dir); -} - -void CurvedTrack::get_endpoints(vector >& a_list) const -{ - a_list.push_back(origin); - - // Assuming 90 degree curves again - const int cos_end = static_cast(cos(deg_to_rad(finish_angle))); - const int cos_start = static_cast(cos(deg_to_rad(start_angle))); - const int sin_end = static_cast(sin(deg_to_rad(finish_angle))); - const int sin_start = static_cast(sin(deg_to_rad(start_angle))); - - const int x_delta = (base_radius - 1) * (sin_end - sin_start); - const int y_delta = (base_radius - 1) * (cos_end - cos_start); - - a_list.push_back(make_point(origin.x + x_delta, origin.y + y_delta)); -} - -void CurvedTrack::get_covers(vector >& output) const -{ - vector > exits; - get_endpoints(exits); - - const Point& start = exits.at(0); - const Point& finish = exits.at(1); - - Point true_origin = - (start_angle == 90 || start_angle == 270) - ? make_point(finish.x, start.y) - : make_point(start.x, finish.y); - - set > tmp; - - // A fiddle factor to put the cover tiles in the best location - const float fiddle_radius = static_cast(base_radius) - 0.5f; - - const float sign = (start_angle == 0 || start_angle == 180) ? 1.0f : -1.0f; - - for (track::Angle angle = start_angle; angle < finish_angle; angle += 5) { - float x = fiddle_radius * sign * cos(deg_to_rad(angle)); - float y = fiddle_radius * sign * sin(deg_to_rad(angle)); - Point p = make_point(static_cast(x), - static_cast(y)); - - if (abs(p.x) >= base_radius || abs(p.y) >= base_radius) - continue; - - Point actual = p + true_origin; - - if (actual != start && actual != finish) - tmp.insert(actual); - } - - copy(tmp.begin(), tmp.end(), back_inserter(output)); -} - -void CurvedTrack::get_height_locked(vector >& output) const -{ - -} - -ITrackSegmentPtr CurvedTrack::merge_exit(Point where, track::Direction dir) -{ - // See if this is already an exit - if (is_valid_direction(dir)) { - vector > exits; - get_endpoints(exits); - - for (vector >::iterator it = exits.begin(); - it != exits.end(); ++it) - if (*it == where) - return shared_from_this(); - } - - // No way to merge this as an exit - return ITrackSegmentPtr(); -} - -void CurvedTrack::merge(IMeshBufferPtr buf) const -{ - const Vector off = make_vector( - static_cast(origin.x), - height, - static_cast(origin.y)); - - merge_curved_track(buf, off, base_radius, start_angle, finish_angle); -} - -xml::element CurvedTrack::to_xml() const -{ - return xml::element("curved-track") - .add_attribute("start-angle", start_angle) - .add_attribute("finish-angle", finish_angle) - .add_attribute("radius", base_radius); -} - -ITrackSegmentPtr make_curved_track(track::Angle a_start_angle, - track::Angle a_finish_angle, int a_radius) -{ - assert(a_start_angle < a_finish_angle); - - return ITrackSegmentPtr - (new CurvedTrack(a_start_angle, a_finish_angle, a_radius)); -} diff --git a/src/Map.cpp b/src/Map.cpp index 3306fdb..5792046 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -1660,11 +1660,9 @@ private: void handle_station_part(const AttributeSet& attrs); void handle_straight_track(const AttributeSet& attrs); void handle_slope_track(const AttributeSet& attrs); - void handle_s_bend_track(const AttributeSet attrs); void handle_points(const AttributeSet& attrs); - void handle_curved_track(const AttributeSet& attrs); void handle_crossover_track(const AttributeSet& attrs); - void handle_gen_track(const AttributeSet& attrs); + void handle_spline_track(const AttributeSet& attrs); shared_ptr my_map; map my_stations; @@ -1685,18 +1683,15 @@ void MapLoader::start_element(const string& local_name, handle_start(attrs); else if (local_name == "straight-track") handle_straight_track(attrs); - else if (local_name == "curved-track") - handle_curved_track(attrs); else if (local_name == "crossover-track") handle_crossover_track(attrs); - else if (local_name == "gen-track") - handle_gen_track(attrs); + else if (local_name == "gen-track" + || local_name == "spline-track") + handle_spline_track(attrs); else if (local_name == "points") handle_points(attrs); else if (local_name == "slope-track") handle_slope_track(attrs); - else if (local_name == "sbend-track") - handle_s_bend_track(attrs); else if (local_name == "station-part") handle_station_part(attrs); else if (local_name == "station") @@ -1814,29 +1809,6 @@ void MapLoader::handle_slope_track(const AttributeSet& attrs) make_slope_track(axis, slope, slope_before, slope_after)); } -void MapLoader::handle_s_bend_track(const AttributeSet attrs) -{ - string align; - attrs.get("align", align); - - track::Direction axis = align == "x" ? axis::X : axis::Y; - - int offset, straight; - attrs.get("offset", offset); - attrs.get("straight", straight); - -#if 1 - Vector delta = axis == axis::X - ? make_vector(straight - 1, offset, 0) - : make_vector(offset, straight - 1, 0); - - my_map->set_track_at(tile, make_spline_track(delta, axis, axis)); -#else - // Legacy S-bend track - my_map->set_track_at(tile, make_s_bend(axis, straight, offset)); -#endif -} - void MapLoader::handle_points(const AttributeSet& attrs) { string align; @@ -1853,60 +1825,12 @@ void MapLoader::handle_points(const AttributeSet& attrs) my_map->set_track_at(tile, make_points(dir, reflect)); } -void MapLoader::handle_curved_track(const AttributeSet& attrs) -{ - int start_angle, finish_angle, radius; - attrs.get("start-angle", start_angle); - attrs.get("finish-angle", finish_angle); - attrs.get("radius", radius); - -#if 1 - ITrackSegmentPtr track; - const int off = radius - 1; - - switch (start_angle) { - case 0: - track = make_spline_track(make_vector(off, -off, 0), - make_vector(1, 0, 0), - make_vector(0, 0, -1)); - break; - case 90: - track = make_spline_track(make_vector(-off, -off, 0), - make_vector(0, 0, -1), - make_vector(-1, 0, 0)); - break; - case 180: - track = make_spline_track(make_vector(-off, off, 0), - make_vector(-1, 0, 0), - make_vector(0, 0, 1)); - break; - case 270: - track = make_spline_track(make_vector(off, off, 0), - make_vector(0, 0, 1), - make_vector(1, 0, 0)); - break; - - default: - throw runtime_error("Invalid curved-track angle" - + boost::lexical_cast(start_angle)); - } - - my_map->set_track_at(tile, track); - -#else - // Legacy CurvedTrack - my_map->set_track_at(tile, - make_curved_track(start_angle, finish_angle, radius)); - -#endif -} - void MapLoader::handle_crossover_track(const AttributeSet& attrs) { my_map->set_track_at(tile, make_crossover_track()); } -void MapLoader::handle_gen_track(const AttributeSet& attrs) +void MapLoader::handle_spline_track(const AttributeSet& attrs) { Vector delta; track::Direction entry_dir, exit_dir; diff --git a/src/SBend.cpp b/src/SBend.cpp deleted file mode 100644 index af417dc..0000000 --- a/src/SBend.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright (C) 2010 Nick Gasson -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "ITrackSegment.hpp" -#include "TrackCommon.hpp" -#include "ILogger.hpp" -#include "XMLBuilder.hpp" -#include "BezierCurve.hpp" -#include "OpenGLHelper.hpp" -#include "Matrix.hpp" - -#include -#include - -#include - -// Spline curves which start and finish in the same direction -class SBend : public ITrackSegment, - private SleeperHelper, - private BezierHelper { -public: - SBend(track::Direction dir, int straight, int off); - - // ITrackSegment interface - void render() const {} - void merge(IMeshBufferPtr buf) const; - void set_origin(int x, int y, float h); - float segment_length(const track::TravelToken& token) const; - bool is_valid_direction(const track::Direction& dir) const; - track::Connection next_position(const track::TravelToken& token) const; - void get_endpoints(vector >& output) const; - void get_covers(vector >& output) const; - void get_height_locked(vector >& output) const; - ITrackSegmentPtr merge_exit(Point where, track::Direction dir); - track::TravelToken get_travel_token(track::Position pos, - track::Direction dir) const; - void next_state() {} - void prev_state() {} - bool has_multiple_states() const { return false; } - void set_state_render_hint() {} - - // IXMLSerialisable interface - xml::element to_xml() const; - -private: - void transform(const track::TravelToken& token, float delta) const; - void ensure_valid_direction(track::Direction dir) const; - - Point origin; - const int straight, offset; - float height; - track::Direction axis; - - BezierCurve curve; - IMeshBufferPtr rail_buf; - - typedef tuple Parameters; - typedef map MeshCache; - static MeshCache mesh_cache; -}; - -SBend::MeshCache SBend::mesh_cache; - -SBend::SBend(track::Direction dir, int straight, int off) - : straight(straight), offset(off), - height(0.0f), - axis(dir) -{ - assert(straight > 0); - - const float pinch = static_cast(straight) / 3.0f; - - const int reflect = (axis == axis::Y ? -1 : 1); - - const float offsetF = static_cast(offset * reflect); - const float straightF = static_cast(straight); - - Vector p1 = make_vector(0.0f, 0.0f, 0.0f); - Vector p2 = make_vector(pinch, 0.0f, 0.0f); - Vector p3 = make_vector(straightF - pinch, 0.0f, offsetF); - Vector p4 = make_vector(straightF, 0.0f, offsetF); - - curve = make_bezier_curve(p1, p2, p3, p4); - - Parameters parms = make_tuple(straight, offset * reflect); - MeshCache::iterator it = mesh_cache.find(parms); - if (it == mesh_cache.end()) { - rail_buf = make_bezier_rail_mesh(curve); - mesh_cache[parms] = rail_buf; - } - else - rail_buf = (*it).second; -} - -void SBend::set_origin(int x, int y, float h) -{ - origin = make_point(x, y); - height = h; -} - -void SBend::merge(IMeshBufferPtr buf) const -{ - Vector off = make_vector( - static_cast(origin.x), - height, - static_cast(origin.y)); - - float y_angle = axis == axis::Y ? -90.0f : 0.0f; - - { - Vector t = make_vector(-0.5f, 0.0f, 0.0f); - buf->merge(rail_buf, off + rotateY(t, y_angle), y_angle); - } - - // Draw the sleepers - for (float i = 0.2f; i < curve.length; i += 0.25f) { - Vector v = curve(i / curve.length); - - Vector t = make_vector(v.x - 0.5f, 0.0f, v.z); - - const Vector deriv = curve.deriv(i / curve.length); - const float angle = - rad_to_deg(atanf(deriv.z / deriv.x)); - - merge_sleeper(buf, off + rotateY(t, y_angle), y_angle - angle); - } -} - -float SBend::segment_length(const track::TravelToken& token) const -{ - return curve.length; -} - -bool SBend::is_valid_direction(const track::Direction& dir) const -{ - if (axis == axis::X) - return dir == axis::X || -dir == axis::X; - else - return dir == axis::Y || -dir == axis::Y; -} - -track::Connection SBend::next_position(const track::TravelToken& token) const -{ - ensure_valid_direction(token.direction); - - Point disp; - - if (token.direction == axis::X) - disp = make_point(straight, offset); - else if (token.direction == -axis::X) - disp = make_point(-1, 0); - else if (token.direction == axis::Y) - disp = make_point(offset, straight); - else if (token.direction == -axis::Y) - disp = make_point(0, -1); - else - assert(false); - - return make_pair(origin + disp, token.direction); -} - -void SBend::get_endpoints(vector >& output) const -{ - output.push_back(origin); - - if (axis == axis::X) - output.push_back(origin + make_point(straight - 1, offset)); - else - output.push_back(origin + make_point(offset, straight - 1)); -} - -void SBend::get_covers(vector >& output) const -{ - vector > exits; - get_endpoints(exits); - - set > tmp; - - for (float f = 0.0f; f < 1.0f; f += 0.1f) { - Vector curve_value = curve(f); - - curve_value.z += 0.5f; - - int x, y; - if (axis == axis::X) { - x = static_cast(floor(curve_value.x + origin.x)); - y = static_cast(floor(curve_value.z + origin.y)); - } - else { - x = -static_cast(floor(curve_value.z - origin.x)); - y = static_cast(floor(curve_value.x + origin.y)); - } - - Point p = make_point(x, y); - - if (p != exits.at(0) && p != exits.at(1)) - tmp.insert(p); - } - - copy(tmp.begin(), tmp.end(), back_inserter(output)); -} - -void SBend::get_height_locked(vector >& output) const -{ - -} - -ITrackSegmentPtr SBend::merge_exit(Point where, track::Direction dir) -{ - return ITrackSegmentPtr(); -} - -track::TravelToken SBend::get_travel_token(track::Position pos, - track::Direction dir) const -{ - using namespace placeholders; - - ensure_valid_direction(dir); - - track::TravelToken tok = { - dir, - pos, - bind(&SBend::transform, this, _1, _2), - track::flat_gradient_func, - 1 - }; - return tok; -} - -void SBend::transform(const track::TravelToken& token, float delta) const -{ - assert(delta < curve.length); - - const bool backwards = token.direction == -axis; - if (backwards) - delta = curve.length - delta; - - const float curve_delta = delta / curve.length; - - Vector curve_value = curve(curve_delta); - - const Vector deriv = curve.deriv(curve_delta); - const float angle = - rad_to_deg(atanf(deriv.z / deriv.x)); - - float x_trans, y_trans; - if (axis == axis::X) { - x_trans = curve_value.x; - y_trans = curve_value.z; - } - else if (axis == axis::Y) { - x_trans = -curve_value.z; - y_trans = curve_value.x; - } - else - assert(false); - - glTranslatef( - static_cast(origin.x) + x_trans, - height, - static_cast(origin.y) + y_trans); - - if (axis == axis::Y) - glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); - - glTranslatef(-0.5f, 0.0f, 0.0f); - - glRotatef(-angle, 0.0f, 1.0f, 0.0f); - - if (backwards) - glRotatef(180.0f, 0.0f, 1.0f, 0.0f); -} - -void SBend::ensure_valid_direction(track::Direction dir) const -{ - if (!is_valid_direction(dir)) - throw runtime_error - ("Invalid direction on s-bend track: " - + boost::lexical_cast(dir) - + " (should be parallel to " - + boost::lexical_cast(axis) + ")"); -} - -xml::element SBend::to_xml() const -{ - return xml::element("sbend-track") - .add_attribute("align", axis == axis::X ? "x" : "y") - .add_attribute("offset", offset) - .add_attribute("straight", straight); -} - -ITrackSegmentPtr makeSBend(track::Direction dir, int straight, int off) -{ - return ITrackSegmentPtr(new SBend(dir, straight, off)); -} -- 2.39.2