diff options
-rw-r--r-- | game/network/network.cpp | 1 | ||||
-rw-r--r-- | game/terrain.cpp | 2 | ||||
-rw-r--r-- | game/vehicles/railVehicleClass.cpp | 14 | ||||
-rw-r--r-- | lib/cache.cpp | 1 | ||||
-rw-r--r-- | lib/cache.h | 39 | ||||
-rw-r--r-- | lib/glContainer.h | 6 | ||||
-rw-r--r-- | lib/gl_traits.h | 8 | ||||
-rw-r--r-- | test/Jamfile.jam | 2 | ||||
-rw-r--r-- | test/test-glContainer.cpp | 9 | ||||
-rw-r--r-- | test/test-text.cpp | 19 | ||||
-rw-r--r-- | ui/editNetwork.cpp | 5 | ||||
-rw-r--r-- | ui/editNetwork.h | 2 | ||||
-rw-r--r-- | ui/font.cpp | 4 | ||||
-rw-r--r-- | ui/font.h | 5 | ||||
-rw-r--r-- | ui/gameMainSelector.cpp | 12 | ||||
-rw-r--r-- | ui/gameMainSelector.h | 3 | ||||
-rw-r--r-- | ui/text.cpp | 70 | ||||
-rw-r--r-- | ui/text.h | 20 |
18 files changed, 100 insertions, 122 deletions
diff --git a/game/network/network.cpp b/game/network/network.cpp index 500742c..b6c52b8 100644 --- a/game/network/network.cpp +++ b/game/network/network.cpp @@ -1,7 +1,6 @@ #include "network.h" #include "routeWalker.h" #include <array> -#include <cache.h> #include <game/network/link.h> #include <gfx/models/texture.h> #include <glm/gtx/intersect.hpp> diff --git a/game/terrain.cpp b/game/terrain.cpp index a4b6510..d2c8593 100644 --- a/game/terrain.cpp +++ b/game/terrain.cpp @@ -2,9 +2,7 @@ #include "game/geoData.h" #include "gfx/models/texture.h" #include <algorithm> -#include <cache.h> #include <cstddef> -#include <filesystem> #include <gfx/gl/sceneShader.h> #include <gfx/gl/shadowMapper.h> #include <gfx/image.h> diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index 5fd7580..34c1359 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -2,26 +2,12 @@ #include "gfx/gl/sceneShader.h" #include "gfx/gl/shadowMapper.h" #include "gfx/gl/vertexArrayObject.h" -#include "gfx/models/mesh.h" -#include "gfx/models/texture.h" -#include "stream_support.h" -#include <algorithm> #include <array> -#include <cache.h> -#include <cmath> -#include <cstddef> -#include <filesystem> #include <glm/glm.hpp> -#include <iterator> #include <lib/resource.h> #include <location.h> -#include <map> #include <maths.h> #include <memory> -#include <set> -#include <string> -#include <utility> -#include <vector> bool RailVehicleClass::persist(Persistence::PersistenceStore & store) diff --git a/lib/cache.cpp b/lib/cache.cpp deleted file mode 100644 index 05b26b0..0000000 --- a/lib/cache.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "cache.h" diff --git a/lib/cache.h b/lib/cache.h deleted file mode 100644 index f5fd227..0000000 --- a/lib/cache.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "special_members.h" -#include <functional> -#include <map> -#include <memory> -#include <tuple> - -template<typename Obj, typename... KeyParts> class Cache { -public: - using Ptr = std::shared_ptr<Obj>; - using Key = std::tuple<KeyParts...>; - - Cache() = default; - virtual ~Cache() = default; - DEFAULT_MOVE(Cache); - NO_COPY(Cache); - - [[nodiscard]] Ptr - get(const KeyParts &... keyparts) - { - auto key = std::tie(keyparts...); - if (auto e = cached.find(key); e != cached.end()) { - return e->second; - } - return cached.emplace(key, construct(keyparts...)).first->second; - } - - [[nodiscard]] virtual Ptr - construct(const KeyParts &... keyparts) const - { - return std::make_shared<Obj>(keyparts...); - } - -private: - std::map<Key, Ptr, std::less<>> cached; -}; - -// IWYU pragma: no_forward_declare Cache diff --git a/lib/glContainer.h b/lib/glContainer.h index ce88916..2ccc1c2 100644 --- a/lib/glContainer.h +++ b/lib/glContainer.h @@ -38,6 +38,12 @@ public: clear(); } + template<template<typename, typename...> typename C> explicit glContainer(const C<T> & src) + { + reserve(src.size()); + std::copy(src.begin(), src.end(), std::back_inserter(*this)); + } + DEFAULT_MOVE_NO_COPY(glContainer); [[nodiscard]] iterator diff --git a/lib/gl_traits.h b/lib/gl_traits.h index 14ac9d8..b3c6909 100644 --- a/lib/gl_traits.h +++ b/lib/gl_traits.h @@ -83,6 +83,14 @@ template<> struct gl_traits<glm::uint32> : public gl_traits_integer { template<typename T, std::size_t S> struct gl_traits<std::array<T, S>> : public gl_traits<T> { static constexpr GLint size {S * gl_traits<T>::size}; + static constexpr auto vertexAttribFunc { + [](GLuint index, GLint, GLenum type, GLsizei stride, const void * pointer) -> GLuint { + const auto base = static_cast<const T *>(pointer); + for (GLuint e = 0; e < S; e++) { + glVertexAttribPointer(index + e, gl_traits<T>::size, type, GL_FALSE, stride, base + e); + } + return S; + }}; }; template<glm::length_t L, typename T, glm::qualifier Q> struct gl_traits<glm::vec<L, T, Q>> : public gl_traits<T> { diff --git a/test/Jamfile.jam b/test/Jamfile.jam index c109051..733ef05 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -49,7 +49,7 @@ run test-lib.cpp ; run test-geoData.cpp : -- : fixtures/height/SD19.asc : <library>test ; run test-network.cpp : : : <library>test ; run test-persistence.cpp : -- : [ sequence.insertion-sort [ glob-tree $(fixtures)/json : *.json ] ] : <library>test ; -run test-text.cpp : : : <library>test ; +run test-text.cpp : -- : test-glContainer : <library>test ; run test-enumDetails.cpp ; run test-render.cpp : -- : test-assetFactory : <library>test ; run test-glContextBhvr.cpp ; diff --git a/test/test-glContainer.cpp b/test/test-glContainer.cpp index 0597470..ccf3b90 100644 --- a/test/test-glContainer.cpp +++ b/test/test-glContainer.cpp @@ -305,6 +305,15 @@ BOOST_AUTO_TEST_CASE(iter_compare) BOOST_AUTO_TEST_SUITE_END(); +BOOST_AUTO_TEST_CASE(create_copy_source, *boost::unit_test::timeout(1)) +{ + const std::vector src {4, 6, 2, 4, 6, 0}; + glContainer dst {src}; + static_assert(std::is_same_v<decltype(src)::value_type, decltype(dst)::value_type>); + dst.unmap(); + BOOST_CHECK_EQUAL_COLLECTIONS(src.begin(), src.end(), dst.begin(), dst.end()); +} + struct C { int x; float y; diff --git a/test/test-text.cpp b/test/test-text.cpp index 166a6fa..f652670 100644 --- a/test/test-text.cpp +++ b/test/test-text.cpp @@ -6,10 +6,12 @@ #include <stream_support.h> #include "testMainWindow.h" +#include "testRenderOutput.h" #include "ui/applicationBase.h" +#include "ui/text.h" #include <array> +#include <gfx/models/texture.h> #include <glm/glm.hpp> -#include <span> #include <ui/font.h> #include <unicode.h> #include <vector> @@ -86,7 +88,7 @@ BOOST_DATA_TEST_CASE(initialize_chardata_A, static_assert(glm::vec2 {862, 0} / glm::vec2 {2048, 64} == glm::vec2 {0.4208984375, 0}); static_assert(glm::vec2 {866, 35} / glm::vec2 {2048, 64} == glm::vec2 {0.4228515625, 0.546875}); -BOOST_AUTO_TEST_CASE(render_text) +BOOST_AUTO_TEST_CASE(render_font) { constexpr std::string_view text {"I Like Trains"}; const auto spaces = static_cast<std::size_t>(std::count_if(text.begin(), text.end(), isspace)); @@ -112,6 +114,19 @@ BOOST_AUTO_TEST_CASE(render_text) } } +BOOST_AUTO_TEST_CASE(render_text) +{ + TestRenderOutput output; + glBindFramebuffer(GL_FRAMEBUFFER, output.output); + glViewport(0, 0, 640, 480); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + Text t {"I Like Trains", *this, {{10, 10}, {200, 40}}, {1, 1, 1}}; + UIShader s {640, 480}; + t.render(s, {}); + Texture::save(output.outImage, "/tmp/text.tga"); +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_CASE(stream_vec) diff --git a/ui/editNetwork.cpp b/ui/editNetwork.cpp index 7fbde32..ac2d93d 100644 --- a/ui/editNetwork.cpp +++ b/ui/editNetwork.cpp @@ -8,6 +8,7 @@ #include <gfx/gl/sceneShader.h> #include <gfx/models/texture.h> +const std::filesystem::path fontpath {"/usr/share/fonts/hack/Hack-Regular.ttf"}; constexpr const glm::u8vec4 TRANSPARENT_BLUE {30, 50, 255, 200}; EditNetwork::EditNetwork(Network * n) : @@ -17,7 +18,7 @@ EditNetwork::EditNetwork(Network * n) : {"ui/icon/network.png", mode.toggle<BuilderJoin>()}, {"ui/icon/network.png", mode.toggle<BuilderFreeExtend>()}, }, - blue {1, 1, &TRANSPARENT_BLUE} + blue {1, 1, &TRANSPARENT_BLUE}, font {fontpath, 15} { } @@ -66,7 +67,7 @@ void EditNetwork::render(const UIShader & shader, const UIComponent::Position & parentPos) const { if (builder) { - Text {builder->hint(), {{50, 10}, {0, 15}}, {1, 1, 0}}.render(shader, parentPos); + Text {builder->hint(), font, {{50, 10}, {0, 15}}, {1, 1, 0}}.render(shader, parentPos); } builderToolbar.render(shader, parentPos); } diff --git a/ui/editNetwork.h b/ui/editNetwork.h index 23dcf43..ec06fa7 100644 --- a/ui/editNetwork.h +++ b/ui/editNetwork.h @@ -7,7 +7,6 @@ #include <game/gamestate.h> #include <game/network/network.h> #include <gfx/models/texture.h> -#include <optional> template<typename> class Ray; @@ -43,6 +42,7 @@ private: Mode<Builder::Ptr, ModeSecondClick::NoAction> mode {builder}; Toolbar builderToolbar; Texture blue; + const Font font; }; template<typename T> class EditNetworkOf : public EditNetwork { diff --git a/ui/font.cpp b/ui/font.cpp index 305e0f3..b6669b0 100644 --- a/ui/font.cpp +++ b/ui/font.cpp @@ -1,6 +1,5 @@ #include "font.h" #include <algorithm> -#include <cache.h> #include <cctype> #include <ft2build.h> #include FT_FREETYPE_H @@ -60,8 +59,6 @@ using Face = glRef<FT_Face, }, FT_Done_Face>; -Cache<Font, std::filesystem::path, unsigned int> Font::cachedFontRenderings; - Font::Font(std::filesystem::path p, unsigned s) : path {std::move(p)}, size {getTextureSize(s)} { generateChars(BASIC_CHARS); @@ -77,6 +74,7 @@ Font::generateChars(const utf8_string_view chars) const if (charsData.find(codepoint) == charsData.end()) { if (!ft) { ft.emplace(); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); } if (!face) { face.emplace(*ft, path.c_str()); @@ -1,22 +1,17 @@ #pragma once #include <array> -#include <cache.h> #include <cstddef> -#include <cstdint> #include <filesystem> #include <glArrays.h> #include <glad/gl.h> #include <glm/glm.hpp> #include <map> -#include <string_view> #include <unicode.h> #include <vector> class Font { public: - static Cache<Font, std::filesystem::path, unsigned int> cachedFontRenderings; - Font(std::filesystem::path path, unsigned int height); using Quad = std::array<glm::vec4, 4>; diff --git a/ui/gameMainSelector.cpp b/ui/gameMainSelector.cpp index a577838..5bef48d 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, ScreenAbsCoord size) : UIComponent {{{}, size}}, camera {c} { } +const std::filesystem::path fontpath {"/usr/share/fonts/hack/Hack-Regular.ttf"}; + +GameMainSelector::GameMainSelector(const Camera * c, ScreenAbsCoord size) : + UIComponent {{{}, size}}, camera {c}, font {fontpath, 15} +{ +} constexpr ScreenAbsCoord TargetPos {5, 45}; @@ -26,7 +28,7 @@ GameMainSelector::render(const UIShader & shader, const Position & parentPos) co target->render(shader, parentPos + position + TargetPos); } if (!clicked.empty()) { - Text {clicked, {{50, 10}, {0, 15}}, {1, 1, 0}}.render(shader, parentPos); + Text {clicked, font, {{50, 10}, {0, 15}}, {1, 1, 0}}.render(shader, parentPos); } } diff --git a/ui/gameMainSelector.h b/ui/gameMainSelector.h index cc30707..ccf0fa0 100644 --- a/ui/gameMainSelector.h +++ b/ui/gameMainSelector.h @@ -2,7 +2,7 @@ #include "SDL_events.h" #include "config/types.h" -#include "special_members.h" +#include "font.h" #include "uiComponent.h" #include "worldOverlay.h" #include <glm/glm.hpp> @@ -40,5 +40,6 @@ public: private: const Camera * camera; + const Font font; std::string clicked; }; diff --git a/ui/text.cpp b/ui/text.cpp index b776b90..5675061 100644 --- a/ui/text.cpp +++ b/ui/text.cpp @@ -1,44 +1,48 @@ #include "text.h" #include "font.h" #include "gfx/gl/uiShader.h" +#include "gfx/gl/vertexArrayObject.h" #include "uiComponent.h" #include <array> -#include <cache.h> -#include <filesystem> +#include <collections.h> #include <glArrays.h> #include <glm/gtc/type_ptr.hpp> -#include <map> -#include <memory> +#include <maths.h> +#include <numeric> #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} +Text::Text(std::string_view s, const Font & font, Position pos, glm::vec3 c) : + UIComponent {pos}, colour {c}, font {font} { - for (const auto & textureQuads : - Font::cachedFontRenderings.get(font, static_cast<unsigned int>(pos.size.y))->render(s)) { - auto & rendering - = models.emplace_back(textureQuads.first, static_cast<GLsizei>(6 * textureQuads.second.size())); - glBindVertexArray(rendering.vao); - - glBindBuffer(GL_ARRAY_BUFFER, rendering.vbo); - std::vector<glm::vec4> vertices; - vertices.reserve(6 * textureQuads.second.size()); - for (const auto & quad : textureQuads.second) { - for (auto offset = 0U; offset < 3; offset += 2) { - for (auto vertex = 0U; vertex < 3; vertex += 1) { - vertices.emplace_back(quad[(vertex + offset) % 4] + glm::vec4 {position.origin, 0, 0}); - } - } - }; - glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(glm::vec4)) * rendering.count, - glm::value_ptr(vertices.front()), GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), nullptr); + VertexArrayObject {vao}.addAttribs<Font::Quad::value_type>(quads.bufferName(), 0); + operator=(s); +} - glBindVertexArray(0); +Text & +Text::operator=(const std::string_view s) +{ + auto tquads = font.render(s); + models.resize(tquads.size()); + const auto glyphCount = std::accumulate(tquads.begin(), tquads.end(), size_t {}, [](auto && init, const auto & q) { + return init += q.second.size(); + }); + quads.resize(glyphCount); + GLint current = 0; + auto model = models.begin(); + auto quad = quads.begin(); + for (const auto & [texture, fquads] : tquads) { + model->first = texture; + model->second = {fquads.size() * 4, current * 4}; + current += static_cast<GLint>(fquads.size()); + model++; + quad = std::transform(fquads.begin(), fquads.end(), quad, [this](const Font::Quad & q) { + return q * [this](const glm::vec4 & corner) { + return corner + glm::vec4 {this->position.origin, 0, 0}; + }; + }); } + quads.unmap(); + return *this; } void @@ -46,10 +50,10 @@ Text::render(const UIShader & shader, const Position &) const { shader.text.use(colour); glActiveTexture(GL_TEXTURE0); + glBindVertexArray(vao); for (const auto & m : models) { - glBindTexture(GL_TEXTURE_2D, m.texture); - glBindVertexArray(m.vao); - glDrawArrays(GL_TRIANGLES, 0, m.count); + glBindTexture(GL_TEXTURE_2D, m.first); + glDrawArrays(GL_QUADS, m.second.second, m.second.first); } glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, 0); @@ -60,5 +64,3 @@ Text::handleInput(const SDL_Event &, const Position &) { return false; } - -Text::Model::Model(GLuint t, GLsizei c) : texture {t}, count {c} { } @@ -1,31 +1,29 @@ #pragma once +#include "font.h" +#include "glContainer.h" #include "uiComponent.h" #include <glArrays.h> #include <glad/gl.h> #include <glm/glm.hpp> #include <string_view> -#include <vector> class UIShader; union SDL_Event; class Text : public UIComponent { public: - Text(std::string_view s, Position, glm::vec3 colour); + Text(std::string_view s, const Font &, Position, glm::vec3 colour); void render(const UIShader &, const Position & parentPos) const override; bool handleInput(const SDL_Event &, const Position & parentPos) override; -private: - struct Model { - Model(GLuint, GLsizei); - GLuint texture; - GLsizei count; - glVertexArray vao; - glBuffer vbo; - }; + Text & operator=(const std::string_view s); - std::vector<Model> models; +private: + std::vector<std::pair<GLuint, std::pair<GLsizei, GLint>>> models; + glContainer<Font::Quad> quads; + glVertexArray vao; glm::vec3 colour; + const Font & font; }; |