#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(); rhs._vao = VAO(); return *this; } size_t VertexGroup::buffer(VertexBuffer&& buf_) { _vertex_data.emplace_back( std::make_shared>(std::move(buf_)) ); VertexBuffer* 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& VertexGroup::buffer(size_t idx) { return *_vertex_data[idx]; } std::vector>> VertexGroup::buffers() { return _vertex_data; } size_t VertexGroup::buffers(std::vector>&& bufs_) { _vertex_data.clear(); for (auto& buf : bufs_) { _vertex_data.emplace_back( std::make_shared>(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&& VertexGroup::dropBuffer(size_t idx) { if (idx >= _vertex_data.size()) { THROW(BufferError(BufferError::Codes::INVALID_BUFFER)); } std::vector> tmp; std::shared_ptr> ret_ptr; size_t i = 0; for (auto buf : _vertex_data) { if (i == idx) { ret_ptr = std::make_shared>(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