#include "opengl/data/point_cloud_data.hpp" #include "opengl/type_utils.hpp" #include "opengl/error.hpp" #include #include "GL/glew.h" std::error_code zgl::point_cloud_data::build_from( std::span point_buffer, std::span component_types, std::span component_lengths, GLsizei stride, point_cloud_data& data ) { if (not std::ranges::all_of(component_types, type_utils::is_valid_type)) { return std::make_error_code(std::errc::invalid_argument); } const auto points_byte_count = point_buffer.size() * sizeof(std::uint8_t); if (points_byte_count > std::numeric_limits::max()) { return std::make_error_code(std::errc::value_too_large); } auto error = std::error_code{}; auto check_error = [&error, ec = static_cast(GL_NO_ERROR)]() mutable -> const std::error_code& { ec = glGetError(); if (ec != GL_NO_ERROR) { error = make_error_code(ec); } return error; }; ztu::u32 vao_id; glGenVertexArrays(1, &vao_id); if (check_error()) return error; glBindVertexArray(vao_id); if (check_error()) return error; ztu::u32 vertex_buffer_id; glGenBuffers(1, &vertex_buffer_id); if (check_error()) return error; glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id); if (check_error()) return error; glBufferData( GL_ARRAY_BUFFER, static_cast(points_byte_count), point_buffer.data(), GL_STATIC_DRAW ); if (check_error()) return error; glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id); if (check_error()) return error; auto offset = GLsizei{ 0 }; for (std::size_t i{}; i != component_types.size(); ++i) { const auto type = component_types[i]; const auto length = component_lengths[i]; const auto byte_count = type_utils::size_of(type); glVertexAttribPointer( i, length, type, GL_FALSE, stride, reinterpret_cast(offset) ); if (check_error()) return error; glEnableVertexAttribArray(i); if (check_error()) return error; offset += length * byte_count; } glBindBuffer(GL_ARRAY_BUFFER, 0); if (check_error()) return error; glBindVertexArray(0); if (check_error()) return error; data = point_cloud_data( vertex_buffer_id, vao_id, point_buffer.size() ); return {}; }