diff options
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; |