From 5998b18978bd8e7a0c9deb516474634e1d3521c9 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Mon, 3 Aug 2015 17:37:58 +0200 Subject: [PATCH] "streamlined" model/VAO handling --- src/graphics/VertexArray.hpp | 63 ++++ src/graphics/VertexArray.inl | 133 +++++++++ src/graphics/gl_traits.cpp | 30 ++ src/graphics/gl_traits.hpp | 119 ++++++++ src/graphics/render.cpp | 9 +- src/model/BlockModel.hpp | 34 +-- src/model/{Model.hpp => EntityModel.hpp} | 40 ++- src/model/OutlineModel.hpp | 55 ++-- src/model/Shape.hpp | 30 +- src/model/SpriteModel.hpp | 67 +++-- src/model/model.cpp | 347 +++-------------------- src/model/shape.cpp | 14 +- src/ui/HUD.hpp | 6 +- src/ui/ui.cpp | 22 +- src/world/BlockType.hpp | 10 +- src/world/Chunk.hpp | 2 +- src/world/Entity.cpp | 2 +- src/world/Entity.hpp | 4 +- src/world/block.cpp | 12 +- src/world/chunk.cpp | 2 +- tst/graphics/GLTraitsTest.cpp | 143 ++++++++++ tst/graphics/GLTraitsTest.hpp | 31 ++ 22 files changed, 711 insertions(+), 464 deletions(-) create mode 100644 src/graphics/VertexArray.hpp create mode 100644 src/graphics/VertexArray.inl create mode 100644 src/graphics/gl_traits.cpp create mode 100644 src/graphics/gl_traits.hpp rename src/model/{Model.hpp => EntityModel.hpp} (73%) create mode 100644 tst/graphics/GLTraitsTest.cpp create mode 100644 tst/graphics/GLTraitsTest.hpp diff --git a/src/graphics/VertexArray.hpp b/src/graphics/VertexArray.hpp new file mode 100644 index 0000000..c1c7495 --- /dev/null +++ b/src/graphics/VertexArray.hpp @@ -0,0 +1,63 @@ +#ifndef BLANK_GRAPHICS_VERTEXARRAY_HPP_ +#define BLANK_GRAPHICS_VERTEXARRAY_HPP_ + +#include +#include + + +namespace blank { + +template +class VertexArray { + +public: + static constexpr std::size_t NUM_ATTRS = N; + +public: + VertexArray() noexcept; + ~VertexArray() noexcept; + + VertexArray(const VertexArray &) = delete; + VertexArray &operator =(const VertexArray &) = delete; + + VertexArray(VertexArray &&) noexcept; + VertexArray &operator =(VertexArray &&) noexcept; + +public: + void Bind() const noexcept; + + template + void PushAttribute(std::size_t which, const std::vector &data) noexcept; + + template + void PushIndices(std::size_t which, const std::vector &indices) noexcept; + + void DrawLineElements() const noexcept; + void DrawTriangleElements() const noexcept; + +private: + void BindAttribute(std::size_t which) const noexcept; + void EnableAttribute(std::size_t which) noexcept; + template + void AttributeData(const std::vector &) noexcept; + template + void AttributePointer(std::size_t which) noexcept; + + void BindIndex(std::size_t which) const noexcept; + template + void IndexData(const std::vector &) noexcept; + +private: + GLuint array_id; + GLuint attr_id[NUM_ATTRS]; + + std::size_t idx_count; + GLenum idx_type; + +}; + +} + +#include "VertexArray.inl" + +#endif diff --git a/src/graphics/VertexArray.inl b/src/graphics/VertexArray.inl new file mode 100644 index 0000000..1b532b7 --- /dev/null +++ b/src/graphics/VertexArray.inl @@ -0,0 +1,133 @@ +#include "../graphics/gl_traits.hpp" + +namespace blank { + +template +VertexArray::VertexArray() noexcept +: idx_count(0) +, idx_type(GL_UNSIGNED_INT) { + glGenVertexArrays(1, &array_id); + glGenBuffers(N, attr_id); +} + +template +VertexArray::~VertexArray() noexcept { + if (array_id != 0) { + glDeleteBuffers(N, attr_id); + glDeleteVertexArrays(1, &array_id); + } +} + +template +VertexArray::VertexArray(VertexArray &&other) noexcept +: array_id(other.array_id) +, idx_count(other.idx_count) +, idx_type(other.idx_type) { + other.array_id = 0; + for (std::size_t i = 0; i < N; ++i) { + attr_id[i] = other.attr_id[i]; + other.attr_id[i] = 0; + } +} + +template +VertexArray &VertexArray::operator =(VertexArray &&other) noexcept { + std::swap(array_id, other.array_id); + for (std::size_t i = 0; i < N; ++i) { + std::swap(attr_id[i], other.attr_id[i]); + } + idx_count = other.idx_count; + idx_type = other.idx_type; + return *this; +} + +template +void VertexArray::Bind() const noexcept { + glBindVertexArray(array_id); +} + +template +template +void VertexArray::PushAttribute(std::size_t which, const std::vector &data) noexcept { + BindAttribute(which); + AttributeData(data); + EnableAttribute(which); + AttributePointer(which); +} + +template +void VertexArray::BindAttribute(std::size_t i) const noexcept { + assert(i < NUM_ATTRS && "vertex attribute ID out of bounds"); + glBindBuffer(GL_ARRAY_BUFFER, attr_id[i]); +} + +template +void VertexArray::EnableAttribute(std::size_t i) noexcept { + assert(i < NUM_ATTRS && "vertex attribute ID out of bounds"); + glEnableVertexAttribArray(i); +} + +template +template +void VertexArray::AttributeData(const std::vector &buf) noexcept { + glBufferData(GL_ARRAY_BUFFER, buf.size() * sizeof(T), buf.data(), GL_STATIC_DRAW); +} + +template +template +void VertexArray::AttributePointer(std::size_t which) noexcept { + glVertexAttribPointer( + which, // program location + gl_traits::size, // element size + gl_traits::type, // element type + GL_FALSE, // normalize to [-1,1] or [0,1] for unsigned types + 0, // stride + nullptr // offset + ); +} + +template +template +void VertexArray::PushIndices(std::size_t which, const std::vector &indices) noexcept { + BindIndex(which); + IndexData(indices); +} + +template +void VertexArray::BindIndex(std::size_t i) const noexcept { + assert(i < NUM_ATTRS && "element index ID out of bounds"); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, attr_id[i]); +} + +template +template +void VertexArray::IndexData(const std::vector &buf) noexcept { + glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.size() * sizeof(T), buf.data(), GL_STATIC_DRAW); + idx_count = buf.size(); + idx_type = gl_traits::type; +} + + +template +void VertexArray::DrawLineElements() const noexcept { + Bind(); + glDrawElements( + GL_LINES, // how + idx_count, // count + idx_type, // type + nullptr // offset + ); +} + +template +void VertexArray::DrawTriangleElements() const noexcept { + Bind(); + glDrawElements( + GL_TRIANGLES, // how + idx_count, // count + idx_type, // type + nullptr // offset + ); +} + +} diff --git a/src/graphics/gl_traits.cpp b/src/graphics/gl_traits.cpp new file mode 100644 index 0000000..7ce4d59 --- /dev/null +++ b/src/graphics/gl_traits.cpp @@ -0,0 +1,30 @@ +#include "gl_traits.hpp" + + +namespace blank { + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +constexpr GLint gl_traits::size; +constexpr GLenum gl_traits::type; + +} diff --git a/src/graphics/gl_traits.hpp b/src/graphics/gl_traits.hpp new file mode 100644 index 0000000..2a599b3 --- /dev/null +++ b/src/graphics/gl_traits.hpp @@ -0,0 +1,119 @@ +#ifndef BLANK_GRAPHICS_GL_TRAITS_HPP_ +#define BLANK_GRAPHICS_GL_TRAITS_HPP_ + +#include +#include + + +namespace blank { + +template +struct gl_traits { + + /// number of components per generic attribute + /// must be 1, 2, 3, 4 + // static constexpr GLint size; + + /// component type + /// accepted values are: + /// GL_BYTE, GL_UNSIGNED_BYTE, + /// GL_SHORT, GL_UNSIGNED_SHORT, + /// GL_INT, GL_UNSIGNED_INT, + /// GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, + /// GL_FIXED, GL_INT_2_10_10_10_REV, GL_UNSIGNED_INT_2_10_10_10_REV + // static constexpr GLenum type; + +}; + + +// basic types + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_BYTE; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_UNSIGNED_BYTE; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_SHORT; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_UNSIGNED_SHORT; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_INT; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_UNSIGNED_INT; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_FLOAT; +}; + +template<> struct gl_traits { + static constexpr GLint size = 1; + static constexpr GLenum type = GL_DOUBLE; +}; + +// composite types + +template<> +template +struct gl_traits> { + static constexpr GLint size = 1; + static constexpr GLenum type = gl_traits::type; +}; +template +constexpr GLint gl_traits>::size; +template +constexpr GLenum gl_traits>::type; + +template<> +template +struct gl_traits> { + static constexpr GLint size = 2; + static constexpr GLenum type = gl_traits::type; +}; +template +constexpr GLint gl_traits>::size; +template +constexpr GLenum gl_traits>::type; + +template<> +template +struct gl_traits> { + static constexpr GLint size = 3; + static constexpr GLenum type = gl_traits::type; +}; +template +constexpr GLint gl_traits>::size; +template +constexpr GLenum gl_traits>::type; + +template<> +template +struct gl_traits> { + static constexpr GLint size = 4; + static constexpr GLenum type = gl_traits::type; +}; +template +constexpr GLint gl_traits>::size; +template +constexpr GLenum gl_traits>::type; + +} + +#endif diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 747bfa2..f78f9cb 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -234,8 +234,15 @@ void Text::Set(const Font &font, const char *text) { dirty = true; } +namespace { + +SpriteModel::Buffer sprite_buf; + +} + void Text::Update() { - sprite.LoadRect(size.x, size.y, align(pivot, size)); + sprite_buf.LoadRect(size.x, size.y, align(pivot, size)); + sprite.Update(sprite_buf); dirty = false; } diff --git a/src/model/BlockModel.hpp b/src/model/BlockModel.hpp index d1a37c9..0d93758 100644 --- a/src/model/BlockModel.hpp +++ b/src/model/BlockModel.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_MODEL_BLOCKMODEL_HPP_ #define BLANK_MODEL_BLOCKMODEL_HPP_ +#include "../graphics/VertexArray.hpp" + #include #include #include @@ -21,7 +23,14 @@ public: using Lights = std::vector; using Indices = std::vector; -public: + enum Attribute { + ATTRIB_VERTEX, + ATTRIB_COLOR, + ATTRIB_LIGHT, + ATTRIB_INDEX, + ATTRIB_COUNT, + }; + struct Buffer { Positions vertices; @@ -45,32 +54,15 @@ public: }; -public: - BlockModel() noexcept; - ~BlockModel() noexcept; - - BlockModel(const BlockModel &) = delete; - BlockModel &operator =(const BlockModel &) = delete; - - BlockModel(BlockModel &&) noexcept; - BlockModel &operator =(BlockModel &&) noexcept; + using VAO = VertexArray; +public: void Update(const Buffer &) noexcept; void Draw() const noexcept; private: - enum Attribute { - ATTRIB_VERTEX, - ATTRIB_COLOR, - ATTRIB_LIGHT, - ATTRIB_INDEX, - ATTRIB_COUNT, - }; - - GLuint va; - GLuint handle[ATTRIB_COUNT]; - size_t count; + VAO vao; }; diff --git a/src/model/Model.hpp b/src/model/EntityModel.hpp similarity index 73% rename from src/model/Model.hpp rename to src/model/EntityModel.hpp index 95ad086..bd56a43 100644 --- a/src/model/Model.hpp +++ b/src/model/EntityModel.hpp @@ -1,5 +1,7 @@ -#ifndef BLANK_MODEL_MODEL_HPP_ -#define BLANK_MODEL_MODEL_HPP_ +#ifndef BLANK_MODEL_ENTITYMODEL_HPP_ +#define BLANK_MODEL_ENTITYMODEL_HPP_ + +#include "../graphics/VertexArray.hpp" #include #include @@ -8,7 +10,7 @@ namespace blank { -class Model { +class EntityModel { public: using Position = glm::vec3; @@ -21,7 +23,14 @@ public: using Normals = std::vector; using Indices = std::vector; -public: + enum Attribute { + ATTRIB_VERTEX, + ATTRIB_COLOR, + ATTRIB_NORMAL, + ATTRIB_INDEX, + ATTRIB_COUNT, + }; + struct Buffer { Positions vertices; @@ -45,32 +54,15 @@ public: }; -public: - Model() noexcept; - ~Model() noexcept; - - Model(const Model &) = delete; - Model &operator =(const Model &) = delete; - - Model(Model &&) noexcept; - Model &operator =(Model &&) noexcept; + using VAO = VertexArray; +public: void Update(const Buffer &) noexcept; void Draw() const noexcept; private: - enum Attribute { - ATTRIB_VERTEX, - ATTRIB_COLOR, - ATTRIB_NORMAL, - ATTRIB_INDEX, - ATTRIB_COUNT, - }; - - GLuint va; - GLuint handle[ATTRIB_COUNT]; - size_t count; + VAO vao; }; diff --git a/src/model/OutlineModel.hpp b/src/model/OutlineModel.hpp index 308ab51..ba85fc8 100644 --- a/src/model/OutlineModel.hpp +++ b/src/model/OutlineModel.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_MODEL_OUTLINEMODEL_HPP_ #define BLANK_MODEL_OUTLINEMODEL_HPP_ +#include "../graphics/VertexArray.hpp" + #include #include #include @@ -19,39 +21,42 @@ public: using Colors = std::vector; using Indices = std::vector; -public: - Positions vertices; - Colors colors; - Indices indices; + enum Attribute { + ATTRIB_VERTEX, + ATTRIB_COLOR, + ATTRIB_INDEX, + ATTRIB_COUNT, + }; -public: - OutlineModel() noexcept; - ~OutlineModel() noexcept; + struct Buffer { - OutlineModel(const OutlineModel &) = delete; - OutlineModel &operator =(const OutlineModel &) = delete; + Positions vertices; + Colors colors; + Indices indices; - void Invalidate() noexcept { dirty = true; } + void Clear() noexcept { + vertices.clear(); + colors.clear(); + indices.clear(); + } - void Clear() noexcept; - void Reserve(int vtx_count, int idx_count); + void Reserve(size_t p, size_t i) { + vertices.reserve(p); + colors.reserve(p); + indices.reserve(i); + } - void Draw() noexcept; + }; -private: - void Update() noexcept; + using VAO = VertexArray; -private: - enum Attribute { - ATTRIB_VERTEX, - ATTRIB_COLOR, - ATTRIB_INDEX, - ATTRIB_COUNT, - }; +public: + void Update(const Buffer &) noexcept; - GLuint va; - GLuint handle[ATTRIB_COUNT]; - bool dirty; + void Draw() noexcept; + +private: + VAO vao; }; diff --git a/src/model/Shape.hpp b/src/model/Shape.hpp index 212e439..c6964f9 100644 --- a/src/model/Shape.hpp +++ b/src/model/Shape.hpp @@ -2,7 +2,7 @@ #define BLANK_MODEL_SHAPE_HPP_ #include "BlockModel.hpp" -#include "Model.hpp" +#include "EntityModel.hpp" #include "OutlineModel.hpp" #include @@ -21,26 +21,26 @@ struct Shape { /// the number of vertex indices this shape has size_t VertexIndexCount() const noexcept { return vtx_idx.size(); } - const Model::Normal &VertexNormal(size_t idx) const noexcept { return vtx_nrm[idx]; } - Model::Normal VertexNormal( + const EntityModel::Normal &VertexNormal(size_t idx) const noexcept { return vtx_nrm[idx]; } + EntityModel::Normal VertexNormal( size_t idx, const glm::mat4 &transform ) const noexcept { - return Model::Normal(transform * glm::vec4(vtx_nrm[idx], 0.0f)); + return EntityModel::Normal(transform * glm::vec4(vtx_nrm[idx], 0.0f)); } /// fill given buffers with this shape's elements with an /// optional transform and offset void Vertices( - Model::Positions &vertex, - Model::Normals &normal, - Model::Indices &index + EntityModel::Positions &vertex, + EntityModel::Normals &normal, + EntityModel::Indices &index ) const; void Vertices( - Model::Positions &vertex, - Model::Normals &normal, - Model::Indices &index, + EntityModel::Positions &vertex, + EntityModel::Normals &normal, + EntityModel::Indices &index, const glm::mat4 &transform, - Model::Index idx_offset = 0 + EntityModel::Index idx_offset = 0 ) const; void Vertices( BlockModel::Positions &vertex, @@ -85,7 +85,7 @@ struct Shape { ) const noexcept = 0; protected: - void SetShape(const Model::Positions &pos, const Model::Normals &nrm, const Model::Indices &idx) { + void SetShape(const EntityModel::Positions &pos, const EntityModel::Normals &nrm, const EntityModel::Indices &idx) { vtx_pos = pos; vtx_nrm = nrm; vtx_idx = idx; @@ -96,9 +96,9 @@ protected: } private: - Model::Positions vtx_pos; - Model::Normals vtx_nrm; - Model::Indices vtx_idx; + EntityModel::Positions vtx_pos; + EntityModel::Normals vtx_nrm; + EntityModel::Indices vtx_idx; OutlineModel::Positions out_pos; OutlineModel::Indices out_idx; diff --git a/src/model/SpriteModel.hpp b/src/model/SpriteModel.hpp index d661501..c5670fc 100644 --- a/src/model/SpriteModel.hpp +++ b/src/model/SpriteModel.hpp @@ -1,6 +1,8 @@ #ifndef BLANK_MODEL_SPRITEMODEL_HPP_ #define BLANK_MODEL_SPRITEMODEL_HPP_ +#include "../graphics/VertexArray.hpp" + #include #include #include @@ -19,46 +21,49 @@ public: using TexCoords = std::vector; using Indices = std::vector; -public: - Positions vertices; - TexCoords coords; - Indices indices; + enum Attribute { + ATTRIB_VERTEX, + ATTRIB_TEXCOORD, + ATTRIB_INDEX, + ATTRIB_COUNT, + }; -public: - SpriteModel() noexcept; - ~SpriteModel() noexcept; + struct Buffer { - SpriteModel(const SpriteModel &) = delete; - SpriteModel &operator =(const SpriteModel &) = delete; + Positions vertices; + TexCoords coords; + Indices indices; - void Invalidate() noexcept { dirty = true; } + void Clear() noexcept { + vertices.clear(); + coords.clear(); + indices.clear(); + } - void Clear() noexcept; - void Reserve(int vtx_count, int idx_count); + void Reserve(size_t p, size_t i) { + vertices.reserve(p); + coords.reserve(p); + indices.reserve(i); + } - void LoadRect( - float w, float h, - const glm::vec2 &pivot = glm::vec2(0.0f), - const glm::vec2 &tex_begin = glm::vec2(0.0f), - const glm::vec2 &tex_end = glm::vec2(1.0f, 1.0f) - ); + void LoadRect( + float w, float h, + const glm::vec2 &pivot = glm::vec2(0.0f), + const glm::vec2 &tex_begin = glm::vec2(0.0f), + const glm::vec2 &tex_end = glm::vec2(1.0f, 1.0f) + ); - void Draw() noexcept; + }; -private: - void Update() noexcept; + using VAO = VertexArray; -private: - enum Attribute { - ATTRIB_VERTEX, - ATTRIB_TEXCOORD, - ATTRIB_INDEX, - ATTRIB_COUNT, - }; +public: + void Update(const Buffer &) noexcept; - GLuint va; - GLuint handle[ATTRIB_COUNT]; - bool dirty; + void Draw() noexcept; + +private: + VAO vao; }; diff --git a/src/model/model.cpp b/src/model/model.cpp index 4e00080..b834298 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -1,326 +1,82 @@ #include "BlockModel.hpp" -#include "Model.hpp" +#include "EntityModel.hpp" #include "OutlineModel.hpp" #include "SpriteModel.hpp" +#include #include namespace blank { -Model::Model() noexcept -: va(0) -, handle{} -, count(0) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} - -Model::~Model() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); -} - -Model::Model(Model &&other) noexcept -: va(other.va) -, count(other.count) { - other.va = 0; - for (int i = 0; i < ATTRIB_COUNT; ++i) { - handle[i] = other.handle[i]; - other.handle[i] = 0; - } -} - -Model &Model::operator =(Model &&other) noexcept { - std::swap(va, other.va); - for (int i = 0; i < ATTRIB_COUNT; ++i) { - std::swap(handle[i], other.handle[i]); - } - count = other.count; - return *this; -} - -void Model::Update(const Buffer &buf) noexcept { - glBindVertexArray(va); - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, buf.vertices.size() * sizeof(glm::vec3), buf.vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - +void EntityModel::Update(const Buffer &buf) noexcept { #ifndef NDEBUG if (buf.colors.size() < buf.vertices.size()) { - std::cerr << "Model: not enough colors!" << std::endl; + std::cerr << "EntityModel: not enough colors!" << std::endl; } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, buf.colors.size() * sizeof(glm::vec3), buf.colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG if (buf.normals.size() < buf.vertices.size()) { - std::cerr << "Model: not enough normals!" << std::endl; + std::cerr << "EntityModel: not enough normals!" << std::endl; } #endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_NORMAL]); - glBufferData(GL_ARRAY_BUFFER, buf.normals.size() * sizeof(glm::vec3), buf.normals.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_NORMAL); - glVertexAttribPointer( - ATTRIB_NORMAL, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.indices.size() * sizeof(Index), buf.indices.data(), GL_STATIC_DRAW); - count = buf.indices.size(); -} - -void Model::Draw() const noexcept { - glBindVertexArray(va); - glDrawElements( - GL_TRIANGLES, // how - count, // count - GL_UNSIGNED_INT, // type - nullptr // offset - ); + vao.Bind(); + vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); + vao.PushAttribute(ATTRIB_COLOR, buf.colors); + vao.PushAttribute(ATTRIB_NORMAL, buf.normals); + vao.PushIndices(ATTRIB_INDEX, buf.indices); } -BlockModel::BlockModel() noexcept -: va(0) -, handle{} -, count(0) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} - -BlockModel::~BlockModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); +void EntityModel::Draw() const noexcept { + vao.DrawTriangleElements(); } -BlockModel::BlockModel(BlockModel &&other) noexcept -: va(other.va) -, count(other.count) { - other.va = 0; - for (int i = 0; i < ATTRIB_COUNT; ++i) { - handle[i] = other.handle[i]; - other.handle[i] = 0; - } -} - -BlockModel &BlockModel::operator =(BlockModel &&other) noexcept { - std::swap(va, other.va); - for (int i = 0; i < ATTRIB_COUNT; ++i) { - std::swap(handle[i], other.handle[i]); - } - count = other.count; - return *this; -} void BlockModel::Update(const Buffer &buf) noexcept { - glBindVertexArray(va); - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, buf.vertices.size() * sizeof(glm::vec3), buf.vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - #ifndef NDEBUG if (buf.colors.size() < buf.vertices.size()) { std::cerr << "BlockModel: not enough colors!" << std::endl; } -#endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, buf.colors.size() * sizeof(glm::vec3), buf.colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - -#ifndef NDEBUG if (buf.lights.size() < buf.vertices.size()) { std::cerr << "BlockModel: not enough lights!" << std::endl; } #endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_LIGHT]); - glBufferData(GL_ARRAY_BUFFER, buf.lights.size() * sizeof(float), buf.lights.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_LIGHT); - glVertexAttribPointer( - ATTRIB_LIGHT, // location (for shader) - 1, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, buf.indices.size() * sizeof(Index), buf.indices.data(), GL_STATIC_DRAW); - count = buf.indices.size(); + vao.Bind(); + vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); + vao.PushAttribute(ATTRIB_COLOR, buf.colors); + vao.PushAttribute(ATTRIB_LIGHT, buf.lights); + vao.PushIndices(ATTRIB_INDEX, buf.indices); } void BlockModel::Draw() const noexcept { - glBindVertexArray(va); - glDrawElements( - GL_TRIANGLES, // how - count, // count - GL_UNSIGNED_INT, // type - nullptr // offset - ); -} - -OutlineModel::OutlineModel() noexcept -: vertices() -, colors() -, indices() -, va(0) -, handle{} -, dirty(false) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); + vao.DrawTriangleElements(); } -OutlineModel::~OutlineModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); -} - - -void OutlineModel::Clear() noexcept { - vertices.clear(); - colors.clear(); - indices.clear(); - Invalidate(); -} - -void OutlineModel::Reserve(int v, int i) { - vertices.reserve(v); - colors.reserve(v); - indices.reserve(i); -} - - -void OutlineModel::Update() noexcept { - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); +void OutlineModel::Update(const Buffer &buf) noexcept { #ifndef NDEBUG - if (colors.size() < vertices.size()) { + if (buf.colors.size() < buf.vertices.size()) { std::cerr << "OutlineModel: not enough colors!" << std::endl; - colors.resize(vertices.size(), { 1, 0, 1 }); } #endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_COLOR]); - glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_COLOR); - glVertexAttribPointer( - ATTRIB_COLOR, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), GL_STATIC_DRAW); - dirty = false; + vao.Bind(); + vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); + vao.PushAttribute(ATTRIB_COLOR, buf.colors); + vao.PushIndices(ATTRIB_INDEX, buf.indices); } void OutlineModel::Draw() noexcept { - glBindVertexArray(va); - - if (dirty) { - Update(); - } - glEnable(GL_LINE_SMOOTH); glLineWidth(2.0f); - - glDrawElements( - GL_LINES, // how - indices.size(), // count - GL_UNSIGNED_SHORT, // type - nullptr // offset - ); -} - - -SpriteModel::SpriteModel() noexcept -: vertices() -, coords() -, indices() -, va(0) -, handle{} -, dirty(false) { - glGenVertexArrays(1, &va); - glGenBuffers(ATTRIB_COUNT, handle); -} - -SpriteModel::~SpriteModel() noexcept { - glDeleteBuffers(ATTRIB_COUNT, handle); - glDeleteVertexArrays(1, &va); + vao.DrawLineElements(); } -void SpriteModel::Clear() noexcept { - vertices.clear(); - coords.clear(); - indices.clear(); - Invalidate(); -} - -void SpriteModel::Reserve(int v, int i) { - vertices.reserve(v); - coords.reserve(v); - indices.reserve(i); -} - - -void SpriteModel::LoadRect( +void SpriteModel::Buffer::LoadRect( float w, float h, const glm::vec2 &pivot, const glm::vec2 &tex_begin, @@ -340,62 +96,25 @@ void SpriteModel::LoadRect( coords.emplace_back(tex_end.x, tex_end.y); indices.assign({ 0, 2, 1, 1, 2, 3 }); - - Invalidate(); } -void SpriteModel::Update() noexcept { - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_VERTEX]); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Position), vertices.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_VERTEX); - glVertexAttribPointer( - ATTRIB_VERTEX, // location (for shader) - 3, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - +void SpriteModel::Update(const Buffer &buf) noexcept { #ifndef NDEBUG - if (coords.size() < vertices.size()) { + if (buf.coords.size() < buf.vertices.size()) { std::cerr << "SpriteModel: not enough coords!" << std::endl; - coords.resize(vertices.size(), { 1, 1 }); } #endif - glBindBuffer(GL_ARRAY_BUFFER, handle[ATTRIB_TEXCOORD]); - glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(TexCoord), coords.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(ATTRIB_TEXCOORD); - glVertexAttribPointer( - ATTRIB_TEXCOORD, // location (for shader) - 2, // size - GL_FLOAT, // type - GL_FALSE, // normalized - 0, // stride - nullptr // offset - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle[ATTRIB_INDEX]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), GL_STATIC_DRAW); - dirty = false; + vao.Bind(); + vao.PushAttribute(ATTRIB_VERTEX, buf.vertices); + vao.PushAttribute(ATTRIB_TEXCOORD, buf.coords); + vao.PushIndices(ATTRIB_INDEX, buf.indices); } void SpriteModel::Draw() noexcept { - glBindVertexArray(va); - - if (dirty) { - Update(); - } - - glDrawElements( - GL_TRIANGLES, // how - indices.size(), // count - GL_UNSIGNED_SHORT, // type - nullptr // offset - ); + vao.DrawTriangleElements(); } } diff --git a/src/model/shape.cpp b/src/model/shape.cpp index df98f93..e9364bd 100644 --- a/src/model/shape.cpp +++ b/src/model/shape.cpp @@ -5,9 +5,9 @@ namespace blank { void Shape::Vertices( - Model::Positions &vertex, - Model::Normals &normal, - Model::Indices &index + EntityModel::Positions &vertex, + EntityModel::Normals &normal, + EntityModel::Indices &index ) const { for (const auto &pos : vtx_pos) { vertex.emplace_back(pos); @@ -21,11 +21,11 @@ void Shape::Vertices( } void Shape::Vertices( - Model::Positions &vertex, - Model::Normals &normal, - Model::Indices &index, + EntityModel::Positions &vertex, + EntityModel::Normals &normal, + EntityModel::Indices &index, const glm::mat4 &transform, - Model::Index idx_offset + EntityModel::Index idx_offset ) const { for (const auto &pos : vtx_pos) { vertex.emplace_back(transform * glm::vec4(pos, 1.0f)); diff --git a/src/ui/HUD.hpp b/src/ui/HUD.hpp index 718e712..a1662f4 100644 --- a/src/ui/HUD.hpp +++ b/src/ui/HUD.hpp @@ -2,7 +2,7 @@ #define BLANK_UI_HUD_H_ #include "../graphics/FixedText.hpp" -#include "../model/Model.hpp" +#include "../model/EntityModel.hpp" #include "../model/OutlineModel.hpp" #include @@ -31,8 +31,8 @@ private: const BlockTypeRegistry &types; const Font &font; - Model block; - Model::Buffer block_buf; + EntityModel block; + EntityModel::Buffer block_buf; glm::mat4 block_transform; FixedText block_label; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 8a17be2..198defb 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -34,15 +34,16 @@ HUD::HUD(const BlockTypeRegistry &types, const Font &font) block_transform = glm::rotate(block_transform, 3.5f, glm::vec3(1.0f, 0.0f, 0.0f)); block_transform = glm::rotate(block_transform, 0.35f, glm::vec3(0.0f, 1.0f, 0.0f)); - crosshair.vertices = std::vector({ + OutlineModel::Buffer buf; + buf.vertices = std::vector({ { -10.0f, 0.0f, 0.0f }, { 10.0f, 0.0f, 0.0f }, { 0.0f, -10.0f, 0.0f }, { 0.0f, 10.0f, 0.0f }, }); - crosshair.indices = std::vector({ + buf.indices = std::vector({ 0, 1, 2, 3 }); - crosshair.colors.resize(4, { 10.0f, 10.0f, 10.0f }); - crosshair.Invalidate(); + buf.colors.resize(4, { 10.0f, 10.0f, 10.0f }); + crosshair.Update(buf); block_label.Position( glm::vec3(50.0f, 85.0f, 0.0f), @@ -58,7 +59,7 @@ void HUD::Display(const Block &b) { const BlockType &type = types.Get(b.type); block_buf.Clear(); - type.FillModel(block_buf, b.Transform()); + type.FillEntityModel(block_buf, b.Transform()); block.Update(block_buf); block_label.Set(font, type.label); @@ -488,11 +489,18 @@ void Interface::Update(int dt) { } } +namespace { + +OutlineModel::Buffer outl_buf; + +} + void Interface::CheckAim() { float dist; if (world.Intersection(aim, glm::mat4(1.0f), aim_chunk, aim_block, dist, aim_normal)) { - outline.Clear(); - aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline); + outl_buf.Clear(); + aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outl_buf); + outline.Update(outl_buf); outline_transform = glm::scale(glm::vec3(1.0002f)); outline_transform *= aim_chunk->Transform(world.Player().ChunkCoords()); outline_transform *= aim_chunk->ToTransform(Chunk::ToPos(aim_block), aim_block); diff --git a/src/world/BlockType.hpp b/src/world/BlockType.hpp index caccb8f..786c76c 100644 --- a/src/world/BlockType.hpp +++ b/src/world/BlockType.hpp @@ -3,7 +3,7 @@ #include "Block.hpp" #include "../model/BlockModel.hpp" -#include "../model/Model.hpp" +#include "../model/EntityModel.hpp" #include "../model/OutlineModel.hpp" #include "../model/shapes.hpp" @@ -63,10 +63,10 @@ struct BlockType { return fill[block.OrientedFace(face)]; } - void FillModel( - Model::Buffer &m, + void FillEntityModel( + EntityModel::Buffer &m, const glm::mat4 &transform = glm::mat4(1.0f), - Model::Index idx_offset = 0 + EntityModel::Index idx_offset = 0 ) const noexcept; void FillBlockModel( BlockModel::Buffer &m, @@ -74,7 +74,7 @@ struct BlockType { BlockModel::Index idx_offset = 0 ) const noexcept; void FillOutlineModel( - OutlineModel &m, + OutlineModel::Buffer &m, const glm::vec3 &pos_offset = { 0, 0, 0 }, OutlineModel::Index idx_offset = 0 ) const noexcept; diff --git a/src/world/Chunk.hpp b/src/world/Chunk.hpp index 535f7d7..7b84b6e 100644 --- a/src/world/Chunk.hpp +++ b/src/world/Chunk.hpp @@ -131,7 +131,7 @@ public: int GetLight(const Pos &pos) const noexcept { return GetLight(ToIndex(pos)); } int GetLight(const Block::Pos &pos) const noexcept { return GetLight(ToIndex(pos)); } - float GetVertexLight(const Pos &, const BlockModel::Position &, const Model::Normal &) const noexcept; + float GetVertexLight(const Pos &, const BlockModel::Position &, const EntityModel::Normal &) const noexcept; bool Intersection( const Ray &ray, diff --git a/src/world/Entity.cpp b/src/world/Entity.cpp index 844f74b..79a09ea 100644 --- a/src/world/Entity.cpp +++ b/src/world/Entity.cpp @@ -7,7 +7,7 @@ namespace { -blank::Model::Buffer model_buffer; +blank::EntityModel::Buffer model_buffer; } diff --git a/src/world/Entity.hpp b/src/world/Entity.hpp index 7c96f4f..a5723f4 100644 --- a/src/world/Entity.hpp +++ b/src/world/Entity.hpp @@ -4,7 +4,7 @@ #include "Block.hpp" #include "Chunk.hpp" #include "../model/geometry.hpp" -#include "../model/Model.hpp" +#include "../model/EntityModel.hpp" #include #include @@ -59,7 +59,7 @@ public: private: const Shape *shape; - Model model; + EntityModel model; std::string name; diff --git a/src/world/block.cpp b/src/world/block.cpp index 510771a..442e54f 100644 --- a/src/world/block.cpp +++ b/src/world/block.cpp @@ -88,10 +88,10 @@ BlockType::BlockType(bool v, const glm::vec3 &col, const Shape *s) noexcept } -void BlockType::FillModel( - Model::Buffer &buf, +void BlockType::FillEntityModel( + EntityModel::Buffer &buf, const glm::mat4 &transform, - Model::Index idx_offset + EntityModel::Index idx_offset ) const noexcept { shape->Vertices(buf.vertices, buf.normals, buf.indices, transform, idx_offset); buf.colors.insert(buf.colors.end(), shape->VertexCount(), color); @@ -107,12 +107,12 @@ void BlockType::FillBlockModel( } void BlockType::FillOutlineModel( - OutlineModel &model, + OutlineModel::Buffer &buf, const glm::vec3 &pos_offset, OutlineModel::Index idx_offset ) const noexcept { - shape->Outline(model.vertices, model.indices, pos_offset, idx_offset); - model.colors.insert(model.colors.end(), shape->OutlineCount(), outline_color); + shape->Outline(buf.vertices, buf.indices, pos_offset, idx_offset); + buf.colors.insert(buf.colors.end(), shape->OutlineCount(), outline_color); } diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index c421be9..190fe3d 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -319,7 +319,7 @@ int Chunk::GetLight(int index) const noexcept { return light[index]; } -float Chunk::GetVertexLight(const Pos &pos, const BlockModel::Position &vtx, const Model::Normal &norm) const noexcept { +float Chunk::GetVertexLight(const Pos &pos, const BlockModel::Position &vtx, const EntityModel::Normal &norm) const noexcept { int index = ToIndex(pos); float light = GetLight(index); diff --git a/tst/graphics/GLTraitsTest.cpp b/tst/graphics/GLTraitsTest.cpp new file mode 100644 index 0000000..9567331 --- /dev/null +++ b/tst/graphics/GLTraitsTest.cpp @@ -0,0 +1,143 @@ +#include "GLTraitsTest.hpp" + +#include "graphics/gl_traits.hpp" + +CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::GLTraitsTest); + + +namespace blank { +namespace test { + +void GLTraitsTest::setUp() { + +} + +void GLTraitsTest::tearDown() { + +} + + +void GLTraitsTest::testSize() { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for byte", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for ubyte", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for short", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for ushort", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for int", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for uint", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for float", + 1, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for double", + 1, gl_traits::size + ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec2", + 2, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec3", + 3, gl_traits::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec4", + 4, gl_traits::size + ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec2i", + 2, gl_traits>::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec3i", + 3, gl_traits>::size + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad number of components for vec4i", + 4, gl_traits>::size + ); +} + +void GLTraitsTest::testType() { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for byte", + GLenum(GL_BYTE), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for ubyte", + GLenum(GL_UNSIGNED_BYTE), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for short", + GLenum(GL_SHORT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for ushort", + GLenum(GL_UNSIGNED_SHORT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for int", + GLenum(GL_INT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for uint", + GLenum(GL_UNSIGNED_INT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for float", + GLenum(GL_FLOAT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for double", + GLenum(GL_DOUBLE), gl_traits::type + ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec2", + GLenum(GL_FLOAT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec3", + GLenum(GL_FLOAT), gl_traits::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec4", + GLenum(GL_FLOAT), gl_traits::type + ); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec2i", + GLenum(GL_INT), gl_traits>::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec3i", + GLenum(GL_INT), gl_traits>::type + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "bad component type for vec4i", + GLenum(GL_INT), gl_traits>::type + ); +} + +} +} diff --git a/tst/graphics/GLTraitsTest.hpp b/tst/graphics/GLTraitsTest.hpp new file mode 100644 index 0000000..3745f9e --- /dev/null +++ b/tst/graphics/GLTraitsTest.hpp @@ -0,0 +1,31 @@ +#ifndef BLANK_TEST_GRAPHICS_GLTRAITSTEST_HPP_ +#define BLANK_TEST_GRAPHICS_GLTRAITSTEST_HPP_ + +#include + +namespace blank { +namespace test { + +class GLTraitsTest +: public CppUnit::TestFixture { + +CPPUNIT_TEST_SUITE(GLTraitsTest); + +CPPUNIT_TEST(testSize); +CPPUNIT_TEST(testType); + +CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testSize(); + void testType(); + +}; + +} +} + +#endif -- 2.39.2