diff options
Diffstat (limited to 'game/network/rail.cpp')
-rw-r--r-- | game/network/rail.cpp | 156 |
1 files changed, 90 insertions, 66 deletions
diff --git a/game/network/rail.cpp b/game/network/rail.cpp index fd07ace..c0e597d 100644 --- a/game/network/rail.cpp +++ b/game/network/rail.cpp @@ -1,4 +1,5 @@ #include "rail.h" +#include "game/gamestate.h" #include "network.h" #include <game/network/network.impl.h> // IWYU pragma: keep #include <gfx/gl/sceneShader.h> @@ -8,7 +9,7 @@ template class NetworkOf<RailLink, RailLinkStraight, RailLinkCurve>; constexpr auto RAIL_CROSSSECTION_VERTICES {5U}; -constexpr Size3D RAIL_HEIGHT {0, 0, 250.F}; +constexpr Size3D RAIL_HEIGHT {0, 0, 50.F}; RailLinks::RailLinks() : NetworkOf<RailLink, RailLinkStraight, RailLinkCurve> {"rails.jpg"} { } @@ -32,40 +33,39 @@ RailLinks::addLinksBetween(GlobalPosition3D start, GlobalPosition3D end) } // Find start link/end - opposite entry dir to existing link; so pi +... const Angle dir = pi + findNodeDirection(node1ins.first); - if (dir == vector_yaw(end - start)) { + if (dir == vector_yaw(difference(end, start))) { return addLink<RailLinkStraight>(start, end); } const auto flatStart {start.xy()}, flatEnd {end.xy()}; if (node2ins.second == NodeIs::InNetwork) { auto midheight = [&](auto mid) { - const auto sm = glm::length(RelativePosition2D(flatStart - mid)), - em = glm::length(RelativePosition2D(flatEnd - mid)); - return start.z + GlobalDistance(RelativeDistance(end.z - start.z) * (sm / (sm + em))); + const auto startToMid = ::distance<2>(flatStart, mid); + const auto endToMid = ::distance<2>(flatEnd, mid); + return start.z + GlobalDistance(RelativeDistance(end.z - start.z) * (startToMid / (startToMid + endToMid))); }; const float dir2 = pi + findNodeDirection(node2ins.first); - if (const auto radii = find_arcs_radius(flatStart, dir, flatEnd, dir2); radii.first < radii.second) { - const auto radius {radii.first}; - const auto c1 = flatStart + (sincosf(dir + half_pi) * radius); - const auto c2 = flatEnd + (sincosf(dir2 + half_pi) * radius); - const auto mid = (c1 + c2) / 2; + const auto radii = find_arcs_radius(flatStart, dir, flatEnd, dir2); + if (radii.first < radii.second) { + const auto radius = radii.first; + const auto centre1 = flatStart + (sincos(dir + half_pi) * radius); + const auto centre2 = flatEnd + (sincos(dir2 + half_pi) * radius); + const auto mid = (centre1 + centre2) / 2; const auto midh = mid || midheight(mid); - addLink<RailLinkCurve>(start, midh, c1); - return addLink<RailLinkCurve>(end, midh, c2); - } - else { - const auto radius {radii.second}; - const auto c1 = flatStart + (sincosf(dir - half_pi) * radius); - const auto c2 = flatEnd + (sincosf(dir2 - half_pi) * radius); - const auto mid = (c1 + c2) / 2; - const auto midh = mid || midheight(mid); - addLink<RailLinkCurve>(midh, start, c1); - return addLink<RailLinkCurve>(midh, end, c2); + addLink<RailLinkCurve>(start, midh, centre1); + return addLink<RailLinkCurve>(end, midh, centre2); } + const auto radius = radii.second; + const auto centre1 = flatStart + (sincos(dir - half_pi) * radius); + const auto centre2 = flatEnd + (sincos(dir2 - half_pi) * radius); + const auto mid = (centre1 + centre2) / 2; + const auto midh = mid || midheight(mid); + addLink<RailLinkCurve>(midh, start, centre1); + return addLink<RailLinkCurve>(midh, end, centre2); } - const auto diff {end - start}; - const auto vy {vector_yaw(diff)}; - const auto n2ed {(vy * 2) - dir - pi}; - const auto centre {find_arc_centre(flatStart, dir, flatEnd, n2ed)}; + const auto diff = difference(end, start); + const auto yaw = vector_yaw(diff); + const auto n2ed = (yaw * 2) - dir - pi; + const auto centre = find_arc_centre(flatStart, dir, flatEnd, n2ed); if (centre.second) { // right hand arc std::swap(start, end); @@ -73,53 +73,61 @@ RailLinks::addLinksBetween(GlobalPosition3D start, GlobalPosition3D end) return addLink<RailLinkCurve>(start, end, centre.first); } -constexpr const std::array<RelativePosition3D, RAIL_CROSSSECTION_VERTICES> railCrossSection {{ - {-1900.F, 0.F, 0.F}, - {-608.F, 0.F, RAIL_HEIGHT.z}, - {0, 0.F, RAIL_HEIGHT.z * .7F}, - {608.F, 0.F, RAIL_HEIGHT.z}, - {1900.F, 0.F, 0.F}, -}}; -constexpr const std::array<float, RAIL_CROSSSECTION_VERTICES> railTexturePos { - 0.F, - .34F, - .5F, - .66F, - 1.F, -}; -constexpr auto sleepers {5.F}; // There are 5 repetitions of sleepers in the texture - -inline auto -round_sleepers(const float v) -{ - return round_frac(v, sleepers); +namespace { + constexpr const std::array<RelativePosition3D, RAIL_CROSSSECTION_VERTICES> RAIL_CROSS_SECTION {{ + {-1330.F, 0.F, 0}, + {-608.F, 0.F, RAIL_HEIGHT.z}, + {0, 0.F, RAIL_HEIGHT.z / 2}, + {608.F, 0.F, RAIL_HEIGHT.z}, + {1330.F, 0.F, 0}, + }}; + constexpr const std::array<float, RAIL_CROSSSECTION_VERTICES> RAIL_TEXTURE_POS { + 0.15F, + .34F, + .5F, + .66F, + 0.85F, + }; + template<std::floating_point T> constexpr T SLEEPERS_PER_TEXTURE {5}; + template<std::floating_point T> constexpr T TEXTURE_LENGTH {2'000}; + template<std::floating_point T> constexpr T SLEEPER_LENGTH {T {1} / SLEEPERS_PER_TEXTURE<T>}; + + template<std::floating_point T> + constexpr auto + roundSleepers(const T length) + { + return round_frac(length / TEXTURE_LENGTH<T>, SLEEPER_LENGTH<T>); + } } -RailLinkStraight::RailLinkStraight(NetworkLinkHolder<RailLinkStraight> & instances, const Node::Ptr & a, - const Node::Ptr & b) : RailLinkStraight(instances, a, b, b->pos - a->pos) +RailLinkStraight::RailLinkStraight(NetworkLinkHolder<RailLinkStraight> & instances, const Node::Ptr & nodeA, + const Node::Ptr & nodeB) : RailLinkStraight(instances, nodeA, nodeB, nodeB->pos - nodeA->pos) { } -RailLinkStraight::RailLinkStraight( - NetworkLinkHolder<RailLinkStraight> & instances, Node::Ptr a, Node::Ptr b, const RelativePosition3D & diff) : - Link({std::move(a), vector_yaw(diff)}, {std::move(b), vector_yaw(-diff)}, glm::length(diff)), +RailLinkStraight::RailLinkStraight(NetworkLinkHolder<RailLinkStraight> & instances, Node::Ptr nodeA, Node::Ptr nodeB, + const RelativePosition3D & diff) : + Link({.node = std::move(nodeA), .dir = vector_yaw(diff)}, {.node = std::move(nodeB), .dir = vector_yaw(-diff)}, + glm::length(diff)), instance {instances.vertices.acquire( - ends[0].node->pos, ends[1].node->pos, flat_orientation(diff), round_sleepers(length / 2000.F))} + ends[0].node->pos, ends[1].node->pos, flat_orientation(diff), roundSleepers(length))} { } -RailLinkCurve::RailLinkCurve(NetworkLinkHolder<RailLinkCurve> & instances, const Node::Ptr & a, const Node::Ptr & b, - GlobalPosition2D c) : RailLinkCurve(instances, a, b, c || a->pos.z, {c, a->pos, b->pos}) +RailLinkCurve::RailLinkCurve(NetworkLinkHolder<RailLinkCurve> & instances, const Node::Ptr & nodeA, + const Node::Ptr & nodeB, GlobalPosition2D centre) : + RailLinkCurve(instances, nodeA, nodeB, centre || nodeA->pos.z, ::distance<2>(nodeA->pos.xy(), centre), + {centre, nodeA->pos, nodeB->pos}) { } -RailLinkCurve::RailLinkCurve(NetworkLinkHolder<RailLinkCurve> & instances, const Node::Ptr & a, const Node::Ptr & b, - GlobalPosition3D c, const Arc arc) : - Link({a, normalize(arc.first + half_pi)}, {b, normalize(arc.second - half_pi)}, - glm::length(RelativePosition3D(a->pos - c)) * arc.length()), - LinkCurve {c, glm::length(RelativePosition3D(ends[0].node->pos - c)), arc}, - instance {instances.vertices.acquire(ends[0].node->pos, ends[1].node->pos, c, round_sleepers(length / 2000.F), - half_pi - arc.first, half_pi - arc.second, radius)} +RailLinkCurve::RailLinkCurve(NetworkLinkHolder<RailLinkCurve> & instances, const Node::Ptr & nodeA, + const Node::Ptr & nodeB, GlobalPosition3D centre, RelativeDistance radius, const Arc arc) : + Link({.node = nodeA, .dir = normalize(arc.first + half_pi)}, + {.node = nodeB, .dir = normalize(arc.second - half_pi)}, + glm::length(RelativePosition2D {radius * arc.length(), difference(nodeA->pos, nodeB->pos).z})), + LinkCurve {centre, radius, arc}, instance {instances.vertices.acquire(ends[0].node->pos, ends[1].node->pos, centre, + roundSleepers(length), half_pi - arc.first, half_pi - arc.second, radius)} { } @@ -148,23 +156,39 @@ template<> NetworkLinkHolder<RailLinkCurve>::NetworkLinkHolder() namespace { template<typename LinkType> void - renderType(const NetworkLinkHolder<LinkType> & n, auto & s) + renderType(const NetworkLinkHolder<LinkType> & networkLinks, auto & shader) { - if (auto count = n.vertices.size()) { - s.use(railCrossSection, railTexturePos); - glBindVertexArray(n.vao); + if (auto count = networkLinks.vertices.size()) { + shader.use(RAIL_CROSS_SECTION, RAIL_TEXTURE_POS); + glBindVertexArray(networkLinks.vao); glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(count)); } }; } void -RailLinks::render(const SceneShader & shader) const +RailLinks::render(const SceneShader & shader, const Frustum &) const { - if (!links.objects.empty()) { + if (!links.empty()) { texture->bind(); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1, 0); renderType<RailLinkStraight>(*this, shader.networkStraight); renderType<RailLinkCurve>(*this, shader.networkCurve); + glDisable(GL_POLYGON_OFFSET_FILL); glBindVertexArray(0); } } + +const Surface * +RailLinks::getBaseSurface() const +{ + return gameState->assets.at("terrain.surface.gravel").dynamicCast<const Surface>().get(); +} + +RelativeDistance +RailLinks::getBaseWidth() const +{ + static constexpr auto BASE_WIDTH = 5'700; + return BASE_WIDTH; +} |