summaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
Diffstat (limited to 'game')
-rw-r--r--game/activity.h2
-rw-r--r--game/gamestate.h1
-rw-r--r--game/geoData.cpp71
-rw-r--r--game/geoData.h50
-rw-r--r--game/network/link.cpp14
-rw-r--r--game/network/link.h14
-rw-r--r--game/network/network.cpp18
-rw-r--r--game/network/network.h44
-rw-r--r--game/network/network.impl.h12
-rw-r--r--game/network/rail.cpp45
-rw-r--r--game/network/rail.h12
-rw-r--r--game/objective.h2
-rw-r--r--game/orders.h1
-rw-r--r--game/scenary/foliage.cpp3
-rw-r--r--game/scenary/foliage.h3
-rw-r--r--game/scenary/plant.cpp2
-rw-r--r--game/scenary/plant.h2
-rw-r--r--game/selectable.h3
-rw-r--r--game/vehicles/linkHistory.cpp2
-rw-r--r--game/vehicles/railVehicle.cpp54
-rw-r--r--game/vehicles/railVehicle.h8
-rw-r--r--game/vehicles/railVehicleClass.cpp8
-rw-r--r--game/vehicles/railVehicleClass.h2
-rw-r--r--game/vehicles/train.cpp2
-rw-r--r--game/vehicles/train.h2
-rw-r--r--game/vehicles/vehicle.h1
26 files changed, 212 insertions, 166 deletions
diff --git a/game/activity.h b/game/activity.h
index e0585f7..38f6524 100644
--- a/game/activity.h
+++ b/game/activity.h
@@ -16,10 +16,12 @@ public:
template<typename T> class Of;
};
+
using ActivityPtr = std::unique_ptr<Activity>;
template<typename T>
concept ActivityConcept = std::is_base_of_v<Activity, T>;
+
template<ActivityConcept AC> class Can {
public:
Can() = default;
diff --git a/game/gamestate.h b/game/gamestate.h
index 6f3f382..f07f844 100644
--- a/game/gamestate.h
+++ b/game/gamestate.h
@@ -19,4 +19,5 @@ public:
std::shared_ptr<GeoData> geoData;
AssetFactory::Assets assets;
};
+
extern GameState * gameState;
diff --git a/game/geoData.cpp b/game/geoData.cpp
index 61dedda..7710efe 100644
--- a/game/geoData.cpp
+++ b/game/geoData.cpp
@@ -21,16 +21,20 @@ GeoData::loadFromAsciiGrid(const std::filesystem::path & input)
f >> *properties.at(property);
properties.erase(property);
}
+ xllcorner *= 1000;
+ yllcorner *= 1000;
+ cellsize *= 1000;
std::vector<VertexHandle> vertices;
vertices.reserve(ncols * nrows);
GeoData mesh;
- mesh.lowerExtent = {xllcorner, yllcorner, std::numeric_limits<float>::max()};
+ mesh.lowerExtent = {xllcorner, yllcorner, std::numeric_limits<GlobalDistance>::max()};
mesh.upperExtent = {xllcorner + (cellsize * (ncols - 1)), yllcorner + (cellsize * (nrows - 1)),
- std::numeric_limits<float>::min()};
+ std::numeric_limits<GlobalDistance>::min()};
for (size_t row = 0; row < nrows; ++row) {
for (size_t col = 0; col < ncols; ++col) {
- float height = 0;
- f >> height;
+ float heightf = 0;
+ f >> heightf;
+ const auto height = static_cast<GlobalDistance>(std::round(heightf * 1000.F));
mesh.upperExtent.z = std::max(mesh.upperExtent.z, height);
mesh.lowerExtent.z = std::min(mesh.lowerExtent.z, height);
vertices.push_back(mesh.add_vertex({xllcorner + (col * cellsize), yllcorner + (row * cellsize), height}));
@@ -60,12 +64,12 @@ GeoData::loadFromAsciiGrid(const std::filesystem::path & input)
};
GeoData
-GeoData::createFlat(glm::vec2 lower, glm::vec2 upper, float h)
+GeoData::createFlat(GlobalPosition2D lower, GlobalPosition2D upper, GlobalDistance h)
{
GeoData mesh;
- mesh.lowerExtent = lower ^ h;
- mesh.upperExtent = upper ^ h;
+ mesh.lowerExtent = {lower, h};
+ mesh.upperExtent = {upper, h};
const auto ll = mesh.add_vertex({lower.x, lower.y, h}), lu = mesh.add_vertex({lower.x, upper.y, h}),
ul = mesh.add_vertex({upper.x, lower.y, h}), uu = mesh.add_vertex({upper.x, upper.y, h});
@@ -80,14 +84,17 @@ GeoData::createFlat(glm::vec2 lower, glm::vec2 upper, float h)
}
OpenMesh::FaceHandle
-GeoData::findPoint(glm::vec2 p) const
+GeoData::findPoint(GlobalPosition2D p) const
{
return findPoint(p, *faces_begin());
}
-GeoData::PointFace::PointFace(const glm::vec2 p, const GeoData * mesh) : PointFace {p, mesh, *mesh->faces_begin()} { }
+GeoData::PointFace::PointFace(const GlobalPosition2D p, const GeoData * mesh) :
+ PointFace {p, mesh, *mesh->faces_begin()}
+{
+}
-GeoData::PointFace::PointFace(const glm::vec2 p, const GeoData * mesh, FaceHandle start) :
+GeoData::PointFace::PointFace(const GlobalPosition2D p, const GeoData * mesh, FaceHandle start) :
PointFace {p, mesh->findPoint(p, start)}
{
}
@@ -113,9 +120,9 @@ GeoData::PointFace::face(const GeoData * mesh) const
namespace {
template<template<typename> typename Op>
[[nodiscard]] constexpr inline auto
- pointLineOp(const glm::vec2 p, const glm::vec2 e1, const glm::vec2 e2)
+ pointLineOp(const GlobalPosition2D p, const GlobalPosition2D e1, const GlobalPosition2D e2)
{
- return Op {}((e2.x - e1.x) * (p.y - e1.y), (e2.y - e1.y) * (p.x - e1.x));
+ return Op {}(int64_t(e2.x - e1.x) * int64_t(p.y - e1.y), int64_t(e2.y - e1.y) * int64_t(p.x - e1.x));
}
constexpr auto pointLeftOfLine = pointLineOp<std::greater>;
@@ -125,9 +132,13 @@ namespace {
static_assert(pointLeftOfLine({2, 1}, {2, 2}, {1, 1}));
static_assert(pointLeftOfLine({2, 2}, {1, 2}, {2, 1}));
static_assert(pointLeftOfLine({1, 1}, {2, 1}, {1, 2}));
+ static_assert(pointLeftOfOrOnLine({310000000, 490000000}, {310000000, 490000000}, {310050000, 490050000}));
+ static_assert(pointLeftOfOrOnLine({310000000, 490000000}, {310050000, 490050000}, {310000000, 490050000}));
+ static_assert(pointLeftOfOrOnLine({310000000, 490000000}, {310000000, 490050000}, {310000000, 490000000}));
[[nodiscard]] constexpr inline bool
- linesCross(const glm::vec2 a1, const glm::vec2 a2, const glm::vec2 b1, const glm::vec2 b2)
+ linesCross(
+ const GlobalPosition2D a1, const GlobalPosition2D a2, const GlobalPosition2D b1, const GlobalPosition2D b2)
{
return (pointLeftOfLine(a2, b1, b2) == pointLeftOfLine(a1, b2, b1))
&& (pointLeftOfLine(b1, a1, a2) == pointLeftOfLine(b2, a2, a1));
@@ -137,7 +148,8 @@ namespace {
static_assert(linesCross({2, 2}, {1, 1}, {1, 2}, {2, 1}));
[[nodiscard]] constexpr inline bool
- linesCrossLtR(const glm::vec2 a1, const glm::vec2 a2, const glm::vec2 b1, const glm::vec2 b2)
+ linesCrossLtR(
+ const GlobalPosition2D a1, const GlobalPosition2D a2, const GlobalPosition2D b1, const GlobalPosition2D b2)
{
return pointLeftOfLine(a2, b1, b2) && pointLeftOfLine(a1, b2, b1) && pointLeftOfLine(b1, a1, a2)
&& pointLeftOfLine(b2, a2, a1);
@@ -148,7 +160,7 @@ namespace {
}
OpenMesh::FaceHandle
-GeoData::findPoint(glm::vec2 p, OpenMesh::FaceHandle f) const
+GeoData::findPoint(GlobalPosition2D p, OpenMesh::FaceHandle f) const
{
while (f.is_valid() && !triangleContainsPoint(p, triangle<2>(f))) {
for (auto next = cfh_iter(f); next.is_valid(); ++next) {
@@ -166,30 +178,31 @@ GeoData::findPoint(glm::vec2 p, OpenMesh::FaceHandle f) const
return f;
}
-glm::vec3
+GlobalPosition3D
GeoData::positionAt(const PointFace & p) const
{
- glm::vec3 out {};
+ RelativePosition3D out {};
const auto t = triangle<3>(p.face(this));
- glm::intersectLineTriangle(p.point ^ 0.F, up, t[0], t[1], t[2], out);
- return p.point ^ out[0];
+ glm::intersectLineTriangle<RelativePosition3D>({p.point, 0}, up, t[0], t[1], t[2], out);
+ return {p.point, out[0]};
}
-[[nodiscard]] std::optional<glm::vec3>
+[[nodiscard]] std::optional<GlobalPosition3D>
GeoData::intersectRay(const Ray & ray) const
{
return intersectRay(ray, findPoint(ray.start));
}
-[[nodiscard]] std::optional<glm::vec3>
+[[nodiscard]] std::optional<GlobalPosition3D>
GeoData::intersectRay(const Ray & ray, FaceHandle face) const
{
- std::optional<glm::vec3> out;
+ std::optional<GlobalPosition3D> out;
walkUntil(PointFace {ray.start, face}, ray.start + (ray.direction * 10000.F), [&out, &ray, this](FaceHandle face) {
- glm::vec2 bari {};
+ BaryPosition bari {};
float dist {};
const auto t = triangle<3>(face);
- if (glm::intersectRayTriangle(ray.start, ray.direction, t[0], t[1], t[2], bari, dist)) {
+ if (glm::intersectRayTriangle<RelativePosition3D::value_type, glm::defaultp>(
+ ray.start, ray.direction, t[0], t[1], t[2], bari, dist)) {
out = t * bari;
return true;
}
@@ -199,7 +212,7 @@ GeoData::intersectRay(const Ray & ray, FaceHandle face) const
}
void
-GeoData::walk(const PointFace & from, const glm::vec2 to, const std::function<void(FaceHandle)> & op) const
+GeoData::walk(const PointFace & from, const GlobalPosition2D to, const std::function<void(FaceHandle)> & op) const
{
walkUntil(from, to, [&op](const auto & fh) {
op(fh);
@@ -208,7 +221,7 @@ GeoData::walk(const PointFace & from, const glm::vec2 to, const std::function<vo
}
void
-GeoData::walkUntil(const PointFace & from, const glm::vec2 to, const std::function<bool(FaceHandle)> & op) const
+GeoData::walkUntil(const PointFace & from, const GlobalPosition2D to, const std::function<bool(FaceHandle)> & op) const
{
auto f = from.face(this);
if (!f.is_valid()) {
@@ -269,7 +282,7 @@ GeoData::boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> & op, Halfe
}
GeoData::HalfedgeHandle
-GeoData::findEntry(const glm::vec2 from, const glm::vec2 to) const
+GeoData::findEntry(const GlobalPosition2D from, const GlobalPosition2D to) const
{
HalfedgeHandle entry;
boundaryWalkUntil([this, from, to, &entry](auto he) {
@@ -285,14 +298,14 @@ GeoData::findEntry(const glm::vec2 from, const glm::vec2 to) const
}
bool
-GeoData::triangleContainsPoint(const glm::vec2 p, const Triangle<2> & t)
+GeoData::triangleContainsPoint(const GlobalPosition2D p, const Triangle<2> & t)
{
return pointLeftOfOrOnLine(p, t[0], t[1]) && pointLeftOfOrOnLine(p, t[1], t[2])
&& pointLeftOfOrOnLine(p, t[2], t[0]);
}
bool
-GeoData::triangleContainsPoint(const glm::vec2 p, FaceHandle face) const
+GeoData::triangleContainsPoint(const GlobalPosition2D p, FaceHandle face) const
{
return triangleContainsPoint(p, triangle<2>(face));
}
diff --git a/game/geoData.h b/game/geoData.h
index 474731b..3141dbe 100644
--- a/game/geoData.h
+++ b/game/geoData.h
@@ -1,6 +1,7 @@
#pragma once
#include "collections.h" // IWYU pragma: keep IterableCollection
+#include "config/types.h"
#include "ray.h"
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <filesystem>
@@ -13,8 +14,8 @@ struct GeoDataTraits : public OpenMesh::DefaultTraits {
EdgeAttributes(OpenMesh::Attributes::Status);
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
HalfedgeAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
- using Point = glm::vec3;
- using Normal = glm::vec3;
+ using Point = GlobalPosition3D;
+ using Normal = Normal3D;
};
class GeoData : public OpenMesh::TriMesh_ArrayKernelT<GeoDataTraits> {
@@ -23,18 +24,18 @@ private:
public:
static GeoData loadFromAsciiGrid(const std::filesystem::path &);
- static GeoData createFlat(glm::vec2 lower, glm::vec2, float h);
+ static GeoData createFlat(GlobalPosition2D lower, GlobalPosition2D upper, GlobalDistance h);
struct PointFace {
// NOLINTNEXTLINE(hicpp-explicit-conversions)
- PointFace(const glm::vec2 p) : point {p} { }
+ PointFace(const GlobalPosition2D p) : point {p} { }
- PointFace(const glm::vec2 p, FaceHandle face) : point {p}, _face {face} { }
+ PointFace(const GlobalPosition2D p, FaceHandle face) : point {p}, _face {face} { }
- PointFace(const glm::vec2 p, const GeoData *);
- PointFace(const glm::vec2 p, const GeoData *, FaceHandle start);
+ PointFace(const GlobalPosition2D p, const GeoData *);
+ PointFace(const GlobalPosition2D p, const GeoData *, FaceHandle start);
- const glm::vec2 point;
+ const GlobalPosition2D point;
[[nodiscard]] FaceHandle face(const GeoData *) const;
[[nodiscard]] FaceHandle face(const GeoData *, FaceHandle start) const;
@@ -48,8 +49,8 @@ public:
mutable FaceHandle _face {};
};
- template<glm::length_t Dim> struct Triangle : public glm::vec<3, glm::vec<Dim, glm::vec2::value_type>> {
- using base = glm::vec<3, glm::vec<Dim, glm::vec2::value_type>>;
+ template<glm::length_t Dim> struct Triangle : public glm::vec<3, glm::vec<Dim, GlobalDistance>> {
+ using base = glm::vec<3, glm::vec<Dim, GlobalDistance>>;
using base::base;
template<IterableCollection Range> Triangle(const GeoData * m, Range range)
@@ -60,30 +61,31 @@ public:
});
}
- glm::vec<Dim, glm::vec2::value_type>
- operator*(glm::vec2 bari) const
+ glm::vec<Dim, GlobalDistance>
+ operator*(BaryPosition bari) const
{
const auto & t {*this};
- return t[0] + ((t[1] - t[0]) * bari.x) + ((t[2] - t[1]) * bari.y);
+ return t[0] + GlobalPosition<Dim>(RelativePosition<Dim>(t[1] - t[0]) * bari.x)
+ + GlobalPosition<Dim>(RelativePosition<Dim>(t[2] - t[1]) * bari.y);
}
};
- [[nodiscard]] FaceHandle findPoint(glm::vec2) const;
- [[nodiscard]] FaceHandle findPoint(glm::vec2, FaceHandle start) const;
+ [[nodiscard]] FaceHandle findPoint(GlobalPosition2D) const;
+ [[nodiscard]] FaceHandle findPoint(GlobalPosition2D, FaceHandle start) const;
- [[nodiscard]] glm::vec3 positionAt(const PointFace &) const;
- [[nodiscard]] std::optional<glm::vec3> intersectRay(const Ray &) const;
- [[nodiscard]] std::optional<glm::vec3> intersectRay(const Ray &, FaceHandle start) const;
+ [[nodiscard]] GlobalPosition3D positionAt(const PointFace &) const;
+ [[nodiscard]] std::optional<GlobalPosition3D> intersectRay(const Ray &) const;
+ [[nodiscard]] std::optional<GlobalPosition3D> intersectRay(const Ray &, FaceHandle start) const;
- void walk(const PointFace & from, const glm::vec2 to, const std::function<void(FaceHandle)> & op) const;
- void walkUntil(const PointFace & from, const glm::vec2 to, const std::function<bool(FaceHandle)> & op) const;
+ void walk(const PointFace & from, const GlobalPosition2D to, const std::function<void(FaceHandle)> & op) const;
+ void walkUntil(const PointFace & from, const GlobalPosition2D to, const std::function<bool(FaceHandle)> & op) const;
void boundaryWalk(const std::function<void(HalfedgeHandle)> &) const;
void boundaryWalk(const std::function<void(HalfedgeHandle)> &, HalfedgeHandle start) const;
void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &) const;
void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &, HalfedgeHandle start) const;
- [[nodiscard]] HalfedgeHandle findEntry(const glm::vec2 from, const glm::vec2 to) const;
+ [[nodiscard]] HalfedgeHandle findEntry(const GlobalPosition2D from, const GlobalPosition2D to) const;
[[nodiscard]] auto
getExtents() const
@@ -99,10 +101,10 @@ protected:
return {this, fv_range(f)};
}
- [[nodiscard]] static bool triangleContainsPoint(const glm::vec2, const Triangle<2> &);
- [[nodiscard]] bool triangleContainsPoint(const glm::vec2, FaceHandle) const;
+ [[nodiscard]] static bool triangleContainsPoint(const GlobalPosition2D, const Triangle<2> &);
+ [[nodiscard]] bool triangleContainsPoint(const GlobalPosition2D, FaceHandle) const;
[[nodiscard]] HalfedgeHandle findBoundaryStart() const;
private:
- glm::vec3 lowerExtent {}, upperExtent {};
+ GlobalPosition3D lowerExtent {}, upperExtent {};
};
diff --git a/game/network/link.cpp b/game/network/link.cpp
index bb27a52..498afe4 100644
--- a/game/network/link.cpp
+++ b/game/network/link.cpp
@@ -8,10 +8,10 @@
Link::Link(End a, End b, float l) : ends {{std::move(a), std::move(b)}}, length {l} { }
-LinkCurve::LinkCurve(glm::vec3 c, float r, Arc a) : centreBase {c}, radius {r}, arc {std::move(a)} { }
+LinkCurve::LinkCurve(Position3D c, float r, Arc a) : centreBase {c}, radius {r}, arc {std::move(a)} { }
bool
-operator<(const glm::vec3 & a, const glm::vec3 & b)
+operator<(const Position3D & a, const Position3D & b)
{
// NOLINTNEXTLINE(hicpp-use-nullptr,modernize-use-nullptr)
return std::tie(a.x, a.y, a.z) < std::tie(b.x, b.y, b.z);
@@ -48,7 +48,7 @@ LinkCurve::positionAt(float dist, unsigned char start) const
const auto ang {as.first + ((as.second - as.first) * frac)};
const auto relPos {!sincosf(ang) * radius};
const auto relClimb {vehiclePositionOffset()
- + glm::vec3 {0, 0, es.first->pos.z - centreBase.z + ((es.second->pos.z - es.first->pos.z) * frac)}};
+ + Position3D {0, 0, es.first->pos.z - centreBase.z + ((es.second->pos.z - es.first->pos.z) * frac)}};
const auto pitch {vector_pitch({0, 0, (es.second->pos.z - es.first->pos.z) / length})};
return Location {relPos + relClimb + centreBase, {pitch, normalize(ang + dirOffset[start]), 0}};
}
@@ -60,14 +60,14 @@ LinkCurve::intersectRay(const Ray & ray) const
const auto & e1p {ends[1].node->pos};
const auto slength = round_frac(length / 2.F, 5.F);
const auto segs = std::round(15.F * slength / std::pow(radius, 0.7F));
- const auto step {glm::vec3 {arc_length(arc), e1p.z - e0p.z, slength} / segs};
+ const auto step {Position3D {arc_length(arc), e1p.z - e0p.z, slength} / segs};
const auto trans {glm::translate(centreBase)};
auto segCount = static_cast<std::size_t>(std::lround(segs)) + 1;
- std::vector<glm::vec3> points;
+ std::vector<Position3D> points;
points.reserve(segCount);
- for (glm::vec3 swing = {arc.first, centreBase.z - e0p.z, 0.F}; segCount; swing += step, --segCount) {
- const auto t {trans * glm::rotate(half_pi - swing.x, up) * glm::translate(glm::vec3 {radius, 0.F, swing.y})};
+ for (Position3D swing = {arc.first, centreBase.z - e0p.z, 0.F}; segCount; swing += step, --segCount) {
+ const auto t {trans * glm::rotate(half_pi - swing.x, up) * glm::translate(Position3D {radius, 0.F, swing.y})};
points.emplace_back(t * glm::vec4 {0, 0, 0, 1});
}
return ray.passesCloseToEdges(points, 1.F);
diff --git a/game/network/link.h b/game/network/link.h
index 4a9f83f..78d3e91 100644
--- a/game/network/link.h
+++ b/game/network/link.h
@@ -17,12 +17,12 @@ class Ray;
// it has location
class Node : public StdTypeDefs<Node> {
public:
- explicit Node(glm::vec3 p) noexcept : pos(p) {};
+ explicit Node(Position3D p) noexcept : pos(p) {};
virtual ~Node() noexcept = default;
NO_COPY(Node);
NO_MOVE(Node);
- glm::vec3 pos;
+ Position3D pos;
};
// Generic network link
@@ -51,14 +51,14 @@ public:
float length;
protected:
- [[nodiscard]] virtual glm::vec3
+ [[nodiscard]] virtual Position3D
vehiclePositionOffset() const
{
return {};
}
};
-bool operator<(const glm::vec3 & a, const glm::vec3 & b);
+bool operator<(const Position3D & a, const Position3D & b);
bool operator<(const Node & a, const Node & b);
class LinkStraight : public virtual Link {
@@ -71,20 +71,22 @@ public:
[[nodiscard]] Location positionAt(float dist, unsigned char start) const override;
[[nodiscard]] bool intersectRay(const Ray &) const override;
};
+
LinkStraight::~LinkStraight() = default;
class LinkCurve : public virtual Link {
public:
inline ~LinkCurve() override = 0;
- LinkCurve(glm::vec3, float, Arc);
+ LinkCurve(Position3D, float, Arc);
NO_COPY(LinkCurve);
NO_MOVE(LinkCurve);
[[nodiscard]] Location positionAt(float dist, unsigned char start) const override;
[[nodiscard]] bool intersectRay(const Ray &) const override;
- glm::vec3 centreBase;
+ Position3D centreBase;
float radius;
Arc arc;
};
+
LinkCurve::~LinkCurve() = default;
diff --git a/game/network/network.cpp b/game/network/network.cpp
index 083b08e..d18345c 100644
--- a/game/network/network.cpp
+++ b/game/network/network.cpp
@@ -14,13 +14,13 @@
Network::Network(const std::string & tn) : texture {Texture::cachedTexture.get(tn)} { }
Node::Ptr
-Network::nodeAt(glm::vec3 pos)
+Network::nodeAt(Position3D pos)
{
return newNodeAt(pos).first;
}
Network::NodeInsertion
-Network::newNodeAt(glm::vec3 pos)
+Network::newNodeAt(Position3D pos)
{
if (auto [n, i] = candidateNodeAt(pos); i == NodeIs::NotInNetwork) {
return {*nodes.insert(std::move(n)).first, i};
@@ -31,7 +31,7 @@ Network::newNodeAt(glm::vec3 pos)
}
Node::Ptr
-Network::findNodeAt(glm::vec3 pos) const
+Network::findNodeAt(Position3D pos) const
{
if (const auto n = nodes.find(pos); n != nodes.end()) {
return *n;
@@ -40,7 +40,7 @@ Network::findNodeAt(glm::vec3 pos) const
}
Network::NodeInsertion
-Network::candidateNodeAt(glm::vec3 pos) const
+Network::candidateNodeAt(Position3D pos) const
{
if (const auto n = nodes.find(pos); n != nodes.end()) {
return {*n, NodeIs::InNetwork};
@@ -54,7 +54,7 @@ Network::intersectRayNodes(const Ray & ray) const
// Click within 2m of a node
if (const auto node = std::find_if(nodes.begin(), nodes.end(),
[&ray](const Node::Ptr & node) {
- glm::vec3 ipos, inorm;
+ Position3D ipos, inorm;
return glm::intersectRaySphere(ray.start, ray.direction, node->pos, 2.F, ipos, inorm);
});
node != nodes.end()) {
@@ -79,7 +79,7 @@ Network::joinLinks(const Link::Ptr & l, const Link::Ptr & ol)
}
Link::Nexts
-Network::routeFromTo(const Link::End & start, glm::vec3 dest) const
+Network::routeFromTo(const Link::End & start, Position3D dest) const
{
auto destNode {findNodeAt(dest)};
if (!destNode) {
@@ -95,7 +95,7 @@ Network::routeFromTo(const Link::End & end, const Node::Ptr & dest) const
}
GenCurveDef
-Network::genCurveDef(const glm::vec3 & start, const glm::vec3 & end, float startDir)
+Network::genCurveDef(const Position3D & start, const Position3D & end, float startDir)
{
const auto diff {end - start};
const auto vy {vector_yaw(diff)};
@@ -111,11 +111,11 @@ Network::genCurveDef(const glm::vec3 & start, const glm::vec3 & end, float start
}
std::pair<GenCurveDef, GenCurveDef>
-Network::genCurveDef(const glm::vec3 & start, const glm::vec3 & end, float startDir, float endDir)
+Network::genCurveDef(const Position3D & start, const Position3D & end, float startDir, float endDir)
{
startDir += pi;
endDir += pi;
- const glm::vec2 flatStart {!start}, flatEnd {!end};
+ const Position2D flatStart {!start}, flatEnd {!end};
auto midheight = [&](auto mid) {
const auto sm = glm::distance(flatStart, mid), em = glm::distance(flatEnd, mid);
return start.z + ((end.z - start.z) * (sm / (sm + em)));
diff --git a/game/network/network.h b/game/network/network.h
index b9316eb..8af06a9 100644
--- a/game/network/network.h
+++ b/game/network/network.h
@@ -16,7 +16,7 @@ class Texture;
class SceneShader;
class Ray;
-template<size_t... n> using GenDef = std::tuple<glm::vec<n, float>...>;
+template<size_t... n> using GenDef = std::tuple<glm::vec<n, Distance>...>;
using GenCurveDef = GenDef<3, 3, 2>;
class Network {
@@ -26,32 +26,32 @@ public:
virtual ~Network() = default;
DEFAULT_MOVE_NO_COPY(Network);
- [[nodiscard]] Node::Ptr findNodeAt(glm::vec3) const;
- [[nodiscard]] Node::Ptr nodeAt(glm::vec3);
+ [[nodiscard]] Node::Ptr findNodeAt(Position3D) const;
+ [[nodiscard]] Node::Ptr nodeAt(Position3D);
enum class NodeIs { InNetwork, NotInNetwork };
using NodeInsertion = std::pair<Node::Ptr, NodeIs>;
- [[nodiscard]] NodeInsertion newNodeAt(glm::vec3);
- [[nodiscard]] NodeInsertion candidateNodeAt(glm::vec3) const;
+ [[nodiscard]] NodeInsertion newNodeAt(Position3D);
+ [[nodiscard]] NodeInsertion candidateNodeAt(Position3D) const;
[[nodiscard]] virtual Link::Ptr intersectRayLinks(const Ray &) const = 0;
[[nodiscard]] virtual Node::Ptr intersectRayNodes(const Ray &) const;
- [[nodiscard]] Link::Nexts routeFromTo(const Link::End &, glm::vec3) const;
+ [[nodiscard]] Link::Nexts routeFromTo(const Link::End &, Position3D) const;
[[nodiscard]] Link::Nexts routeFromTo(const Link::End &, const Node::Ptr &) const;
- virtual Link::CCollection candidateStraight(glm::vec3, glm::vec3) = 0;
- virtual Link::CCollection candidateJoins(glm::vec3, glm::vec3) = 0;
- virtual Link::CCollection candidateExtend(glm::vec3, glm::vec3) = 0;
- virtual Link::CCollection addStraight(glm::vec3, glm::vec3) = 0;
- virtual Link::CCollection addJoins(glm::vec3, glm::vec3) = 0;
- virtual Link::CCollection addExtend(glm::vec3, glm::vec3) = 0;
+ virtual Link::CCollection candidateStraight(Position3D, Position3D) = 0;
+ virtual Link::CCollection candidateJoins(Position3D, Position3D) = 0;
+ virtual Link::CCollection candidateExtend(Position3D, Position3D) = 0;
+ virtual Link::CCollection addStraight(Position3D, Position3D) = 0;
+ virtual Link::CCollection addJoins(Position3D, Position3D) = 0;
+ virtual Link::CCollection addExtend(Position3D, Position3D) = 0;
[[nodiscard]] virtual float findNodeDirection(Node::AnyCPtr) const = 0;
protected:
static void joinLinks(const Link::Ptr & l, const Link::Ptr & ol);
- static GenCurveDef genCurveDef(const glm::vec3 & start, const glm::vec3 & end, float startDir);
+ static GenCurveDef genCurveDef(const Position3D & start, const Position3D & end, float startDir);
static std::pair<GenCurveDef, GenCurveDef> genCurveDef(
- const glm::vec3 & start, const glm::vec3 & end, float startDir, float endDir);
+ const Position3D & start, const Position3D & end, float startDir, float endDir);
using Nodes = std::set<Node::Ptr, PtrMemberSorter<Node::Ptr, &Node::pos>>;
Nodes nodes;
@@ -71,7 +71,7 @@ protected:
public:
template<typename L, typename... Params>
std::shared_ptr<L>
- candidateLink(glm::vec3 a, glm::vec3 b, Params &&... params)
+ candidateLink(Position3D a, Position3D b, Params &&... params)
requires std::is_base_of_v<T, L>
{
const auto node1 = candidateNodeAt(a).first, node2 = candidateNodeAt(b).first;
@@ -80,7 +80,7 @@ public:
template<typename L, typename... Params>
std::shared_ptr<L>
- addLink(glm::vec3 a, glm::vec3 b, Params &&... params)
+ addLink(Position3D a, Position3D b, Params &&... params)
requires std::is_base_of_v<T, L>
{
const auto node1 = nodeAt(a), node2 = nodeAt(b);
@@ -89,12 +89,12 @@ public:
return l;
}
- Link::CCollection candidateStraight(glm::vec3 n1, glm::vec3 n2) override;
- Link::CCollection candidateJoins(glm::vec3, glm::vec3) override;
- Link::CCollection candidateExtend(glm::vec3, glm::vec3) override;
- Link::CCollection addStraight(glm::vec3 n1, glm::vec3 n2) override;
- Link::CCollection addJoins(glm::vec3, glm::vec3) override;
- Link::CCollection addExtend(glm::vec3, glm::vec3) override;
+ Link::CCollection candidateStraight(Position3D n1, Position3D n2) override;
+ Link::CCollection candidateJoins(Position3D, Position3D) override;
+ Link::CCollection candidateExtend(Position3D, Position3D) override;
+ Link::CCollection addStraight(Position3D n1, Position3D n2) override;
+ Link::CCollection addJoins(Position3D, Position3D) override;
+ Link::CCollection addExtend(Position3D, Position3D) override;
[[nodiscard]] float findNodeDirection(Node::AnyCPtr) const override;
diff --git a/game/network/network.impl.h b/game/network/network.impl.h
index 045335f..8e9e85c 100644
--- a/game/network/network.impl.h
+++ b/game/network/network.impl.h
@@ -54,14 +54,14 @@ NetworkOf<T>::findNodeDirection(Node::AnyCPtr n) const
template<typename T>
Link::CCollection
-NetworkOf<T>::candidateStraight(glm::vec3 n1, glm::vec3 n2)
+NetworkOf<T>::candidateStraight(Position3D n1, Position3D n2)
{
return {candidateLink<typename T::StraightLink>(n1, n2)};
}
template<typename T>
Link::CCollection
-NetworkOf<T>::candidateJoins(glm::vec3 start, glm::vec3 end)
+NetworkOf<T>::candidateJoins(Position3D start, Position3D end)
{
if (glm::distance(start, end) < 2.F) {
return {};
@@ -75,7 +75,7 @@ NetworkOf<T>::candidateJoins(glm::vec3 start, glm::vec3 end)
template<typename T>
Link::CCollection
-NetworkOf<T>::candidateExtend(glm::vec3 start, glm::vec3 end)
+NetworkOf<T>::candidateExtend(Position3D start, Position3D end)
{
const auto [cstart, cend, centre] = genCurveDef(start, end, findNodeDirection(candidateNodeAt(start).first));
return {candidateLink<typename T::CurveLink>(cstart, cend, centre)};
@@ -83,14 +83,14 @@ NetworkOf<T>::candidateExtend(glm::vec3 start, glm::vec3 end)
template<typename T>
Link::CCollection
-NetworkOf<T>::addStraight(glm::vec3 n1, glm::vec3 n2)
+NetworkOf<T>::addStraight(Position3D n1, Position3D n2)
{
return {addLink<typename T::StraightLink>(n1, n2)};
}
template<typename T>
Link::CCollection
-NetworkOf<T>::addJoins(glm::vec3 start, glm::vec3 end)
+NetworkOf<T>::addJoins(Position3D start, Position3D end)
{
if (glm::distance(start, end) < 2.F) {
return {};
@@ -103,7 +103,7 @@ NetworkOf<T>::addJoins(glm::vec3 start, glm::vec3 end)
template<typename T>
Link::CCollection
-NetworkOf<T>::addExtend(glm::vec3 start, glm::vec3 end)
+NetworkOf<T>::addExtend(Position3D start, Position3D end)
{
const auto [cstart, cend, centre] = genCurveDef(start, end, findNodeDirection(nodeAt(start)));
return {addLink<typename T::CurveLink>(cstart, cend, centre)};
diff --git a/game/network/rail.cpp b/game/network/rail.cpp
index bd24a2b..ff101d4 100644
--- a/game/network/rail.cpp
+++ b/game/network/rail.cpp
@@ -18,16 +18,17 @@
template class NetworkOf<RailLink>;
constexpr auto RAIL_CROSSSECTION_VERTICES {5U};
-constexpr glm::vec3 RAIL_HEIGHT {0, 0, .25F};
+constexpr Size3D RAIL_HEIGHT {0, 0, 250.F};
RailLinks::RailLinks() : NetworkOf<RailLink> {"rails.jpg"} { }
+
void
RailLinks::tick(TickDuration)
{
}
std::shared_ptr<RailLink>
-RailLinks::addLinksBetween(glm::vec3 start, glm::vec3 end)
+RailLinks::addLinksBetween(Position3D start, Position3D end)
{
auto node1ins = newNodeAt(start), node2ins = newNodeAt(end);
if (node1ins.second == NodeIs::NotInNetwork && node2ins.second == NodeIs::NotInNetwork) {
@@ -44,7 +45,7 @@ RailLinks::addLinksBetween(glm::vec3 start, glm::vec3 end)
if (dir == vector_yaw(end - start)) {
return addLink<RailLinkStraight>(start, end);
}
- const glm::vec2 flatStart {!start}, flatEnd {!end};
+ const Position2D flatStart {!start}, flatEnd {!end};
if (node2ins.second == NodeIs::InNetwork) {
auto midheight = [&](auto mid) {
const auto sm = glm::distance(flatStart, mid), em = glm::distance(flatEnd, mid);
@@ -99,15 +100,15 @@ RailLink::render(const SceneShader &) const
mesh->Draw();
}
-constexpr const std::array<std::pair<glm::vec3, float>, RAIL_CROSSSECTION_VERTICES> railCrossSection {{
+constexpr const std::array<std::pair<Position3D, float>, RAIL_CROSSSECTION_VERTICES> railCrossSection {{
// ___________
// _/ \_
// left to right
- {{-1.9F, 0.F, 0.F}, 0.F},
- {{-.608F, 0.F, RAIL_HEIGHT.z}, 0.34F},
- {{0, 0.F, RAIL_HEIGHT.z * .7F}, 0.5F},
- {{.608F, 0.F, RAIL_HEIGHT.z}, 0.66F},
- {{1.9F, 0.F, 0.F}, 1.F},
+ {{-1900.F, 0.F, 0.F}, 0.F},
+ {{-608.F, 0.F, RAIL_HEIGHT.z}, .34F},
+ {{0, 0.F, RAIL_HEIGHT.z * .7F}, .5F},
+ {{608.F, 0.F, RAIL_HEIGHT.z}, .66F},
+ {{1900.F, 0.F, 0.F}, 1.F},
}};
constexpr auto sleepers {5.F}; // There are 5 repetitions of sleepers in the texture
@@ -121,31 +122,31 @@ RailLinkStraight::RailLinkStraight(const Node::Ptr & a, const Node::Ptr & b) : R
{
}
-RailLinkStraight::RailLinkStraight(Node::Ptr a, Node::Ptr b, const glm::vec3 & diff) :
+RailLinkStraight::RailLinkStraight(Node::Ptr a, Node::Ptr b, const Position3D & diff) :
Link({std::move(a), vector_yaw(diff)}, {std::move(b), vector_yaw(-diff)}, glm::length(diff))
{
if (glGenVertexArrays) {
std::vector<Vertex> vertices;
vertices.reserve(2 * railCrossSection.size());
- const auto len = round_sleepers(length / 2.F);
+ const auto len = round_sleepers(length / 2000.F);
const auto e {flat_orientation(diff)};
for (auto ei : {1U, 0U}) {
const auto trans {glm::translate(ends[ei].node->pos) * e};
for (const auto & rcs : railCrossSection) {
- const glm::vec3 m {(trans * glm::vec4 {rcs.first, 1})};
- vertices.emplace_back(m, glm::vec2 {rcs.second, len * static_cast<float>(ei)}, up);
+ const Position3D m {(trans * (rcs.first ^ 1))};
+ vertices.emplace_back(m, Position2D {rcs.second, len * static_cast<float>(ei)}, up);
}
}
mesh = defaultMesh(vertices);
}
}
-RailLinkCurve::RailLinkCurve(const Node::Ptr & a, const Node::Ptr & b, glm::vec2 c) :
+RailLinkCurve::RailLinkCurve(const Node::Ptr & a, const Node::Ptr & b, Position2D c) :
RailLinkCurve(a, b, c ^ a->pos.z, {!c, a->pos, b->pos})
{
}
-RailLinkCurve::RailLinkCurve(const Node::Ptr & a, const Node::Ptr & b, glm::vec3 c, const Arc arc) :
+RailLinkCurve::RailLinkCurve(const Node::Ptr & a, const Node::Ptr & b, Position3D c, const Arc arc) :
Link({a, normalize(arc.first + half_pi)}, {b, normalize(arc.second - half_pi)},
(glm::length(a->pos - c)) * arc_length(arc)),
LinkCurve {c, glm::length(ends[0].node->pos - c), arc}
@@ -154,26 +155,26 @@ RailLinkCurve::RailLinkCurve(const Node::Ptr & a, const Node::Ptr & b, glm::vec3
const auto & e0p {ends[0].node->pos};
const auto & e1p {ends[1].node->pos};
const auto slength = round_sleepers(length / 2.F);
- const auto segs = std::round(15.F * slength / std::pow(radius, 0.7F));
- const auto step {glm::vec3 {arc_length(arc), e1p.z - e0p.z, slength} / segs};
+ const auto segs = std::round(slength / std::pow(radius, 0.7F));
+ const auto step {Position3D {arc_length(arc), e1p.z - e0p.z, slength / 1000.F} / segs};
const auto trans {glm::translate(centreBase)};
auto segCount = static_cast<std::size_t>(std::lround(segs)) + 1;
std::vector<Vertex> vertices;
vertices.reserve(segCount * railCrossSection.size());
- for (glm::vec3 swing = {arc.first, centreBase.z - e0p.z, 0.F}; segCount; swing += step, --segCount) {
+ for (Position3D swing = {arc.first, centreBase.z - e0p.z, 0.F}; segCount; swing += step, --segCount) {
const auto t {
- trans * glm::rotate(half_pi - swing.x, up) * glm::translate(glm::vec3 {radius, 0.F, swing.y})};
+ trans * glm::rotate(half_pi - swing.x, up) * glm::translate(Position3D {radius, 0.F, swing.y})};
for (const auto & rcs : railCrossSection) {
- const glm::vec3 m {(t * glm::vec4 {rcs.first, 1})};
- vertices.emplace_back(m, glm::vec2 {rcs.second, swing.z}, up);
+ const Position3D m {(t * (rcs.first ^ 1))};
+ vertices.emplace_back(m, Position2D {rcs.second, swing.z}, up);
}
}
mesh = defaultMesh(vertices);
}
}
-glm::vec3
+Position3D
RailLink::vehiclePositionOffset() const
{
return RAIL_HEIGHT;
diff --git a/game/network/rail.h b/game/network/rail.h
index 611eb67..4a1932f 100644
--- a/game/network/rail.h
+++ b/game/network/rail.h
@@ -18,6 +18,7 @@ struct Arc;
// A piece of rail track
class RailLinkStraight;
class RailLinkCurve;
+
class RailLink : public virtual Link, public Renderable {
public:
RailLink() = default;
@@ -31,11 +32,12 @@ public:
NO_MOVE(RailLink);
protected:
- [[nodiscard]] glm::vec3 vehiclePositionOffset() const override;
+ [[nodiscard]] Position3D vehiclePositionOffset() const override;
[[nodiscard]] static Mesh::Ptr defaultMesh(const std::span<Vertex> vertices);
Mesh::Ptr mesh;
};
+
RailLink::~RailLink() = default;
class RailLinkStraight : public RailLink, public LinkStraight {
@@ -43,22 +45,22 @@ public:
RailLinkStraight(const Node::Ptr &, const Node::Ptr &);
private:
- RailLinkStraight(Node::Ptr, Node::Ptr, const glm::vec3 & diff);
+ RailLinkStraight(Node::Ptr, Node::Ptr, const Position3D & diff);
};
class RailLinkCurve : public RailLink, public LinkCurve {
public:
- RailLinkCurve(const Node::Ptr &, const Node::Ptr &, glm::vec2);
+ RailLinkCurve(const Node::Ptr &, const Node::Ptr &, Position2D);
private:
- RailLinkCurve(const Node::Ptr &, const Node::Ptr &, glm::vec3, const Arc);
+ RailLinkCurve(const Node::Ptr &, const Node::Ptr &, Position3D, const Arc);
};
class RailLinks : public NetworkOf<RailLink>, public WorldObject {
public:
RailLinks();
- std::shared_ptr<RailLink> addLinksBetween(glm::vec3 start, glm::vec3 end);
+ std::shared_ptr<RailLink> addLinksBetween(Position3D start, Position3D end);
private:
void tick(TickDuration elapsed) override;
diff --git a/game/objective.h b/game/objective.h
index 130015f..f5c6e48 100644
--- a/game/objective.h
+++ b/game/objective.h
@@ -10,6 +10,7 @@ class Orders;
class Objective {
public:
explicit Objective(Orders * os) : orders(os) { }
+
DEFAULT_MOVE_COPY(Objective);
virtual ~Objective() = default;
@@ -19,4 +20,5 @@ public:
Orders * orders;
};
+
using ObjectivePtr = std::unique_ptr<Objective>;
diff --git a/game/orders.h b/game/orders.h
index f29e208..ca5cfdb 100644
--- a/game/orders.h
+++ b/game/orders.h
@@ -10,4 +10,5 @@ public:
[[nodiscard]] Objective * current() const;
Objective * next();
};
+
using OrdersPtr = std::shared_ptr<Orders>;
diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp
index 702a52c..c258b77 100644
--- a/game/scenary/foliage.cpp
+++ b/game/scenary/foliage.cpp
@@ -15,7 +15,8 @@ void
Foliage::postLoad()
{
texture = getTexture();
- bodyMesh->configureVAO(instanceVAO).addAttribs<glm::mat4>(instances.bufferName(), 1);
+ bodyMesh->configureVAO(instanceVAO)
+ .addAttribs<LocationVertex, &LocationVertex::first, &LocationVertex::second>(instances.bufferName(), 1);
}
void
diff --git a/game/scenary/foliage.h b/game/scenary/foliage.h
index b72a9c2..bbb6200 100644
--- a/game/scenary/foliage.h
+++ b/game/scenary/foliage.h
@@ -15,7 +15,8 @@ class Foliage : public Asset, public Renderable, public StdTypeDefs<Foliage> {
glVertexArray instanceVAO;
public:
- mutable InstanceVertices<glm::mat4> instances;
+ using LocationVertex = std::pair<glm::mat4, GlobalPosition3D>;
+ mutable InstanceVertices<LocationVertex> instances;
void render(const SceneShader &) const override;
void shadows(const ShadowMapper &) const override;
diff --git a/game/scenary/plant.cpp b/game/scenary/plant.cpp
index 4fb3cb5..b39c28b 100644
--- a/game/scenary/plant.cpp
+++ b/game/scenary/plant.cpp
@@ -2,6 +2,6 @@
#include "location.h"
Plant::Plant(std::shared_ptr<const Foliage> type, const Location & position) :
- type {std::move(type)}, location {this->type->instances.acquire(position.getTransform())}
+ type {std::move(type)}, location {this->type->instances.acquire(position.getRotationTransform(), position.pos)}
{
}
diff --git a/game/scenary/plant.h b/game/scenary/plant.h
index 82ab0e5..77c9ff7 100644
--- a/game/scenary/plant.h
+++ b/game/scenary/plant.h
@@ -7,7 +7,7 @@ class Location;
class Plant : public WorldObject {
std::shared_ptr<const Foliage> type;
- InstanceVertices<glm::mat4>::InstanceProxy location;
+ InstanceVertices<Foliage::LocationVertex>::InstanceProxy location;
void
tick(TickDuration) override
diff --git a/game/selectable.h b/game/selectable.h
index 31287d8..9732dca 100644
--- a/game/selectable.h
+++ b/game/selectable.h
@@ -1,5 +1,6 @@
#pragma once
+#include "config/types.h"
#include <glm/glm.hpp>
#include <special_members.h>
@@ -11,5 +12,5 @@ public:
virtual ~Selectable() = default;
DEFAULT_MOVE_COPY(Selectable);
- [[nodiscard]] virtual bool intersectRay(const Ray &, glm::vec2 *, float *) const = 0;
+ [[nodiscard]] virtual bool intersectRay(const Ray &, Position2D *, float *) const = 0;
};
diff --git a/game/vehicles/linkHistory.cpp b/game/vehicles/linkHistory.cpp
index 2802109..e6bab36 100644
--- a/game/vehicles/linkHistory.cpp
+++ b/game/vehicles/linkHistory.cpp
@@ -8,7 +8,7 @@ LinkHistory::add(const Link::WPtr & l, unsigned char d)
links.insert(links.begin(), {l, d});
const auto lp = l.lock();
totalLen += lp->length;
- while (totalLen >= 1000.F && !links.empty()) {
+ while (totalLen >= 1000000.F && !links.empty()) {
totalLen -= links.back().first.lock()->length;
links.pop_back();
}
diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp
index 2d820b6..30b615c 100644
--- a/game/vehicles/railVehicle.cpp
+++ b/game/vehicles/railVehicle.cpp
@@ -12,10 +12,22 @@
#include <ray.h>
RailVehicle::RailVehicle(RailVehicleClassPtr rvc) :
- RailVehicleClass::Instance {rvc->instances.acquire()}, rvClass {std::move(rvc)}, location {&LV::body, *this},
+ RailVehicleClass::Instance {rvc->instances.acquire()}, rvClass {std::move(rvc)},
+ location {[this](const BufferedLocation * l) {
+ this->get()->body = l->getRotationTransform();
+ this->get()->bodyPos = l->position();
+ }},
bogies {{
- {&LV::front, *this, glm::vec3 {0, rvClass->wheelBase / 2.F, 0}},
- {&LV::back, *this, glm::vec3 {0, -rvClass->wheelBase / 2.F, 0}},
+ {[this](const BufferedLocation * l) {
+ this->get()->front = l->getRotationTransform();
+ this->get()->frontPos = l->position();
+ },
+ Position3D {0, rvClass->wheelBase / 2.F, 0}},
+ {[this](const BufferedLocation * l) {
+ this->get()->back = l->getRotationTransform();
+ this->get()->backPos = l->position();
+ },
+ Position3D {0, -rvClass->wheelBase / 2.F, 0}},
}}
{
}
@@ -26,29 +38,29 @@ RailVehicle::move(const Train * t, float & trailBy)
const auto overhang {(rvClass->length - rvClass->wheelBase) / 2};
const auto & b1Pos = bogies[0] = t->getBogiePosition(t->linkDist, trailBy += overhang);
const auto & b2Pos = bogies[1] = t->getBogiePosition(t->linkDist, trailBy += rvClass->wheelBase);
- const auto diff = glm::normalize(b2Pos.position() - b1Pos.position());
- location.setLocation((b1Pos.position() + b2Pos.position()) / 2.F, {vector_pitch(diff), vector_yaw(diff), 0});
- trailBy += 0.6F + overhang;
+ const auto diff = glm::normalize(RelativePosition3D(b2Pos.position() - b1Pos.position()));
+ location.setLocation((b1Pos.position() + b2Pos.position()) / 2, {vector_pitch(diff), vector_yaw(diff), 0});
+ trailBy += 600.F + overhang;
}
bool
-RailVehicle::intersectRay(const Ray & ray, glm::vec2 * baryPos, float * distance) const
+RailVehicle::intersectRay(const Ray & ray, Position2D * baryPos, float * distance) const
{
- constexpr const auto X = 1.35F;
+ constexpr const auto X = 1350.F;
const auto Y = this->rvClass->length / 2.F;
- constexpr const auto Z = 3.9F;
- const auto moveBy = location.getTransform();
- const std::array<glm::vec3, 8> cornerVertices {{
- moveBy * glm::vec4 {-X, Y, 0, 1}, // LFB
- moveBy * glm::vec4 {X, Y, 0, 1}, // RFB
- moveBy * glm::vec4 {-X, Y, Z, 1}, // LFT
- moveBy * glm::vec4 {X, Y, Z, 1}, // RFT
- moveBy * glm::vec4 {-X, -Y, 0, 1}, // LBB
- moveBy * glm::vec4 {X, -Y, 0, 1}, // RBB
- moveBy * glm::vec4 {-X, -Y, Z, 1}, // LBT
- moveBy * glm::vec4 {X, -Y, Z, 1}, // RBT
+ constexpr const auto Z = 3900.F;
+ const auto moveBy = location.getRotationTransform();
+ const std::array<Position3D, 8> cornerVertices {{
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {-X, Y, 0, 1}).xyz(), // LFB
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {X, Y, 0, 1}).xyz(), // RFB
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {-X, Y, Z, 1}).xyz(), // LFT
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {X, Y, Z, 1}).xyz(), // RFT
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {-X, -Y, 0, 1}).xyz(), // LBB
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {X, -Y, 0, 1}).xyz(), // RBB
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {-X, -Y, Z, 1}).xyz(), // LBT
+ location.position() + GlobalPosition3D(moveBy * glm::vec4 {X, -Y, Z, 1}).xyz(), // RBT
}};
- static constexpr const std::array<glm::uvec3, 10> triangles {{
+ static constexpr const std::array<glm::vec<3, uint8_t>, 10> triangles {{
// Front
{0, 1, 2},
{1, 2, 3},
@@ -66,7 +78,7 @@ RailVehicle::intersectRay(const Ray & ray, glm::vec2 * baryPos, float * distance
{3, 6, 7},
}};
return std::any_of(
- triangles.begin(), triangles.end(), [&cornerVertices, &ray, &baryPos, &distance](const glm::uvec3 idx) {
+ triangles.begin(), triangles.end(), [&cornerVertices, &ray, &baryPos, &distance](const auto & idx) {
return glm::intersectRayTriangle(ray.start, ray.direction, cornerVertices[idx[0]],
cornerVertices[idx[1]], cornerVertices[idx[2]], *baryPos, *distance);
});
diff --git a/game/vehicles/railVehicle.h b/game/vehicles/railVehicle.h
index f34643e..20d1ea1 100644
--- a/game/vehicles/railVehicle.h
+++ b/game/vehicles/railVehicle.h
@@ -17,12 +17,12 @@ public:
void move(const Train *, float & trailBy);
- [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override;
+ [[nodiscard]] bool intersectRay(const Ray &, Position2D *, float *) const override;
RailVehicleClassPtr rvClass;
using LV = RailVehicleClass::LocationVertex;
- using BLocation = BufferedLocationT<glm::mat4 LV::*, RailVehicleClass::Instance &>;
- BLocation location;
- std::array<BLocation, 2> bogies;
+ BufferedLocationUpdater location;
+ std::array<BufferedLocationUpdater, 2> bogies;
};
+
using RailVehiclePtr = std::unique_ptr<RailVehicle>;
diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp
index 324148c..7a6a9fe 100644
--- a/game/vehicles/railVehicleClass.cpp
+++ b/game/vehicles/railVehicleClass.cpp
@@ -35,13 +35,15 @@ void
RailVehicleClass::postLoad()
{
texture = getTexture();
- bodyMesh->configureVAO(instanceVAO).addAttribs<LocationVertex, &LocationVertex::body>(instances.bufferName(), 1);
+ bodyMesh->configureVAO(instanceVAO)
+ .addAttribs<LocationVertex, &LocationVertex::body, &LocationVertex::bodyPos>(instances.bufferName(), 1);
bogies.front()
->configureVAO(instancesBogiesVAO.front())
- .addAttribs<LocationVertex, &LocationVertex::front>(instances.bufferName(), 1);
+ .addAttribs<LocationVertex, &LocationVertex::front, &LocationVertex::frontPos>(instances.bufferName(), 1);
bogies.back()
->configureVAO(instancesBogiesVAO.back())
- .addAttribs<LocationVertex, &LocationVertex::back>(instances.bufferName(), 1);
+ .addAttribs<LocationVertex, &LocationVertex::back, &LocationVertex::backPos>(instances.bufferName(), 1);
+ static_assert(sizeof(LocationVertex) == 228UL);
}
void
diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h
index 80b3fda..913feea 100644
--- a/game/vehicles/railVehicleClass.h
+++ b/game/vehicles/railVehicleClass.h
@@ -20,6 +20,7 @@ public:
struct LocationVertex {
glm::mat4 body, front, back;
+ GlobalPosition3D bodyPos, frontPos, backPos;
};
std::array<Mesh::Ptr, 2> bogies;
@@ -41,4 +42,5 @@ private:
glVertexArray instanceVAO;
std::array<glVertexArray, 2> instancesBogiesVAO;
};
+
using RailVehicleClassPtr = std::shared_ptr<RailVehicleClass>;
diff --git a/game/vehicles/train.cpp b/game/vehicles/train.cpp
index 6f3b036..4aa24dc 100644
--- a/game/vehicles/train.cpp
+++ b/game/vehicles/train.cpp
@@ -20,7 +20,7 @@ Train::getBogiePosition(float linkDist, float dist) const
}
bool
-Train::intersectRay(const Ray & ray, glm::vec2 * baryPos, float * distance) const
+Train::intersectRay(const Ray & ray, Position2D * baryPos, float * distance) const
{
return applyOne(&RailVehicle::intersectRay, ray, baryPos, distance) != end();
}
diff --git a/game/vehicles/train.h b/game/vehicles/train.h
index 20c3bc4..7f0bb99 100644
--- a/game/vehicles/train.h
+++ b/game/vehicles/train.h
@@ -27,7 +27,7 @@ public:
return objects.front()->location;
}
- [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override;
+ [[nodiscard]] bool intersectRay(const Ray &, Position2D *, float *) const override;
void tick(TickDuration elapsed) override;
void doActivity(Go *, TickDuration) override;
diff --git a/game/vehicles/vehicle.h b/game/vehicles/vehicle.h
index 763ade9..354f904 100644
--- a/game/vehicles/vehicle.h
+++ b/game/vehicles/vehicle.h
@@ -27,4 +27,5 @@ protected:
void move(TickDuration dur);
LinkHistory linkHist;
};
+
using VehicleWPtr = std::weak_ptr<Vehicle>;