diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-11-26 13:51:33 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-11-26 14:14:13 +0000 |
commit | 7fba471728f2216d7e3b7900297fc3b3531e286c (patch) | |
tree | 5caef3b2efc23aefccb215ec9005cd8e7d2e91b8 | |
parent | Fix todo for handling a terrain walk from outside the mesh (diff) | |
parent | Model positions as integers (diff) | |
download | ilt-7fba471728f2216d7e3b7900297fc3b3531e286c.tar.bz2 ilt-7fba471728f2216d7e3b7900297fc3b3531e286c.tar.xz ilt-7fba471728f2216d7e3b7900297fc3b3531e286c.zip |
Merge branch 'ints' into terrain
Conflicts fix, compiles, some test failures remain.
Trees not added, possibility of OM invalid handle assertion failures,
normals broken due to integer overflow in Newell's method.
142 files changed, 864 insertions, 574 deletions
diff --git a/application/main.cpp b/application/main.cpp index 9e4ca33..5db2539 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -26,7 +26,6 @@ #include <ui/applicationBase.h> #include <ui/gameMainWindow.h> #include <ui/window.h> -#include <vector> static const int DISPLAY_WIDTH = 1280; static const int DISPLAY_HEIGHT = 1024; @@ -48,10 +47,10 @@ public: { auto rl = world.create<RailLinks>(); - const glm::vec3 j {-1120, -1100, 3}, k {-1100, -1000, 15}, l {-1000, -800, 20}, m {-900, -600, 30}, - n {-600, -500, 32}, o {-500, -800, 30}, p {-600, -900, 25}, q {-1025, -1175, 10}, - r {-925, -1075, 10}; - const glm::vec3 s {-1100, -500, 15}, t {-1100, -450, 15}, u {-1000, -400, 15}; + const Position3D j {-1120000, -1100000, 3000}, k {-1100000, -1000000, 15000}, l {-1000000, -800000, 20000}, + m {-900000, -600000, 30000}, n {-600000, -500000, 32000}, o {-500000, -800000, 30000}, + p {-600000, -900000, 25000}, q {-1025000, -1175000, 10000}, r {-925000, -1075000, 10000}; + const Position3D s {-1100000, -500000, 15000}, t {-1100000, -450000, 15000}, u {-1000000, -400000, 15000}; auto l3 = rl->addLinksBetween(j, k); rl->addLinksBetween(k, l); rl->addLinksBetween(l, m); @@ -75,13 +74,14 @@ public: train->create<RailVehicle>(b47); } train->orders.removeAll(); - train->orders.create<GoTo>(&train->orders, l3->ends[1], l3->length, rl->findNodeAt({-1100, -450, 15})); + train->orders.create<GoTo>( + &train->orders, l3->ends[1], l3->length, rl->findNodeAt({-1100000, -450000, 15000})); train->currentActivity = train->orders.current()->createActivity(); // auto foliage = std::dynamic_pointer_cast<Foliage>(assets.at("Tree-01-1")); - // for (float x = 900; x < 1100; x += 3) { - // for (float y = 900; y < 1100; y += 3) { - // world.create<Plant>(foliage, Location {terrainMesh->positionAt(glm::vec2 {-x, -y})}); + // for (float x = 900000; x < 1100000; x += 5000) { + // for (float y = 900000; y < 1100000; y += 5000) { + // world.create<Plant>(foliage, Location {geoData->positionAt({{-x, -y}})}); //} //} } diff --git a/assetFactory/assetFactory.h b/assetFactory/assetFactory.h index e449ce2..787f0a4 100644 --- a/assetFactory/assetFactory.h +++ b/assetFactory/assetFactory.h @@ -15,10 +15,9 @@ public: using Assets = std::map<std::string, Asset::Ptr, std::less<>>; using AssImps = std::map<std::string, AssImp::Ptr, std::less<>>; using TextureFragments = std::map<std::string, TextureFragment::Ptr, std::less<>>; - using Colour = glm::vec3; - using ColourAlpha = glm::vec4; + using Colour = RGB; + using ColourAlpha = RGBA; using Colours = std::map<std::string, Colour, std::less<>>; - using TextureFragmentCoords = std::array<glm::vec2, 4>; AssetFactory(); [[nodiscard]] static std::shared_ptr<AssetFactory> loadXML(const std::filesystem::path &); diff --git a/assetFactory/assimp.cpp b/assetFactory/assimp.cpp index 9dc7842..bd5467b 100644 --- a/assetFactory/assimp.cpp +++ b/assetFactory/assimp.cpp @@ -30,6 +30,7 @@ operator!(const aiVector3t<T> & v) } using SceneCPtr = std::shared_ptr<const aiScene>; + class AssImpNode : public Shape { public: AssImpNode(SceneCPtr scene, const aiNode * node) : scene(std::move(scene)), node(node) { } diff --git a/assetFactory/cuboid.cpp b/assetFactory/cuboid.cpp index a8ddcd9..cfb6cfb 100644 --- a/assetFactory/cuboid.cpp +++ b/assetFactory/cuboid.cpp @@ -4,7 +4,7 @@ Cuboid::CreatedFaces Cuboid::createMesh(ModelFactoryMesh & mesh, float) const { - static constexpr std::array<glm::vec3, 8> VERTICES {{ + static constexpr std::array<Position3D, 8> VERTICES {{ // bottom {n, n, z}, {n, y, z}, diff --git a/assetFactory/cylinder.cpp b/assetFactory/cylinder.cpp index 7d22e36..ed034fd 100644 --- a/assetFactory/cylinder.cpp +++ b/assetFactory/cylinder.cpp @@ -9,8 +9,8 @@ Cylinder::createMesh(ModelFactoryMesh & mesh, float lodf) const const auto step = two_pi / static_cast<float>(P); // Generate 2D circumference points - std::vector<glm::vec2> circumference(P); - std::generate(circumference.begin(), circumference.end(), [a = 0.f, step]() mutable { + std::vector<Position2D> circumference(P); + std::generate(circumference.begin(), circumference.end(), [a = 0.F, step]() mutable { return sincosf(a += step) * .5F; }); @@ -19,7 +19,7 @@ Cylinder::createMesh(ModelFactoryMesh & mesh, float lodf) const // Generate bottom face vertices std::vector<OpenMesh::VertexHandle> bottom(P); std::transform(circumference.begin(), circumference.end(), bottom.begin(), [&mesh](const auto & xy) { - return mesh.add_vertex(xy ^ 0.f); + return mesh.add_vertex(xy ^ 0.F); }); surface.insert(mesh.add_namedFace("bottom", bottom)); } diff --git a/assetFactory/faceController.h b/assetFactory/faceController.h index 0376241..fb89d25 100644 --- a/assetFactory/faceController.h +++ b/assetFactory/faceController.h @@ -18,12 +18,14 @@ public: private: friend Persistence::SelectionPtrBase<std::unique_ptr<Split>>; bool persist(Persistence::PersistenceStore & store) override; + std::string getId() const override { return {}; }; }; + using FaceControllers = std::map<std::string, std::unique_ptr<FaceController>>; using Splits = std::map<std::string, std::unique_ptr<Split>>; @@ -38,6 +40,7 @@ public: private: friend Persistence::SelectionPtrBase<std::unique_ptr<FaceController>>; bool persist(Persistence::PersistenceStore & store) override; + std::string getId() const override { diff --git a/assetFactory/factoryMesh.cpp b/assetFactory/factoryMesh.cpp index 46bcf6f..3caf5e8 100644 --- a/assetFactory/factoryMesh.cpp +++ b/assetFactory/factoryMesh.cpp @@ -30,7 +30,7 @@ FactoryMesh::createMesh() const const auto & point = mesh.point(vertex); const auto & normal = useVertexNormals ? mesh.property(mesh.vertex_normals_pph(), vertex) : mesh.property(mesh.face_normals_pph(), face); - Vertex outVertex {point, textureUV, normal, colour, material}; + Vertex outVertex {point * 1000.F, textureUV, normal, colour, material}; if (const auto existingItr = std::find(vertices.rbegin(), vertices.rend(), outVertex); existingItr != vertices.rend()) { faceIndices.push_back(static_cast<unsigned int>(std::distance(existingItr, vertices.rend()) - 1)); diff --git a/assetFactory/factoryMesh.h b/assetFactory/factoryMesh.h index f71c737..b09b54f 100644 --- a/assetFactory/factoryMesh.h +++ b/assetFactory/factoryMesh.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "gfx/models/mesh.h" #include "stdTypeDefs.h" #include "use.h" @@ -9,7 +10,7 @@ public: Mesh::Ptr createMesh() const; std::string id; - glm::vec3 size; + Size3D size; Use::Collection uses; private: diff --git a/assetFactory/modelFactoryMesh.h b/assetFactory/modelFactoryMesh.h index 2129fb5..06fd7b8 100644 --- a/assetFactory/modelFactoryMesh.h +++ b/assetFactory/modelFactoryMesh.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "modelFactoryMesh_fwd.h" #include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh> #include <glad/gl.h> @@ -13,10 +14,10 @@ struct ModelFactoryTraits : public OpenMesh::DefaultTraits { EdgeAttributes(OpenMesh::Attributes::Status); VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); HalfedgeAttributes(OpenMesh::Attributes::TexCoord2D); - using Point = glm::vec3; - using Normal = glm::vec3; - using Color = glm::vec4; - using TexCoord2D = glm::vec2; + using Point = Position3D; + using Normal = Normal3D; + using Color = RGBA; + using TexCoord2D = TextureRelCoord; }; struct ModelFactoryMesh : public OpenMesh::PolyMesh_ArrayKernelT<ModelFactoryTraits> { diff --git a/assetFactory/mutation.cpp b/assetFactory/mutation.cpp index 9a6a988..c5c3f5b 100644 --- a/assetFactory/mutation.cpp +++ b/assetFactory/mutation.cpp @@ -27,6 +27,7 @@ Mutation::relativeLevelOfDetail() const { return std::max({scale.x, scale.y, scale.z}); } + bool Mutation::persist(Persistence::PersistenceStore & store) { diff --git a/assetFactory/mutation.h b/assetFactory/mutation.h index 2432174..b571dea 100644 --- a/assetFactory/mutation.h +++ b/assetFactory/mutation.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "persistence.h" #include <glm/mat4x4.hpp> #include <glm/vec3.hpp> @@ -13,9 +14,9 @@ struct Mutation { float relativeLevelOfDetail() const; - glm::vec3 position {}; - glm::vec3 rotation {}; - glm::vec3 scale {1}; + Position3D position {}; + Rotation3D rotation {}; + Scale3D scale {1}; protected: bool persist(Persistence::PersistenceStore & store); diff --git a/assetFactory/object.h b/assetFactory/object.h index f47c512..77e1469 100644 --- a/assetFactory/object.h +++ b/assetFactory/object.h @@ -18,6 +18,7 @@ public: private: friend Persistence::SelectionPtrBase<std::shared_ptr<Object>>; bool persist(Persistence::PersistenceStore & store) override; + std::string getId() const override { diff --git a/assetFactory/plane.cpp b/assetFactory/plane.cpp index c6e1b5a..28fb690 100644 --- a/assetFactory/plane.cpp +++ b/assetFactory/plane.cpp @@ -4,7 +4,7 @@ Plane::CreatedFaces Plane::createMesh(ModelFactoryMesh & mesh, float) const { - static constexpr std::array<glm::vec3, 4> VERTICES {{ + static constexpr std::array<Position3D, 4> VERTICES {{ {n, n, z}, {y, n, z}, {y, y, z}, diff --git a/assetFactory/shape.cpp b/assetFactory/shape.cpp index 1bfbdbb..0f83ee5 100644 --- a/assetFactory/shape.cpp +++ b/assetFactory/shape.cpp @@ -1,11 +1,9 @@ #include "shape.h" -#include "gfx/models/vertex.h" -#include "maths.h" #include "modelFactoryMesh.h" #include "shape.h" std::vector<OpenMesh::VertexHandle> -Shape::addToMesh(ModelFactoryMesh & mesh, const std::span<const glm::vec3> vertices) +Shape::addToMesh(ModelFactoryMesh & mesh, const std::span<const Position3D> vertices) { std::vector<OpenMesh::VertexHandle> vhs; std::transform(vertices.begin(), vertices.end(), std::back_inserter(vhs), [&mesh](const auto & p) { diff --git a/assetFactory/shape.h b/assetFactory/shape.h index ea3e4e7..136e24f 100644 --- a/assetFactory/shape.h +++ b/assetFactory/shape.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "modelFactoryMesh_fwd.h" #include "stdTypeDefs.h" #include <OpenMesh/Core/Mesh/Handles.hh> @@ -21,5 +22,5 @@ public: virtual CreatedFaces createMesh(ModelFactoryMesh &, float levelOfDetailFactor) const = 0; static std::vector<OpenMesh::VertexHandle> addToMesh( - ModelFactoryMesh & mesh, const std::span<const glm::vec3> vertices); + ModelFactoryMesh & mesh, const std::span<const Position3D> vertices); }; diff --git a/assetFactory/style.cpp b/assetFactory/style.cpp index ea67fc2..265becb 100644 --- a/assetFactory/style.cpp +++ b/assetFactory/style.cpp @@ -33,10 +33,10 @@ Style::applyStyle( const auto material = mf->getMaterialIndex(texture); mesh.property(mesh.materialFaceProperty, face) = material; static constexpr std::array<ModelFactoryTraits::TexCoord2D, 4> coords {{ - {0.f, 0.f}, - {1.f, 0.f}, - {1.f, 1.f}, - {0.f, 1.f}, + {0.F, 0.F}, + {1.F, 0.F}, + {1.F, 1.F}, + {0.F, 1.F}, }}; auto coord = coords.begin(); // Wild assumption that face is a quad and the texture should apply linearly @@ -58,9 +58,10 @@ Style::getColour(const StyleStack & parents) bool Style::persist(Persistence::PersistenceStore & store) { - struct ColourParser : public Persistence::SelectionV<ColourAlpha> { - using Persistence::SelectionV<ColourAlpha>::SelectionV; - using Persistence::SelectionV<ColourAlpha>::setValue; + struct ColourParser : public Persistence::SelectionV<RGBA> { + using Persistence::SelectionV<RGBA>::SelectionV; + using Persistence::SelectionV<RGBA>::setValue; + void setValue(std::string && str) override { diff --git a/assetFactory/style.h b/assetFactory/style.h index d931f98..2a437aa 100644 --- a/assetFactory/style.h +++ b/assetFactory/style.h @@ -10,9 +10,7 @@ class Style { public: using StyleStack = std::vector<const Style *>; - using Colour = glm::vec3; - using ColourAlpha = glm::vec4; - using EffectiveColour = std::optional<std::reference_wrapper<const ColourAlpha>>; + using EffectiveColour = std::optional<std::reference_wrapper<const RGBA>>; void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const Shape::CreatedFaces &) const; void applyStyle(ModelFactoryMesh &, const StyleStack & parents, const ModelFactoryMesh::FaceHandle &) const; @@ -30,7 +28,7 @@ public: static EffectiveColour getColour(const StyleStack & parents); - ColourAlpha colour {}; + RGBA colour {}; std::optional<bool> smooth; std::string texture; std::string textureRotation; // Multiples of 90deg, no int/enum support diff --git a/assetFactory/texturePacker.cpp b/assetFactory/texturePacker.cpp index dbafc4b..0d0fdb6 100644 --- a/assetFactory/texturePacker.cpp +++ b/assetFactory/texturePacker.cpp @@ -14,9 +14,7 @@ TexturePacker::TexturePacker(std::span<const Image> in) : std::sort(sortedIndexes.rbegin(), sortedIndexes.rend(), [this](const auto a, const auto b) { return area(inputImages[a]) < area(inputImages[b]); }); - int mts; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts); - maxTextureSize = static_cast<unsigned int>(mts); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); } TexturePacker::Result diff --git a/assetFactory/texturePacker.h b/assetFactory/texturePacker.h index a1b270b..05e3204 100644 --- a/assetFactory/texturePacker.h +++ b/assetFactory/texturePacker.h @@ -1,13 +1,14 @@ #pragma once +#include "config/types.h" #include <glm/vec2.hpp> #include <span> #include <vector> class TexturePacker { public: - using Position = glm::uvec2; - using Size = glm::uvec2; + using Position = TextureAbsCoord; + using Size = TextureAbsCoord; struct Area { #ifndef __cpp_aggregate_paren_init @@ -16,12 +17,14 @@ public: Position position; Size size; + bool operator<(const Area & other) const { return area(size) < area(other.size); } }; + using Image = Size; using Space = Area; using Positions = std::vector<Position>; @@ -38,5 +41,5 @@ public: private: std::span<const Image> inputImages; std::vector<size_t> sortedIndexes; - unsigned int maxTextureSize; + GLsizei maxTextureSize; }; diff --git a/assetFactory/use.cpp b/assetFactory/use.cpp index 5314321..0994c8c 100644 --- a/assetFactory/use.cpp +++ b/assetFactory/use.cpp @@ -35,6 +35,7 @@ Use::createMesh(ModelFactoryMesh & mesh, float levelOfDetailFactor) const struct Lookup : public Persistence::SelectionV<Shape::CPtr> { using Persistence::SelectionV<Shape::CPtr>::SelectionV; using Persistence::SelectionV<Shape::CPtr>::setValue; + void setValue(std::string && str) override { diff --git a/assetFactory/use.h b/assetFactory/use.h index a91685b..289bf6e 100644 --- a/assetFactory/use.h +++ b/assetFactory/use.h @@ -19,6 +19,7 @@ public: private: friend Persistence::SelectionPtrBase<std::shared_ptr<Use>>; bool persist(Persistence::PersistenceStore & store) override; + std::string getId() const override { diff --git a/config/types.h b/config/types.h new file mode 100644 index 0000000..6fc7b61 --- /dev/null +++ b/config/types.h @@ -0,0 +1,48 @@ +#pragma once + +#include "glad/gl.h" +#include <glm/geometric.hpp> + +using Distance = float; // deprecate +using RelativeDistance = float; +using GlobalDistance = int32_t; +using Angle = float; + +template<glm::length_t D> using Position = glm::vec<D, Distance>; // deprecate +template<glm::length_t D> using RelativePosition = glm::vec<D, RelativeDistance>; +template<glm::length_t D> using GlobalPosition = glm::vec<D, GlobalDistance>; +template<glm::length_t D> using Size = glm::vec<D, Distance>; +template<glm::length_t D> using Scale = glm::vec<D, float>; +template<glm::length_t D> using Direction = glm::vec<D, float>; +template<glm::length_t D> using Normal = Direction<D>; +template<glm::length_t D> using Rotation = glm::vec<D, Angle>; +template<glm::length_t Channels> using Colour = glm::vec<Channels, float>; + +using Position2D = Position<2>; // deprecate +using Position3D = Position<3>; // deprecate +using BaryPosition = glm::vec<2, float>; +using RelativePosition2D = RelativePosition<2>; +using RelativePosition3D = RelativePosition<3>; +using RelativePosition4D = RelativePosition<4>; +using GlobalPosition2D = GlobalPosition<2>; +using GlobalPosition3D = GlobalPosition<3>; +using GlobalPosition4D = GlobalPosition<4>; +using Size2D = Size<2>; +using Size3D = Size<3>; +using Scale2D = Scale<2>; +using Scale3D = Scale<3>; +using Direction2D = Direction<2>; +using Direction3D = Direction<3>; +using Normal2D = Normal<2>; +using Normal3D = Normal<3>; +using Rotation2D = Rotation<2>; +using Rotation3D = Rotation<3>; +using TextureRelCoord = glm::vec<2, float>; +using TextureRelRegion = glm::vec<4, float>; +using TextureAbsCoord = glm::vec<2, GLsizei>; +using TextureAbsRegion = glm::vec<4, GLsizei>; +using RGB = Colour<3>; +using RGBA = Colour<4>; +using ScreenRelCoord = glm::vec<2, float>; +using ScreenAbsCoord = glm::vec<2, uint16_t>; +using ViewPort = glm::vec<4, GLsizei>; 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>; diff --git a/gfx/followCameraController.cpp b/gfx/followCameraController.cpp index 5b08483..aee2187 100644 --- a/gfx/followCameraController.cpp +++ b/gfx/followCameraController.cpp @@ -24,11 +24,11 @@ FollowCameraController::updateCamera(Camera * camera) const break; case Mode::Ride: - camera->setView(pos + (up * 4.8F), !-sincosf(rot.y)); + camera->setView(pos + GlobalPosition3D(up * 4.8F), !-sincosf(rot.y)); break; case Mode::ISO: - camera->setView(pos + ((up + north + east) * 40.F), glm::normalize(down + south + west), + camera->setView(pos + GlobalPosition3D((up + north + east) * 40.F), glm::normalize(down + south + west), glm::normalize(up - north - east)); break; } diff --git a/gfx/gl/bufferedLocation.cpp b/gfx/gl/bufferedLocation.cpp index eb3dac3..d6a63b9 100644 --- a/gfx/gl/bufferedLocation.cpp +++ b/gfx/gl/bufferedLocation.cpp @@ -1,9 +1,8 @@ #include "bufferedLocation.h" #include "location.h" -#include "maths.h" #include <glm/gtx/transform.hpp> -BufferedLocation::BufferedLocation(glm::vec3 p, glm::vec3 r) : BufferedLocation {Location {p, r}} { } +BufferedLocation::BufferedLocation(GlobalPosition3D p, Rotation3D r) : BufferedLocation {Location {p, r}} { } BufferedLocation::BufferedLocation(const Location & l) : loc {l} { } @@ -20,20 +19,20 @@ BufferedLocation::operator=(const Location & l) return *this; } -glm::vec3 +GlobalPosition3D BufferedLocation::position() const { return loc.pos; } -glm::vec3 +Position3D BufferedLocation::rotation() const { return loc.rot; } void -BufferedLocation::setPosition(glm::vec3 p, bool update) +BufferedLocation::setPosition(GlobalPosition3D p, bool update) { loc.pos = p; if (update) { @@ -42,7 +41,7 @@ BufferedLocation::setPosition(glm::vec3 p, bool update) } void -BufferedLocation::setRotation(glm::vec3 r, bool update) +BufferedLocation::setRotation(Position3D r, bool update) { loc.rot = r; if (update) { @@ -51,7 +50,7 @@ BufferedLocation::setRotation(glm::vec3 r, bool update) } void -BufferedLocation::setLocation(glm::vec3 p, glm::vec3 r) +BufferedLocation::setLocation(GlobalPosition3D p, Rotation3D r) { loc.pos = p; loc.rot = r; @@ -59,7 +58,13 @@ BufferedLocation::setLocation(glm::vec3 p, glm::vec3 r) } glm::mat4 -BufferedLocation::getTransform() const +BufferedLocation::getRotationTransform() const { - return loc.getTransform(); + return loc.getRotationTransform(); +} + +void +BufferedLocationUpdater::updateBuffer() const +{ + onUpdate(this); } diff --git a/gfx/gl/bufferedLocation.h b/gfx/gl/bufferedLocation.h index 8096489..87b957f 100644 --- a/gfx/gl/bufferedLocation.h +++ b/gfx/gl/bufferedLocation.h @@ -4,11 +4,11 @@ #include <functional> #include <glm/mat4x4.hpp> #include <glm/vec3.hpp> -#include <tuple> +#include <utility> class BufferedLocation { public: - BufferedLocation(glm::vec3 = {}, glm::vec3 = {}); + BufferedLocation(GlobalPosition3D = {}, Rotation3D = {}); BufferedLocation(const Location &); virtual ~BufferedLocation() = default; @@ -16,25 +16,25 @@ public: operator const Location &() const; - glm::vec3 position() const; - glm::vec3 rotation() const; - void setPosition(glm::vec3, bool update = true); - void setRotation(glm::vec3, bool update = true); - void setLocation(glm::vec3, glm::vec3); + [[nodiscard]] GlobalPosition3D position() const; + [[nodiscard]] Rotation3D rotation() const; + void setPosition(GlobalPosition3D, bool update = true); + void setRotation(Rotation3D, bool update = true); + void setLocation(GlobalPosition3D, Rotation3D); - glm::mat4 getTransform() const; + [[nodiscard]] glm::mat4 getRotationTransform() const; private: - virtual void updateBuffer() = 0; + virtual void updateBuffer() const = 0; Location loc; }; -template<typename... Target> class BufferedLocationT : public BufferedLocation { +class BufferedLocationUpdater : public BufferedLocation { public: template<typename... LocationArgs> - BufferedLocationT(Target &&... target, LocationArgs &&... t) : - BufferedLocation {std::forward<LocationArgs>(t)...}, target {std::forward<Target>(target)...} + BufferedLocationUpdater(std::function<void(const BufferedLocation *)> onUpdate, LocationArgs &&... t) : + BufferedLocation {std::forward<LocationArgs>(t)...}, onUpdate {std::move(onUpdate)} { updateBuffer(); } @@ -42,11 +42,7 @@ public: using BufferedLocation::operator=; private: - void - updateBuffer() override - { - std::apply(std::invoke<const Target &...>, target) = getTransform(); - } + void updateBuffer() const override; - std::tuple<Target...> target; + std::function<void(const BufferedLocation *)> onUpdate; }; diff --git a/gfx/gl/camera.cpp b/gfx/gl/camera.cpp index c4c9544..15f76c4 100644 --- a/gfx/gl/camera.cpp +++ b/gfx/gl/camera.cpp @@ -2,19 +2,19 @@ #include <collections.h> #include <glm/gtx/intersect.hpp> // IWYU pragma: keep #include <glm/gtx/transform.hpp> // IWYU pragma: keep +#include <math.h> #include <maths.h> #include <ray.h> -Camera::Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar) : +Camera::Camera(Position3D pos, Angle fov, Angle aspect, Distance zNear, Distance zFar) : position {pos}, forward {::north}, up {::up}, near {zNear}, far {zFar}, - projection {glm::perspective(fov, aspect, zNear, zFar)}, - viewProjection {projection * glm::lookAt(position, position + forward, up)}, - inverseViewProjection {glm::inverse(viewProjection)} + projection {glm::perspective(fov, aspect, zNear, zFar)}, viewProjection {}, inverseViewProjection {} { + updateView(); } Ray -Camera::unProject(const glm::vec2 & mouse) const +Camera::unProject(const ScreenRelCoord & mouse) const { static constexpr const glm::vec4 screen {0, 0, 1, 1}; const auto mouseProjection = glm::lookAt(::origin, forward, up); @@ -24,12 +24,12 @@ Camera::unProject(const glm::vec2 & mouse) const void Camera::updateView() { - viewProjection = projection * glm::lookAt(position, position + forward, up); - inverseViewProjection = glm::inverse(viewProjection); + viewProjection = projection * glm::lookAt(origin, forward, up); + inverseViewProjection = glm::inverse(projection * glm::lookAt(position, position + forward, up)); } -glm::vec3 -Camera::upFromForward(const glm::vec3 & forward) +Direction3D +Camera::upFromForward(const Direction3D & forward) { const auto right = glm::cross(forward, ::down); return glm::cross(forward, right); @@ -38,11 +38,11 @@ Camera::upFromForward(const glm::vec3 & forward) std::array<glm::vec4, 4> Camera::extentsAtDist(const float dist) const { - const auto clampToSeaFloor = [this, dist](const glm::vec3 & target) { + const auto clampToSeaFloor = [this, dist](const Position3D & target) { if (target.z < -1.5F) { const auto vec = glm::normalize(target - position); - constexpr glm::vec3 seafloor {0, 0, -1.5F}; - float outdist; + constexpr Position3D seafloor {0, 0, -1.5F}; + float outdist {}; if (glm::intersectRayPlane(position, vec, seafloor, ::up, outdist)) { return (vec * outdist + position) ^ outdist; } diff --git a/gfx/gl/camera.h b/gfx/gl/camera.h index 3f1c3a7..469df0d 100644 --- a/gfx/gl/camera.h +++ b/gfx/gl/camera.h @@ -1,60 +1,69 @@ #pragma once +#include "config/types.h" #include <glm/glm.hpp> #include <maths.h> #include <ray.h> class Camera { public: - Camera(glm::vec3 pos, float fov, float aspect, float zNear, float zFar); + Camera(Position3D, Angle fov, Angle aspect, Distance zNear, Distance zFar); [[nodiscard]] glm::mat4 getViewProjection() const { return viewProjection; } - [[nodiscard]] Ray unProject(const glm::vec2 &) const; + + [[nodiscard]] Ray unProject(const ScreenRelCoord &) const; void - setPosition(const glm::vec3 & p) + setPosition(const Position3D & p) { position = p; updateView(); } + void - setForward(const glm::vec3 & f) + setForward(const Direction3D & f) { setForward(f, upFromForward(f)); } + void - setForward(const glm::vec3 & f, const glm::vec3 & u) + setForward(const Direction3D & f, const Direction3D & u) { forward = f; up = u; updateView(); } + void - setView(const glm::vec3 & p, const glm::vec3 & f) + setView(const Position3D & p, const Direction3D & f) { position = p; setForward(f); } + void - setView(const glm::vec3 & p, const glm::vec3 & f, const glm::vec3 & u) + setView(const Position3D & p, const Direction3D & f, const Direction3D & u) { position = p; setView(f, u); } + void - lookAt(const glm::vec3 & target) + lookAt(const Position3D & target) { setForward(glm::normalize(target - position)); } + [[nodiscard]] auto getForward() const { return forward; } + [[nodiscard]] auto getPosition() const { @@ -63,14 +72,14 @@ public: [[nodiscard]] std::array<glm::vec4, 4> extentsAtDist(float) const; - [[nodiscard]] static glm::vec3 upFromForward(const glm::vec3 & forward); + [[nodiscard]] static Direction3D upFromForward(const Direction3D & forward); private: void updateView(); - glm::vec3 position; - glm::vec3 forward; - glm::vec3 up; + Position3D position; + Direction3D forward; + Direction3D up; float near, far; glm::mat4 projection; diff --git a/gfx/gl/instanceVertices.h b/gfx/gl/instanceVertices.h index 7b0341b..a89aa78 100644 --- a/gfx/gl/instanceVertices.h +++ b/gfx/gl/instanceVertices.h @@ -13,9 +13,11 @@ public: class [[nodiscard]] InstanceProxy { public: InstanceProxy(InstanceVertices * iv, std::size_t idx) : instances {iv}, index {idx} { } + InstanceProxy(InstanceProxy && other) : instances {std::exchange(other.instances, nullptr)}, index {other.index} { } + NO_COPY(InstanceProxy); ~InstanceProxy() @@ -35,6 +37,7 @@ public: index = other.index; return *this; } + template<typename U> T & operator=(U && v) @@ -42,40 +45,46 @@ public: return instances->lookup(index) = std::forward<U>(v); } - [[nodiscard]] - operator T &() + [[nodiscard]] operator T &() { return instances->lookup(index); } + [[nodiscard]] operator const T &() const { return instances->lookup(index); } + [[nodiscard]] T * get() { return &instances->lookup(index); } + [[nodiscard]] const T * get() const { return &instances->lookup(index); } + [[nodiscard]] T * operator->() { return get(); } + [[nodiscard]] const T * operator->() const { return get(); } + [[nodiscard]] T & operator*() { return instances->lookup(index); } + [[nodiscard]] const T & operator*() const { diff --git a/gfx/gl/program.h b/gfx/gl/program.h index 76b6742..1a1c306 100644 --- a/gfx/gl/program.h +++ b/gfx/gl/program.h @@ -9,6 +9,7 @@ class Location; using ProgramRef = glRef<GLuint, &glCreateProgram, &glDeleteProgram>; + class Program { public: template<typename... S> explicit Program(const S &... srcs) @@ -16,12 +17,14 @@ public: (glAttachShader(m_program, srcs.compile()), ...); linkAndValidate(); } + virtual ~Program() = default; DEFAULT_MOVE_NO_COPY(Program); class UniformLocation { public: UniformLocation(GLuint prog, const char * name); + // NOLINTNEXTLINE(hicpp-explicit-conversions) operator auto() const { diff --git a/gfx/gl/sceneProvider.cpp b/gfx/gl/sceneProvider.cpp index 0163b36..2e8604c 100644 --- a/gfx/gl/sceneProvider.cpp +++ b/gfx/gl/sceneProvider.cpp @@ -7,6 +7,7 @@ SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) renderer.setAmbientLight({0.5F, 0.5F, 0.5F}); renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {-1, 1, -1}, *this); } + void SceneProvider::shadows(const ShadowMapper &) const { diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index aa9453a..53178e5 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -13,8 +13,9 @@ static constexpr const std::array<const glm::i8vec4, 4> displayVAOdata {{ {1, 1, 1, 1}, {1, -1, 1, 0}, }}; -SceneRenderer::SceneRenderer(glm::ivec2 s, GLuint o) : - camera {{-1250.0F, -1250.0F, 35.0F}, quarter_pi, ratio(s), 0.1F, 10000.0F}, size {s}, output {o}, + +SceneRenderer::SceneRenderer(ScreenAbsCoord s, GLuint o) : + camera {{-1250000.0F, -1250000.0F, 35.0F}, quarter_pi, ratio(s), 100.F, 10000000.0F}, size {s}, output {o}, lighting {lighting_vs, lighting_fs}, shadowMapper {{2048, 2048}} { shader.setViewPort({0, 0, size.x, size.y}); @@ -51,7 +52,7 @@ SceneRenderer::SceneRenderer(glm::ivec2 s, GLuint o) : void SceneRenderer::render(const SceneProvider & scene) const { - shader.setViewProjection(camera.getViewProjection()); + shader.setViewProjection(camera.getPosition(), camera.getViewProjection()); glViewport(0, 0, size.x, size.y); // Geometry pass @@ -96,7 +97,7 @@ SceneRenderer::render(const SceneProvider & scene) const } void -SceneRenderer::setAmbientLight(const glm::vec3 & colour) const +SceneRenderer::setAmbientLight(const RGB & colour) const { glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClearColor(colour.r, colour.g, colour.b, 1.0F); @@ -104,8 +105,7 @@ SceneRenderer::setAmbientLight(const glm::vec3 & colour) const } void -SceneRenderer::setDirectionalLight( - const glm::vec3 & colour, const glm::vec3 & direction, const SceneProvider & scene) const +SceneRenderer::setDirectionalLight(const RGB & colour, const Direction3D & direction, const SceneProvider & scene) const { if (colour.r > 0 || colour.g > 0 || colour.b > 0) { const auto lvp = shadowMapper.update(scene, direction, camera); @@ -134,8 +134,8 @@ SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() : } void -SceneRenderer::DirectionalLightProgram::setDirectionalLight(const glm::vec3 & c, const glm::vec3 & d, - const std::span<const glm::mat4x4> lvp, const std::span<const glm::vec4> shadowMapRegions, +SceneRenderer::DirectionalLightProgram::setDirectionalLight(const RGB & c, const Direction3D & d, + const std::span<const glm::mat4x4> lvp, const std::span<const TextureRelRegion> shadowMapRegions, std::size_t maps) const { glUniform3fv(colourLoc, 1, glm::value_ptr(c)); diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h index d4af665..30fd8d3 100644 --- a/gfx/gl/sceneRenderer.h +++ b/gfx/gl/sceneRenderer.h @@ -11,34 +11,36 @@ class SceneRenderer { public: - explicit SceneRenderer(glm::ivec2 size, GLuint output); + explicit SceneRenderer(ScreenAbsCoord size, GLuint output); void render(const SceneProvider &) const; - void setAmbientLight(const glm::vec3 & colour) const; - void setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction, const SceneProvider &) const; + void setAmbientLight(const RGB & colour) const; + void setDirectionalLight(const RGB & colour, const Direction3D & direction, const SceneProvider &) const; Camera camera; private: void renderQuad() const; - glm::ivec2 size; + ScreenAbsCoord size; GLuint output; glFrameBuffer gBuffer; glTexture gPosition, gNormal, gAlbedoSpec, gIllumination; glRenderBuffer depth; + class DeferredLightProgram : public Program { public: using Program::Program; using Program::use; }; + class DirectionalLightProgram : public Program { public: DirectionalLightProgram(); using Program::use; - void setDirectionalLight(const glm::vec3 &, const glm::vec3 &, const std::span<const glm::mat4x4>, - const std::span<const glm::vec4>, std::size_t maps) const; + void setDirectionalLight(const RGB &, const Direction3D &, const std::span<const glm::mat4x4>, + const std::span<const TextureRelRegion>, std::size_t maps) const; private: RequiredUniformLocation directionLoc, colourLoc, lightViewProjectionLoc, lightViewProjectionCountLoc, diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp index 1354611..59a9748 100644 --- a/gfx/gl/sceneShader.cpp +++ b/gfx/gl/sceneShader.cpp @@ -26,16 +26,16 @@ SceneShader::SceneShader() : } void -SceneShader::setViewProjection(const glm::mat4 & viewProjection) const +SceneShader::setViewProjection(const Position3D & viewPoint, const glm::mat4 & viewProjection) const { for (const auto & prog : std::array<const SceneProgram *, 7> { &basic, &basicInst, &water, &landmass, &absolute, &pointLight, &spotLight}) { - prog->setViewProjection(viewProjection); + prog->setViewProjection(viewPoint, viewProjection); } } void -SceneShader::setViewPort(const glm::ivec4 & viewPort) const +SceneShader::setViewPort(const ViewPort & viewPort) const { for (const auto & prog : std::array<const SceneProgram *, 7> { &basic, &basicInst, &water, &landmass, &absolute, &pointLight, &spotLight}) { @@ -44,14 +44,15 @@ SceneShader::setViewPort(const glm::ivec4 & viewPort) const } void -SceneShader::SceneProgram::setViewProjection(const glm::mat4 & viewProjection) const +SceneShader::SceneProgram::setViewProjection(const Position3D & viewPoint, const glm::mat4 & viewProjection) const { glUseProgram(*this); glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection)); + glUniform3fv(viewPointLoc, 1, glm::value_ptr(viewPoint)); } void -SceneShader::SceneProgram::setViewPort(const glm::ivec4 & viewPort) const +SceneShader::SceneProgram::setViewPort(const ViewPort & viewPort) const { if (viewPortLoc >= 0) { glUseProgram(*this); @@ -59,13 +60,16 @@ SceneShader::SceneProgram::setViewPort(const glm::ivec4 & viewPort) const } } -SceneShader::BasicProgram::BasicProgram() : SceneProgram {dynamicPoint_vs, material_fs}, modelLoc {*this, "model"} { } +SceneShader::BasicProgram::BasicProgram() : + SceneProgram {dynamicPoint_vs, material_fs}, modelLoc {*this, "model"}, modelPosLoc {*this, "modelPos"} +{ +} void SceneShader::BasicProgram::setModel(Location const & location) const { - const auto model {glm::translate(location.pos) * rotate_ypr(location.rot)}; - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(rotate_ypr(location.rot))); + glUniform3iv(modelPosLoc, 1, glm::value_ptr(location.pos)); } void @@ -81,38 +85,40 @@ void SceneShader::WaterProgram::use(float waveCycle) const { Program::use(); - glm::vec3 waves {waveCycle, 0.F, 0.F}; + Position3D waves {waveCycle, 0.F, 0.F}; glUniform3fv(waveLoc, 1, glm::value_ptr(waves)); } SceneShader::PointLightShader::PointLightShader() : - SceneProgram {pointLight_vs, pointLight_gs, pointLight_fs}, colourLoc {*this, "colour"}, kqLoc {*this, "kq"} + SceneProgram {pointLight_vs, pointLight_gs, pointLight_fs}, colourLoc {*this, "colour"}, kqLoc {*this, "kq"}, + viewPointLoc {*this, "viewPoint"} { - VertexArrayObject {va}.addAttribs<glm::vec3>(b); + VertexArrayObject {va}.addAttribs<Position3D>(b); } void -SceneShader::PointLightShader::add(const glm::vec3 & position, const glm::vec3 & colour, const float kq) const +SceneShader::PointLightShader::add(const Position3D & position, const RGB & colour, const float kq) const { Program::use(); glBindVertexArray(va); glBindBuffer(GL_ARRAY_BUFFER, b); glUniform3fv(colourLoc, 1, glm::value_ptr(colour)); glUniform1f(kqLoc, kq); - glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3), glm::value_ptr(position), GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(Position3D), glm::value_ptr(position), GL_DYNAMIC_DRAW); glDrawArrays(GL_POINTS, 0, 1); } SceneShader::SpotLightShader::SpotLightShader() : SceneProgram {spotLight_vs, spotLight_gs, spotLight_fs}, directionLoc {*this, "v_direction"}, - colourLoc {*this, "colour"}, kqLoc {*this, "kq"}, arcLoc {*this, "arc"} + colourLoc {*this, "colour"}, kqLoc {*this, "kq"}, arcLoc {*this, "arc"}, viewPointLoc {*this, "viewPoint"} + { - using v3pair = std::pair<glm::vec3, glm::vec3>; + using v3pair = std::pair<Position3D, Direction3D>; VertexArrayObject {va}.addAttribs<v3pair, &v3pair::first, &v3pair::second>(b); } void -SceneShader::SpotLightShader::add(const glm::vec3 & position, const glm::vec3 & direction, const glm::vec3 & colour, +SceneShader::SpotLightShader::add(const Position3D & position, const Direction3D & direction, const RGB & colour, const float kq, const float arc) const { Program::use(); @@ -122,6 +128,6 @@ SceneShader::SpotLightShader::add(const glm::vec3 & position, const glm::vec3 & glUniform3fv(directionLoc, 1, glm::value_ptr(direction)); glUniform1f(kqLoc, kq); glUniform1f(arcLoc, arc); - glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3), glm::value_ptr(position), GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(Position3D), glm::value_ptr(position), GL_DYNAMIC_DRAW); glDrawArrays(GL_POINTS, 0, 1); } diff --git a/gfx/gl/sceneShader.h b/gfx/gl/sceneShader.h index ead184e..83c234c 100644 --- a/gfx/gl/sceneShader.h +++ b/gfx/gl/sceneShader.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "program.h" #include <glArrays.h> @@ -10,15 +11,16 @@ class SceneShader { public: template<typename... S> inline explicit SceneProgram(const S &... srcs) : - Program {srcs...}, viewProjectionLoc {*this, "viewProjection"}, viewPortLoc {*this, "viewPort"} + Program {srcs...}, viewProjectionLoc {*this, "viewProjection"}, viewPointLoc {*this, "viewPoint"}, + viewPortLoc {*this, "viewPort"} { } - void setViewProjection(const glm::mat4 &) const; - void setViewPort(const glm::ivec4 &) const; + void setViewProjection(const Position3D &, const glm::mat4 &) const; + void setViewPort(const ViewPort &) const; private: - RequiredUniformLocation viewProjectionLoc; + RequiredUniformLocation viewProjectionLoc, viewPointLoc; UniformLocation viewPortLoc; }; @@ -30,6 +32,7 @@ class SceneShader { private: RequiredUniformLocation modelLoc; + RequiredUniformLocation modelPosLoc; }; class AbsolutePosProgram : public SceneProgram { @@ -52,11 +55,12 @@ class SceneShader { public: PointLightShader(); - void add(const glm::vec3 & position, const glm::vec3 & colour, const float kq) const; + void add(const Position3D & position, const RGB & colour, const float kq) const; private: UniformLocation colourLoc; UniformLocation kqLoc; + UniformLocation viewPointLoc; glVertexArray va; glBuffer b; }; @@ -65,7 +69,7 @@ class SceneShader { public: SpotLightShader(); - void add(const glm::vec3 & position, const glm::vec3 & direction, const glm::vec3 & colour, const float kq, + void add(const Position3D & position, const Direction3D & direction, const RGB & colour, const float kq, const float arc) const; private: @@ -73,6 +77,7 @@ class SceneShader { UniformLocation colourLoc; UniformLocation kqLoc; UniformLocation arcLoc; + UniformLocation viewPointLoc; glVertexArray va; glBuffer b; }; @@ -86,6 +91,6 @@ public: PointLightShader pointLight; SpotLightShader spotLight; - void setViewProjection(const glm::mat4 & viewProjection) const; - void setViewPort(const glm::ivec4 & viewPort) const; + void setViewProjection(const Position3D & viewPoint, const glm::mat4 & viewProjection) const; + void setViewPort(const ViewPort & viewPort) const; }; diff --git a/gfx/gl/shader.h b/gfx/gl/shader.h index 0810e6b..cff2281 100644 --- a/gfx/gl/shader.h +++ b/gfx/gl/shader.h @@ -8,6 +8,7 @@ class Shader { public: using ShaderRef = glRef<GLuint, &glCreateShader, &glDeleteShader>; + constexpr Shader(const GLchar * text, GLint len, GLuint type) : text {text}, len {len}, type {type} { } [[nodiscard]] ShaderRef compile() const; diff --git a/gfx/gl/shaders/commonPoint.glsl b/gfx/gl/shaders/commonPoint.glsl index 35510e1..046da27 100644 --- a/gfx/gl/shaders/commonPoint.glsl +++ b/gfx/gl/shaders/commonPoint.glsl @@ -24,5 +24,5 @@ main() Colour = colour; Material = getMaterialDetail(material); - gl_Position = viewProjection * worldPos; + gl_Position = viewProjection * vec4(FragPos - viewPoint + modelPos, 1); } diff --git a/gfx/gl/shaders/commonShadowPoint.glsl b/gfx/gl/shaders/commonShadowPoint.glsl index c7cbd3e..216642e 100644 --- a/gfx/gl/shaders/commonShadowPoint.glsl +++ b/gfx/gl/shaders/commonShadowPoint.glsl @@ -1,6 +1,7 @@ void main() { - gl_Position = viewProjection * model * vec4(position, 1.0); + vec4 worldPos = model * vec4(position, 1.0); + gl_Position = viewProjection * vec4(worldPos.xyz - viewPoint + modelPos, 1); gl_Position.z = max(gl_Position.z, -1); } diff --git a/gfx/gl/shaders/dynamicPoint.vs b/gfx/gl/shaders/dynamicPoint.vs index 961535c..667f247 100644 --- a/gfx/gl/shaders/dynamicPoint.vs +++ b/gfx/gl/shaders/dynamicPoint.vs @@ -5,6 +5,8 @@ include(`meshIn.glsl') include(`materialInterface.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; uniform mat4 model; +uniform ivec3 modelPos; include(`commonPoint.glsl') diff --git a/gfx/gl/shaders/dynamicPointInst.vs b/gfx/gl/shaders/dynamicPointInst.vs index 2d6cee5..adf39bd 100644 --- a/gfx/gl/shaders/dynamicPointInst.vs +++ b/gfx/gl/shaders/dynamicPointInst.vs @@ -5,6 +5,8 @@ include(`meshIn.glsl') include(`materialInterface.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; layout(location = 5) in mat4 model; +layout(location = 9) in ivec3 modelPos; include(`commonPoint.glsl') diff --git a/gfx/gl/shaders/fixedPoint.vs b/gfx/gl/shaders/fixedPoint.vs index ed78c96..6e1ab49 100644 --- a/gfx/gl/shaders/fixedPoint.vs +++ b/gfx/gl/shaders/fixedPoint.vs @@ -5,6 +5,8 @@ include(`meshIn.glsl') include(`materialInterface.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; const mat4 model = mat4(1); +const vec3 modelPos = ivec3(0); include(`commonPoint.glsl') diff --git a/gfx/gl/shaders/landmass.fs b/gfx/gl/shaders/landmass.fs index 4dc92bb..9865d11 100644 --- a/gfx/gl/shaders/landmass.fs +++ b/gfx/gl/shaders/landmass.fs @@ -11,9 +11,9 @@ const vec3 rock = vec3(.2, .2, .1); const vec3 sand = vec3(.76, .7, .5); const vec3 snow = vec3(.97, .97, .99); -const float beachline = .5; -const float snowline_low = 28; -const float snowline_high = 30; +const float beachline = 500; +const float snowline_low = 28000; +const float snowline_high = 30000; const float slope_min = .99; const float slope_mid = .95; diff --git a/gfx/gl/shaders/pointLight.fs b/gfx/gl/shaders/pointLight.fs index bd32c05..1a68df8 100644 --- a/gfx/gl/shaders/pointLight.fs +++ b/gfx/gl/shaders/pointLight.fs @@ -26,5 +26,5 @@ main() if (normalDot < 0) { discard; } - FragColor = (colour * normalDot) / (1 + (kq * pow(lightDist, 2))); + FragColor = (colour * normalDot) / (1 + (kq * pow(lightDist / 1000.0, 2))); } diff --git a/gfx/gl/shaders/pointLight.gs b/gfx/gl/shaders/pointLight.gs index 03d131d..ec089f5 100644 --- a/gfx/gl/shaders/pointLight.gs +++ b/gfx/gl/shaders/pointLight.gs @@ -19,6 +19,7 @@ const vec3[] cube = vec3[]( // http://www.cs.umd.edu/gvil/papers/av_ts.pdf vec3(1, 1, -1) // Back-top-right ); uniform mat4 viewProjection; +uniform vec3 viewPoint; in vec3 centre[]; in float size[]; diff --git a/gfx/gl/shaders/pointLight.vs b/gfx/gl/shaders/pointLight.vs index 35682fa..7694a25 100644 --- a/gfx/gl/shaders/pointLight.vs +++ b/gfx/gl/shaders/pointLight.vs @@ -4,6 +4,7 @@ layout(location = 0) in vec3 position; uniform vec3 colour; uniform float kq; +uniform vec3 viewPoint; out vec3 centre; out float size; @@ -12,6 +13,6 @@ void main() { centre = position; - size = (8 * sqrt(max(max(colour.r, colour.g), colour.b))) / sqrt(kq); - gl_Position = vec4(centre, 0); + size = (8000 * sqrt(max(max(colour.r, colour.g), colour.b))) / sqrt(kq); + gl_Position = vec4(centre - viewPoint, 0); } diff --git a/gfx/gl/shaders/shadowDynamicPoint.vs b/gfx/gl/shaders/shadowDynamicPoint.vs index f3ed533..e20d31a 100644 --- a/gfx/gl/shaders/shadowDynamicPoint.vs +++ b/gfx/gl/shaders/shadowDynamicPoint.vs @@ -3,6 +3,8 @@ include(`meshIn.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; uniform mat4 model; +uniform ivec3 modelPos; include(`commonShadowPoint.glsl') diff --git a/gfx/gl/shaders/shadowDynamicPointInst.vs b/gfx/gl/shaders/shadowDynamicPointInst.vs index 1bf74ef..ab3e976 100644 --- a/gfx/gl/shaders/shadowDynamicPointInst.vs +++ b/gfx/gl/shaders/shadowDynamicPointInst.vs @@ -3,6 +3,8 @@ include(`meshIn.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; layout(location = 5) in mat4 model; +layout(location = 9) in ivec3 modelPos; include(`commonShadowPoint.glsl') diff --git a/gfx/gl/shaders/shadowFixedPoint.vs b/gfx/gl/shaders/shadowFixedPoint.vs index 8921707..a9fb4a3 100644 --- a/gfx/gl/shaders/shadowFixedPoint.vs +++ b/gfx/gl/shaders/shadowFixedPoint.vs @@ -3,6 +3,8 @@ include(`meshIn.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; const mat4 model = mat4(1); +const ivec3 modelPos = ivec3(0); include(`commonShadowPoint.glsl') diff --git a/gfx/gl/shaders/spotLight.fs b/gfx/gl/shaders/spotLight.fs index add86fd..78b8f72 100644 --- a/gfx/gl/shaders/spotLight.fs +++ b/gfx/gl/shaders/spotLight.fs @@ -30,5 +30,5 @@ main() if (normalDot < 0) { discard; } - FragColor = (colour * normalDot) / (1 + (kq * pow(lightDist, 2))); + FragColor = (colour * normalDot) / (1 + (kq * pow(lightDist / 1000.0, 2))); } diff --git a/gfx/gl/shaders/spotLight.gs b/gfx/gl/shaders/spotLight.gs index ad65675..0529614 100644 --- a/gfx/gl/shaders/spotLight.gs +++ b/gfx/gl/shaders/spotLight.gs @@ -10,6 +10,7 @@ const vec3[] pyramid = vec3[]( // four-sided vec3(1, -1, 1) // Front-right ); uniform mat4 viewProjection; +uniform vec3 viewPoint; uniform float arc; in vec3 position[]; diff --git a/gfx/gl/shaders/spotLight.vs b/gfx/gl/shaders/spotLight.vs index dca0854..08197a4 100644 --- a/gfx/gl/shaders/spotLight.vs +++ b/gfx/gl/shaders/spotLight.vs @@ -6,6 +6,7 @@ uniform vec3 v_direction; uniform vec3 colour; uniform float kq; uniform float arc; +uniform vec3 viewPoint; out vec3 position; out vec3 direction; @@ -17,7 +18,7 @@ main() { position = v_position; direction = normalize(v_direction); - size = (8 * sqrt(max(max(colour.r, colour.g), colour.b))) / sqrt(kq); + size = (8000 * sqrt(max(max(colour.r, colour.g), colour.b))) / sqrt(kq); cosarc = cos(arc / 2); - gl_Position = vec4(position, 0); + gl_Position = vec4(position - viewPoint, 0); } diff --git a/gfx/gl/shaders/water.fs b/gfx/gl/shaders/water.fs index 04aa94c..2ccc924 100644 --- a/gfx/gl/shaders/water.fs +++ b/gfx/gl/shaders/water.fs @@ -13,5 +13,5 @@ main() gPosition = vec4(FragPos, 1); gNormal = vec4(Normal, 1); gAlbedoSpec = texture(texture0, TexCoords); - gAlbedoSpec.a *= clamp(-FragPos.z * .7, .1, 1.0); + gAlbedoSpec.a *= clamp(-FragPos.z * .0007, .1, 1.0); } diff --git a/gfx/gl/shaders/water.vs b/gfx/gl/shaders/water.vs index a21b49f..03eabb2 100644 --- a/gfx/gl/shaders/water.vs +++ b/gfx/gl/shaders/water.vs @@ -4,17 +4,18 @@ include(`meshIn.glsl') include(`materialInterface.glsl') uniform mat4 viewProjection; +uniform vec3 viewPoint; uniform vec3 waves; void main() { - vec4 wpos = vec4(position.x + cos(waves.x), position.y + cos(waves.x * waves.y / 2), - cos(waves.x + position.x + (position.y / 8)) * .3, 1.0); + vec3 wpos = vec3(position.x + (cos(waves.x) * 1000.0), position.y + (cos(waves.x * waves.y / 2) * 1000.0), + cos(waves.x + (position.x / 1000.0) + (position.y * 125.0)) * 300.0); FragPos = vec3(wpos.xy, position.z); TexCoords = texCoord; Normal = normal; - gl_Position = viewProjection * wpos; + gl_Position = viewProjection * vec4(wpos - viewPoint, 1.0); } diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 55d986c..07db6a1 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -15,7 +15,7 @@ #include <tuple> #include <vector> -ShadowMapper::ShadowMapper(const glm::ivec2 & s) : +ShadowMapper::ShadowMapper(const TextureAbsCoord & s) : fixedPoint {shadowFixedPoint_vs}, dynamicPointInst {shadowDynamicPointInst_vs}, size {s} { glBindTexture(GL_TEXTURE_2D, depthMap); @@ -24,7 +24,7 @@ ShadowMapper::ShadowMapper(const glm::ivec2 & s) : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - static constexpr glm::vec4 border {std::numeric_limits<float>::infinity()}; + static constexpr RGBA border {std::numeric_limits<RGBA::value_type>::infinity()}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(border)); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); @@ -37,7 +37,7 @@ ShadowMapper::ShadowMapper(const glm::ivec2 & s) : glBindFramebuffer(GL_FRAMEBUFFER, 0); } -constexpr std::array<std::array<glm::ivec4, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS> viewports {{ +constexpr std::array<std::array<TextureAbsRegion, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS> viewports {{ {{ {31, 31, 0, 0}, // full }}, @@ -57,33 +57,34 @@ constexpr std::array<std::array<glm::ivec4, ShadowMapper::SHADOW_BANDS>, ShadowM {1, 1, 1, 1}, // upper right }}, }}; -constexpr std::array<std::array<glm::vec4, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS> shadowMapRegions {{ - {{ - {0.5F, 0.5F, 0.5F, 0.5F}, // full - }}, - {{ - {0.5F, 0.25F, 0.5F, 0.25F}, // lower half - {0.5F, 0.25F, 0.5F, 0.75F}, // upper half - }}, - {{ - {0.5F, 0.25F, 0.5F, 0.25F}, // lower half - {0.25F, 0.25F, 0.25F, 0.75F}, // upper left - {0.25F, 0.25F, 0.75F, 0.75F}, // upper right - }}, - - {{ - {0.25F, 0.25F, 0.25F, 0.25F}, // lower left - {0.25F, 0.25F, 0.75F, 0.25F}, // lower right - {0.25F, 0.25F, 0.25F, 0.75F}, // upper left - {0.25F, 0.25F, 0.75F, 0.75F}, // upper right - }}, -}}; +constexpr std::array<std::array<TextureRelRegion, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS> + shadowMapRegions {{ + {{ + {0.5F, 0.5F, 0.5F, 0.5F}, // full + }}, + {{ + {0.5F, 0.25F, 0.5F, 0.25F}, // lower half + {0.5F, 0.25F, 0.5F, 0.75F}, // upper half + }}, + {{ + {0.5F, 0.25F, 0.5F, 0.25F}, // lower half + {0.25F, 0.25F, 0.25F, 0.75F}, // upper left + {0.25F, 0.25F, 0.75F, 0.75F}, // upper right + }}, + + {{ + {0.25F, 0.25F, 0.25F, 0.25F}, // lower left + {0.25F, 0.25F, 0.75F, 0.25F}, // lower right + {0.25F, 0.25F, 0.25F, 0.75F}, // upper left + {0.25F, 0.25F, 0.75F, 0.75F}, // upper right + }}, + }}; constexpr std::array<float, ShadowMapper::SHADOW_BANDS + 1> shadowBands { - 1.F, - 250.F, - 750.F, - 2500.F, - 10000.F, + 1000.F, + 250000.F, + 750000.F, + 2500000.F, + 10000000.F, }; static_assert(viewports.size() == shadowMapRegions.size()); static_assert(shadowBands.size() == shadowMapRegions.size() + 1); @@ -94,22 +95,24 @@ struct DefinitionsInserter { { return out.maps++; }; + auto operator*() { return std::tie(out.projections[out.maps], out.regions[out.maps]); } + ShadowMapper::Definitions & out; }; -std::vector<std::array<glm::vec3, 4>> +std::vector<std::array<Position3D, 4>> ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightView) { - std::vector<std::array<glm::vec3, 4>> bandViewExtents; + std::vector<std::array<Position3D, 4>> bandViewExtents; for (const auto dist : shadowBands) { const auto extents = camera.extentsAtDist(dist); - bandViewExtents.emplace_back(extents * [&lightView](const auto & e) -> glm::vec3 { - return lightView * glm::vec4(glm::vec3 {e}, 1); + bandViewExtents.emplace_back(extents * [&lightView](const auto & e) -> Position3D { + return lightView * glm::vec4(Position3D {e}, 1); }); if (std::none_of(extents.begin(), extents.end(), [targetDist = dist * 0.99F](const glm::vec4 & e) { return e.w > targetDist; @@ -121,7 +124,7 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV } ShadowMapper::Definitions -ShadowMapper::update(const SceneProvider & scene, const glm::vec3 & dir, const Camera & camera) const +ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const Camera & camera) const { glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); @@ -161,12 +164,14 @@ ShadowMapper::update(const SceneProvider & scene, const glm::vec3 & dir, const C } ShadowMapper::FixedPoint::FixedPoint(const Shader & vs) : Program {vs}, viewProjectionLoc {*this, "viewProjection"} { } + void ShadowMapper::FixedPoint::setViewProjection(const glm::mat4 & viewProjection) const { use(); glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection)); } + void ShadowMapper::FixedPoint::use() const { @@ -174,26 +179,28 @@ ShadowMapper::FixedPoint::use() const } ShadowMapper::DynamicPoint::DynamicPoint() : - Program {shadowDynamicPoint_vs}, viewProjectionLoc {*this, "viewProjection"}, modelLoc {*this, "model"} + Program {shadowDynamicPoint_vs}, viewProjectionLoc {*this, "viewProjection"}, modelLoc {*this, "model"}, + modelPosLoc {*this, "modelPos"} { } + void ShadowMapper::DynamicPoint::setViewProjection(const glm::mat4 & viewProjection) const { glUseProgram(*this); glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection)); } + void ShadowMapper::DynamicPoint::use(const Location & location) const { glUseProgram(*this); setModel(location); - const auto model = glm::translate(location.pos) * rotate_ypr(location.rot); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); } + void ShadowMapper::DynamicPoint::setModel(const Location & location) const { - const auto model = glm::translate(location.pos) * rotate_ypr(location.rot); - glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(rotate_ypr(location.rot))); + glUniform3iv(modelPosLoc, 1, glm::value_ptr(location.pos)); } diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 36371eb..b53a7f1 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "lib/glArrays.h" #include "program.h" #include <glm/vec2.hpp> @@ -8,17 +9,20 @@ class SceneProvider; class Camera; #include <gfx/models/texture.h> + class ShadowMapper { public: - explicit ShadowMapper(const glm::ivec2 & size); + explicit ShadowMapper(const TextureAbsCoord & size); static constexpr std::size_t SHADOW_BANDS {4}; + struct Definitions { std::array<glm::mat4x4, SHADOW_BANDS> projections {}; - std::array<glm::vec4, SHADOW_BANDS> regions {}; + std::array<TextureRelRegion, SHADOW_BANDS> regions {}; size_t maps {}; }; - [[nodiscard]] Definitions update(const SceneProvider &, const glm::vec3 & direction, const Camera &) const; + + [[nodiscard]] Definitions update(const SceneProvider &, const Direction3D & direction, const Camera &) const; class FixedPoint : public Program { public: @@ -29,6 +33,7 @@ public: private: RequiredUniformLocation viewProjectionLoc; }; + class DynamicPoint : public Program { public: DynamicPoint(); @@ -39,7 +44,9 @@ public: private: RequiredUniformLocation viewProjectionLoc; RequiredUniformLocation modelLoc; + RequiredUniformLocation modelPosLoc; }; + FixedPoint fixedPoint, dynamicPointInst; DynamicPoint dynamicPoint; @@ -50,9 +57,9 @@ public: } private: - [[nodiscard]] static std::vector<std::array<glm::vec3, 4>> getBandViewExtents( + [[nodiscard]] static std::vector<std::array<Position3D, 4>> getBandViewExtents( const Camera &, const glm::mat4 & lightView); glFrameBuffer depthMapFBO; glTexture depthMap; - glm::ivec2 size; + TextureAbsCoord size; }; diff --git a/gfx/gl/uiShader.cpp b/gfx/gl/uiShader.cpp index 78e0064..dc4f4dc 100644 --- a/gfx/gl/uiShader.cpp +++ b/gfx/gl/uiShader.cpp @@ -9,6 +9,7 @@ #include <initializer_list> UIShader::IconProgram::IconProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShader_fs} { } + UIShader::TextProgram::TextProgram(const glm::mat4 & vp) : UIProgram {vp, uiShader_vs, uiShaderFont_fs}, colorLoc {*this, "colour"} { @@ -18,10 +19,11 @@ UIShader::UIShader(size_t width, size_t height) : UIShader {glm::ortho<float>(0, static_cast<float>(width), 0, static_cast<float>(height))} { } + UIShader::UIShader(const glm::mat4 & viewProjection) : icon {viewProjection}, text {viewProjection} { } void -UIShader::TextProgram::use(const glm::vec3 & colour) const +UIShader::TextProgram::use(const RGB & colour) const { Program::use(); glUniform3fv(colorLoc, 1, glm::value_ptr(colour)); diff --git a/gfx/gl/uiShader.h b/gfx/gl/uiShader.h index 2766af8..362e90c 100644 --- a/gfx/gl/uiShader.h +++ b/gfx/gl/uiShader.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include "program.h" #include <cstddef> #include <glad/gl.h> @@ -33,7 +34,7 @@ private: class TextProgram : public UIProgram { public: explicit TextProgram(const glm::mat4 & vp); - void use(const glm::vec3 & colour) const; + void use(const RGB & colour) const; private: RequiredUniformLocation colorLoc; diff --git a/gfx/gl/vertexArrayObject.h b/gfx/gl/vertexArrayObject.h index fa6baa3..57daaf3 100644 --- a/gfx/gl/vertexArrayObject.h +++ b/gfx/gl/vertexArrayObject.h @@ -11,22 +11,27 @@ public: { glBindVertexArray(arrayObject); } + ~VertexArrayObject() { glBindVertexArray(0); } + NO_MOVE(VertexArrayObject); NO_COPY(VertexArrayObject); template<typename m, typename T> struct MP { constexpr MP(m T::*p) : P {p} { } + operator void *() const { return &(static_cast<T *>(nullptr)->*P); } + m T::*P; using value_type = m; }; + template<typename m, typename T> MP(m T::*) -> MP<m, T>; template<typename VertexT, MP... attribs> diff --git a/gfx/image.h b/gfx/image.h index 8bb4067..6fbbdd1 100644 --- a/gfx/image.h +++ b/gfx/image.h @@ -7,7 +7,9 @@ class Image { public: Image(const char * fileName, int flags); + Image(const std::string & fileName, int flags) : Image(fileName.c_str(), flags) { } + Image(std::span<unsigned char> data, int flags); ~Image(); diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 380f2e0..1685d34 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -1,4 +1,5 @@ #include "texture.h" +#include "config/types.h" #include "glArrays.h" #include "tga.h" #include <cache.h> @@ -60,10 +61,10 @@ Texture::bind(GLenum unit) const glBindTexture(type, m_texture); } -glm::ivec2 +TextureAbsCoord Texture::getSize(const glTexture & texture) { - glm::ivec2 size; + TextureAbsCoord size; glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_WIDTH, &size.x); glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_HEIGHT, &size.y); return size; @@ -136,14 +137,16 @@ TextureAtlas::bind(GLenum unit) const } GLuint -TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions to) +TextureAtlas::add(TextureAbsCoord position, TextureAbsCoord size, void * data, TextureOptions to) { glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data); + struct Material { glm::vec<2, uint16_t> position, size; TextureOptions::MapMode wrapU; TextureOptions::MapMode wrapV; } material {position, size, to.wrapU, to.wrapV}; + static_assert(sizeof(Material) <= 32); glTextureSubImage2D(m_atlas, 0, 0, static_cast<GLsizei>(used), 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material); return ++used; diff --git a/gfx/models/texture.h b/gfx/models/texture.h index 1b66c64..5e1b440 100644 --- a/gfx/models/texture.h +++ b/gfx/models/texture.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include <cache.h> #include <filesystem> #include <glArrays.h> @@ -42,7 +43,7 @@ public: protected: static void save(const glTexture &, GLenum, GLenum, uint8_t channels, const char * path, uint8_t tgaFormat); - static glm::ivec2 getSize(const glTexture &); + static TextureAbsCoord getSize(const glTexture &); glTexture m_texture; GLenum type; @@ -53,7 +54,7 @@ public: TextureAtlas(GLsizei width, GLsizei height, GLuint count); void bind(GLenum unit = GL_TEXTURE0) const override; - GLuint add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions = {}); + GLuint add(TextureAbsCoord position, TextureAbsCoord size, void * data, TextureOptions = {}); private: glTexture m_atlas; diff --git a/gfx/models/tga.h b/gfx/models/tga.h index 1f400ef..3d072fb 100644 --- a/gfx/models/tga.h +++ b/gfx/models/tga.h @@ -4,11 +4,13 @@ #include <glm/vec2.hpp> struct TGAHead { + using XY = glm::vec<2, uint16_t>; uint8_t idLength {}, colorMapType {}, format {}; uint16_t __attribute__((packed)) colorMapFirst {}, colorMapLength {}; uint8_t colorMapEntrySize {}; - glm::vec<2, uint16_t> origin {}, size {}; + XY origin {}, size {}; uint8_t pixelDepth {}; uint8_t descriptor {}; }; + static_assert(sizeof(TGAHead) == 18); diff --git a/gfx/models/vertex.h b/gfx/models/vertex.h index 0464ea7..5635fa1 100644 --- a/gfx/models/vertex.h +++ b/gfx/models/vertex.h @@ -1,12 +1,12 @@ #pragma once +#include "config/types.h" #include <glad/gl.h> -#include <glm/glm.hpp> class Vertex { public: #ifndef __cpp_aggregate_paren_init - constexpr Vertex(glm::vec3 pos, glm::vec2 texCoord, glm::vec3 normal, glm::vec4 colour = {}, GLuint material = 0) : + constexpr Vertex(Position3D pos, TextureRelCoord texCoord, Normal3D normal, RGBA colour = {}, GLuint material = 0) : pos {std::move(pos)}, texCoord {std::move(texCoord)}, normal {std::move(normal)}, colour {std::move(colour)}, material {material} { @@ -15,9 +15,9 @@ public: bool operator==(const Vertex &) const = default; - glm::vec3 pos; - glm::vec2 texCoord; - glm::vec3 normal; - glm::vec4 colour {}; + Position3D pos {}; + TextureRelCoord texCoord {}; + Normal3D normal {}; + RGBA colour {}; GLuint material {}; }; diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp index 539efb1..0340189 100644 --- a/gfx/renderable.cpp +++ b/gfx/renderable.cpp @@ -4,6 +4,7 @@ void Renderable::lights(const SceneShader &) const { } + void Renderable::shadows(const ShadowMapper &) const { diff --git a/lib/cache.h b/lib/cache.h index 2c3975b..f5fd227 100644 --- a/lib/cache.h +++ b/lib/cache.h @@ -35,4 +35,5 @@ public: private: std::map<Key, Ptr, std::less<>> cached; }; + // IWYU pragma: no_forward_declare Cache diff --git a/lib/collections.h b/lib/collections.h index 7d78ef9..943b986 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -149,11 +149,14 @@ template<typename T> struct pair_range { { return pair.first; } + constexpr auto & end() const noexcept { return pair.second; } + const std::pair<T, T> & pair; }; + template<typename T> pair_range(std::pair<T, T>) -> pair_range<T>; diff --git a/lib/enumDetails.h b/lib/enumDetails.h index 5966be2..b6ff046 100644 --- a/lib/enumDetails.h +++ b/lib/enumDetails.h @@ -26,11 +26,13 @@ template<typename E> struct EnumTypeDetails : EnumDetailsBase { protected: #endif constexpr static std::string_view SEARCH_TYPE {"E = "}; + constexpr static auto typeraw() { return std::string_view {__PRETTY_FUNCTION__}; }; + constexpr static auto typeNameStart {typeraw().find(SEARCH_TYPE) + SEARCH_TYPE.length()}; constexpr static auto typeNameEnd {typeraw().find_first_of("];", typeNameStart)}; constexpr static auto typeNameLen {typeNameEnd - typeNameStart}; @@ -47,11 +49,13 @@ template<auto value> struct EnumValueDetails : public EnumTypeDetails<decltype(v private: #endif using T = EnumTypeDetails<decltype(value)>; + constexpr static auto raw() { return std::string_view {__PRETTY_FUNCTION__}; }; + constexpr static auto nameStart {raw().find_last_of(": ") + 1}; constexpr static auto nameEnd {raw().find_first_of("];", nameStart)}; constexpr static auto nameLen {nameEnd - nameStart}; @@ -84,12 +88,14 @@ private: return std::array {EnumValueDetails<static_cast<E>(n)>::valid...}; #pragma GCC diagnostic pop } + template<auto... n> constexpr static auto get_values(std::integer_sequence<int, n...>) { return std::array {EnumValueDetails<static_cast<E>(n)>::raw_value...}; } + template<auto... n> constexpr static auto get_valueNames(std::integer_sequence<int, n...>) diff --git a/lib/geometricPlane.cpp b/lib/geometricPlane.cpp index ea4f02d..567f98a 100644 --- a/lib/geometricPlane.cpp +++ b/lib/geometricPlane.cpp @@ -4,10 +4,10 @@ #include <glm/gtx/intersect.hpp> GeometricPlane::PlaneRelation -GeometricPlane::getRelation(glm::vec3 p) const +GeometricPlane::getRelation(Position3D p) const { const auto d = glm::dot(normal, p - origin); - return d < 0.f ? PlaneRelation::Below : d > 0.f ? PlaneRelation::Above : PlaneRelation::On; + return d < 0.F ? PlaneRelation::Below : d > 0.F ? PlaneRelation::Above : PlaneRelation::On; } bool diff --git a/lib/geometricPlane.h b/lib/geometricPlane.h index dc8df50..c74beff 100644 --- a/lib/geometricPlane.h +++ b/lib/geometricPlane.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include <glm/vec3.hpp> #include <optional> @@ -9,14 +10,15 @@ class GeometricPlane { public: struct DistAndPosition { float dist; - glm::vec3 position; + Position3D position; }; enum class PlaneRelation { Above, Below, On }; - glm::vec3 origin, normal; + Position3D origin; + Normal3D normal; - PlaneRelation getRelation(glm::vec3 point) const; - std::optional<DistAndPosition> getRayIntersectPosition(const Ray &) const; + [[nodiscard]] PlaneRelation getRelation(Position3D point) const; + [[nodiscard]] std::optional<DistAndPosition> getRayIntersectPosition(const Ray &) const; static bool isIntersect(PlaneRelation a, PlaneRelation b); }; diff --git a/lib/glArrays.h b/lib/glArrays.h index 86385d9..787ea17 100644 --- a/lib/glArrays.h +++ b/lib/glArrays.h @@ -15,7 +15,8 @@ public: CUSTOM_MOVE(glArraysBase); // NOLINTNEXTLINE(hicpp-explicit-conversions) - inline operator GLuint() const + inline + operator GLuint() const { static_assert(N == 1, "Implicit cast only if N == 1"); return ids.front(); diff --git a/lib/glContainer.h b/lib/glContainer.h index 993170e..8177618 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -9,6 +9,7 @@ template<typename I, typename Direction> class basic_glContainer_iterator { public: explicit basic_glContainer_iterator(I * i) : i {i} { } + template<typename OtherI> basic_glContainer_iterator(const basic_glContainer_iterator<OtherI, Direction> & other) : i {&*other} { @@ -20,17 +21,20 @@ public: i = Direction {}(i, 1); return *this; } + auto operator++(int) noexcept { return basic_glContainer_iterator<I, Direction> {std::exchange(i, Direction {}(i, 1))}; } + auto & operator--() noexcept { i = Direction {}(i, -1); return *this; } + auto operator--(int) noexcept { @@ -76,6 +80,7 @@ public: { return this->i == other.i; } + [[nodiscard]] bool operator!=(const basic_glContainer_iterator & other) const noexcept { @@ -87,6 +92,7 @@ public: { return i; } + [[nodiscard]] auto & operator*() const noexcept { diff --git a/lib/gl_traits.h b/lib/gl_traits.h index a930eba..934b505 100644 --- a/lib/gl_traits.h +++ b/lib/gl_traits.h @@ -6,9 +6,11 @@ #include <glm/fwd.hpp> template<typename T> struct gl_traits; + struct gl_traits_base { static constexpr GLint size {1}; }; + struct gl_traits_float : public gl_traits_base { static constexpr auto vertexAttribFunc { [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint { @@ -16,6 +18,7 @@ struct gl_traits_float : public gl_traits_base { return 1; }}; }; + struct gl_traits_longfloat : public gl_traits_base { static constexpr auto vertexAttribFunc { [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint { @@ -23,6 +26,7 @@ struct gl_traits_longfloat : public gl_traits_base { return 1; }}; }; + struct gl_traits_integer : public gl_traits_base { static constexpr auto vertexAttribFunc { [](GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) -> GLuint { @@ -30,27 +34,35 @@ struct gl_traits_integer : public gl_traits_base { return 1; }}; }; + template<> struct gl_traits<glm::f32> : public gl_traits_float { static constexpr GLenum type {GL_FLOAT}; }; + template<> struct gl_traits<glm::f64> : public gl_traits_longfloat { static constexpr GLenum type {GL_DOUBLE}; }; + template<> struct gl_traits<glm::int8> : public gl_traits_integer { static constexpr GLenum type {GL_BYTE}; }; + template<> struct gl_traits<glm::int16> : public gl_traits_integer { static constexpr GLenum type {GL_SHORT}; }; + template<> struct gl_traits<glm::int32> : public gl_traits_integer { static constexpr GLenum type {GL_INT}; }; + template<> struct gl_traits<glm::uint8> : public gl_traits_integer { static constexpr GLenum type {GL_UNSIGNED_BYTE}; }; + template<> struct gl_traits<glm::uint16> : public gl_traits_integer { static constexpr GLenum type {GL_UNSIGNED_SHORT}; }; + template<> struct gl_traits<glm::uint32> : public gl_traits_integer { static constexpr GLenum type {GL_UNSIGNED_INT}; }; diff --git a/lib/jsonParse-persistence.cpp b/lib/jsonParse-persistence.cpp index fe8bf8d..5c0011a 100644 --- a/lib/jsonParse-persistence.cpp +++ b/lib/jsonParse-persistence.cpp @@ -93,17 +93,20 @@ namespace Persistence { { strm.put(ch); } + static inline void wrh(std::ostream & strm, char ch) { using namespace std::literals; strm << R"(\u)"sv << std::setw(4) << std::hex << static_cast<int>(ch) << std::setw(1); } + static inline void wre(std::ostream & strm, char e) { strm << '\\' << e; } + template<char E> static inline void wre(std::ostream & strm, char) diff --git a/lib/location.cpp b/lib/location.cpp index 732dd6d..ff7cfa6 100644 --- a/lib/location.cpp +++ b/lib/location.cpp @@ -3,7 +3,7 @@ #include <glm/gtx/transform.hpp> glm::mat4 -Location::getTransform() const +Location::getRotationTransform() const { - return glm::translate(pos) * rotate_ypr(rot); + return rotate_ypr(rot); } diff --git a/lib/location.h b/lib/location.h index 078f5d3..8570fc2 100644 --- a/lib/location.h +++ b/lib/location.h @@ -1,14 +1,16 @@ #pragma once +#include "config/types.h" #include <glm/mat4x4.hpp> -#include <glm/vec3.hpp> class Location { public: - explicit Location(glm::vec3 pos = {}, glm::vec3 rot = {}) : pos {pos}, rot {rot} { } +#ifndef __cpp_aggregate_paren_init + explicit Location(GlobalPosition3D pos = {}, Rotation3D rot = {}) : pos {pos}, rot {rot} { } +#endif - glm::mat4 getTransform() const; + [[nodiscard]] glm::mat4 getRotationTransform() const; - glm::vec3 pos; - glm::vec3 rot; + GlobalPosition3D pos; + Rotation3D rot; }; diff --git a/lib/maths.cpp b/lib/maths.cpp index b8dbd34..5430ef6 100644 --- a/lib/maths.cpp +++ b/lib/maths.cpp @@ -6,7 +6,7 @@ #include <stdexcept> glm::mat4 -flat_orientation(const glm::vec3 & diff) +flat_orientation(const Direction3D & diff) { static const auto oneeighty {glm::rotate(pi, up)}; const auto flatdiff {glm::normalize(!!diff)}; @@ -16,17 +16,17 @@ flat_orientation(const glm::vec3 & diff) } // Helper to lookup into a matrix given an xy vector coordinate -template<typename M> +template<typename M, typename I> inline auto & -operator^(M & m, glm::ivec2 xy) +operator^(M & m, glm::vec<2, I> xy) { return m[xy.x][xy.y]; } // Create a matrix for the angle, given the targets into the matrix -template<typename M> +template<typename M, typename I> inline auto -rotation(typename M::value_type a, glm::ivec2 c1, glm::ivec2 s1, glm::ivec2 c2, glm::ivec2 ms2) +rotation(typename M::value_type a, glm::vec<2, I> c1, glm::vec<2, I> s1, glm::vec<2, I> c2, glm::vec<2, I> ms2) { M m(1); sincosf(a, m ^ s1, m ^ c1); @@ -39,51 +39,51 @@ rotation(typename M::value_type a, glm::ivec2 c1, glm::ivec2 s1, glm::ivec2 c2, glm::mat2 rotate_flat(float a) { - return rotation<glm::mat2>(a, {0, 0}, {0, 1}, {1, 1}, {1, 0}); + return rotation<glm::mat2, glm::length_t>(a, {0, 0}, {0, 1}, {1, 1}, {1, 0}); } // Create a yaw transformation matrix glm::mat4 rotate_yaw(float a) { - return rotation<glm::mat4>(a, {0, 0}, {1, 0}, {1, 1}, {0, 1}); + return rotation<glm::mat4, glm::length_t>(a, {0, 0}, {1, 0}, {1, 1}, {0, 1}); } // Create a roll transformation matrix glm::mat4 rotate_roll(float a) { - return rotation<glm::mat4>(a, {0, 0}, {2, 0}, {2, 2}, {0, 2}); + return rotation<glm::mat4, glm::length_t>(a, {0, 0}, {2, 0}, {2, 2}, {0, 2}); } // Create a pitch transformation matrix glm::mat4 rotate_pitch(float a) { - return rotation<glm::mat4>(a, {1, 1}, {1, 2}, {2, 2}, {2, 1}); + return rotation<glm::mat4, glm::length_t>(a, {1, 1}, {1, 2}, {2, 2}, {2, 1}); } // Create a combined yaw, pitch, roll transformation matrix glm::mat4 -rotate_ypr(glm::vec3 a) +rotate_ypr(Rotation3D a) { return rotate_yaw(a.y) * rotate_pitch(a.x) * rotate_roll(a.z); } glm::mat4 -rotate_yp(glm::vec2 a) +rotate_yp(Rotation2D a) { return rotate_yaw(a.y) * rotate_pitch(a.x); } float -vector_yaw(const glm::vec3 & diff) +vector_yaw(const Direction3D & diff) { return std::atan2(diff.x, diff.y); } float -vector_pitch(const glm::vec3 & diff) +vector_pitch(const Direction3D & diff) { return std::atan(diff.z); } @@ -106,7 +106,7 @@ normalize(float ang) return ang; } -Arc::Arc(const glm::vec3 & centre3, const glm::vec3 & e0p, const glm::vec3 & e1p) : +Arc::Arc(const Position3D & centre3, const Position3D & e0p, const Position3D & e1p) : Arc([&]() -> Arc { const auto diffa = e0p - centre3; const auto diffb = e1p - centre3; @@ -120,8 +120,8 @@ Arc::Arc(const glm::vec3 & centre3, const glm::vec3 & e0p, const glm::vec3 & e1p { } -std::pair<glm::vec2, bool> -find_arc_centre(glm::vec2 as, float entrys, glm::vec2 bs, float entrye) +std::pair<Position2D, bool> +find_arc_centre(Position2D as, float entrys, Position2D bs, float entrye) { if (as == bs) { return {as, false}; @@ -129,8 +129,8 @@ find_arc_centre(glm::vec2 as, float entrys, glm::vec2 bs, float entrye) return find_arc_centre(as, sincosf(entrys + half_pi), bs, sincosf(entrye - half_pi)); } -std::pair<glm::vec2, bool> -find_arc_centre(glm::vec2 as, glm::vec2 ad, glm::vec2 bs, glm::vec2 bd) +std::pair<Position2D, bool> +find_arc_centre(Position2D as, Position2D ad, Position2D bs, Position2D bd) { const auto det = bd.x * ad.y - bd.y * ad.x; if (det != 0) { // near parallel line will yield noisy results @@ -142,7 +142,7 @@ find_arc_centre(glm::vec2 as, glm::vec2 ad, glm::vec2 bs, glm::vec2 bd) } std::pair<float, float> -find_arcs_radius(glm::vec2 start, float entrys, glm::vec2 end, float entrye) +find_arcs_radius(Position2D start, float entrys, Position2D end, float entrye) { const auto getrad = [&](float leftOrRight) { return find_arcs_radius(start, sincosf(entrys + leftOrRight), end, sincosf(entrye + leftOrRight)); @@ -151,7 +151,7 @@ find_arcs_radius(glm::vec2 start, float entrys, glm::vec2 end, float entrye) } float -find_arcs_radius(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd) +find_arcs_radius(Position2D start, Position2D ad, Position2D end, Position2D bd) { // Short name functions for big forula auto sqrt = [](float v) { @@ -177,12 +177,14 @@ find_arcs_radius(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd) / (2 * (sq(X) - 2 * X * Z + sq(Z) + sq(Y) - 2 * Y * W + sq(W) - 4)); } -float operator"" _mph(const long double v) +float +operator"" _mph(const long double v) { return static_cast<float>(mph_to_ms(v)); } -float operator"" _kph(const long double v) +float +operator"" _kph(const long double v) { return static_cast<float>(kph_to_ms(v)); } diff --git a/lib/maths.h b/lib/maths.h index b95b706..67b2a15 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include <cmath> #include <glm/glm.hpp> #include <glm/gtc/constants.hpp> @@ -9,7 +10,7 @@ struct Arc : public std::pair<float, float> { using std::pair<float, float>::pair; - Arc(const glm::vec3 & centre3, const glm::vec3 & e0p, const glm::vec3 & e1p); + Arc(const Position3D & centre3, const Position3D & e0p, const Position3D & e1p); float operator[](unsigned int i) const @@ -18,19 +19,19 @@ struct Arc : public std::pair<float, float> { } }; -constexpr const glm::vec3 origin {0, 0, 0}; -constexpr const glm::vec3 up {0, 0, 1}; -constexpr const glm::vec3 down {0, 0, -1}; -constexpr const glm::vec3 north {0, 1, 0}; -constexpr const glm::vec3 south {0, -1, 0}; -constexpr const glm::vec3 east {1, 0, 0}; -constexpr const glm::vec3 west {-1, 0, 0}; +constexpr const Position3D origin {0, 0, 0}; +constexpr const Position3D up {0, 0, 1}; +constexpr const Position3D down {0, 0, -1}; +constexpr const Position3D north {0, 1, 0}; +constexpr const Position3D south {0, -1, 0}; +constexpr const Position3D east {1, 0, 0}; +constexpr const Position3D west {-1, 0, 0}; constexpr auto half_pi {glm::half_pi<float>()}; constexpr auto quarter_pi {half_pi / 2}; constexpr auto pi {glm::pi<float>()}; constexpr auto two_pi {glm::two_pi<float>()}; -glm::mat4 flat_orientation(const glm::vec3 & diff); +glm::mat4 flat_orientation(const Rotation3D & diff); // C++ wrapper for C's sincosf, but with references, not pointers inline auto @@ -39,10 +40,10 @@ sincosf(float a, float & s, float & c) return sincosf(a, &s, &c); } -inline glm::vec2 +inline Rotation2D sincosf(float a) { - glm::vec2 sc; + Rotation2D sc; sincosf(a, sc.x, sc.y); return sc; } @@ -51,11 +52,11 @@ glm::mat2 rotate_flat(float); glm::mat4 rotate_roll(float); glm::mat4 rotate_yaw(float); glm::mat4 rotate_pitch(float); -glm::mat4 rotate_yp(glm::vec2); -glm::mat4 rotate_ypr(glm::vec3); +glm::mat4 rotate_yp(Rotation2D); +glm::mat4 rotate_ypr(Rotation3D); -float vector_yaw(const glm::vec3 & diff); -float vector_pitch(const glm::vec3 & diff); +float vector_yaw(const Direction3D & diff); +float vector_pitch(const Direction3D & diff); float round_frac(const float & v, const float & frac); @@ -87,26 +88,26 @@ perspective_divide(glm::vec<4, T, Q> v) return v / v.w; } -constexpr inline glm::vec2 -operator!(const glm::vec3 & v) +constexpr inline Position2D +operator!(const Position3D & v) { return {v.x, v.y}; } -constexpr inline glm::vec3 -operator^(const glm::vec2 & v, float z) +constexpr inline Position3D +operator^(const Position2D & v, float z) { return {v.x, v.y, z}; } constexpr inline glm::vec4 -operator^(const glm::vec3 & v, float w) +operator^(const Position3D & v, float w) { return {v.x, v.y, v.z, w}; } -constexpr inline glm::vec3 -operator!(const glm::vec2 & v) +constexpr inline Position3D +operator!(const Position2D & v) { return v ^ 0.F; } @@ -125,15 +126,15 @@ operator||(const glm::vec<L, T, Q> v1, const T v2) return {v1, v2}; } -inline glm::vec3 -operator%(const glm::vec3 & p, const glm::mat4 & mutation) +inline Position3D +operator%(const Position3D & p, const glm::mat4 & mutation) { const auto p2 = mutation * (p ^ 1); return p2 / p2.w; } -inline glm::vec3 -operator%=(glm::vec3 & p, const glm::mat4 & mutation) +inline Position3D +operator%=(Position3D & p, const glm::mat4 & mutation) { return p = p % mutation; } @@ -146,10 +147,10 @@ arc_length(const Arc & arc) float normalize(float ang); -std::pair<glm::vec2, bool> find_arc_centre(glm::vec2 start, float entrys, glm::vec2 end, float entrye); -std::pair<glm::vec2, bool> find_arc_centre(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd); -std::pair<float, float> find_arcs_radius(glm::vec2 start, float entrys, glm::vec2 end, float entrye); -float find_arcs_radius(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd); +std::pair<Position2D, bool> find_arc_centre(Position2D start, float entrys, Position2D end, float entrye); +std::pair<Position2D, bool> find_arc_centre(Position2D start, Position2D ad, Position2D end, Position2D bd); +std::pair<float, float> find_arcs_radius(Position2D start, float entrys, Position2D end, float entrye); +float find_arcs_radius(Position2D start, Position2D ad, Position2D end, Position2D bd); template<typename T> auto diff --git a/lib/persistence.cpp b/lib/persistence.cpp index e22d74d..38e2ac6 100644 --- a/lib/persistence.cpp +++ b/lib/persistence.cpp @@ -167,6 +167,7 @@ namespace Persistence { { throw std::logic_error("Default write op shouldn't ever get called"); } + /// LCOV_EXCL_STOP ParseBase::ParseBase() : sharedObjectsInstance {std::make_shared<SharedObjects>()} diff --git a/lib/persistence.h b/lib/persistence.h index 5d71d4c..92f3052 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -153,6 +153,7 @@ namespace Persistence { }; struct Persistable; + struct PersistenceStore { using SelectionFactory = std::function<SelectionPtr()>; PersistenceStore() = default; @@ -163,6 +164,7 @@ namespace Persistence { enum class NameAction { Push, HandleAndContinue, Ignore }; using NameActionSelection = std::pair<NameAction, SelectionPtr>; + template<typename Helper, typename T> [[nodiscard]] inline bool persistValue(const std::string_view key, T & value) @@ -267,6 +269,7 @@ namespace Persistence { template<glm::length_t L, typename T, glm::qualifier Q> struct SelectionT<glm::vec<L, T, Q>> : public SelectionT<std::span<T>> { SelectionT(glm::vec<L, T, Q> & v) : SelectionT<std::span<T>> {spn}, spn {&v[0], L} { } + std::span<T> spn; }; @@ -316,6 +319,7 @@ namespace Persistence { MapByMember(Map & m) : Persistence::SelectionT<Type> {s}, map {m} { } using Persistence::SelectionT<Type>::SelectionT; + void endObject(Persistence::Stack & stk) override { @@ -332,7 +336,9 @@ namespace Persistence { template<typename Container, typename Type = typename Container::value_type> struct Appender : public Persistence::SelectionT<Type> { Appender(Container & c) : Persistence::SelectionT<Type> {s}, container {c} { } + using Persistence::SelectionT<Type>::SelectionT; + void endObject(Persistence::Stack & stk) override { @@ -407,6 +413,7 @@ namespace Persistence { { return std::dynamic_pointer_cast<T>(Persistence::ParseBase::sharedObjects.lock()->at(k)); } + template<typename... T> static auto emplaceShared(T &&... v) @@ -421,6 +428,7 @@ namespace Persistence { inline static thread_local SharedObjectsWPtr sharedObjects; SharedObjectsPtr sharedObjectsInstance; }; + // TODO Move these using SeenSharedObjects = std::map<void *, std::string>; inline SeenSharedObjects seenSharedObjects; @@ -428,6 +436,7 @@ namespace Persistence { template<typename Ptr> struct SelectionPtrBase : public SelectionV<Ptr> { static constexpr auto shared = std::is_copy_assignable_v<Ptr>; using T = typename Ptr::element_type; + struct SelectionObj : public SelectionV<Ptr> { struct MakeObjectByTypeName : public SelectionV<Ptr> { using SelectionV<Ptr>::SelectionV; @@ -55,6 +55,7 @@ public: protected: explicit wrapped_ptr(Obj * o) : obj {o} { } + Obj * obj; }; diff --git a/lib/ray.cpp b/lib/ray.cpp index c4e0d8c..9fb3648 100644 --- a/lib/ray.cpp +++ b/lib/ray.cpp @@ -2,13 +2,13 @@ #include <algorithm> Ray -Ray::fromPoints(glm::vec3 start, glm::vec3 p) +Ray::fromPoints(Position3D start, Position3D p) { return {start, glm::normalize(p - start)}; } float -Ray::distanceToLine(const glm::vec3 & p1, const glm::vec3 & e1) const +Ray::distanceToLine(const Position3D & p1, const Position3D & e1) const { // https://en.wikipedia.org/wiki/Skew_lines const auto diff = p1 - e1; @@ -25,10 +25,10 @@ Ray::distanceToLine(const glm::vec3 & p1, const glm::vec3 & e1) const } bool -Ray::passesCloseToEdges(const std::span<const glm::vec3> positions, float distance) const +Ray::passesCloseToEdges(const std::span<const Position3D> positions, float distance) const { return std::adjacent_find(positions.begin(), positions.end(), - [this, distance](const glm::vec3 & a, const glm::vec3 & b) { + [this, distance](const Position3D & a, const Position3D & b) { return distanceToLine(a, b) <= distance; }) != positions.end(); @@ -1,17 +1,20 @@ #pragma once +#include "config/types.h" #include <glm/glm.hpp> #include <span> class Ray { public: - Ray(glm::vec3 start, glm::vec3 direction) : start {start}, direction {direction} { } +#ifndef __cpp_aggregate_paren_init + Ray(Position3D start, Direction3D direction) : start {start}, direction {direction} { } +#endif - static Ray fromPoints(glm::vec3, glm::vec3); + static Ray fromPoints(Position3D, Position3D); - glm::vec3 start; - glm::vec3 direction; + Position3D start; + Direction3D direction; - float distanceToLine(const glm::vec3 & a, const glm::vec3 & b) const; - bool passesCloseToEdges(const std::span<const glm::vec3> positions, float distance) const; + [[nodiscard]] float distanceToLine(const Position3D & a, const Position3D & b) const; + [[nodiscard]] bool passesCloseToEdges(const std::span<const Position3D> positions, float distance) const; }; diff --git a/lib/resource.h b/lib/resource.h index 37dd657..9af3632 100644 --- a/lib/resource.h +++ b/lib/resource.h @@ -16,5 +16,6 @@ public: Resource::setBasePath(RESDIR); } }; + BOOST_GLOBAL_FIXTURE(SetResourcePath); #endif diff --git a/lib/saxParse-persistence.h b/lib/saxParse-persistence.h index 6043b25..bd5db57 100644 --- a/lib/saxParse-persistence.h +++ b/lib/saxParse-persistence.h @@ -10,6 +10,7 @@ namespace Persistence { private: template<typename T> struct Root : public Persistable { T t {}; + bool persist(PersistenceStore & store) { diff --git a/lib/stdTypeDefs.h b/lib/stdTypeDefs.h index 317cdb3..beab630 100644 --- a/lib/stdTypeDefs.h +++ b/lib/stdTypeDefs.h @@ -6,18 +6,22 @@ template<typename T> struct AnyPtr { // cppcheck-suppress noExplicitConstructor AnyPtr(T * p) : ptr {p} { } + // cppcheck-suppress noExplicitConstructor template<typename S> AnyPtr(const S & p) : ptr {p.get()} { } + auto get() const { return ptr; } + auto operator->() const { return ptr; } + auto & operator*() const { diff --git a/lib/unicode.h b/lib/unicode.h index f69c43c..bc491f3 100644 --- a/lib/unicode.h +++ b/lib/unicode.h @@ -50,6 +50,7 @@ struct utf8_string_view { constexpr utf8_string_view(const Str & str) : begin_ {str.data()}, end_ {str.data() + str.length()} { } + // cppcheck-suppress noExplicitConstructor; NOLINTNEXTLINE(hicpp-explicit-conversions) constexpr utf8_string_view(const char * const str) : utf8_string_view {std::string_view {str}} { } @@ -70,6 +71,7 @@ struct utf8_string_view { private: const char *begin_, *end_; }; + template<> struct std::iterator_traits<utf8_string_view::iter> { using difference_type = size_t; using value_type = uint32_t; diff --git a/lib/worker.h b/lib/worker.h index 0d15ca2..95bb4ec 100644 --- a/lib/worker.h +++ b/lib/worker.h @@ -16,6 +16,7 @@ public: class WorkItem { protected: WorkItem(Worker * worker) : worker {worker} { } + virtual ~WorkItem() = default; NO_MOVE(WorkItem); NO_COPY(WorkItem); @@ -25,6 +26,7 @@ public: { worker->assist(); } + Worker * worker; public: @@ -57,6 +59,7 @@ public: { return instance.addWorkImpl(std::forward<Params>(params)...); } + template<typename T> using WorkPtrT = std::shared_ptr<WorkItemT<T>>; private: diff --git a/res/brush47.xml b/res/brush47.xml index 31518c8..dc33282 100644 --- a/res/brush47.xml +++ b/res/brush47.xml @@ -61,7 +61,7 @@ <textureFragment id="roofSideWithVents" path="rail/roofSideWithVents.png"/> <textureFragment id="roofTopWithVents" path="rail/roofTopWithVents.png"/> <textureFragment id="cabWindowFront" path="rail/cabWindowFront.png"/> - <asset p.typeid="RailVehicleClass" id="brush-47" name="Brush 47" length="19.38" wheelBase="15.70" maxSpeed="42.4688"> + <asset p.typeid="RailVehicleClass" id="brush-47" name="Brush 47" length="19380" wheelBase="15700" maxSpeed="42468.8"> <bodyMesh id="body" size="2.69,19.38,3.9"> <use type="cuboid" position="0,0,1.2" scale="2.69,19.38,0.3" colour="goldenrod"> <face id="bottom" colour="#2c3539"/> diff --git a/test/perf-geoData.cpp b/test/perf-geoData.cpp index 4fed632..4d4505e 100644 --- a/test/perf-geoData.cpp +++ b/test/perf-geoData.cpp @@ -8,17 +8,17 @@ namespace { terrain_findPoint(benchmark::State & state) { for (auto _ : state) { - benchmark::DoNotOptimize(tm.findPoint({315555, 495556})); + benchmark::DoNotOptimize(tm.findPoint({315555000, 495556000})); } } void terrain_walk(benchmark::State & state) { - const glm::vec2 point {310001, 490000}; + const glm::vec2 point {310001000, 490000000}; const GeoData::PointFace start {point, tm.findPoint(point)}; for (auto _ : state) { - tm.walk(start, {319999, 500000}, [](auto f) { + tm.walk(start, {319999000, 500000000}, [](auto f) { benchmark::DoNotOptimize(f); }); } diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 145481e..c8183df 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -25,7 +25,7 @@ BOOST_GLOBAL_FIXTURE(TestMainWindow); const std::filesystem::path TMP {"/tmp"}; -class FactoryFixture : public TestRenderOutputSize<glm::ivec2 {2048, 1024}>, public SceneProvider { +class FactoryFixture : public TestRenderOutputSize<TextureAbsCoord {2048, 1024}>, public SceneProvider { public: FactoryFixture() : sceneRenderer {size, output} { } @@ -64,7 +64,7 @@ public: } void - render(float dist = 10.f) + render(float dist) { sceneRenderer.camera.setView({-dist, dist * 1.2f, dist * 1.2f}, south + east + down); sceneRenderer.render(*this); @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(brush47xml, *boost::unit_test::timeout(5)) auto railVehicle = std::make_shared<RailVehicle>(brush47rvc); objects.objects.push_back(brush47rvc); - render(); + render(10000); } BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) @@ -116,13 +116,13 @@ BOOST_AUTO_TEST_CASE(foliage, *boost::unit_test::timeout(5)) auto tree_01_1_f = std::dynamic_pointer_cast<Foliage>(tree_01_1); BOOST_REQUIRE(tree_01_1_f); - auto plant1 = std::make_shared<Plant>(tree_01_1_f, Location {{-2, 2, 0}, {0, 0, 0}}); - auto plant2 = std::make_shared<Plant>(tree_01_1_f, Location {{3, -4, 0}, {0, 1, 0}}); - auto plant3 = std::make_shared<Plant>(tree_01_1_f, Location {{-2, -4, 0}, {0, 2, 0}}); - auto plant4 = std::make_shared<Plant>(tree_01_1_f, Location {{3, 2, 0}, {0, 3, 0}}); + auto plant1 = std::make_shared<Plant>(tree_01_1_f, Location {{-2000, 2000, 0}, {0, 0, 0}}); + auto plant2 = std::make_shared<Plant>(tree_01_1_f, Location {{3000, -4000, 0}, {0, 1, 0}}); + auto plant3 = std::make_shared<Plant>(tree_01_1_f, Location {{-2000, -4000, 0}, {0, 2, 0}}); + auto plant4 = std::make_shared<Plant>(tree_01_1_f, Location {{3000, 2000, 0}, {0, 3, 0}}); objects.objects.push_back(tree_01_1_f); - render(5); + render(6000); } BOOST_AUTO_TEST_SUITE_END(); @@ -183,14 +183,15 @@ BOOST_AUTO_TEST_CASE(texturePacker_many, *boost::unit_test::timeout(5)) { std::vector<TexturePacker::Image> images(256); std::fill(images.begin(), images.end(), TexturePacker::Image {32, 32}); - const auto totalSize = std::accumulate(images.begin(), images.end(), 0U, [](auto t, const auto & i) { + const auto totalSize = std::accumulate(images.begin(), images.end(), 0, [](auto t, const auto & i) { return t + TexturePacker::area(i); }); TexturePacker tp {images}; BOOST_CHECK_EQUAL(TexturePacker::Size(32, 32), tp.minSize()); const auto result = tp.pack(); BOOST_CHECK_EQUAL(result.first.size(), images.size()); - BOOST_CHECK_GE(TexturePacker::area(result.second), TexturePacker::area(images.front()) * images.size()); + BOOST_CHECK_GE(TexturePacker::area(result.second), + TexturePacker::area(images.front()) * static_cast<GLsizei>(images.size())); BOOST_CHECK_EQUAL(totalSize, TexturePacker::area(result.second)); } diff --git a/test/test-geoData.cpp b/test/test-geoData.cpp index 447ab37..4e85f73 100644 --- a/test/test-geoData.cpp +++ b/test/test-geoData.cpp @@ -11,7 +11,7 @@ public: TestTerrainMesh() : GeoData {GeoData::loadFromAsciiGrid(FIXTURESDIR "height/SD19.asc")} { } }; -constexpr size_t ncols = 200, nrows = 200, xllcorner = 310000, yllcorner = 490000, cellsize = 50; +constexpr size_t ncols = 200, nrows = 200, xllcorner = 310000000, yllcorner = 490000000, cellsize = 50000; BOOST_FIXTURE_TEST_SUITE(ttm, TestTerrainMesh); @@ -20,18 +20,22 @@ BOOST_AUTO_TEST_CASE(loadSuccess) BOOST_CHECK_EQUAL(ncols * nrows, n_vertices()); BOOST_CHECK_EQUAL(2 * (ncols - 1) * (nrows - 1), n_faces()); const auto [lower, upper] = getExtents(); - BOOST_CHECK_EQUAL(lower, glm::vec3(310000, 490000, -2.6)); - BOOST_CHECK_EQUAL(upper, glm::vec3(319950, 499950, 571.6)); + BOOST_CHECK_EQUAL(lower, GlobalPosition3D(310000000, 490000000, -2600)); + BOOST_CHECK_EQUAL(upper, GlobalPosition3D(319950000, 499950000, 571600)); } BOOST_AUTO_TEST_CASE(normalsAllPointUp) { - BOOST_CHECK(std::all_of(faces_begin(), faces_end(), [this](auto && vh) { - return normal(vh).z > 0; - })); - BOOST_CHECK(std::all_of(vertices_begin(), vertices_end(), [this](auto && vh) { - return normal(vh).z > 0; - })); + BOOST_CHECK_EQUAL(std::count_if(faces_begin(), faces_end(), + [this](auto && vh) { + return normal(vh).z > 0; + }), + n_faces()); + BOOST_CHECK_EQUAL(std::count_if(vertices_begin(), vertices_end(), + [this](auto && vh) { + return normal(vh).z > 0; + }), + n_vertices()); } BOOST_AUTO_TEST_CASE(trianglesContainsPoints) @@ -39,13 +43,13 @@ BOOST_AUTO_TEST_CASE(trianglesContainsPoints) const auto face = face_handle(0); BOOST_TEST_CONTEXT(GeoData::Triangle<2>(this, fv_range(face))) { - BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner, yllcorner}, face)); - BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + cellsize, yllcorner + cellsize}, face)); - BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner, yllcorner + cellsize}, face)); - BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + 1, yllcorner + 1}, face)); - BOOST_CHECK(triangleContainsPoint(glm::vec2 {xllcorner + 1, yllcorner + 2}, face)); - BOOST_CHECK(!triangleContainsPoint(glm::vec2 {xllcorner + 3, yllcorner + 2}, face)); - BOOST_CHECK(!triangleContainsPoint(glm::vec2 {xllcorner + cellsize, yllcorner}, face)); + BOOST_CHECK(triangleContainsPoint(GlobalPosition2D {xllcorner, yllcorner}, face)); + BOOST_CHECK(triangleContainsPoint(GlobalPosition2D {xllcorner + cellsize, yllcorner + cellsize}, face)); + BOOST_CHECK(triangleContainsPoint(GlobalPosition2D {xllcorner, yllcorner + cellsize}, face)); + BOOST_CHECK(triangleContainsPoint(GlobalPosition2D {xllcorner + 1, yllcorner + 1}, face)); + BOOST_CHECK(triangleContainsPoint(GlobalPosition2D {xllcorner + 1, yllcorner + 2}, face)); + BOOST_CHECK(!triangleContainsPoint(GlobalPosition2D {xllcorner + 3, yllcorner + 2}, face)); + BOOST_CHECK(!triangleContainsPoint(GlobalPosition2D {xllcorner + cellsize, yllcorner}, face)); } } @@ -55,7 +59,7 @@ static const TestTerrainMesh fixedTerrtain; BOOST_AUTO_TEST_CASE(locatePointFace) { - const GeoData::PointFace pf {{310002, 490003}}; + const GeoData::PointFace pf {{310002000, 490003000}}; BOOST_CHECK(!pf.isLocated()); BOOST_CHECK(pf.face(&fixedTerrtain).is_valid()); BOOST_CHECK_EQUAL(pf.face(&fixedTerrtain).idx(), 0); @@ -63,19 +67,19 @@ BOOST_AUTO_TEST_CASE(locatePointFace) BOOST_AUTO_TEST_CASE(preLocatePointFace) { - const GeoData::PointFace pf {{310002, 490003}, &fixedTerrtain}; + const GeoData::PointFace pf {{310002000, 490003000}, &fixedTerrtain}; BOOST_CHECK(pf.isLocated()); BOOST_CHECK_EQUAL(pf.face(&fixedTerrtain).idx(), 0); } -using FindPointData = std::tuple<glm::vec2, int>; +using FindPointData = std::tuple<GlobalPosition2D, int>; // No boundary cases as these can produce different valid results depending on starting point BOOST_DATA_TEST_CASE(findPointOnTerrain, boost::unit_test::data::make<FindPointData>({ {{0, 0}, -1}, {{xllcorner, 0}, -1}, {{0, yllcorner}, -1}, {{xllcorner + 1, yllcorner + 2}, 0}, {{xllcorner + (cellsize * (nrows - 1)) - 2, yllcorner + (cellsize * (ncols - 1)) - 1}, 79200}, - {{315555, 495556}, 44400}, // perf test target + {{315555000, 495556000}, 44400}, // perf test target }) * boost::unit_test::data::make<int>( {0, 1, 2, 3, 4, 5, 6, 10, 100, 150, 200, 1000, 1234, 17439, 79201, 79200, 79199}), @@ -84,38 +88,38 @@ BOOST_DATA_TEST_CASE(findPointOnTerrain, BOOST_CHECK_EQUAL(fh, fixedTerrtain.findPoint(p, GeoData::FaceHandle(start)).idx()); } -using FindPositionData = std::tuple<glm::vec2, float>; +using FindPositionData = std::tuple<GlobalPosition2D, GlobalDistance>; BOOST_DATA_TEST_CASE(findPositionAt, boost::unit_test::data::make<FindPositionData>({ // corners - {{310000, 490000}, 32.8F}, - {{310050, 490050}, 33.0F}, - {{310000, 490050}, 32.7F}, - {{310050, 490000}, 33.2F}, - {{310750, 490150}, 58.4F}, + {{310000000, 490000000}, 32800}, + {{310050000, 490050000}, 33000}, + {{310000000, 490050000}, 32700}, + {{310050000, 490000000}, 33200}, + {{310750000, 490150000}, 58399}, // midpoints - {{310025, 490025}, 32.9F}, - {{310025, 490050}, 32.85F}, - {{310000, 490025}, 32.75F}, + {{310025000, 490025000}, 32900}, + {{310025000, 490050000}, 32850}, + {{310000000, 490025000}, 32750}, // other - {{310751, 490152}, 58.326F}, + {{310751000, 490152000}, 58326}, }), p, h) { - BOOST_CHECK_CLOSE_VEC(fixedTerrtain.positionAt(p), p ^ h); + BOOST_CHECK_EQUAL(fixedTerrtain.positionAt(p), GlobalPosition3D(p, h)); } -using FindRayIntersectData = std::tuple<glm::vec3, glm::vec3, glm::vec3>; +using FindRayIntersectData = std::tuple<GlobalPosition3D, Direction3D, GlobalPosition3D>; BOOST_DATA_TEST_CASE(findRayIntersect, boost::unit_test::data::make<FindRayIntersectData>({ - {{310000, 490000, 50}, {1, 1, -2}, {310008.59, 490008.59, 32.834301}}, - {{310000, 490000, 50}, {1, 1, -1}, {310017.12, 490017.12, 32.868526}}, + {{310000000, 490000000, 50000}, {1, 1, -2}, {310008585, 490008585, 32834}}, + {{310000000, 490000000, 50000}, {1, 1, -1}, {310017136, 490017136, 32868}}, }), p, d, i) { - BOOST_CHECK_CLOSE_VEC(fixedTerrtain.intersectRay({p, d}).value(), i); + BOOST_CHECK_EQUAL(fixedTerrtain.intersectRay({p, d}).value(), i); } BOOST_AUTO_TEST_CASE(boundaryWalk) @@ -128,22 +132,22 @@ BOOST_AUTO_TEST_CASE(boundaryWalk) BOOST_CHECK_EQUAL(count, 2 * (ncols + nrows - 2)); } -using WalkTerrainData = std::tuple<glm::vec2, glm::vec2, std::vector<int>>; +using WalkTerrainData = std::tuple<GlobalPosition2D, GlobalPosition2D, std::vector<int>>; BOOST_DATA_TEST_CASE(walkTerrain, boost::unit_test::data::make<WalkTerrainData>({ - {{310002, 490003}, {310002, 490003}, {0}}, - {{310003, 490002}, {310003, 490002}, {1}}, - {{310002, 490003}, {310003, 490002}, {0, 1}}, - {{310003, 490002}, {310002, 490003}, {1, 0}}, - {{310002, 490003}, {310202, 490003}, {0, 1, 2, 3, 4, 5, 6, 7, 8}}, - {{310202, 490003}, {310002, 490003}, {8, 7, 6, 5, 4, 3, 2, 1, 0}}, - {{310002, 490003}, {310002, 490203}, {0, 399, 398, 797, 796, 1195, 1194, 1593, 1592}}, - {{310002, 490003}, {309999, 489999}, {0}}, - {{309999, 489999}, {310002, 490003}, {0}}, - {{320002, 500003}, {319949, 499948}, {79201}}, - {{309999, 490003}, {310004, 489997}, {0, 1}}, - {{310004, 489997}, {309999, 490003}, {1, 0}}, + {{310002000, 490003000}, {310002000, 490003000}, {0}}, + {{310003000, 490002000}, {310003000, 490002000}, {1}}, + {{310002000, 490003000}, {310003000, 490002000}, {0, 1}}, + {{310003000, 490002000}, {310002000, 490003000}, {1, 0}}, + {{310002000, 490003000}, {310202000, 490003000}, {0, 1, 2, 3, 4, 5, 6, 7, 8}}, + {{310202000, 490003000}, {310002000, 490003000}, {8, 7, 6, 5, 4, 3, 2, 1, 0}}, + {{310002000, 490003000}, {310002000, 490203000}, {0, 399, 398, 797, 796, 1195, 1194, 1593, 1592}}, + {{310002000, 490003000}, {309999000, 489999000}, {0}}, + {{309999000, 489999000}, {310002000, 490003000}, {0}}, + {{320002000, 500003000}, {319949000, 499948000}, {79201}}, + {{309999000, 490003000}, {310004000, 489997000}, {0, 1}}, + {{310004000, 489997000}, {309999000, 490003000}, {1, 0}}, }), from, to, visits) { @@ -156,10 +160,10 @@ BOOST_DATA_TEST_CASE(walkTerrain, BOOST_DATA_TEST_CASE(walkTerrainSetsFromFace, boost::unit_test::data::make<WalkTerrainData>({ - {{310002, 490003}, {310002, 490003}, {0}}, - {{310003, 490002}, {310003, 490002}, {1}}, - {{310002, 490003}, {310003, 490002}, {0, 1}}, - {{310003, 490002}, {310002, 490003}, {1, 0}}, + {{310002000, 490003000}, {310002000, 490003000}, {0}}, + {{310003000, 490002000}, {310003000, 490002000}, {1}}, + {{310002000, 490003000}, {310003000, 490002000}, {0, 1}}, + {{310003000, 490002000}, {310002000, 490003000}, {1, 0}}, }), from, to, visits) { @@ -170,13 +174,13 @@ BOOST_DATA_TEST_CASE(walkTerrainSetsFromFace, BOOST_DATA_TEST_CASE(walkTerrainUntil, boost::unit_test::data::make<WalkTerrainData>({ - {{310002, 490003}, {310002, 490003}, {0}}, - {{310003, 490002}, {310003, 490002}, {1}}, - {{310002, 490003}, {310003, 490002}, {0, 1}}, - {{310003, 490002}, {310002, 490003}, {1, 0}}, - {{310002, 490003}, {310202, 490003}, {0, 1, 2, 3, 4}}, - {{310202, 490003}, {310002, 490003}, {8, 7, 6, 5, 4}}, - {{310002, 490003}, {310002, 490203}, {0, 399, 398, 797, 796}}, + {{310002000, 490003000}, {310002000, 490003000}, {0}}, + {{310003000, 490002000}, {310003000, 490002000}, {1}}, + {{310002000, 490003000}, {310003000, 490002000}, {0, 1}}, + {{310003000, 490002000}, {310002000, 490003000}, {1, 0}}, + {{310002000, 490003000}, {310202000, 490003000}, {0, 1, 2, 3, 4}}, + {{310202000, 490003000}, {310002000, 490003000}, {8, 7, 6, 5, 4}}, + {{310002000, 490003000}, {310002000, 490203000}, {0, 399, 398, 797, 796}}, }), from, to, visits) { diff --git a/test/test-glContextBhvr.cpp b/test/test-glContextBhvr.cpp index 2f71aec..26b45d9 100644 --- a/test/test-glContextBhvr.cpp +++ b/test/test-glContextBhvr.cpp @@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(windowContextThingsBehaviour1) const SDL_GLContextPtr context {window}; BOOST_REQUIRE(context); BOOST_REQUIRE(!glCreateProgram); - BOOST_REQUIRE_EQUAL(gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress)), 40006); + BOOST_REQUIRE_GT(gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress)), 0); BOOST_REQUIRE(glCreateProgram); CreateProgramTest(); } // Context destroyed diff --git a/test/test-maths.cpp b/test/test-maths.cpp index 2560319..9eae918 100644 --- a/test/test-maths.cpp +++ b/test/test-maths.cpp @@ -196,12 +196,12 @@ BOOST_DATA_TEST_CASE(straight1, const TestLinkStraight l(v); { const auto p = l.positionAt(0, 0); - BOOST_CHECK_EQUAL(p.pos, origin); + BOOST_CHECK_EQUAL(p.pos, GlobalPosition3D {origin}); BOOST_CHECK_EQUAL(p.rot, glm::vec3(0, angFor, 0)); } { const auto p = l.positionAt(0, 1); - BOOST_CHECK_EQUAL(p.pos, v); + BOOST_CHECK_EQUAL(p.pos, GlobalPosition3D {v}); BOOST_CHECK_EQUAL(p.rot, glm::vec3(0, angBack, 0)); } } @@ -231,12 +231,12 @@ BOOST_DATA_TEST_CASE(curve1, BOOST_CHECK_EQUAL(l.radius, 1.F); { const auto p = l.positionAt(0, 0); - BOOST_CHECK_CLOSE_VEC(p.pos, origin); + BOOST_CHECK_CLOSE_VEC(RelativePosition3D {p.pos}, origin); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angFor, 0)); } { const auto p = l.positionAt(0, 1); - BOOST_CHECK_CLOSE_VEC(p.pos, e1); + BOOST_CHECK_CLOSE_VEC(RelativePosition3D {p.pos}, e1); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angBack, 0)); } } @@ -247,13 +247,13 @@ BOOST_DATA_TEST_CASE(curve1, { const auto p = l.positionAt(0, 0); const auto angForReversed = normalize(vector_yaw(origin - e1) * 2 - angFor); - BOOST_CHECK_CLOSE_VEC(p.pos, e1); + BOOST_CHECK_CLOSE_VEC(RelativePosition3D {p.pos}, e1); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angForReversed, 0)); } { const auto p = l.positionAt(0, 1); const auto angBackReversed = normalize(vector_yaw(e1 - origin) * 2 - angBack); - BOOST_CHECK_CLOSE_VEC(p.pos, origin); + BOOST_CHECK_CLOSE_VEC(RelativePosition3D {p.pos}, origin); BOOST_CHECK_CLOSE_VEC(p.rot, glm::vec3(0, angBackReversed, 0)); } } diff --git a/test/test-render.cpp b/test/test-render.cpp index fb2a71b..f15e51e 100644 --- a/test/test-render.cpp +++ b/test/test-render.cpp @@ -26,7 +26,7 @@ class TestScene : public SceneProvider { std::shared_ptr<RailVehicle> train1, train2; Terrain terrain {[]() { - auto gd = std::make_shared<GeoData>(GeoData::createFlat({0, 0}, {1000, 1000}, 1)); + auto gd = std::make_shared<GeoData>(GeoData::createFlat({0, 0}, {1000000, 1000000}, 1)); return gd; }()}; @@ -34,11 +34,11 @@ public: TestScene() { train1 = std::make_shared<RailVehicle>(brush47rvc); - train1->location.setPosition({52, 50, 2}); + train1->location.setPosition({52000, 50000, 2000}); train1->bogies.front().setPosition(train1->bogies.front().position() + train1->location.position()); train1->bogies.back().setPosition(train1->bogies.back().position() + train1->location.position()); train2 = std::make_shared<RailVehicle>(brush47rvc); - train2->location.setPosition({52, 30, 2}); + train2->location.setPosition({52000, 30000, 2000}); train2->bogies.front().setPosition(train2->bogies.front().position() + train2->location.position()); train2->bogies.back().setPosition(train2->bogies.back().position() + train2->location.position()); } @@ -87,7 +87,7 @@ BOOST_FIXTURE_TEST_SUITE(w, TestRenderOutput); BOOST_AUTO_TEST_CASE(basic) { SceneRenderer ss {size, output}; - ss.camera.setView({-10, -10, 60}, glm::normalize(glm::vec3 {1, 1, -0.5F})); + ss.camera.setView({-10000, -10000, 60000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); const TestScene scene; ss.render(scene); Texture::save(outImage, "/tmp/basic.tga"); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(basic) BOOST_AUTO_TEST_CASE(pointlight) { SceneRenderer ss {size, output}; - ss.camera.setView({-10, -10, 60}, glm::normalize(glm::vec3 {1, 1, -0.5F})); + ss.camera.setView({-10000, -10000, 60000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); class PointLightScene : public TestScene { public: @@ -110,9 +110,9 @@ BOOST_AUTO_TEST_CASE(pointlight) void lights(const SceneShader & shader) const override { - for (int x = 50; x < 100; x += 20) { - for (int y = 50; y < 2000; y += 20) { - shader.pointLight.add({x, y, 4}, {1.0, 1.0, 1.0}, 0.1F); + for (int x = 50000; x < 100000; x += 20000) { + for (int y = 50000; y < 2000000; y += 20000) { + shader.pointLight.add({x, y, 4000}, {1.0, 1.0, 1.0}, 0.1F); } } } @@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(pointlight) BOOST_AUTO_TEST_CASE(spotlight) { SceneRenderer ss {size, output}; - ss.camera.setView({-10, -10, 60}, glm::normalize(glm::vec3 {1, 1, -0.5F})); + ss.camera.setView({-10000, -10000, 60000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); class PointLightScene : public TestScene { public: @@ -140,10 +140,10 @@ BOOST_AUTO_TEST_CASE(spotlight) void lights(const SceneShader & shader) const override { - shader.spotLight.add({50, 50, 15}, down, {1.0, 1.0, 1.0}, 0.01F, 1); - shader.spotLight.add({51, 59.5, 1}, north, {1.0, 1.0, 1.0}, 0.001F, .5); - shader.spotLight.add({53, 59.5, 1}, north, {1.0, 1.0, 1.0}, 0.001F, .5); - shader.spotLight.add({60, 50, 3}, north + east, {1.0, 1.0, 1.0}, 0.0001F, .7F); + shader.spotLight.add({50000, 50000, 15000}, down, {1.0, 1.0, 1.0}, 0.01F, 1); + shader.spotLight.add({51000, 59500, 1000}, north, {1.0, 1.0, 1.0}, 0.001F, .5); + shader.spotLight.add({53000, 59500, 1000}, north, {1.0, 1.0, 1.0}, 0.001F, .5); + shader.spotLight.add({60000, 50000, 3000}, north + east, {1.0, 1.0, 1.0}, 0.0001F, .7F); } }; diff --git a/test/testRenderOutput.cpp b/test/testRenderOutput.cpp index 464b0b3..9af4451 100644 --- a/test/testRenderOutput.cpp +++ b/test/testRenderOutput.cpp @@ -1,7 +1,7 @@ #include "testRenderOutput.h" #include <stdexcept> -TestRenderOutput::TestRenderOutput(glm::ivec2 s) : size {s} +TestRenderOutput::TestRenderOutput(TextureAbsCoord s) : size {s} { glBindFramebuffer(GL_FRAMEBUFFER, output); const auto configuregdata diff --git a/test/testRenderOutput.h b/test/testRenderOutput.h index 13c380f..056d029 100644 --- a/test/testRenderOutput.h +++ b/test/testRenderOutput.h @@ -1,24 +1,25 @@ #pragma once +#include "config/types.h" #include "glArrays.h" #include <glm/vec2.hpp> #include <special_members.h> class TestRenderOutput { public: - TestRenderOutput(glm::ivec2 size = {640, 480}); + explicit TestRenderOutput(TextureAbsCoord size = {640, 480}); virtual ~TestRenderOutput() = default; NO_MOVE(TestRenderOutput); NO_COPY(TestRenderOutput); - const glm::ivec2 size; + const TextureAbsCoord size; glFrameBuffer output; glRenderBuffer depth; glTexture outImage; }; -template<glm::ivec2 Size> class TestRenderOutputSize : public TestRenderOutput { +template<TextureAbsCoord Size> class TestRenderOutputSize : public TestRenderOutput { public: TestRenderOutputSize() : TestRenderOutput {Size} { } }; diff --git a/test/testStructures.h b/test/testStructures.h index 6966052..aaaf940 100644 --- a/test/testStructures.h +++ b/test/testStructures.h @@ -1,5 +1,6 @@ #pragma once +#include "config/types.h" #include <persistence.h> struct AbsObject : public Persistence::Persistable { @@ -31,9 +32,9 @@ struct TestObject : public Persistence::Persistable { float flt {}; std::string str {}; bool bl {}; - glm::vec3 pos {}; + Position3D pos {}; std::vector<float> flts; - std::vector<glm::vec3> poss; + std::vector<Position3D> poss; std::vector<std::vector<std::vector<std::string>>> nest; std::unique_ptr<TestObject> ptr; std::unique_ptr<AbsObject> aptr; diff --git a/thirdparty/openmesh/glmcompat.h b/thirdparty/openmesh/glmcompat.h index 708b1a6..dc5a96e 100644 --- a/thirdparty/openmesh/glmcompat.h +++ b/thirdparty/openmesh/glmcompat.h @@ -1,6 +1,7 @@ #pragma once #include <OpenMesh/Core/Mesh/Traits.hh> +#include <OpenMesh/Core/Utils/vector_cast.hh> #include <glm/geometric.hpp> #include <glm/vec3.hpp> @@ -21,6 +22,18 @@ namespace glm { } namespace OpenMesh { + template<typename dst_t, typename src_t, glm::length_t n, glm::qualifier Q> + struct vector_caster<glm::vec<n, dst_t, Q>, glm::vec<n, src_t, Q>> { + using source_type = glm::vec<n, src_t, Q>; + using return_type = glm::vec<n, dst_t, Q>; + + inline static return_type + cast(const source_type & _src) + { + return return_type {_src}; + } + }; + template<glm::length_t L, typename T, glm::qualifier Q> struct vector_traits<glm::vec<L, T, Q>> { using vector_type = glm::vec<L, T, Q>; using value_type = T; diff --git a/ui/builders/freeExtend.h b/ui/builders/freeExtend.h index 55fe7ff..b276426 100644 --- a/ui/builders/freeExtend.h +++ b/ui/builders/freeExtend.h @@ -9,5 +9,5 @@ class BuilderFreeExtend : public EditNetwork::Builder { void click(Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e, const Ray & ray) override; void move(Network * network, const GeoData * geoData, const SDL_MouseMotionEvent & e, const Ray & ray) override; - std::optional<glm::vec3> p1; + std::optional<Position3D> p1; }; diff --git a/ui/builders/straight.cpp b/ui/builders/straight.cpp index 4fa9585..9b262bb 100644 --- a/ui/builders/straight.cpp +++ b/ui/builders/straight.cpp @@ -47,7 +47,7 @@ BuilderStraight::click(Network * network, const GeoData * geoData, const SDL_Mou } void -BuilderStraight::create(Network * network, glm::vec3 p1, glm::vec3 p2) const +BuilderStraight::create(Network * network, Position3D p1, Position3D p2) const { network->addStraight(p1, p2); } diff --git a/ui/builders/straight.h b/ui/builders/straight.h index 1cde2b0..cf99a1d 100644 --- a/ui/builders/straight.h +++ b/ui/builders/straight.h @@ -9,7 +9,7 @@ class BuilderStraight : public EditNetwork::Builder { void click(Network * network, const GeoData * geoData, const SDL_MouseButtonEvent & e, const Ray & ray) override; void move(Network * network, const GeoData * geoData, const SDL_MouseMotionEvent & e, const Ray & ray) override; - void create(Network * network, glm::vec3 p1, glm::vec3 p2) const; + void create(Network * network, Position3D p1, Position3D p2) const; - std::optional<glm::vec3> p1; + std::optional<Position3D> p1; }; diff --git a/ui/editNetwork.h b/ui/editNetwork.h index eb1677e..e1aaa61 100644 --- a/ui/editNetwork.h +++ b/ui/editNetwork.h @@ -21,7 +21,7 @@ public: void render(const SceneShader &) const override; void render(const UIShader & shader, const UIComponent::Position & pos) const override; - using NetworkClickPos = std::variant<glm::vec3, Node::Ptr>; + using NetworkClickPos = std::variant<Position3D, Node::Ptr>; class Builder { public: diff --git a/ui/font.cpp b/ui/font.cpp index 108f905..ebd856d 100644 --- a/ui/font.cpp +++ b/ui/font.cpp @@ -14,6 +14,7 @@ #include <unicode.h> #include <util.h> #include <utility> + // IWYU pragma: no_forward_declare FT_LibraryRec_ std::string @@ -31,6 +31,7 @@ public: glm::ivec2 bearing; long advance; }; + struct FontTexture { glTexture texture; unsigned int used; diff --git a/ui/gameMainSelector.cpp b/ui/gameMainSelector.cpp index 081718d..a451ee1 100644 --- a/ui/gameMainSelector.cpp +++ b/ui/gameMainSelector.cpp @@ -8,14 +8,16 @@ #include <game/selectable.h> #include <game/worldobject.h> // IWYU pragma: keep #include <gfx/gl/camera.h> +#include <math.h> #include <optional> #include <span> #include <stream_support.h> #include <typeinfo> #include <vector> -GameMainSelector::GameMainSelector(const Camera * c, glm::vec2 size) : UIComponent {{{}, size}}, camera {c} { } -constexpr glm::vec2 TargetPos {5, 45}; +GameMainSelector::GameMainSelector(const Camera * c, ScreenAbsCoord size) : UIComponent {{{}, size}}, camera {c} { } + +constexpr ScreenAbsCoord TargetPos {5, 45}; void GameMainSelector::render(const UIShader & shader, const Position & parentPos) const @@ -40,7 +42,7 @@ bool GameMainSelector::handleInput(const SDL_Event & e, const Position & parentPos) { const auto getRay = [this](const auto & e) { - const auto mouse = glm::vec2 {e.x, e.y} / position.size; + const auto mouse = ScreenRelCoord {e.x, e.y} / position.size; return camera->unProject(mouse); }; if (target) { @@ -71,8 +73,8 @@ GameMainSelector::handleInput(const SDL_Event & e, const Position & parentPos) void GameMainSelector::defaultClick(const Ray & ray) { - glm::vec2 baryPos {}; - float distance; + Position2D baryPos {}; + float distance {}; if (const auto selected = gameState->world.applyOne<Selectable>(&Selectable::intersectRay, ray, &baryPos, &distance); diff --git a/ui/gameMainSelector.h b/ui/gameMainSelector.h index 98cdf53..88db34b 100644 --- a/ui/gameMainSelector.h +++ b/ui/gameMainSelector.h @@ -1,6 +1,7 @@ #pragma once #include "SDL_events.h" +#include "config/types.h" #include "special_members.h" #include "uiComponent.h" #include "worldOverlay.h" @@ -26,7 +27,7 @@ public: virtual void render(const SceneShader &) const; }; - GameMainSelector(const Camera * c, glm::vec2 size); + GameMainSelector(const Camera * c, ScreenAbsCoord size); void render(const UIShader & shader, const Position & pos) const override; void render(const SceneShader & shader) const override; diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index 6981c54..d71c74a 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -31,8 +31,8 @@ public: GameMainWindow::GameMainWindow(size_t w, size_t h) : Window {w, h, "I Like Trains", SDL_WINDOW_OPENGL}, SceneRenderer {Window::size, 0} { - uiComponents.create<ManualCameraController>(glm::vec2 {315000, 495000}); - auto gms = uiComponents.create<GameMainSelector>(&camera, glm::vec2 {w, h}); + uiComponents.create<ManualCameraController>(glm::vec2 {315'000'000, 495'000'000}); + auto gms = uiComponents.create<GameMainSelector>(&camera, ScreenAbsCoord {w, h}); uiComponents.create<GameMainToolbar>(gms.get()); } @@ -48,6 +48,7 @@ GameMainWindow::render() const SceneRenderer::render(*this); Window::render(); } + void GameMainWindow::content(const SceneShader & shader) const { @@ -59,17 +60,20 @@ GameMainWindow::content(const SceneShader & shader) const gameState->world.apply<Renderable>(&Renderable::render, shader); uiComponents.apply<WorldOverlay>(&WorldOverlay::render, shader); } + void GameMainWindow::environment(const SceneShader & s, const SceneRenderer & r) const { // default for now SceneProvider::environment(s, r); } + void GameMainWindow::lights(const SceneShader & shader) const { gameState->world.apply<Renderable>(&Renderable::lights, shader); } + void GameMainWindow::shadows(const ShadowMapper & shadowMapper) const { diff --git a/ui/iconButton.h b/ui/iconButton.h index 6ac9317..0afe92d 100644 --- a/ui/iconButton.h +++ b/ui/iconButton.h @@ -10,6 +10,7 @@ class UIShader; union SDL_Event; static const constexpr glm::vec2 ICON_SIZE {32.F, 32.F}; + class IconButton : public UIComponent { public: IconButton(const std::string & icon, glm::vec2 position, UIEvent click); diff --git a/ui/manualCameraController.cpp b/ui/manualCameraController.cpp index 8e52b0e..f6993a8 100644 --- a/ui/manualCameraController.cpp +++ b/ui/manualCameraController.cpp @@ -59,12 +59,12 @@ ManualCameraController::handleInput(const SDL_Event & e, const Position &) pitch = std::clamp(pitch - 0.01F * static_cast<float>(e.motion.yrel), 0.1F, half_pi); } else { - focus += rotate_flat(-direction) * glm::vec2 {-e.motion.xrel, e.motion.yrel}; + focus += rotate_flat(-direction) * (Position2D {-e.motion.xrel, e.motion.yrel} * dist / 2.0F); } } return true; case SDL_MOUSEWHEEL: - dist = std::clamp(dist - static_cast<float>(e.wheel.y) * 4.F, 5.F, 200.F); + dist = std::clamp(dist - static_cast<float>(e.wheel.y) * 400.F, 5.F, 200000.F); break; } return false; diff --git a/ui/manualCameraController.h b/ui/manualCameraController.h index d15fa76..1efaee1 100644 --- a/ui/manualCameraController.h +++ b/ui/manualCameraController.h @@ -11,7 +11,7 @@ class Camera; class ManualCameraController : public CameraController, public UIComponent { public: - explicit ManualCameraController(glm::vec2 f) : UIComponent {{}}, focus {f} { } + explicit ManualCameraController(Position2D f) : UIComponent {{}}, focus {f} { } bool handleInput(const SDL_Event & e, const Position &) override; void render(const UIShader &, const Position & parentPos) const override; @@ -20,7 +20,7 @@ public: private: bool ctrl {false}, mrb {false}; - glm::vec2 focus; + Position2D focus; float direction {quarter_pi}; - float dist {40}, pitch {quarter_pi}; + float dist {4000}, pitch {quarter_pi}; }; diff --git a/ui/modeHelper.h b/ui/modeHelper.h index 77707f2..d20f2db 100644 --- a/ui/modeHelper.h +++ b/ui/modeHelper.h @@ -4,6 +4,7 @@ union SDL_Event; enum ModeSecondClick { Unset, Reset, NoAction }; + template<typename Target, ModeSecondClick msc = ModeSecondClick::Unset> class Mode { public: explicit Mode(Target & t) : target {t} { } diff --git a/ui/text.cpp b/ui/text.cpp index d24c268..b776b90 100644 --- a/ui/text.cpp +++ b/ui/text.cpp @@ -12,6 +12,7 @@ #include <utility> const std::filesystem::path font {"/usr/share/fonts/hack/Hack-Regular.ttf"}; + Text::Text(std::string_view s, Position pos, glm::vec3 c) : UIComponent {pos}, colour {c} { for (const auto & textureQuads : @@ -25,6 +25,7 @@ private: glVertexArray vao; glBuffer vbo; }; + std::vector<Model> models; glm::vec3 colour; }; diff --git a/ui/uiComponent.cpp b/ui/uiComponent.cpp index e480fbc..aa4838d 100644 --- a/ui/uiComponent.cpp +++ b/ui/uiComponent.cpp @@ -20,6 +20,7 @@ UIComponent::Position::operator&(const glm::vec2 & pos) const { return (pos.x >= origin.x && pos.y >= origin.y && pos.x < origin.x + size.x && pos.y < origin.y + size.y); } + bool UIComponent::Position::operator&(const SDL_MouseButtonEvent & pos) const { diff --git a/ui/uiComponent.h b/ui/uiComponent.h index 75c2284..71d2659 100644 --- a/ui/uiComponent.h +++ b/ui/uiComponent.h @@ -18,6 +18,7 @@ public: bool operator&(const SDL_MouseButtonEvent &) const; bool operator&(const glm::vec2 &) const; }; + explicit UIComponent(Position); virtual ~UIComponent() = default; diff --git a/ui/uiComponentPlacer.cpp b/ui/uiComponentPlacer.cpp index 368e772..5e645d8 100644 --- a/ui/uiComponentPlacer.cpp +++ b/ui/uiComponentPlacer.cpp @@ -16,6 +16,7 @@ UIComponentPlacer::next(glm::vec2 size) max = std::max(max, size[1 - axis]); return n; } + glm::vec2 UIComponentPlacer::getLimit() const { diff --git a/ui/window.h b/ui/window.h index 369228a..8f2b70b 100644 --- a/ui/window.h +++ b/ui/window.h @@ -31,11 +31,12 @@ public: protected: virtual void render() const; + struct GLInitHelper { GLInitHelper(); }; - const glm::ivec2 size; + const ScreenAbsCoord size; SDL_WindowPtr m_window; SDL_GLContextPtr glContext; GLInitHelper glInithelper; |