32 #include "eng3d/font_sdf.hpp"
33 #include "eng3d/state.hpp"
34 #include "eng3d/texture.hpp"
35 #include "eng3d/primitive.hpp"
36 #include "eng3d/shader.hpp"
37 #include "eng3d/state.hpp"
38 #include "eng3d/camera.hpp"
39 #include "eng3d/log.hpp"
42 : advance{ _advance },
43 atlas_bounds{ _atlas_bounds },
44 plane_bounds{ _plane_bounds }
51 sphere_shader = std::make_unique<Eng3D::OpenGL::Program>();
54 sphere_shader->attach_shader(vs_shader);
55 sphere_shader->attach_shader(*s.builtin_shaders[
"fs_font_sdf"].get());
56 sphere_shader->link();
58 flat_shader = std::make_unique<Eng3D::OpenGL::Program>();
60 flat_shader->attach_shader(*s.builtin_shaders[
"vs_font_sdf"].get());
61 flat_shader->attach_shader(*s.builtin_shaders[
"fs_font_sdf"].get());
66 mipmap_options.
min_filter = Eng3D::TextureOptions::Filter::LINEAR;
67 mipmap_options.
mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
68 mipmap_options.
wrap_s = Eng3D::TextureOptions::Wrap::CLAMP_TO_EDGE;
69 mipmap_options.
wrap_t = Eng3D::TextureOptions::Wrap::CLAMP_TO_EDGE;
72 auto asset = s.package_man.get_unique(filename +
".png");
73 atlas = s.tex_man.load(asset->abs_path, mipmap_options);
77 float advance, top, bottom, left, right;
79 std::ifstream glyph_data(s.package_man.get_unique(filename +
".csv")->abs_path);
80 if(glyph_data.is_open()) {
81 while(std::getline(glyph_data, line)) {
82 std::istringstream data(line);
83 data >> unicode >> buff;
84 data >> advance >> buff;
85 data >> left >> buff >> bottom >> buff >> right >> buff >> top >> buff;
87 data >> left >> buff >> bottom >> buff >> right >> buff >> top;
89 right /= atlas->width;
91 bottom /= atlas->height;
94 unicode_map.insert({ unicode, glyph });
101 constexpr T
bezier(
float t,
const T p0,
const T p1,
const T p2) {
102 return (1 - t) * ((1 - t) * p0 + t * p1) + t * ((1 - t) * p1 + t * p2);
105 std::unique_ptr<Eng3D::Label3D>
Eng3D::FontSDF::gen_text(
const std::string& text, glm::vec2 pmin, glm::vec2 pmax, glm::vec2 p0,
float width) {
106 assert(width > 0.f && width < 1.f);
107 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv_utf8_utf32;
108 std::u32string unicode_text = conv_utf8_utf32.from_bytes(text);
110 auto text_width = 0.f;
111 for(
const auto& character : unicode_text) {
112 if(!unicode_map.count(character))
continue;
113 const auto& glyph = unicode_map[character];
114 text_width += glyph.advance;
116 assert(text_width != 0.f);
118 glm::vec2 diff = (pmax - pmin) * (1.f - width);
121 float scale = glm::length(pmax - pmin) / text_width;
123 std::vector<glm::vec3> positions;
124 std::vector<glm::vec2> tex_coords;
126 for(
const auto& character : unicode_text) {
127 if(!unicode_map.count(character))
continue;
128 const auto& glyph = unicode_map.at(character);
133 glm::vec2 atlas_tl(glyph.atlas_bounds.left, glyph.atlas_bounds.bottom);
134 glm::vec2 atlas_bl(glyph.atlas_bounds.left, glyph.atlas_bounds.top);
135 glm::vec2 atlas_tr(glyph.atlas_bounds.right, glyph.atlas_bounds.bottom);
136 glm::vec2 atlas_br(glyph.atlas_bounds.right, glyph.atlas_bounds.top);
137 tex_coords.push_back(atlas_tl);
138 tex_coords.push_back(atlas_br);
139 tex_coords.push_back(atlas_bl);
140 tex_coords.push_back(atlas_tr);
141 tex_coords.push_back(atlas_br);
142 tex_coords.push_back(atlas_tl);
144 glm::vec2 plane_tl(glyph.plane_bounds.left, glyph.plane_bounds.top);
145 glm::vec2 plane_bl(glyph.plane_bounds.left, glyph.plane_bounds.bottom);
146 glm::vec2 plane_tr(glyph.plane_bounds.right, glyph.plane_bounds.top);
147 glm::vec2 plane_br(glyph.plane_bounds.right, glyph.plane_bounds.bottom);
149 const auto t0 = advance / text_width;
150 advance += glyph.advance;
151 glm::vec2 char_tl =
bezier(t0, pmin, p0, pmax) + plane_tl * scale;
152 glm::vec2 char_bl =
bezier(t0, pmin, p0, pmax) + plane_bl * scale;
153 glm::vec2 char_tr =
bezier(t0, pmin, p0, pmax) + plane_tr * scale;
154 glm::vec2 char_br =
bezier(t0, pmin, p0, pmax) + plane_br * scale;
156 positions.emplace_back(char_tl, 0.f);
157 positions.emplace_back(char_br, 0.f);
158 positions.emplace_back(char_bl, 0.f);
159 positions.emplace_back(char_tr, 0.f);
160 positions.emplace_back(char_br, 0.f);
161 positions.emplace_back(char_tl, 0.f);
163 return std::make_unique<Eng3D::Label3D>(
new Eng3D::TriangleList(positions, tex_coords), scale, glm::vec3(p0, 0.f));
166 #include "eng3d/map.hpp"
168 auto& shader = sphere ? *sphere_shader : *flat_shader;
171 shader.set_uniform(
"view", camera.
get_view());
173 shader.set_uniform(
"model", glm::mat4(1));
174 shader.set_texture(0,
"atlas", *atlas);
175 for(
auto& label : labels) {
176 if(label.get() ==
nullptr)
continue;
177 const auto size = label->size * (sphere ? 0.1f : 1.f);
178 shader.set_uniform(
"center", label->center.x, label->center.y);
179 shader.set_uniform(
"radius", Eng3D::GLOBE_RADIUS + 0.01f * size);
180 shader.set_uniform(
"px_range", size * 0.3f);
188 triangles{ _triangles }
glm::vec2 get_map_size() const
Get the size of the map.
virtual glm::mat4 get_view() const =0
Get the view matrix.
virtual glm::mat4 get_projection() const
Get the projection matrix.
static State & get_instance()
enum Eng3D::TextureOptions::Filter min_filter
enum Eng3D::TextureOptions::Wrap wrap_s
constexpr T bezier(float t, const T p0, const T p1, const T p2)
Quadratic bezier curve, p1 is control.
void draw(const std::vector< std::unique_ptr< Label3D >> &labels, const Eng3D::Camera &camera, bool sphere)
FontSDF(const std::string &filename)
std::unique_ptr< Eng3D::Label3D > gen_text(const std::string &text, glm::vec2 pmin, glm::vec2 pmax, glm::vec2 p0, float width)
Label3D(Eng3D::TriangleList *triangles, float size, glm::vec3 center)