Redesign gfx::mesh: stores primitive type, supports loading from pointers & simplices (deduces primitive type in the latter case)
This commit is contained in:
parent
5d44efa2ea
commit
8877f6dedd
2 changed files with 137 additions and 18 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <psemek/geom/vector.hpp>
|
#include <psemek/geom/vector.hpp>
|
||||||
#include <psemek/geom/point.hpp>
|
#include <psemek/geom/point.hpp>
|
||||||
|
#include <psemek/geom/simplex.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
@ -277,23 +278,75 @@ namespace psemek::gfx
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Vertex>
|
template <typename Vertex>
|
||||||
void load(std::vector<Vertex> const & vertices, GLenum usage = gl::STREAM_DRAW)
|
void load(Vertex const * vertices, std::size_t count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
||||||
{
|
{
|
||||||
if (sizeof(Vertex) != stride_)
|
if (sizeof(Vertex) != stride_)
|
||||||
throw std::runtime_error("Vertex size not equal to sum of attribute sizes");
|
throw std::runtime_error("Vertex size not equal to sum of attribute sizes");
|
||||||
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
switch (primitive_type)
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
{
|
||||||
|
case gl::LINES:
|
||||||
|
if ((count % 2) != 0) throw std::runtime_error("Vertex count for GL_LINES should be a multiple of 2");
|
||||||
|
break;
|
||||||
|
case gl::TRIANGLES:
|
||||||
|
if ((count % 3) != 0) throw std::runtime_error("Vertex count for GL_TRIANGLES should be a multiple of 3");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
count_ = vertices.size();
|
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
|
gl::BufferData(gl::ARRAY_BUFFER, count * sizeof(Vertex), vertices, usage);
|
||||||
|
|
||||||
|
count_ = count;
|
||||||
|
primitive_type_ = primitive_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(GLenum mode) const
|
template <typename Vertex>
|
||||||
|
void load(std::vector<Vertex> const & vertices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
load(vertices.data(), vertices.size(), primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vertex, std::size_t N>
|
||||||
|
void load(geom::simplex<Vertex, N> const * simplices, std::size_t count, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(geom::simplex<Vertex, N>) == (N + 1) * sizeof(Vertex));
|
||||||
|
|
||||||
|
GLenum primitive_type;
|
||||||
|
|
||||||
|
if constexpr (N == 0)
|
||||||
|
{
|
||||||
|
primitive_type = gl::POINTS;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 1)
|
||||||
|
{
|
||||||
|
primitive_type = gl::LINES;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 2)
|
||||||
|
{
|
||||||
|
primitive_type = gl::TRIANGLES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert("unknown primitive type");
|
||||||
|
}
|
||||||
|
|
||||||
|
load(reinterpret_cast<Vertex const *>(simplices), count * (N + 1), primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vertex, std::size_t N>
|
||||||
|
void load(std::vector<geom::simplex<Vertex, N>> const & simplices, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
load(simplices.data(), simplices.size(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() const
|
||||||
{
|
{
|
||||||
if (count_ == 0) return;
|
if (count_ == 0) return;
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
gl::BindVertexArray(array_);
|
||||||
gl::DrawArrays(mode, 0, count_);
|
gl::DrawArrays(primitive_type_, 0, count_);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLsizei count() const
|
GLsizei count() const
|
||||||
|
|
@ -301,6 +354,11 @@ namespace psemek::gfx
|
||||||
return count_;
|
return count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum primitive_type() const
|
||||||
|
{
|
||||||
|
return primitive_type_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint array_;
|
GLuint array_;
|
||||||
GLuint buffer_;
|
GLuint buffer_;
|
||||||
|
|
@ -309,6 +367,8 @@ namespace psemek::gfx
|
||||||
|
|
||||||
std::size_t stride_ = 0;
|
std::size_t stride_ = 0;
|
||||||
|
|
||||||
|
GLenum primitive_type_;
|
||||||
|
|
||||||
mesh(int);
|
mesh(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -337,26 +397,78 @@ namespace psemek::gfx
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Vertex, typename Index>
|
template <typename Vertex, typename Index>
|
||||||
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum usage = gl::STREAM_DRAW)
|
void load(Vertex const * vertices, std::size_t vertex_count, Index const * indices, std::size_t index_count, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
||||||
{
|
{
|
||||||
if (sizeof(Vertex) != stride_)
|
if (sizeof(Vertex) != stride_)
|
||||||
throw std::runtime_error("Vertex size not equal to sum of attribute sizes");
|
throw std::runtime_error("Vertex size not equal to sum of attribute sizes");
|
||||||
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
switch (primitive_type)
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage);
|
{
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_);
|
case gl::LINES:
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), usage);
|
if ((index_count % 2) != 0) throw std::runtime_error("Index count for GL_LINES should be a multiple of 2");
|
||||||
|
break;
|
||||||
|
case gl::TRIANGLES:
|
||||||
|
if ((index_count % 3) != 0) throw std::runtime_error("Index count for GL_TRIANGLES should be a multiple of 3");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
count_ = indices.size();
|
gl::BindBuffer(gl::ARRAY_BUFFER, buffer_);
|
||||||
|
gl::BufferData(gl::ARRAY_BUFFER, vertex_count * sizeof(Vertex), vertices, usage);
|
||||||
|
gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_);
|
||||||
|
gl::BufferData(gl::ARRAY_BUFFER, index_count * sizeof(Index), indices, usage);
|
||||||
|
|
||||||
|
count_ = index_count;
|
||||||
index_type_ = detail::gl_type_v<Index>;
|
index_type_ = detail::gl_type_v<Index>;
|
||||||
|
primitive_type_ = primitive_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(GLenum mode) const
|
template <typename Vertex, typename Index>
|
||||||
|
void load(std::vector<Vertex> const & vertices, std::vector<Index> const & indices, GLenum primitive_type, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
load(vertices.data(), vertices.size(), indices.data(), indices.size(), primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vertex, std::size_t N, typename Index>
|
||||||
|
void load(geom::simplex<Vertex, N> const * simplices, std::size_t simplex_count, Index const * indices, std::size_t index_count, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(geom::simplex<Vertex, N>) == (N + 1) * sizeof(Vertex));
|
||||||
|
|
||||||
|
GLenum primitive_type;
|
||||||
|
|
||||||
|
if constexpr (N == 0)
|
||||||
|
{
|
||||||
|
primitive_type = gl::POINTS;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 1)
|
||||||
|
{
|
||||||
|
primitive_type = gl::LINES;
|
||||||
|
}
|
||||||
|
else if constexpr (N == 2)
|
||||||
|
{
|
||||||
|
primitive_type = gl::TRIANGLES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert("unknown primitive type");
|
||||||
|
}
|
||||||
|
|
||||||
|
load(reinterpret_cast<Vertex const *>(simplices), simplex_count * (N + 1), indices, index_count, primitive_type, usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Vertex, std::size_t N, typename Index>
|
||||||
|
void load(std::vector<geom::simplex<Vertex, N>> const & simplices, std::vector<Index> const & indices, GLenum usage = gl::STREAM_DRAW)
|
||||||
|
{
|
||||||
|
load(simplices.data(), simplices.size(), indices.data(), indices.size(), usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() const
|
||||||
{
|
{
|
||||||
if (count_ == 0) return;
|
if (count_ == 0) return;
|
||||||
|
|
||||||
gl::BindVertexArray(array_);
|
gl::BindVertexArray(array_);
|
||||||
gl::DrawElements(mode, count_, index_type_, nullptr);
|
gl::DrawElements(primitive_type_, count_, index_type_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLsizei count() const
|
GLsizei count() const
|
||||||
|
|
@ -364,6 +476,11 @@ namespace psemek::gfx
|
||||||
return count_;
|
return count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum primitive_type() const
|
||||||
|
{
|
||||||
|
return primitive_type_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint array_;
|
GLuint array_;
|
||||||
GLuint buffer_;
|
GLuint buffer_;
|
||||||
|
|
@ -374,6 +491,8 @@ namespace psemek::gfx
|
||||||
|
|
||||||
std::size_t stride_ = 0;
|
std::size_t stride_ = 0;
|
||||||
|
|
||||||
|
GLenum primitive_type_;
|
||||||
|
|
||||||
indexed_mesh(int);
|
indexed_mesh(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -424,24 +424,24 @@ namespace psemek::gfx
|
||||||
|
|
||||||
void painter::render(geom::matrix<float, 4, 4> const & transform)
|
void painter::render(geom::matrix<float, 4, 4> const & transform)
|
||||||
{
|
{
|
||||||
impl().mesh.load(impl().vertices, impl().indices, gl::STREAM_DRAW);
|
impl().mesh.load(impl().vertices, impl().indices, gl::TRIANGLES, gl::STREAM_DRAW);
|
||||||
impl().vertices.clear();
|
impl().vertices.clear();
|
||||||
impl().indices.clear();
|
impl().indices.clear();
|
||||||
|
|
||||||
impl().text_mesh.load(impl().text_vertices, impl().text_indices, gl::STREAM_DRAW);
|
impl().text_mesh.load(impl().text_vertices, impl().text_indices, gl::TRIANGLES, gl::STREAM_DRAW);
|
||||||
impl().text_vertices.clear();
|
impl().text_vertices.clear();
|
||||||
impl().text_indices.clear();
|
impl().text_indices.clear();
|
||||||
|
|
||||||
impl().program.bind();
|
impl().program.bind();
|
||||||
impl().program["u_transform"] = transform;
|
impl().program["u_transform"] = transform;
|
||||||
impl().mesh.draw(gl::TRIANGLES);
|
impl().mesh.draw();
|
||||||
|
|
||||||
impl().text_program.bind();
|
impl().text_program.bind();
|
||||||
impl().text_program["u_transform"] = transform;
|
impl().text_program["u_transform"] = transform;
|
||||||
impl().text_program["u_texture"] = 0;
|
impl().text_program["u_texture"] = 0;
|
||||||
impl().text_program["u_texture_size"] = impl().font_texture.size();
|
impl().text_program["u_texture_size"] = impl().font_texture.size();
|
||||||
impl().font_texture.bind();
|
impl().font_texture.bind();
|
||||||
impl().text_mesh.draw(gl::TRIANGLES);
|
impl().text_mesh.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue