89 lines
1.6 KiB
C++
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...
|
|
);
|
|
};
|
|
|
|
}
|