#ifndef INCLUDE_MESH_BATCH_IMPLEMENTATION # error Never include this file directly include 'mesh_batch.hpp' #endif #include inline mesh_batch::id_type mesh_batch::add( const zgl::mesh_handle& mesh, const aabb& bounding_box, const zgl::model_matrix_handle& transform, const zgl::material_handle& material ) { std::size_t index; if (material.texture) { // Sort by texture id if possible, so meshes the same texture are rendered consecutively. const auto texture_it = std::ranges::upper_bound( m_textures, *material.texture, [](const auto& lhs, const auto& rhs) { return lhs.texture_id < rhs.texture_id; } ); index = texture_it - m_textures.begin(); } else { // TODO inserting by vao might split up texture sequence, this needs more attention // Otherwise, sort by vao, so meshes with the same vertices are rendered consecutively. const auto mesh_it = std::ranges::upper_bound( m_meshes, mesh, [](const auto& lhs, const auto& rhs) { return lhs.vao_id < rhs.vao_id; } ); index = mesh_it - m_meshes.begin(); } m_meshes.insert(m_meshes.begin() + index, mesh); m_bounding_boxes.insert(m_bounding_boxes.begin() + index, bounding_box); m_transforms.insert(m_transforms.begin() + index, transform); if (material.texture) { m_textures.insert(m_textures.begin() + index, *material.texture); } if (material.surface_properties) { m_surface_properties.insert(m_surface_properties.begin() + index, *material.surface_properties); } if (material.alpha) { m_alphas.insert(m_alphas.begin() + index, *material.alpha); } const auto mesh_id = m_next_mesh_id++; m_id_lookup.insert(m_id_lookup.begin() + index, mesh_id); return mesh_id; } std::optional mesh_batch::bounding_box(id_type id) { const auto lookup_it = std::ranges::find(m_id_lookup, id); if (lookup_it == m_id_lookup.end()) { return std::nullopt; } const auto index = lookup_it - m_id_lookup.begin(); const auto& base_bounding_box = m_bounding_boxes[index]; const auto& transform = m_transforms[index]; return base_bounding_box.transformed(transform); } inline bool mesh_batch::remove(const id_type id) { const auto lookup_it = std::ranges::find(m_id_lookup, id); if (lookup_it == m_id_lookup.end()) { return false; } const auto index = lookup_it - m_id_lookup.begin(); m_id_lookup.erase(m_id_lookup.begin() + index); m_meshes.erase(m_meshes.begin() + index); m_bounding_boxes.erase(m_bounding_boxes.begin() + index); m_transforms.erase(m_transforms.begin() + index); if (not m_textures.empty()) { m_textures.erase(m_textures.begin() + index); } if (not m_surface_properties.empty()) { m_surface_properties.erase(m_surface_properties.begin() + index); } if (not m_alphas.empty()) { m_alphas.erase(m_alphas.begin() + index); } return true; } inline std::span mesh_batch::meshes() const { return m_meshes; } inline std::span mesh_batch::bounding_boxes() const { return m_bounding_boxes; } inline std::span mesh_batch::transforms() const { return m_transforms; } inline std::span mesh_batch::textures() const { return m_textures; } inline std::span mesh_batch::surface_properties() const { return m_surface_properties; } inline std::span mesh_batch::alphas() const { return m_alphas; }