// // Created by Vladislav on 09.11.2025. // #pragma once #include "omath/linear_algebra/triangle.hpp" #include #include #include #include #include namespace omath::primitives { template, class UvT = Vector2> struct Vertex final { using VectorType = VecType; using UvType = UvT; VectorType position; VectorType normal; UvType uv; }; template concept HasPosition = requires(T vertex) { vertex.position; }; template concept HasNormal = requires(T vertex) { vertex.normal; }; template concept HasUv = requires(T vertex) { vertex.uv; }; template, class VboType = std::vector, class EboType = std::vector>> class Mesh final { public: using VectorType = VertType::VectorType; using VertexType = VboType::value_type; private: using Vbo = VboType; using Ebo = EboType; public: Vbo m_vertex_buffer; Ebo m_element_buffer_object; Mesh(Vbo vbo, Ebo vao, const VectorType scale = { 1, 1, 1, }) : m_vertex_buffer(std::move(vbo)), m_element_buffer_object(std::move(vao)), m_scale(std::move(scale)) { } void set_origin(const VectorType& new_origin) { m_origin = new_origin; m_to_world_matrix = std::nullopt; } void set_scale(const VectorType& new_scale) { m_scale = new_scale; m_to_world_matrix = std::nullopt; } void set_rotation(const RotationAngles& new_rotation_angles) { m_rotation_angles = new_rotation_angles; m_to_world_matrix = std::nullopt; } [[nodiscard]] const VectorType& get_origin() const { return m_origin; } [[nodiscard]] const VectorType& get_scale() const { return m_scale; } [[nodiscard]] const RotationAngles& get_rotation_angles() const { return m_rotation_angles; } [[nodiscard]] const Mat4X4& get_to_world_matrix() const { if (m_to_world_matrix) return m_to_world_matrix.value(); m_to_world_matrix = mat_translation(m_origin) * MeshTypeTrait::rotation_matrix(m_rotation_angles) * mat_scale(m_scale); return m_to_world_matrix.value(); } [[nodiscard]] VectorType vertex_position_to_world_space(const Vector3& vertex_position) const { auto abs_vec = get_to_world_matrix() * mat_column_from_vector( vertex_position); return {abs_vec.at(0, 0), abs_vec.at(1, 0), abs_vec.at(2, 0)}; } [[nodiscard]] Triangle make_face_in_world_space(const Ebo::const_iterator vao_iterator) const { if constexpr (HasPosition) { return {vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->x).position), vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->y).position), vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->z).position)}; } return {vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->x)), vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->y)), vertex_position_to_world_space(m_vertex_buffer.at(vao_iterator->z))}; } private: VectorType m_origin; VectorType m_scale; RotationAngles m_rotation_angles; mutable std::optional m_to_world_matrix; }; } // namespace omath::primitives