Support 3D text in painter
This commit is contained in:
parent
90ece36fd5
commit
dbc429eaa7
2 changed files with 75 additions and 69 deletions
|
|
@ -60,6 +60,7 @@ namespace psemek::gfx
|
|||
// 3D
|
||||
void axes(geom::point<float, 3> const & p, float length, float width);
|
||||
void sphere(geom::point<float, 3> const & p, float radius, color const & c, int quality = 6);
|
||||
void text3d(geom::point<float, 3> const & p, std::string_view str, text_options const & opts, geom::matrix<float, 3, 3> const & transform);
|
||||
|
||||
// Should be called on each frame
|
||||
void render(geom::matrix<float, 4, 4> const & transform);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ namespace psemek::gfx
|
|||
|
||||
struct text_vertex
|
||||
{
|
||||
geom::point<float, 2> position;
|
||||
geom::point<float, 3> position;
|
||||
color_rgba color;
|
||||
geom::point<std::uint16_t, 2> texcoord;
|
||||
};
|
||||
|
|
@ -108,7 +108,7 @@ namespace psemek::gfx
|
|||
impl()
|
||||
{
|
||||
mesh.setup<geom::vector<float, 3>, gfx::normalized<color_rgba>>();
|
||||
text_mesh.setup<geom::point<float, 2>, gfx::normalized<color_rgba>, geom::point<std::uint16_t, 2>>();
|
||||
text_mesh.setup<geom::point<float, 3>, gfx::normalized<color_rgba>, geom::point<std::uint16_t, 2>>();
|
||||
|
||||
util::memory_istream font_data(resource::font_9x12);
|
||||
font_texture.load(gfx::read_pbm(font_data));
|
||||
|
|
@ -228,73 +228,7 @@ namespace psemek::gfx
|
|||
|
||||
void painter::text(geom::point<float, 2> const & p, std::string_view str, text_options const & opts)
|
||||
{
|
||||
auto const size = text_size(str, opts.f, opts.scale);
|
||||
|
||||
auto pen = p;
|
||||
|
||||
switch (opts.x)
|
||||
{
|
||||
case x_align::left:
|
||||
break;
|
||||
case x_align::center:
|
||||
pen[0] -= size[0] / 2.f;
|
||||
break;
|
||||
case x_align::right:
|
||||
pen[0] -= size[0];
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown x alignment");
|
||||
}
|
||||
|
||||
switch (opts.y)
|
||||
{
|
||||
case y_align::top:
|
||||
break;
|
||||
case y_align::center:
|
||||
pen[1] -= size[1] / 2.f;
|
||||
break;
|
||||
case y_align::bottom:
|
||||
pen[1] -= size[1];
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown y alignment");
|
||||
}
|
||||
|
||||
geom::vector<float, 2> const sx = {9.f * opts.scale, 0.f};
|
||||
geom::vector<float, 2> const sy = {0.f, 12.f * opts.scale};
|
||||
|
||||
auto to_texcoord = [](int tx, int ty, int ix, int iy)
|
||||
{
|
||||
return geom::point<std::uint16_t, 2>{ tx * 11 + (ix == 0 ? 1 : 10), ty * 14 + (iy == 0 ? 1 : 13) };
|
||||
};
|
||||
|
||||
for (char c : str)
|
||||
{
|
||||
// Guard against unsigned char
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
if ((c < 32) || (c >= 128)) c = '?';
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
int ty = (c - 32) / 16;
|
||||
int tx = (c - 32) % 16;
|
||||
|
||||
std::uint32_t const base = impl().text_vertices.size();
|
||||
|
||||
impl().text_vertices.push_back({pen, opts.c, to_texcoord(tx, ty, 0, 0)});
|
||||
impl().text_vertices.push_back({pen + sx, opts.c, to_texcoord(tx, ty, 1, 0)});
|
||||
impl().text_vertices.push_back({pen + sy, opts.c, to_texcoord(tx, ty, 0, 1)});
|
||||
impl().text_vertices.push_back({pen + sx + sy, opts.c, to_texcoord(tx, ty, 1, 1)});
|
||||
|
||||
impl().text_indices.push_back(base + 0);
|
||||
impl().text_indices.push_back(base + 1);
|
||||
impl().text_indices.push_back(base + 3);
|
||||
impl().text_indices.push_back(base + 0);
|
||||
impl().text_indices.push_back(base + 3);
|
||||
impl().text_indices.push_back(base + 2);
|
||||
|
||||
pen += sx;
|
||||
}
|
||||
text3d(geom::point{p[0], p[1], 0.f}, str, opts, geom::matrix<float, 3, 3>::identity());
|
||||
}
|
||||
|
||||
void painter::axes(geom::point<float, 3> const & p, float length, float width)
|
||||
|
|
@ -422,6 +356,77 @@ namespace psemek::gfx
|
|||
}
|
||||
}
|
||||
|
||||
void painter::text3d(geom::point<float, 3> const & p, std::string_view str, text_options const & opts, geom::matrix<float, 3, 3> const & t)
|
||||
{
|
||||
auto const size = text_size(str, opts.f, opts.scale);
|
||||
|
||||
geom::vector<float, 3> pen { 0.f, 0.f, 0.f };
|
||||
|
||||
switch (opts.x)
|
||||
{
|
||||
case x_align::left:
|
||||
break;
|
||||
case x_align::center:
|
||||
pen[0] -= size[0] / 2.f;
|
||||
break;
|
||||
case x_align::right:
|
||||
pen[0] -= size[0];
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown x alignment");
|
||||
}
|
||||
|
||||
switch (opts.y)
|
||||
{
|
||||
case y_align::top:
|
||||
break;
|
||||
case y_align::center:
|
||||
pen[1] -= size[1] / 2.f;
|
||||
break;
|
||||
case y_align::bottom:
|
||||
pen[1] -= size[1];
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown y alignment");
|
||||
}
|
||||
|
||||
geom::vector<float, 3> const sx = {9.f * opts.scale, 0.f, 0.f};
|
||||
geom::vector<float, 3> const sy = {0.f, 12.f * opts.scale, 0.f};
|
||||
|
||||
auto to_texcoord = [](int tx, int ty, int ix, int iy)
|
||||
{
|
||||
return geom::point<std::uint16_t, 2>{ tx * 11 + (ix == 0 ? 1 : 10), ty * 14 + (iy == 0 ? 1 : 13) };
|
||||
};
|
||||
|
||||
for (char c : str)
|
||||
{
|
||||
// Guard against unsigned char
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
if ((c < 32) || (c >= 128)) c = '?';
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
int ty = (c - 32) / 16;
|
||||
int tx = (c - 32) % 16;
|
||||
|
||||
std::uint32_t const base = impl().text_vertices.size();
|
||||
|
||||
impl().text_vertices.push_back({p + t * pen, opts.c, to_texcoord(tx, ty, 0, 0)});
|
||||
impl().text_vertices.push_back({p + t * (pen + sx), opts.c, to_texcoord(tx, ty, 1, 0)});
|
||||
impl().text_vertices.push_back({p + t * (pen + sy), opts.c, to_texcoord(tx, ty, 0, 1)});
|
||||
impl().text_vertices.push_back({p + t * (pen + sx + sy), opts.c, to_texcoord(tx, ty, 1, 1)});
|
||||
|
||||
impl().text_indices.push_back(base + 0);
|
||||
impl().text_indices.push_back(base + 1);
|
||||
impl().text_indices.push_back(base + 3);
|
||||
impl().text_indices.push_back(base + 0);
|
||||
impl().text_indices.push_back(base + 3);
|
||||
impl().text_indices.push_back(base + 2);
|
||||
|
||||
pen += sx;
|
||||
}
|
||||
}
|
||||
|
||||
void painter::render(geom::matrix<float, 4, 4> const & transform)
|
||||
{
|
||||
impl().mesh.load(impl().vertices, impl().indices, gl::TRIANGLES, gl::STREAM_DRAW);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue