NBEngine/engine/NBGraphics/src/VertexArray.cpp
2026-08-20 08:12:54 -05:00

226 lines
5.3 KiB
C++

#include "VertexArray.hpp"
namespace nb {
using VAOErrorCodes = VAOError::Codes;
const std::string VAOError::type = "nb::VAOError";
const ErrorCodeMap VAOError::ErrorMessages = {
{ VAOErrorCodes::UNDEFINED, "Error" },
{ VAOErrorCodes::INVALID_ATTRIBUTE, "Targeting invalid attribute"},
{ VAOErrorCodes::INVALID_VAO, "Targeting invalid VAO" }
};
VAO::VAO(const VertexAttributePointerList& attr_ptrs) {
attributes(attr_ptrs);
}
VAO::VAO(VAO&& other) {
*this = std::move(other);
}
VAO& VAO::operator=(VAO&& rhs) {
_id = rhs._id;
_attrs = rhs._attrs;
rhs._id = 0;
rhs._attrs = {};
return *this;
}
VertexAttributePointerList VAO::attributes() const {
return _attrs;
}
VertexAttributePointerList VAO::attributes(const VertexAttributePointerList& attrs_) {
declare();
disable();
_attrs = attrs_;
bind();
for (auto attr_ptr : attrs_) {
attr_ptr.buffer->bind();
GLuint idx = attr_ptr.index;
glVertexAttribPointer(
idx,
attr_ptr.attribute.GLSLSize,
attr_ptr.attribute.GLSLType,
attr_ptr.attribute.GLSLNormalization,
attr_ptr.attribute.layout.stride,
(void*)attr_ptr.attribute.layout.offset
);
glEnableVertexAttribArray(idx);
}
unbind();
return _attrs;
}
VertexAttributePointer VAO::attr(GLuint idx) const {
for (auto attr_ptr : _attrs) {
if (idx == attr_ptr.index) {
return attr_ptr;
}
}
THROW(BufferError(Codes::INVALID_ATTRIBUTE));
}
void VAO::enable() const {
if (_id) {
bind();
for(auto attr_ptr : _attrs) {
glEnableVertexAttribArray(attr_ptr.index);
}
unbind();
}
}
void VAO::enable(GLuint idx) const {
if(_id) {
bind();
glEnableVertexAttribArray(attr(idx).index);
unbind();
}
}
void VAO::disable() const {
if(_id) {
bind();
for(auto attr_ptr : _attrs) {
glDisableVertexAttribArray(attr_ptr.index);
}
unbind();
}
}
void VAO::disable(GLuint idx) const {
if(_id) {
bind();
glDisableVertexAttribArray(attr(idx).index);
unbind();
}
}
VertexGroup::VertexGroup(VertexGroup&& other) {
*this = std::move(other);
}
VertexGroup& VertexGroup::operator=(VertexGroup&& rhs) {
_vertex_data = rhs._vertex_data;
_elmt_buf = std::move(rhs._elmt_buf);
_vao = std::move(rhs._vao);
rhs._vertex_data = {};
rhs._elmt_buf = ElementBuffer<false>();
rhs._vao = VAO();
return *this;
}
size_t VertexGroup::buffer(VertexBuffer<false>&& buf_) {
_vertex_data.emplace_back(
std::make_shared<VertexBuffer<false>>(std::move(buf_))
);
VertexBuffer<false>* buf_ptr = _vertex_data.back().get();
VertexAttributePointerList attrs = _vao.attributes();
GLuint idx = attrs.size();
for (auto attr : buf_ptr->attributes) {
attrs.emplace_back(
VertexAttributePointer{attr, buf_ptr,idx}
);
idx++;
}
_vao.attributes(attrs);
return _vertex_data.size();
}
VertexBuffer<false>& VertexGroup::buffer(size_t idx) {
return *_vertex_data[idx];
}
std::vector<std::shared_ptr<VertexBuffer<false>>> VertexGroup::buffers() {
return _vertex_data;
}
size_t VertexGroup::buffers(std::vector<VertexBuffer<false>>&& bufs_) {
_vertex_data.clear();
for (auto& buf : bufs_) {
_vertex_data.emplace_back(
std::make_shared<VertexBuffer<false>>(std::move(buf))
);
}
VertexAttributePointerList attr_ptrs;
GLuint idx = 0;
for (auto buf : _vertex_data) {
for (auto attr : buf->attributes) {
attr_ptrs.emplace_back(
VertexAttributePointer{attr, buf.get(), idx}
);
idx++;
}
}
_vao.attributes(attr_ptrs);
return _vertex_data.size();
}
VertexBuffer<false>&& VertexGroup::dropBuffer(size_t idx) {
if (idx >= _vertex_data.size()) {
THROW(BufferError(BufferError::Codes::INVALID_BUFFER));
}
std::vector<VertexBuffer<false>> tmp;
std::shared_ptr<VertexBuffer<false>> ret_ptr;
size_t i = 0;
for (auto buf : _vertex_data) {
if (i == idx) {
ret_ptr = std::make_shared<VertexBuffer<false>>(std::move(tmp[idx]));
} else {
tmp.emplace_back(std::move(*buf));
}
i++;
}
buffers(std::move(tmp));
return std::move(*ret_ptr);
}
VertexAttributePointer VertexGroup::attribute(size_t idx_) const {
return _vao.attr(idx_);
}
void VertexGroup::enableAttr(GLuint idx) {
bind();
_vao.enable(idx);
unbind();
}
void VertexGroup::disableAttr(GLuint idx) {
bind();
_vao.disable(idx);
unbind();
}
void VertexGroup::disableBuffer(size_t idx) {
auto buf_ptr = _vertex_data[idx].get();
bind();
for (auto attr : _vao.attributes()) {
if (attr.buffer == buf_ptr) {
_vao.disable(attr.index);
}
}
unbind();
}
void VertexGroup::enableBuffer(size_t idx) {
auto buf_ptr = _vertex_data[idx].get();
bind();
for (auto attr : _vao.attributes()) {
if (attr.buffer == buf_ptr) {
_vao.enable(attr.index);
}
}
unbind();
}
void VertexGroup::enable() { _vao.enable(); }
void VertexGroup::disable() { _vao.disable(); }
} // namespace nb