From 3e647c3061b5563bc645858ff3bf9d7bec18c252 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 7 Jun 2009 18:10:24 +0100 Subject: [PATCH] Point drawing --- include/ITrackSegment.hpp | 2 +- include/TrackCommon.hpp | 2 ++ src/Editor.cpp | 32 +++++++++++++++++++++++--------- src/Mesh.cpp | 20 +++----------------- src/Points.cpp | 28 +++++++++++++++++++++------- src/StraightTrack.cpp | 33 +++++++++++++++++++++++++++++++-- src/TrackCommon.cpp | 38 +++++++++++++++++++++++++++++++------- 7 files changed, 112 insertions(+), 43 deletions(-) diff --git a/include/ITrackSegment.hpp b/include/ITrackSegment.hpp index 404d8e4..d38b227 100644 --- a/include/ITrackSegment.hpp +++ b/include/ITrackSegment.hpp @@ -113,6 +113,6 @@ ITrackSegmentPtr makeStraightTrack(const track::Direction& aDirection); ITrackSegmentPtr makeCurvedTrack(track::Angle aStartAngle, track::Angle aFinishAngle, int aRadius); ITrackSegmentPtr makeCrossoverTrack(); -ITrackSegmentPtr makePoints(); +ITrackSegmentPtr makePoints(track::Direction aDirection, bool reflect); #endif diff --git a/include/TrackCommon.hpp b/include/TrackCommon.hpp index d2b3f33..e7d7b9c 100644 --- a/include/TrackCommon.hpp +++ b/include/TrackCommon.hpp @@ -24,10 +24,12 @@ void renderSleeper(); void renderStraightRail(); void renderHypTanRail(); +void renderReflectedHypTanRail(); void renderCurvedTrack(int baseRadius, track::Angle startAngle, track::Angle endAngle); void transformToOrigin(int baseRadius, track::Angle startAngle); float hypTanCurveFunc(float x); +float reflectedHypTanCurveFunc(float x); // Track constants namespace track { diff --git a/src/Editor.cpp b/src/Editor.cpp index 1c90d9d..fa998db 100644 --- a/src/Editor.cpp +++ b/src/Editor.cpp @@ -237,21 +237,35 @@ void Editor::drawDraggedStraight(const track::Direction& anAxis, int aLength) // Called when the user has finished dragging a rectangle for track // Connect the beginning and end up in the simplest way possible void Editor::drawDraggedTrack() -{ - // REMOVE - ITrackSegmentPtr p = makePoints(); - p->setOrigin(myDragBegin.x, myDragBegin.y); - myMap->setTrackAt(myDragBegin, p); - return; - - +{ track::Direction straight; // Orientation for straight track section - + int xmin, xmax, ymin, ymax; dragBoxBounds(xmin, xmax, ymin, ymax); int xlen = abs(xmax - xmin) + 1; int ylen = abs(ymax - ymin) + 1; + + // Try to merge the start and end directly + const track::Direction mergeAxis = + xlen > ylen ? (myDragBegin.x < myDragEnd.x ? -axis::X : axis::X) + : (myDragBegin.y < myDragEnd.y ? -axis::Y : axis::Y); + if (myMap->isValidTrack(myDragEnd)) { + ITrackSegmentPtr merged = + myMap->trackAt(myDragEnd)->mergeExit(myDragBegin, mergeAxis); + + if (merged) { + // Erase all the tiles covered + for (int x = xmin; x <= xmax; x++) { + for (int y = ymin; y <= ymax; y++) + myMap->eraseTile(x, y); + } + + myMap->setTrackAt(myDragEnd, merged); + return; + } + } + // Normalise the coordinates so the start is always the one with // the smallest x-coordinate if (myDragBegin.x > myDragEnd.x) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 97e832c..f719545 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -549,27 +549,13 @@ void VBOMesh::render() const IMeshPtr makeMesh(IMeshBufferPtr aBuffer) { - static bool havePrintedMeshChoice = false; - - aBuffer->printStats(); + //aBuffer->printStats(); // Prefer VBOs for large meshes meshes - if (aBuffer->vertexCount() > 100 && GLEW_ARB_vertex_buffer_object) { - if (!havePrintedMeshChoice) { - log() << "Using VBO mesh implementation"; - havePrintedMeshChoice = true; - } - + if (aBuffer->vertexCount() > 100 && GLEW_ARB_vertex_buffer_object) return IMeshPtr(new VBOMesh(aBuffer)); - } - else { - if (!havePrintedMeshChoice) { - log() << "Using vertex array mesh implementation"; - havePrintedMeshChoice = true; - } - + else return IMeshPtr(new VertexArrayMesh(aBuffer)); - } } IMeshBufferPtr makeMeshBuffer() diff --git a/src/Points.cpp b/src/Points.cpp index 1c900e9..893ffeb 100644 --- a/src/Points.cpp +++ b/src/Points.cpp @@ -25,7 +25,7 @@ // Forks in the track class Points : public ITrackSegment { public: - Points(); + Points(track::Direction aDirection, bool reflect); // ITrackSegment interface void render() const; @@ -40,10 +40,13 @@ public: xml::element toXml() const; private: int myX, myY; + track::Direction myAxis; + bool amReflected; }; -Points::Points() - : myX(0), myY(0) +Points::Points(track::Direction aDirection, bool reflect) + : myX(0), myY(0), + myAxis(aDirection), amReflected(reflect) { } @@ -52,7 +55,17 @@ void Points::render() const { glPushMatrix(); - renderHypTanRail(); + if (myAxis == -axis::X) + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); + else if (myAxis == -axis::Y) + glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + else if (myAxis == axis::Y) + glRotatef(270.0f, 0.0f, 1.0f, 0.0f); + + if (amReflected) + renderReflectedHypTanRail(); + else + renderHypTanRail(); glPushMatrix(); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); @@ -104,7 +117,8 @@ void Points::getEndpoints(std::list >& aList) const ITrackSegmentPtr Points::mergeExit(const Point& aPoint, const track::Direction& aDirection) { - + // Cant merge with anything + return ITrackSegmentPtr(); } xml::element Points::toXml() const @@ -112,7 +126,7 @@ xml::element Points::toXml() const } -ITrackSegmentPtr makePoints() +ITrackSegmentPtr makePoints(track::Direction aDirection, bool reflect) { - return ITrackSegmentPtr(new Points); + return ITrackSegmentPtr(new Points(aDirection, reflect)); } diff --git a/src/StraightTrack.cpp b/src/StraightTrack.cpp index 59fb93f..28d2618 100644 --- a/src/StraightTrack.cpp +++ b/src/StraightTrack.cpp @@ -110,14 +110,43 @@ StraightTrack::transformFunc(const track::Direction& aDirection) const ITrackSegmentPtr StraightTrack::mergeExit(const Point& aPoint, const track::Direction& aDirection) { + debug() << "mergeExit aPoint=" << aPoint + << " aDirection=" << aDirection + << " me=" << makePoint(myX, myY); + + const Point me = makePoint(myX, myY); + // See if this is already a valid exit - if (isValidDirection(aDirection) && aPoint == makePoint(myX, myY)) + if (isValidDirection(aDirection) && aPoint == me) return shared_from_this(); // See if we can make this a crossover track - if (myDirection != aDirection) + if (myDirection != aDirection && aPoint == me) return makeCrossoverTrack(); + // See if we can make some points + if (isValidDirection(aDirection)) { + // X-aligned points + if (aPoint == me + makePoint(-2, 1)) + return makePoints(-axis::X, true); + else if (aPoint == me + makePoint(-2, -1)) + return makePoints(-axis::X, false); + else if (aPoint == me + makePoint(2, 1)) + return makePoints(axis::X, false); + else if (aPoint == me + makePoint(2, -1)) + return makePoints(axis::X, true); + + // Y-aligned points + if (aPoint == me + makePoint(1, -2)) + return makePoints(-axis::Y, false); + else if (aPoint == me + makePoint(-1, -2)) + return makePoints(-axis::Y, true); + else if (aPoint == me + makePoint(1, 2)) + return makePoints(axis::Y, true); + else if (aPoint == me + makePoint(-1, 2)) + return makePoints(axis::Y, false); + } + // Not possible to merge return ITrackSegmentPtr(); } diff --git a/src/TrackCommon.cpp b/src/TrackCommon.cpp index 9d210ba..27e808e 100644 --- a/src/TrackCommon.cpp +++ b/src/TrackCommon.cpp @@ -36,7 +36,8 @@ namespace { const float SLEEPER_LENGTH = 0.8f; - IMeshPtr theSleeperMesh, theRailMesh, theHypTanRailMesh; + IMeshPtr theSleeperMesh, theRailMesh; + IMeshPtr theHypTanRailMesh, theReflectedHypTanRailMesh; typedef map CurvedRailMeshMap; CurvedRailMeshMap theCurvedRailMeshes; @@ -122,7 +123,7 @@ namespace { } // The rail mesh used for points and S-bends - void generateHypTanRailMesh() + IMeshPtr generateFuncRailMesh(function aFunc) { IMeshBufferPtr buf = makeMeshBuffer(); @@ -130,10 +131,10 @@ namespace { const float xmax = 3.0f; for (float x = 0.0f; x < xmax - step; x += step) { - const float y1 = hypTanCurveFunc(x); + const float y1 = aFunc(x); debug() << x << " --> " << y1; - const float y2 = hypTanCurveFunc(x + step); + const float y2 = aFunc(x + step); // Top of rail buf->addQuad(makeVector(x, track::RAIL_HEIGHT, y1), @@ -158,7 +159,7 @@ namespace { METAL); } - theHypTanRailMesh = makeMesh(buf); + return makeMesh(buf); } enum RailType { @@ -172,7 +173,7 @@ namespace { - (type == OUTER_RAIL ? 0 : GAUGE); const float r = R - RAIL_WIDTH; - const float step = 0.1f; + const float step = 0.2f; // Top of rail for (float theta = 0; theta < M_PI / 2.0f; theta += step) { @@ -265,6 +266,12 @@ float hypTanCurveFunc(float x) return 0.5f * (1.0f + tanh(1.8f * x - 3.5f)); } +// The above function reflected about the x-axis +float reflectedHypTanCurveFunc(float x) +{ + return -hypTanCurveFunc(x); +} + // Draw a sleeper in the current maxtrix location void renderSleeper() { @@ -290,7 +297,7 @@ void renderStraightRail() void renderHypTanRail() { if (!theHypTanRailMesh) - generateHypTanRailMesh(); + theHypTanRailMesh = generateFuncRailMesh(hypTanCurveFunc); glPushMatrix(); @@ -303,6 +310,23 @@ void renderHypTanRail() glPopMatrix(); } +void renderReflectedHypTanRail() +{ + if (!theReflectedHypTanRailMesh) + theReflectedHypTanRailMesh = + generateFuncRailMesh(reflectedHypTanCurveFunc); + + glPushMatrix(); + + glTranslatef(-0.5f, 0.0f, -GAUGE/2.0f); + theReflectedHypTanRailMesh->render(); + + glTranslatef(0.0f, 0.0f, GAUGE); + theReflectedHypTanRailMesh->render(); + + glPopMatrix(); +} + // Move to the origin of a curved section of track void transformToOrigin(int baseRadius, track::Angle startAngle) { -- 2.39.2