diff options
-rw-r--r-- | Jamroot.jam | 6 | ||||
-rw-r--r-- | application/main.cpp | 14 | ||||
-rw-r--r-- | game/network/link.cpp | 18 | ||||
-rw-r--r-- | game/network/link.h | 51 | ||||
-rw-r--r-- | game/network/rail.cpp | 87 | ||||
-rw-r--r-- | game/network/rail.h | 52 | ||||
-rw-r--r-- | gfx/models/mesh.cpp | 8 | ||||
-rw-r--r-- | gfx/models/mesh.h | 3 | ||||
-rw-r--r-- | iwyu.json | 8 | ||||
-rw-r--r-- | res/rails.jpg | bin | 0 -> 14221 bytes | |||
-rw-r--r-- | utility/stream_support.hpp | 20 |
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
@@ -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 Binary files differnew file mode 100644 index 0000000..7ae0d51 --- /dev/null +++ b/res/rails.jpg 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 |