#pragma once #include "opengl/type_utils.hpp" #include "opengl/metadata/vertex_buffer_metadata.hpp" #include "util/specialised_lambda.hpp" #include #include #include #include #include namespace zgl::vertex_buffer_utils { namespace detail { template concept numeric_type = std::integral or std::floating_point; template void for_enabled_components( const C components, auto&& f, std::span buffers... ) { ( [&, index = std::size_t{}](const auto& buffer) { if ((components & static_cast(1 << index)) != C{}) { f(buffer, index); } ++index; }(buffers), ... ); }; } template void interlace( std::vector& vertex_buffer, const C components, const std::size_t element_count, std::span buffers... ) { std::array byte_offsets; auto stride = std::size_t{}; detail::for_enabled_components( components, [&]( const std::span&, std::size_t index ) { byte_offsets[index] = stride; stride += sizeof(Component); }, buffers... ); const auto buffer_size = stride * element_count; vertex_buffer.resize(buffer_size); detail::for_enabled_components( components, [&](const std::span& buffer, std::size_t index) { const auto byte_offset = byte_offsets[index]; for (const auto& value : buffer.subspan(0, element_count)) { std::memcpy( &vertex_buffer[byte_offset], &value, sizeof(value) ); byte_offset += stride; } }, buffers... ); }; }