summaryrefslogtreecommitdiff
path: root/game/network/rail.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/network/rail.cpp')
-rw-r--r--game/network/rail.cpp156
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;
+}