Add axes & sphere drawing for gfx::painter

This commit is contained in:
Nikita Lisitsa 2020-08-31 09:48:01 +03:00
parent cf6a8e98eb
commit 78fd6db86c
3 changed files with 131 additions and 0 deletions

View file

@ -53,9 +53,14 @@ namespace psemek::gfx
void circle(geom::point<float, 2> const & center, float radius, color const & c);
void line(geom::point<float, 2> const & p0, geom::point<float, 2> const & p1, float width, color const & c, bool smooth = true);
// 2D text
geom::vector<float, 2> text_size(std::string_view str, font f = font::font_9x12, float scale = 1.f);
void text(geom::point<float, 2> const & p, std::string_view str, text_options const & opts);
// 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);
// Should be called on each frame
void render(geom::matrix<float, 4, 4> const & transform);

View file

@ -292,6 +292,131 @@ namespace psemek::gfx
}
}
void painter::axes(geom::point<float, 3> const & p, float length, float width)
{
geom::vector<float, 3> const d[3]
{
{ 1.f, 0.f, 0.f },
{ 0.f, 1.f, 0.f },
{ 0.f, 0.f, 1.f },
};
color const c[3]
{
{ 255, 0, 0, 255 },
{ 0, 255, 0, 255 },
{ 0, 0, 255, 255 },
};
for (int i = 0; i < 3; ++i)
{
int j = (i + 1) % 3;
int k = (i + 2) % 3;
std::uint32_t const base = impl().vertices.size();
impl().vertices.push_back({p + d[i] * length, c[i]});
impl().vertices.push_back({p + d[j] * width, c[i]});
impl().vertices.push_back({p + d[k] * width, c[i]});
impl().vertices.push_back({p - d[j] * width, c[i]});
impl().vertices.push_back({p - d[k] * width, c[i]});
impl().indices.push_back(base + 0);
impl().indices.push_back(base + 1);
impl().indices.push_back(base + 2);
impl().indices.push_back(base + 0);
impl().indices.push_back(base + 2);
impl().indices.push_back(base + 3);
impl().indices.push_back(base + 0);
impl().indices.push_back(base + 3);
impl().indices.push_back(base + 4);
impl().indices.push_back(base + 0);
impl().indices.push_back(base + 4);
impl().indices.push_back(base + 1);
}
std::uint32_t const base = impl().vertices.size();
color const white {255, 255, 255, 255};
impl().vertices.push_back({p - d[0] * width, white});
impl().vertices.push_back({p - d[1] * width, white});
impl().vertices.push_back({p - d[2] * width, white});
impl().indices.push_back(base + 0);
impl().indices.push_back(base + 2);
impl().indices.push_back(base + 1);
}
void painter::sphere(geom::point<float, 3> const & p, float radius, color const & c, int quality)
{
std::uint32_t const base = impl().vertices.size();
impl().vertices.push_back({p - geom::vector{0.f, 0.f, radius}, c});
impl().vertices.push_back({p + geom::vector{0.f, 0.f, radius}, c});
auto const ray = [](float ax, float ay)
{
return geom::vector{std::cos(ax) * std::cos(ay), std::sin(ax) * std::cos(ay), std::sin(ay)};
};
for (int y = - quality + 1; y < quality; ++y)
{
for (int x = 0; x < quality * 4; ++x)
{
float ax = (x * geom::pi) / quality / 2.f;
float ay = (y * geom::pi) / quality / 2.f;
impl().vertices.push_back({p + radius * ray(ax, ay), c});
}
}
auto const index = [quality, base](int x, int y)
{
if (y == -quality)
return base;
if (y == quality)
return base + 1;
return static_cast<std::uint32_t>(2 + (y + quality - 1) * 4 * quality + x);
};
for (int x = 0; x < quality * 4; ++x)
{
int xx = (x + 1) % (quality * 4);
impl().indices.push_back(index(x, - quality + 1));
impl().indices.push_back(index(x, - quality));
impl().indices.push_back(index(xx, - quality + 1));
}
for (int y = - quality + 1; y + 1 < quality; ++y)
{
for (int x = 0; x < quality * 4; ++x)
{
int yy = y + 1;
int xx = (x + 1) % (quality * 4);
impl().indices.push_back(index(x, y));
impl().indices.push_back(index(xx, y));
impl().indices.push_back(index(xx, yy));
impl().indices.push_back(index(x, y));
impl().indices.push_back(index(xx, yy));
impl().indices.push_back(index(x, yy));
}
}
for (int x = 0; x < quality * 4; ++x)
{
int xx = (x + 1) % (quality * 4);
impl().indices.push_back(index(x, quality - 1));
impl().indices.push_back(index(xx, quality - 1));
impl().indices.push_back(index(x, quality));
}
}
void painter::render(geom::matrix<float, 4, 4> const & transform)
{
impl().mesh.load(impl().vertices, impl().indices, gl::STREAM_DRAW);

View file

@ -3,3 +3,4 @@
* Design ui system
* Add platform deployment tools
* Add color utilities
* gfx::painter should support normals & minimal lighting (maybe split into separate 2D & 3D painters?)