summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--game/network/network.cpp1
-rw-r--r--game/terrain.cpp2
-rw-r--r--game/vehicles/railVehicleClass.cpp14
-rw-r--r--lib/cache.cpp1
-rw-r--r--lib/cache.h39
-rw-r--r--lib/glContainer.h6
-rw-r--r--lib/gl_traits.h8
-rw-r--r--test/Jamfile.jam2
-rw-r--r--test/test-glContainer.cpp9
-rw-r--r--test/test-text.cpp19
-rw-r--r--ui/editNetwork.cpp5
-rw-r--r--ui/editNetwork.h2
-rw-r--r--ui/font.cpp4
-rw-r--r--ui/font.h5
-rw-r--r--ui/gameMainSelector.cpp12
-rw-r--r--ui/gameMainSelector.h3
-rw-r--r--ui/text.cpp70
-rw-r--r--ui/text.h20
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());
diff --git a/ui/font.h b/ui/font.h
index 2f3337f..3254f80 100644
--- a/ui/font.h
+++ b/ui/font.h
@@ -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} { }
diff --git a/ui/text.h b/ui/text.h
index de2fe2e..31ed9a5 100644
--- a/ui/text.h
+++ b/ui/text.h
@@ -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;
};