summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamroot.jam6
-rw-r--r--application/main.cpp14
-rw-r--r--game/network/link.cpp18
-rw-r--r--game/network/link.h51
-rw-r--r--game/network/rail.cpp87
-rw-r--r--game/network/rail.h52
-rw-r--r--gfx/models/mesh.cpp8
-rw-r--r--gfx/models/mesh.h3
-rw-r--r--iwyu.json8
-rw-r--r--res/rails.jpgbin0 -> 14221 bytes
-rw-r--r--utility/stream_support.hpp20
11 files changed, 260 insertions, 7 deletions
diff --git a/Jamroot.jam b/Jamroot.jam
index 043ac4f..d062442 100644
--- a/Jamroot.jam
+++ b/Jamroot.jam
@@ -3,6 +3,7 @@ using pkg-config ;
import pkg-config ;
import type : register ;
import generators : register-standard ;
+import testing ;
pkg-config.import sdl2 ;
pkg-config.import glew ;
@@ -51,6 +52,11 @@ exe iliketrains :
<library>ilt
;
+run application/main.cpp
+ : : :
+ <library>ilt
+ ;
+
lib ilt :
[ glob-tree *.cpp *.c *.vs *.fs : bin test ]
:
diff --git a/application/main.cpp b/application/main.cpp
index 94a3b0f..2b62953 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -1,6 +1,9 @@
#include <SDL2/SDL.h>
+#include <array>
#include <chrono>
#include <collection.hpp>
+#include <game/network/link.h>
+#include <game/network/rail.h>
#include <game/terrain.h>
#include <game/world.h>
#include <game/worldobject.h>
@@ -11,13 +14,15 @@
#include <gfx/manualCameraController.h>
#include <gfx/renderable.h>
#include <gfx/window.h>
+#include <glm/glm.hpp>
#include <memory>
#include <special_members.hpp>
+#include <utility>
#include <vector>
#include <worker.h>
-static const int DISPLAY_WIDTH = 800;
-static const int DISPLAY_HEIGHT = 600;
+static const int DISPLAY_WIDTH = 1280;
+static const int DISPLAY_HEIGHT = 1024;
class SDL_Application : public InputHandler, public std::enable_shared_from_this<SDL_Application> {
public:
@@ -62,6 +67,11 @@ public:
Worker w;
world.create<Terrain>();
+ auto rl = world.create<RailLinks>();
+ auto a = rl->addLink<RailLinkStraight>({-1190, 5, -1190}, {-1190, 6, -1180});
+ auto b = rl->addLink<RailLinkStraight>(a->ends.back().first->pos, glm::vec3 {-1180, 5, -1180});
+ auto c = rl->addLink<RailLinkStraight>(b->ends.back().first->pos, glm::vec3 {-1180, 4, -1190});
+ rl->addLink<RailLinkStraight>(c->ends.back().first->pos, a->ends.front().first->pos);
Shader shader;
Camera camera({-1250.0F, 35.0F, -1250.0F}, 70.0F, (float)DISPLAY_WIDTH / (float)DISPLAY_HEIGHT, 0.1F, 10000.0F);
diff --git a/game/network/link.cpp b/game/network/link.cpp
new file mode 100644
index 0000000..65aefd6
--- /dev/null
+++ b/game/network/link.cpp
@@ -0,0 +1,18 @@
+#include "link.h"
+#include <compare>
+#include <tuple>
+
+Link::Link(End a, End b) : ends {{std::move(a), std::move(b)}} { }
+
+bool
+operator<(const glm::vec3 & a, const glm::vec3 & b)
+{
+ // NOLINTNEXTLINE(hicpp-use-nullptr,modernize-use-nullptr)
+ return std::tie(a.x, a.z, a.y) < std::tie(b.x, b.z, b.y);
+}
+
+bool
+operator<(const Node & a, const Node & b)
+{
+ return a.pos < b.pos;
+}
diff --git a/game/network/link.h b/game/network/link.h
new file mode 100644
index 0000000..0da413c
--- /dev/null
+++ b/game/network/link.h
@@ -0,0 +1,51 @@
+#ifndef LINK_H
+#define LINK_H
+
+#include <array>
+#include <glm/glm.hpp>
+#include <memory>
+#include <special_members.hpp>
+#include <utility>
+
+// Generic network node
+// something that can be travelled to
+// it has location
+class Node {
+public:
+ explicit Node(glm::vec3 p) noexcept : pos(p) {};
+ virtual ~Node() noexcept = default;
+ NO_COPY(Node);
+ NO_MOVE(Node);
+
+ glm::vec3 pos;
+};
+using NodePtr = std::shared_ptr<Node>;
+
+// Generic network link
+// something that can be travelled along
+// it joins 2 nodes
+class Link {
+public:
+ // side determines which edges can be moved to next, must alternate
+ using End = std::pair<NodePtr, bool /*side*/>;
+
+ Link(End, End);
+ virtual ~Link() = default;
+ NO_COPY(Link);
+ NO_MOVE(Link);
+
+ std::array<End, 2> ends;
+};
+
+template<typename T> struct PtrSorter {
+ bool
+ operator()(const T & a, const T & b) const
+ {
+ return *a < *b;
+ }
+};
+
+bool operator<(const glm::vec3 & a, const glm::vec3 & b);
+bool operator<(const Node & a, const Node & b);
+
+#endif
diff --git a/game/network/rail.cpp b/game/network/rail.cpp
new file mode 100644
index 0000000..ecec0c0
--- /dev/null
+++ b/game/network/rail.cpp
@@ -0,0 +1,87 @@
+#include "rail.h"
+#include "game/network/link.h"
+#include <GL/glew.h>
+#include <array>
+#include <cache.h>
+#include <cmath>
+#include <gfx/gl/shader.h>
+#include <gfx/models/texture.h>
+#include <gfx/models/vertex.hpp>
+#include <glm/gtx/rotate_vector.hpp>
+#include <glm/gtx/transform.hpp>
+#include <numbers>
+#include <utility>
+
+RailLinks::RailLinks() : texture {Texture::cachedTexture.get("rails.jpg")} { }
+void RailLinks::tick(TickDuration) { }
+
+static const auto identityModel {glm::identity<glm::mat4>()};
+
+void
+RailLinks::render(const Shader & shader) const
+{
+ shader.setModel(identityModel);
+ texture->Bind();
+ links.apply(&RailLink::render, shader);
+}
+
+template<RailLinkConcept T>
+std::shared_ptr<T>
+RailLinks::addLink(glm::vec3 a, glm::vec3 b)
+{
+ const auto node1 = *nodes.insert(std::make_shared<Node>(a)).first;
+ const auto node2 = *nodes.insert(std::make_shared<Node>(b)).first;
+ // TODO set end flag properly
+ return links.create<T>(Link::End {node1, true}, Link::End {node2, true});
+}
+
+template std::shared_ptr<RailLinkStraight> RailLinks::addLink(glm::vec3, glm::vec3);
+void
+RailLink::render(const Shader &) const
+{
+ meshes.apply(&Mesh::Draw);
+}
+
+constexpr const std::array<std::pair<glm::vec3, float>, 4> railCrossSection {{
+ // ___________
+ // _/ \_
+ // left to right
+ {{-1.F, 0.F, 0.F}, 0.F},
+ {{-.75F, .25F, 0.F}, 0.125F},
+ {{.75F, .25F, 0.F}, 0.875F},
+ {{1.F, 0.F, 0.F}, 1.F},
+}};
+constexpr const glm::vec3 up {0, 1, 0};
+constexpr const glm::vec3 north {0, 0, 1};
+const auto oneeighty {glm::rotate(std::numbers::pi_v<float>, up)};
+
+template<typename V>
+auto
+flat_orientation(const V & diff)
+{
+ const auto flatdiff {glm::normalize(glm::vec3 {diff.x, 0, diff.z})};
+ auto e {glm::orientation(flatdiff, north)};
+ // Handle if diff is exactly opposite to north
+ return (std::isnan(e[0][0])) ? oneeighty : e;
+}
+
+RailLinkStraight::RailLinkStraight(End a, End b) : RailLink(std::move(a), std::move(b))
+{
+ vertices.reserve(2 * railCrossSection.size());
+ indices.reserve(2 * railCrossSection.size());
+ const auto diff {ends[1].first->pos - ends[0].first->pos};
+ const auto len = glm::length(diff) / 2.F;
+ const auto e {flat_orientation(diff)};
+ for (int ei = 0; ei < 2; ei++) {
+ const auto trans {glm::translate(ends[ei].first->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, ei ? len : 0.F}, up);
+ if (vertices.size() > railCrossSection.size()) {
+ indices.push_back(vertices.size() - railCrossSection.size() - 1);
+ indices.push_back(vertices.size() - 1);
+ }
+ }
+ }
+ meshes.create<Mesh>(vertices, indices, GL_TRIANGLE_STRIP);
+}
diff --git a/game/network/rail.h b/game/network/rail.h
new file mode 100644
index 0000000..ef119bc
--- /dev/null
+++ b/game/network/rail.h
@@ -0,0 +1,52 @@
+#ifndef RAILLINKS_H
+#define RAILLINKS_H
+
+#include "collection.hpp"
+#include "game/worldobject.h"
+#include "gfx/models/mesh.h"
+#include "gfx/models/vertex.hpp"
+#include "gfx/renderable.h"
+#include "link.h"
+#include <glm/glm.hpp>
+#include <memory>
+#include <set>
+#include <vector>
+class Shader;
+class Texture;
+
+// A piece of rail track
+class RailLink : public Link, public Renderable {
+public:
+ using Link::Link;
+
+ void render(const Shader &) const override;
+
+protected:
+ RailLink();
+ Collection<Mesh, false> meshes;
+ std::vector<Vertex> vertices;
+ std::vector<unsigned int> indices;
+};
+
+class RailLinkStraight : public RailLink {
+public:
+ RailLinkStraight(End, End);
+};
+
+template<typename T> concept RailLinkConcept = std::is_base_of_v<RailLink, T>;
+
+class RailLinks : public Renderable, public WorldObject {
+public:
+ RailLinks();
+ template<RailLinkConcept T> std::shared_ptr<T> addLink(glm::vec3, glm::vec3);
+
+private:
+ using Nodes = std::set<NodePtr, PtrSorter<NodePtr>>;
+ Collection<RailLink> links;
+ Nodes nodes;
+ void render(const Shader &) const override;
+ void tick(TickDuration elapsed) override;
+ std::shared_ptr<Texture> texture;
+};
+
+#endif
diff --git a/gfx/models/mesh.cpp b/gfx/models/mesh.cpp
index 90de8db..4a3d9d4 100644
--- a/gfx/models/mesh.cpp
+++ b/gfx/models/mesh.cpp
@@ -7,7 +7,7 @@
Mesh::Mesh(const std::string & fileName) : Mesh(OBJModel(fileName).ToIndexedModel()) { }
Mesh::Mesh(const IndexedModel & model) :
- m_vertexArrayObject {}, m_vertexArrayBuffers {}, m_numIndices {model.indices.size()}
+ m_vertexArrayObject {}, m_vertexArrayBuffers {}, m_numIndices {model.indices.size()}, mode {GL_TRIANGLES}
{
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
@@ -38,8 +38,8 @@ Mesh::Mesh(const IndexedModel & model) :
glBindVertexArray(0);
}
-Mesh::Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices) :
- m_vertexArrayObject {}, m_vertexArrayBuffers {}, m_numIndices {indices.size()}
+Mesh::Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices, GLenum m) :
+ m_vertexArrayObject {}, m_vertexArrayBuffers {}, m_numIndices {indices.size()}, mode {m}
{
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
@@ -75,7 +75,7 @@ Mesh::Draw() const
{
glBindVertexArray(m_vertexArrayObject);
- glDrawElementsBaseVertex(GL_TRIANGLES, m_numIndices, GL_UNSIGNED_INT, nullptr, 0);
+ glDrawElementsBaseVertex(mode, m_numIndices, GL_UNSIGNED_INT, nullptr, 0);
glBindVertexArray(0);
}
diff --git a/gfx/models/mesh.h b/gfx/models/mesh.h
index e955644..ebd300b 100644
--- a/gfx/models/mesh.h
+++ b/gfx/models/mesh.h
@@ -17,7 +17,7 @@ class Mesh {
public:
explicit Mesh(const std::string & fileName);
explicit Mesh(const IndexedModel & model);
- Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices);
+ Mesh(std::span<Vertex> vertices, std::span<unsigned int> indices, GLenum = GL_TRIANGLES);
virtual ~Mesh();
NO_COPY(Mesh);
@@ -31,6 +31,7 @@ private:
GLuint m_vertexArrayObject;
std::array<GLuint, NUM_BUFFERS> m_vertexArrayBuffers;
size_t m_numIndices;
+ GLenum mode;
};
#endif
diff --git a/iwyu.json b/iwyu.json
index 8bfa310..0df2666 100644
--- a/iwyu.json
+++ b/iwyu.json
@@ -33,6 +33,14 @@
},
{
"include": [
+ "@<glm/gtx/rotate_vector.inl>",
+ "private",
+ "<glm/gtx/rotate_vector.hpp>",
+ "public"
+ ]
+ },
+ {
+ "include": [
"@<glm/gtx/transform.inl>",
"private",
"<glm/gtx/transform.hpp>",
diff --git a/res/rails.jpg b/res/rails.jpg
new file mode 100644
index 0000000..7ae0d51
--- /dev/null
+++ b/res/rails.jpg
Binary files differ
diff --git a/utility/stream_support.hpp b/utility/stream_support.hpp
new file mode 100644
index 0000000..6ab1bd1
--- /dev/null
+++ b/utility/stream_support.hpp
@@ -0,0 +1,20 @@
+#ifndef STREAM_SUPPORT_H
+#define STREAM_SUPPORT_H
+
+#include <iostream>
+
+template<glm::length_t L, glm::length_t R, typename T, glm::qualifier Q>
+std::ostream &
+operator<<(std::ostream & s, glm::mat<L, R, T, Q> & m)
+{
+ for (int y = 0; y < m.length(); y++) {
+ const auto & col = m[y];
+ for (int x = 0; x < col.length(); x++) {
+ s << col[x] << ", ";
+ }
+ s << "\n";
+ }
+ return s;
+}
+
+#endif