diff --git a/include/omath/3d_primitives/mesh.hpp b/include/omath/3d_primitives/mesh.hpp index e60223e..cc09a5b 100644 --- a/include/omath/3d_primitives/mesh.hpp +++ b/include/omath/3d_primitives/mesh.hpp @@ -10,9 +10,13 @@ namespace omath::primitives { - template + template class Mesh final { + public: + using NumericType = Type; + + private: using Vbo = std::vector>; using Vao = std::vector>; @@ -20,9 +24,9 @@ namespace omath::primitives Vbo m_vertex_buffer; Vao m_vertex_array_object; - Mesh(Vbo vbo, Vao vao): m_vertex_buffer(std::move(vbo)), m_vertex_array_object(std::move(vao)) + Mesh(Vbo vbo, Vao vao, const Vector3 scale = {1, 1, 1,}) + : m_vertex_buffer(std::move(vbo)), m_vertex_array_object(std::move(vao)), m_scale(scale) { - } void set_origin(const Vector3& new_origin) { @@ -78,12 +82,13 @@ namespace omath::primitives return {abs_vec.at(0, 0), abs_vec.at(1, 0), abs_vec.at(2, 0)}; } + [[nodiscard]] - Triangle> make_face_in_world_space(const Vao::const_iterator index) const + Triangle> make_face_in_world_space(const Vao::const_iterator vao_iterator) const { - return {vertex_to_world_space(m_vertex_buffer.at(index->x)), - vertex_to_world_space(m_vertex_buffer.at(index->y)), - vertex_to_world_space(m_vertex_buffer.at(index->z))}; + return {vertex_to_world_space(m_vertex_buffer.at(vao_iterator->x)), + vertex_to_world_space(m_vertex_buffer.at(vao_iterator->y)), + vertex_to_world_space(m_vertex_buffer.at(vao_iterator->z))}; } private: diff --git a/include/omath/collision/gjk_algorithm.hpp b/include/omath/collision/gjk_algorithm.hpp index 1380476..886e4d2 100644 --- a/include/omath/collision/gjk_algorithm.hpp +++ b/include/omath/collision/gjk_algorithm.hpp @@ -9,7 +9,7 @@ namespace omath::collision { - template> + template class GjkAlgorithm final { public: diff --git a/include/omath/collision/mesh_collider.hpp b/include/omath/collision/mesh_collider.hpp index 618ea52..ff1438a 100644 --- a/include/omath/collision/mesh_collider.hpp +++ b/include/omath/collision/mesh_collider.hpp @@ -5,52 +5,39 @@ #pragma once #include "omath/engines/source_engine/traits/pred_engine_trait.hpp" #include "omath/linear_algebra/vector3.hpp" +#include #include namespace omath::collision { - template + template class MeshCollider { public: + using NumericType = MeshType::NumericType; + using VertexType = Vector3; - MeshCollider(const std::vector& vertexes, const VertexType& origin, - const VertexType& scale = {1.f, 1.f, 1.f}) - : m_vertexes(vertexes), m_scale(scale), m_origin(origin) + explicit MeshCollider(MeshType mesh): m_mesh(std::move(mesh)) { - if (m_vertexes.empty()) - throw std::runtime_error("Collider cannot have 0 vertexes"); - } - std::vector> m_vertexes; - Vector3 m_scale; - Vector3 m_origin; - source_engine::ViewAngles m_rotation; - - [[nodiscard]] - source_engine::Mat4X4 to_world() const - { - return mat_translation(m_origin) * mat_scale(m_scale) * source_engine::rotation_matrix(m_rotation); } [[nodiscard]] const Vector3& find_furthest_vertex(const Vector3& direction) const { - return *std::ranges::max_element(m_vertexes, [&direction](const auto& first, const auto& second) - { return first.dot(direction) < second.dot(direction); }); + return *std::ranges::max_element(m_mesh.m_vertex_buffer, [&direction](const auto& first, const auto& second) + { + return first.dot(direction) < second.dot(direction); + }); } [[nodiscard]] Vector3 find_abs_furthest_vertex(const Vector3& direction) const { - return vertex_to_world_space(find_furthest_vertex(direction)); + return m_mesh.vertex_to_world_space(find_furthest_vertex(direction)); } - [[nodiscard]] Vector3 vertex_to_world_space(const Vector3& local_vertex) const - { - auto abs_vec = to_world() * mat_column_from_vector(local_vertex); - - return {abs_vec.at(0, 0), abs_vec.at(1, 0), abs_vec.at(2, 0)}; - } + private: + MeshType m_mesh; }; } // namespace omath::collision \ No newline at end of file diff --git a/include/omath/engines/source_engine/collider.hpp b/include/omath/engines/source_engine/collider.hpp new file mode 100644 index 0000000..2c8d9b9 --- /dev/null +++ b/include/omath/engines/source_engine/collider.hpp @@ -0,0 +1,13 @@ +// +// Created by Vladislav on 09.11.2025. +// + +#pragma once +#include "mesh.hpp" +#include "omath/3d_primitives/mesh.hpp" +#include "omath/collision/mesh_collider.hpp" + +namespace omath::source_engine +{ + using MeshCollider = collision::MeshCollider; +} \ No newline at end of file diff --git a/include/omath/engines/source_engine/mesh.hpp b/include/omath/engines/source_engine/mesh.hpp new file mode 100644 index 0000000..31956b3 --- /dev/null +++ b/include/omath/engines/source_engine/mesh.hpp @@ -0,0 +1,12 @@ +// +// Created by Vladislav on 09.11.2025. +// +#pragma once +#include "constants.hpp" +#include "omath/3d_primitives/mesh.hpp" +#include "traits/mesh_trait.hpp" + +namespace omath::source_engine +{ + using Mesh = primitives::Mesh; +} \ No newline at end of file diff --git a/include/omath/engines/source_engine/traits/mesh_trait.hpp b/include/omath/engines/source_engine/traits/mesh_trait.hpp new file mode 100644 index 0000000..d2418d5 --- /dev/null +++ b/include/omath/engines/source_engine/traits/mesh_trait.hpp @@ -0,0 +1,18 @@ +// +// Created by Vladislav on 09.11.2025. +// +#pragma once +#include +#include +namespace omath::source_engine +{ + class MeshTrait final + { + public: + [[nodiscard]] + static Mat4X4 rotation_matrix(const ViewAngles& rotation) + { + return source_engine::rotation_matrix(rotation); + } + }; +} \ No newline at end of file diff --git a/tests/general/unit_test_colider.cpp b/tests/general/unit_test_colider.cpp index 97f0eff..57d8b08 100644 --- a/tests/general/unit_test_colider.cpp +++ b/tests/general/unit_test_colider.cpp @@ -1,16 +1,15 @@ // // Created by Vlad on 11/9/2025. // +#include "omath/engines/source_engine/collider.hpp" #include #include - - TEST(UnitTestColider, CheckToWorld) { - const std::vector> mesh = {{1.f, 1.f, 1.f}, {-1.f, -1.f, -1.f}}; - - const omath::collision::MeshCollider collider(mesh, {0.f, 2.f, 0.f}); + omath::source_engine::Mesh mesh = {std::vector>{{1.f, 1.f, 1.f}, {-1.f, -1.f, -1.f}}, {}}; + mesh.set_origin({0, 2, 0}); + const omath::source_engine::MeshCollider collider(mesh); const auto vertex = collider.find_abs_furthest_vertex({1.f, 0.f, 0.f}); @@ -19,8 +18,8 @@ TEST(UnitTestColider, CheckToWorld) TEST(UnitTestColider, FindFurthestVertex) { - const std::vector> mesh = {{1.f, 1.f, 1.f}, {-1.f, -1.f, -1.f}}; - const omath::collision::MeshCollider collider(mesh, {0.f, 0.f, 0.f}); + const omath::source_engine::Mesh mesh = {{{1.f, 1.f, 1.f}, {-1.f, -1.f, -1.f}}, {}}; + const omath::source_engine::MeshCollider collider(mesh); const auto vertex = collider.find_furthest_vertex({1.f, 0.f, 0.f}); EXPECT_EQ(vertex, omath::Vector3(1.f, 1.f, 1.f)); } diff --git a/tests/general/unit_test_gjk.cpp b/tests/general/unit_test_gjk.cpp index f19b57e..ab1c7ce 100644 --- a/tests/general/unit_test_gjk.cpp +++ b/tests/general/unit_test_gjk.cpp @@ -1,47 +1,55 @@ // // Created by Vlad on 11/9/2025. // +#include "omath/engines/source_engine/collider.hpp" #include #include - +#include namespace { - const std::vector> mesh = { - {-1.f, -1.f, -1.f}, - {-1.f, -1.f, 1.f}, - {-1.f, 1.f, -1.f}, - {-1.f, 1.f, 1.f}, - { 1.f, 1.f, 1.f}, // x = +1 vertices (put {1,1,1} first in case your support breaks ties by first-hit) - { 1.f, 1.f, -1.f}, - { 1.f, -1.f, 1.f}, - { 1.f, -1.f, -1.f} - }; + const omath::source_engine::Mesh mesh = { + {{-1.f, -1.f, -1.f}, + {-1.f, -1.f, 1.f}, + {-1.f, 1.f, -1.f}, + {-1.f, 1.f, 1.f}, + {1.f, 1.f, 1.f}, // x = +1 vertices (put {1,1,1} first in case your support breaks ties by first-hit) + {1.f, 1.f, -1.f}, + {1.f, -1.f, 1.f}, + {1.f, -1.f, -1.f}}, + {}}; } TEST(UnitTestGjk, TestCollisionTrue) { - const omath::collision::MeshCollider collider_a(mesh, {0.f, 0.f, 0.f}); - const omath::collision::MeshCollider collider_b(mesh, {0.f, 0.5f, 0.f}); - const auto result = omath::collision::GjkAlgorithm<>::is_collide(collider_a, collider_b); + const omath::source_engine::MeshCollider collider_a(mesh); + + auto mesh_b = mesh; + mesh_b.set_origin({0.f, 0.5f, 0.f}); + const omath::source_engine::MeshCollider collider_b(mesh_b); + + const auto result = + omath::collision::GjkAlgorithm::is_collide(collider_a, collider_b); EXPECT_TRUE(result); } TEST(UnitTestGjk, TestCollisionFalse) { - const omath::collision::MeshCollider collider_a(mesh, {0.f, 0.f, 0.f}); - const omath::collision::MeshCollider collider_b(mesh, {0.f, 2.1f, 0.f}); + const omath::source_engine::MeshCollider collider_a(mesh); + auto mesh_b = mesh; + mesh_b.set_origin({0.f, 2.1f, 0.f}); + const omath::source_engine::MeshCollider collider_b(mesh_b); - const auto result = omath::collision::GjkAlgorithm<>::is_collide(collider_a, collider_b); + const auto result = omath::collision::GjkAlgorithm::is_collide(collider_a, collider_b); EXPECT_FALSE(result); } TEST(UnitTestGjk, TestCollisionEqualOrigin) { - const omath::collision::MeshCollider collider_a(mesh, {0.f, 0.f, 0.f}); - const omath::collision::MeshCollider collider_b(mesh, {0.f, 0.f, 0.f}); + const omath::source_engine::MeshCollider collider_a(mesh); + const omath::source_engine::MeshCollider collider_b(mesh); - const auto result = omath::collision::GjkAlgorithm<>::is_collide(collider_a, collider_b); + const auto result = omath::collision::GjkAlgorithm::is_collide(collider_a, collider_b); EXPECT_TRUE(result); } \ No newline at end of file