#include "o3d/mesh.hpp" #include #include #include #include #include #include #include "math/vector.hpp" #include "vulkan_utils.hpp" using namespace engine::o3d; template struct VertexIndicesHasher { // taken from boost's container_hash std::size_t operator()(const std::array& vertex_indices) const { size_t h = 0; for (const auto& idx : vertex_indices) h ^= std::hash{}(idx) + 0x9e3779b9 + (h << 6) + (h >> 2); return h; } }; Mesh Mesh::plane(float width, float height) { const float w2 = width / 2, h2 = height / 2; return { { { -w2 / 2, 0.f, -h2 / 2 }, { +w2 / 2, 0.f, -h2 / 2 }, { +w2 / 2, 0.f, +h2 / 2 }, { -w2 / 2, 0.f, +h2 / 2 }, }, { { 0.f, -1.f, 0.f }, { 0.f, +1.f, 0.f }, }, { { 0.f, 0.f }, { 1.f, 0.f }, { 1.f, 1.f }, { 0.f, 1.f }, }, { {{ {{ 0, 0, 0 }}, {{ 1, 0, 1 }}, {{ 2, 0, 2 }} }}, {{ {{ 2, 0, 2 }}, {{ 3, 0, 3 }}, {{ 0, 0, 0 }} }}, {{ {{ 0, 1, 0 }}, {{ 3, 1, 3 }}, {{ 2, 1, 2 }} }}, {{ {{ 2, 1, 2 }}, {{ 1, 1, 1 }}, {{ 0, 1, 0 }} }}, } }; } std::tuple, std::vector> Mesh::linearize_indices() const & { std::unordered_map, size_t, VertexIndicesHasher<3>> unique_vertices; std::vector linearized_vertices; std::vector linearized_indices; for (const auto& triangle_indices : this->indices) { for (const auto& vertex_indices : triangle_indices) { auto it = unique_vertices.find(vertex_indices); if (it == unique_vertices.end()) { linearized_vertices.emplace_back(this->vertices[vertex_indices[0]], this->normals[vertex_indices[1]], this->uvs[vertex_indices[2]]); size_t idx = linearized_vertices.size() - 1; unique_vertices.emplace(vertex_indices, idx); linearized_indices.emplace_back(idx); } else { linearized_indices.emplace_back((*it).second); } } } // TODO: I'm not sure if passing vectors like that makes a copy or not, because they are passed // to a structured which is instantly returned. I think that copy-ellision catches that return std::tuple { linearized_vertices, linearized_indices }; }