From b3ee5f28eb7da7b23b35bb7e932ced54dd1db3f4 Mon Sep 17 00:00:00 2001 From: Nick Gasson <nick@nickg.me.uk> Date: Sun, 30 May 2010 20:12:27 +0100 Subject: [PATCH] Start making track part of the static scenery --- include/ITrackSegment.hpp | 6 +++- include/TrackCommon.hpp | 24 +++++++++++++++- src/CrossoverTrack.cpp | 49 ++++++++++++++++++++++++++++---- src/CurvedTrack.cpp | 3 +- src/Map.cpp | 14 ++++++--- src/Points.cpp | 3 +- src/SBend.cpp | 1 + src/SlopeTrack.cpp | 1 + src/StraightTrack.cpp | 31 ++++++++++++++++++-- src/TrackCommon.cpp | 60 ++++++++++++++++++++++++++++++++++----- 10 files changed, 170 insertions(+), 22 deletions(-) diff --git a/include/ITrackSegment.hpp b/include/ITrackSegment.hpp index 1946f69..5e57844 100644 --- a/include/ITrackSegment.hpp +++ b/include/ITrackSegment.hpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -21,6 +21,7 @@ #include "Platform.hpp" #include "Maths.hpp" #include "IXMLSerialisable.hpp" +#include "IMesh.hpp" #include <vector> #include <set> @@ -98,6 +99,9 @@ struct ITrackSegment : IXMLSerialisable { // Render the track with the origin in the centre virtual void render() const = 0; + // Merge this track segment's mesh into a scenery mesh buffer + virtual void merge(IMeshBufferPtr buf) const = 0; + // Set the absolute position of the track in the world virtual void setOrigin(int x, int y, float height) = 0; diff --git a/include/TrackCommon.hpp b/include/TrackCommon.hpp index 499e524..8afd796 100644 --- a/include/TrackCommon.hpp +++ b/include/TrackCommon.hpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -22,9 +22,31 @@ #include "IMesh.hpp" #include "BezierCurve.hpp" +class StraightTrackHelper { +public: + void mergeStraightRail(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const; + +private: + void mergeOneRail(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const; + + static IMeshBufferPtr railBuf; +}; + +class SleeperHelper { +public: + void mergeSleeper(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const; + +private: + static IMeshBufferPtr sleeperBuf; +}; + // Common track rendering functions void renderSleeper(); void renderStraightRail(); + void renderCurvedTrack(int baseRadius, track::Angle startAngle, track::Angle endAngle); void renderRailMesh(IMeshPtr aMesh); diff --git a/src/CrossoverTrack.cpp b/src/CrossoverTrack.cpp index e8459e4..0f45b8f 100644 --- a/src/CrossoverTrack.cpp +++ b/src/CrossoverTrack.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -27,14 +27,14 @@ #include <GL/glu.h> #include <boost/lexical_cast.hpp> -using namespace std; -using namespace std::tr1; -using namespace std::tr1::placeholders; +using namespace placeholders; using namespace boost; // A section of track that allows travelling along both axis class CrossoverTrack : public ITrackSegment, - public enable_shared_from_this<CrossoverTrack> { + public enable_shared_from_this<CrossoverTrack>, + private StraightTrackHelper, + private SleeperHelper { public: CrossoverTrack() : myX(0), myY(0), height(0.0f) {} ~CrossoverTrack() {} @@ -42,6 +42,8 @@ public: void setOrigin(int x, int y, float h); void render() const; + void merge(IMeshBufferPtr buf) const; + float segmentLength(const track::TravelToken& aToken) const; bool isValidDirection(const track::Direction& aDirection) const; track::Connection nextPosition(const track::TravelToken& aToken) const; @@ -65,6 +67,43 @@ private: float height; }; +void CrossoverTrack::merge(IMeshBufferPtr buf) const +{ + // Render the y-going rails and sleepers + { + Vector<float> off = makeVector( + static_cast<float>(myX), + height, + static_cast<float>(myY)); + + mergeStraightRail(buf, off, 0.0f); + + off += makeVector(0.0f, 0.0f, -0.4f); + + for (int i = 0; i < 4; i++) { + mergeSleeper(buf, off, 90.0f); + off += makeVector(0.0f, 0.0f, 0.25f); + } + } + + // Render the x-going rails and sleepers + { + Vector<float> off = makeVector( + static_cast<float>(myX), + height, + static_cast<float>(myY)); + + mergeStraightRail(buf, off, 90.0f); + + off += makeVector(-0.4f, 0.0f, 0.0f); + + for (int i = 0; i < 4; i++) { + mergeSleeper(buf, off, 0.0f); + off += makeVector(0.25f, 0.0f, 0.0f); + } + } +} + void CrossoverTrack::render() const { glPushMatrix(); diff --git a/src/CurvedTrack.cpp b/src/CurvedTrack.cpp index 713662c..1f24abd 100644 --- a/src/CurvedTrack.cpp +++ b/src/CurvedTrack.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -41,6 +41,7 @@ public: ~CurvedTrack(); void render() const; + void merge(IMeshBufferPtr buf) const {} void setOrigin(int x, int y, float h); float segmentLength(const track::TravelToken& aToken) const; diff --git a/src/Map.cpp b/src/Map.cpp index c61db22..b510bdf 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -620,6 +620,15 @@ void Map::buildMesh(int id, Point<int> botLeft, Point<int> topRight) if (tile.scenery) tile.scenery->merge(buf); + + // Draw the track, if any + if (tile.track && tile.track->needsRendering(frameNum)) { + // TODO: how will this work with track that spans + // multiple sectors? + tile.track->get()->merge(buf); + + tile.track->renderedOn(frameNum); + } } } @@ -769,12 +778,9 @@ void Map::renderSector(IGraphicsPtr aContext, int id, glEnd(); } - // Draw the track, if any Tile& tile = tileAt(x, y); + if (tile.track && tile.track->needsRendering(frameNum)) { - tile.track->get()->render(); - tile.track->renderedOn(frameNum); - #if 0 // Draw the endpoints for debugging vector<Point<int> > tiles; diff --git a/src/Points.cpp b/src/Points.cpp index 22e4f52..4452996 100644 --- a/src/Points.cpp +++ b/src/Points.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -33,6 +33,7 @@ public: // ITrackSegment interface void render() const; + void merge(IMeshBufferPtr buf) const {} void setOrigin(int x, int y, float h) { myX = x; myY = y; height = h; } float segmentLength(const track::TravelToken& aToken) const; bool isValidDirection(const track::Direction& aDirection) const; diff --git a/src/SBend.cpp b/src/SBend.cpp index 6b1695c..44a235e 100644 --- a/src/SBend.cpp +++ b/src/SBend.cpp @@ -34,6 +34,7 @@ public: // ITrackSegment interface void render() const; + void merge(IMeshBufferPtr buf) const {} void setOrigin(int x, int y, float h); float segmentLength(const track::TravelToken& token) const; bool isValidDirection(const track::Direction& dir) const; diff --git a/src/SlopeTrack.cpp b/src/SlopeTrack.cpp index c6f83f7..a5164c1 100644 --- a/src/SlopeTrack.cpp +++ b/src/SlopeTrack.cpp @@ -37,6 +37,7 @@ public: // ITrackSegment interface void render() const; + void merge(IMeshBufferPtr buf) const {} void setOrigin(int x, int y, float h); float segmentLength(const track::TravelToken& token) const; track::TravelToken getTravelToken(track::Position pos, diff --git a/src/StraightTrack.cpp b/src/StraightTrack.cpp index d7b67d7..a12ea00 100644 --- a/src/StraightTrack.cpp +++ b/src/StraightTrack.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -19,6 +19,7 @@ #include "TrackCommon.hpp" #include "ILogger.hpp" #include "XMLBuilder.hpp" +#include "Matrix.hpp" #include <cassert> #include <stdexcept> @@ -33,12 +34,15 @@ using namespace track; // Concrete implementation of straight-line pieces of track class StraightTrack : public ITrackSegment, - public enable_shared_from_this<StraightTrack> { + public enable_shared_from_this<StraightTrack>, + private StraightTrackHelper, + private SleeperHelper { public: StraightTrack(const Direction& aDirection); ~StraightTrack(); void render() const; + void merge(IMeshBufferPtr buf) const; void setOrigin(int x, int y, float h); float segmentLength(const track::TravelToken& token) const { return 1.0f; } @@ -232,6 +236,29 @@ void StraightTrack::render() const glPopMatrix(); } +void StraightTrack::merge(IMeshBufferPtr buf) const +{ + Vector<float> off = makeVector( + static_cast<float>(origin.x), + height, + static_cast<float>(origin.y)); + + float yAngle = direction == axis::X ? 90.0f : 0.0f; + + mergeStraightRail(buf, off, yAngle); + + yAngle += 90.0f; + + Matrix<float, 4> r = Matrix<float, 4>::rotation(yAngle, 0.0f, 1.0f, 0.0f); + off += r.transform(makeVector(-0.4f, 0.0f, 0.0f)); + + for (int i = 0; i < 4; i++) { + mergeSleeper(buf, off, yAngle); + + off += r.transform(makeVector(0.25f, 0.0f, 0.0f)); + } +} + xml::element StraightTrack::toXml() const { return xml::element("straightTrack") diff --git a/src/TrackCommon.cpp b/src/TrackCommon.cpp index 78b4867..51888fd 100644 --- a/src/TrackCommon.cpp +++ b/src/TrackCommon.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2009 Nick Gasson +// 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 @@ -19,6 +19,7 @@ #include "ILogger.hpp" #include "Maths.hpp" #include "IMesh.hpp" +#include "Matrix.hpp" #include <cmath> #include <map> @@ -40,7 +41,7 @@ namespace { const Colour METAL = makeColour(0.5f, 0.5f, 0.5f); - void generateSleeperMesh() + IMeshBufferPtr generateSleeperMeshBuffer() { IMeshBufferPtr buf = makeMeshBuffer(); @@ -87,10 +88,15 @@ namespace { makeVector(-sleeperOff, 0.0f, r), brown); - theSleeperMesh = makeMesh(buf); + return buf; } - void generateRailMesh() + void generateSleeperMesh() + { + theSleeperMesh = makeMesh(generateSleeperMeshBuffer()); + } + + IMeshBufferPtr generateRailMeshBuffer() { IMeshBufferPtr buf = makeMeshBuffer(); @@ -113,9 +119,14 @@ namespace { makeVector(RAIL_WIDTH/2.0f, 0.0f, 1.0f), makeVector(RAIL_WIDTH/2.0f, 0.0f, 0.0f), makeVector(RAIL_WIDTH/2.0f, track::RAIL_HEIGHT, 0.0f), - METAL); - - theRailMesh = makeMesh(buf); + METAL); + + return buf; + } + + void generateRailMesh() + { + theRailMesh = makeMesh(generateRailMeshBuffer()); } void buildOneBezierRail(const BezierCurve<float>& func, @@ -261,6 +272,7 @@ namespace { theRailMesh->render(); } + } IMeshPtr makeBezierRailMesh(const BezierCurve<float>& aFunc) @@ -268,6 +280,17 @@ IMeshPtr makeBezierRailMesh(const BezierCurve<float>& aFunc) return generateBezierRailMesh(aFunc); } +IMeshBufferPtr SleeperHelper::sleeperBuf; + +void SleeperHelper::mergeSleeper(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const +{ + if (!sleeperBuf) + sleeperBuf = generateSleeperMeshBuffer(); + + buf->merge(sleeperBuf, off, yAngle); +} + // Draw a sleeper in the current matrix location void renderSleeper() { @@ -304,6 +327,29 @@ void renderStraightRail() glPopMatrix(); } +IMeshBufferPtr StraightTrackHelper::railBuf; + +void StraightTrackHelper::mergeOneRail(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const +{ + if (!railBuf) + railBuf= generateRailMeshBuffer(); + + buf->merge(railBuf, off, yAngle); +} + +void StraightTrackHelper::mergeStraightRail(IMeshBufferPtr buf, + Vector<float> off, float yAngle) const +{ + Matrix<float, 4> r = Matrix<float, 4>::rotation(yAngle, 0.0f, 1.0f, 0.0f); + + off += r.transform(makeVector(-GAUGE/2.0f, 0.0f, -0.5f)); + mergeOneRail(buf, off, yAngle); + + off += r.transform(makeVector(GAUGE, 0.0f, 0.0f)); + mergeOneRail(buf, off, yAngle); +} + // Move to the origin of a curved section of track void transformToOrigin(int baseRadius, track::Angle startAngle) { -- 2.39.5