NBEngine/engine/NBGraphics/VertexArray.hpp
2026-07-19 22:20:05 -05:00

238 lines
5.3 KiB
C++

#pragma once
#ifndef _NB_VERTEX_ARRAY
#define _NB_VERTEX_ARRAY
#include "GLLoad.hpp"
#include <NBCore/Errors.hpp>
#include "Buffers.hpp"
#include "OGLObjects.hpp"
namespace nb {
static uint8_t GLSLTypeSize(GLenum type) {
switch(type) {
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_HALF_FLOAT:
return 2;
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
return 4;
break;
case GL_DOUBLE:
return 8;
break;
default:
return 1;
break;
}
}
struct VertexAttributeLayout {
int32_t offset = 0;
GLsizei stride = 0;
GLuint divisor = 0;
};
struct VertexAttribute {
GLint GLSLSize;
GLenum GLSLType;
GLboolean GLSLNormalization;
VertexAttributeLayout layout;
};
struct VertexAttributePointer {
VertexAttribute attribute;
GLuint buffer;
GLuint index;
};
static bool isIndexInVertexAttribute(int i, const VertexAttribute& va) {
if ((i -= va.layout.offset) < 0) { return false; }
return (i%va.layout.stride) < GLSLTypeSize(va.GLSLType) * va.GLSLSize;
}
typedef std::vector<VertexAttribute> VertexAttributeList;
typedef std::vector<VertexAttributePointer> VertexAttributePointerList;
class VAOError : public Error<VAOError> {
using Base = Error<VAOError>;
public:
using Base::Base;
enum Codes : unsigned int {
UNDEFINED, INVALID_ATTRIBUTE
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
class VAO : public OpenGLObject {
using Base = OpenGLObject;
using Codes = VAOError::Codes;
public:
using Base::Base;
VAO() = default;
VAO(const VertexAttributePointerList&);
VAO(VAO&&);
VAO& operator=(VAO&&);
virtual void bind() const override {
if(_id) {
glBindVertexArray(_id);
} else {
THROW(OGLError(
OGLError::Codes::INVALID_OBJECT,
"w/ VertexArrayObject"
));
}
}
virtual void unbind() const override { glBindVertexArray(0); }
VertexAttributePointerList attributes() const;
VertexAttributePointerList attributes(const VertexAttributePointerList&);
VertexAttributePointer attr(GLuint) const;
void enable() const;
void enable(GLuint) const;
void disable() const;
void disable(GLuint) const;
protected:
using Base::_id;
VertexAttributePointerList _attrs;
virtual void remove() override {
if(_id) {
disable();
bind();
glDeleteVertexArrays(1, &_id);
_id = 0;
}
}
virtual GLuint declare() override {
if (!_id) {
glGenVertexArrays(1, &_id);
}
bind();
return _id;
}
};
class VertexError : public Error<VertexError> {
protected:
using Base = Error<VertexError>;
public:
using Base::Base;
enum Codes : unsigned int {
UNDEFINED, MISALIGNED_DATA
};
static const std::string type;
static const ErrorCodeMap ErrorMessages;
};
using VBO = ArrayBuffer;
using VertBufVec = SharedVector<VBO>;
using EBO = ElementBuffer;
struct VertexData {
std::shared_ptr<VBO> vbo;
VertexAttributeList attrs;
};
using VertexDataVec = std::vector<VertexData>;
class VertexGroup {
protected:
using Codes = VertexError::Codes;
VertexDataVec _vertex_data;
std::shared_ptr<EBO> _ebo;
std::shared_ptr<VAO> _vao;
GLenum _primitive;
public:
GLenum primitive=GL_TRIANGLES;
VertexGroup(VertexGroup&&);
VertexGroup& operator=(VertexGroup&&);
VertexGroup(
const VertexDataVec& vertex_data,
const std::shared_ptr<EBO>& ebo
)
: _vao(std::make_shared<VAO>()), _ebo(ebo) {
setBuffers(vertex_data);
}
template<typename... T>
VertexGroup(
const VertexDataVec& vertex_data,
T... args
)
: VertexGroup(vertex_data, std::make_shared<EBO>(args...)) {
setBuffers(vertex_data);
}
template<typename... T>
VertexGroup(
const VertexData& vertex_data,
T... args
)
: VertexGroup(VertexDataVec{vertex_data}, args...) {}
template<typename... T>
VertexGroup(
const ByteVector& vertex_data,
const VertexAttributeList& vertex_specification,
T... args
) : VertexGroup({
std::make_shared<VBO>(vertex_data),
vertex_specification},
args...
) {}
void bind() const {
_vao->bind();
_ebo->bind();
}
void unbind() const {
_vao->unbind();
_ebo->unbind();
}
void draw() const;
VertexDataVec getBuffers();
VertexData getBuffers(size_t);
size_t setBuffers(const VertexDataVec&);
size_t addBuffer(const VertexData&);
size_t addBuffer(const ByteVector& data, const VertexAttributeList& attrs);
VertexDataVec dropBuffers();
VertexData dropBuffer(size_t);
VertexAttributePointer attribute(size_t) const;
void enableAttr(GLuint);
void disableAttr(GLuint);
void enableBuffer(size_t);
void disableBuffer(size_t);
void enable();
void disable();
std::shared_ptr<EBO> indices() const;
std::shared_ptr<EBO> indices(const std::vector<unsigned int>& data);
std::shared_ptr<EBO> indices(std::shared_ptr<EBO> buffer);
};
} // namespace nb
#endif // _NB_VERTEX_ARRAY