Files
Z3D/include/opengl/vertex_buffer_utils.hpp

89 lines
1.6 KiB
C++

#pragma once
#include "opengl/type_utils.hpp"
#include "opengl/metadata/vertex_buffer_metadata.hpp"
#include "util/specialised_lambda.hpp"
#include <span>
#include <tuple>
#include <vector>
#include <cstring>
#include <bits/ranges_algo.h>
namespace zgl::vertex_buffer_utils
{
namespace detail
{
template <typename T>
concept numeric_type = std::integral<T> or std::floating_point<T>;
template<typename C, typename... Ts>
void for_enabled_components(
const C components,
auto&& f,
std::span<Ts> buffers...
) {
(
[&, index = std::size_t{}](const auto& buffer)
{
if ((components & static_cast<C>(1 << index)) != C{})
{
f(buffer, index);
}
++index;
}(buffers),
...
);
};
}
template<typename C, typename... Ts>
void interlace(
std::vector<ztu::u8>& vertex_buffer,
const C components,
const std::size_t element_count,
std::span<Ts> buffers...
) {
std::array<std::size_t, sizeof...(buffers)> byte_offsets;
auto stride = std::size_t{};
detail::for_enabled_components(
components,
[&]<class Component>(
const std::span<Component>&,
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,
[&]<class Component>(const std::span<Component>& 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...
);
};
}