From 7fb5ea47ddf6526ab0e9b6a7f94f4f885551a227 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 9 Dec 2025 08:18:04 +0300 Subject: [PATCH 01/14] added check method --- include/omath/projection/camera.hpp | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/include/omath/projection/camera.hpp b/include/omath/projection/camera.hpp index 35bb1f0..291f189 100644 --- a/include/omath/projection/camera.hpp +++ b/include/omath/projection/camera.hpp @@ -5,6 +5,7 @@ #pragma once #include "omath/linear_algebra/mat.hpp" +#include "omath/linear_algebra/triangle.hpp" #include "omath/linear_algebra/vector3.hpp" #include "omath/projection/error_codes.hpp" #include @@ -175,6 +176,53 @@ namespace omath::projection std::unreachable(); } + [[nodiscard]] bool is_culled_by_frustum(const Triangle>& triangle) const noexcept + { + // Transform to clip space (before perspective divide) + auto to_clip = [this](const Vector3& point) + { + auto clip = get_view_projection_matrix() + * mat_column_from_vector(point); + return std::array{ + clip.at(0, 0), // x + clip.at(1, 0), // y + clip.at(2, 0), // z + clip.at(3, 0) // w + }; + }; + + const auto c0 = to_clip(triangle.m_vertex1); + const auto c1 = to_clip(triangle.m_vertex2); + const auto c2 = to_clip(triangle.m_vertex3); + + // If all vertices are behind the camera (w <= 0), trivially reject + if (c0[3] <= 0.f && c1[3] <= 0.f && c2[3] <= 0.f) + return true; + + // Helper: all three vertices outside the same clip plane + auto all_outside_plane = [](const int axis, const std::array& a, const std::array& b, + const std::array& c, const bool positive_side) + { + if (positive_side) + return a[axis] > a[3] && b[axis] > b[3] && c[axis] > c[3]; + return a[axis] < -a[3] && b[axis] < -b[3] && c[axis] < -c[3]; + }; + + // Clip volume in clip space (OpenGL-style): + // -w <= x <= w + // -w <= y <= w + // -w <= z <= w + + for (int i = 0; i < 3; i++) + { + if (all_outside_plane(i, c0, c1, c2, false)) + return true; // x < -w (left) + if (all_outside_plane(i, c0, c1, c2, true)) + return true; // x > w (right) + } + return false; + } + [[nodiscard]] std::expected, Error> world_to_view_port(const Vector3& world_position) const noexcept { From 17e21cde4b302e55f222f5a01911fe6c245f4c4d Mon Sep 17 00:00:00 2001 From: Orange Date: Fri, 12 Dec 2025 18:34:56 +0300 Subject: [PATCH 02/14] added missing include --- include/omath/collision/collider_interface.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/omath/collision/collider_interface.hpp b/include/omath/collision/collider_interface.hpp index b27487b..7047d7c 100644 --- a/include/omath/collision/collider_interface.hpp +++ b/include/omath/collision/collider_interface.hpp @@ -2,7 +2,7 @@ // Created by Vladislav on 06.12.2025. // #pragma once - +#include namespace omath::collision { From 60a3a42140b922c6468d41f53ed2729534c8bdaf Mon Sep 17 00:00:00 2001 From: Orange Date: Sat, 13 Dec 2025 00:06:45 +0300 Subject: [PATCH 03/14] improved pmr stuff --- include/omath/collision/epa_algorithm.hpp | 33 +++++++++++++---------- tests/general/unit_test_epa.cpp | 4 +-- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index e98cf05..5b88149 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -50,24 +50,23 @@ namespace omath::collision [[nodiscard]] static std::optional solve(const ColliderInterfaceType& a, const ColliderInterfaceType& b, const Simplex& simplex, const Params params = {}, - std::shared_ptr mem_resource = { - std::shared_ptr{}, std::pmr::get_default_resource()}) + std::pmr::memory_resource& mem_resource = *std::pmr::get_default_resource()) { // --- Build initial polytope from simplex (4 points) --- - std::pmr::vector vertexes{mem_resource.get()}; + std::pmr::vector vertexes{&mem_resource}; vertexes.reserve(simplex.size()); for (std::size_t i = 0; i < simplex.size(); ++i) vertexes.emplace_back(simplex[i]); // Initial tetra faces (windings corrected in make_face) - std::pmr::vector faces{mem_resource.get()}; + std::pmr::vector faces{&mem_resource}; faces.reserve(4); faces.emplace_back(make_face(vertexes, 0, 1, 2)); faces.emplace_back(make_face(vertexes, 0, 2, 3)); faces.emplace_back(make_face(vertexes, 0, 3, 1)); faces.emplace_back(make_face(vertexes, 1, 3, 2)); - auto heap = rebuild_heap(faces); + auto heap = rebuild_heap(faces, mem_resource); Result out{}; @@ -80,7 +79,7 @@ namespace omath::collision // (We could keep face handles; this is fine for small Ns.) if (const auto top = heap.top(); faces[top.idx].d != top.d) - heap = rebuild_heap(faces); + heap = rebuild_heap(faces, mem_resource); if (heap.empty()) break; @@ -110,8 +109,8 @@ namespace omath::collision vertexes.emplace_back(p); // Mark faces visible from p and collect their horizon - std::pmr::vector to_delete(faces.size(), false, mem_resource.get()); // uses single bits - std::pmr::vector boundary{mem_resource.get()}; + std::pmr::vector to_delete(faces.size(), false, &mem_resource); // uses single bits + std::pmr::vector boundary{&mem_resource}; boundary.reserve(faces.size() * 2); for (int i = 0; i < static_cast(faces.size()); ++i) @@ -129,7 +128,7 @@ namespace omath::collision } // Remove visible faces - std::pmr::vector new_faces{mem_resource.get()}; + std::pmr::vector new_faces{&mem_resource}; new_faces.reserve(faces.size() + boundary.size()); for (int i = 0; i < static_cast(faces.size()); ++i) if (!to_delete[i]) @@ -141,7 +140,7 @@ namespace omath::collision faces.emplace_back(make_face(vertexes, e.a, e.b, new_idx)); // Rebuild heap after topology change - heap = rebuild_heap(faces); + heap = rebuild_heap(faces, mem_resource); if (!std::isfinite(vertexes.back().dot(vertexes.back()))) break; // safety @@ -193,15 +192,21 @@ namespace omath::collision return lhs.d > rhs.d; // min-heap by distance } }; - using Heap = std::priority_queue, HeapCmp>; + + using Heap = std::priority_queue, HeapCmp>; [[nodiscard]] - static Heap rebuild_heap(const std::pmr::vector& faces) + static Heap rebuild_heap(const std::pmr::vector& faces, auto& memory_resource) { - Heap h; + std::pmr::vector storage{ &memory_resource }; + storage.reserve(faces.size()); // optional but recommended + + Heap h{ HeapCmp{}, std::move(storage) }; + for (int i = 0; i < static_cast(faces.size()); ++i) h.emplace(faces[i].d, i); - return h; + + return h; // allocator is preserved } [[nodiscard]] diff --git a/tests/general/unit_test_epa.cpp b/tests/general/unit_test_epa.cpp index 3e8d0ad..97838d3 100644 --- a/tests/general/unit_test_epa.cpp +++ b/tests/general/unit_test_epa.cpp @@ -45,7 +45,7 @@ TEST(UnitTestEpa, TestCollisionTrue) auto pool = std::make_shared(1024); params.max_iterations = 64; params.tolerance = 1e-4f; - auto epa = EPA::solve(A, B, gjk.simplex, params, pool); + auto epa = EPA::solve(A, B, gjk.simplex, params, *pool); ASSERT_TRUE(epa.has_value()) << "EPA should converge"; // Normal is unit @@ -119,7 +119,7 @@ TEST(UnitTestEpa, TestCollisionTrue2) params.max_iterations = 64; params.tolerance = 1e-4f; auto pool = std::make_shared(1024); - auto epa = EPA::solve(A, B, gjk.simplex, params, pool); + auto epa = EPA::solve(A, B, gjk.simplex, params, *pool); ASSERT_TRUE(epa.has_value()) << "EPA should converge"; // Normal is unit-length From c9ac61935e320d51e20b04ce4072e83625395d06 Mon Sep 17 00:00:00 2001 From: Orange Date: Sat, 13 Dec 2025 23:34:15 +0300 Subject: [PATCH 04/14] updated preset file --- CMakePresets.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index d9f232d..5b8b205 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -38,7 +38,7 @@ }, { "name": "windows-debug-vcpkg", - "displayName": "Debug", + "displayName": "Windows Debug Vcpkg", "inherits": "windows-base-vcpkg", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" @@ -46,7 +46,7 @@ }, { "name": "windows-release-vcpkg", - "displayName": "Release", + "displayName": "Windows Release Vcpkg", "inherits": "windows-base-vcpkg", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", @@ -157,7 +157,7 @@ }, { "name": "darwin-debug-vcpkg", - "displayName": "Darwin Debug", + "displayName": "Darwin Debug Vcpkg", "inherits": "darwin-base-vcpkg", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" @@ -173,7 +173,7 @@ }, { "name": "darwin-release-vcpkg", - "displayName": "Darwin Release", + "displayName": "Darwin Release Vcpkg", "inherits": "darwin-base-vcpkg", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" From bf30957acffdb0c6c6b7551d2afcc199a33ed39e Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 09:50:46 +0300 Subject: [PATCH 05/14] renamed stuff --- include/omath/3d_primitives/mesh.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/omath/3d_primitives/mesh.hpp b/include/omath/3d_primitives/mesh.hpp index cc2e5e4..bac5513 100644 --- a/include/omath/3d_primitives/mesh.hpp +++ b/include/omath/3d_primitives/mesh.hpp @@ -38,7 +38,7 @@ namespace omath::primitives public: Vbo m_vertex_buffer; - Ebo m_vertex_array_object; + Ebo m_element_buffer_object; Mesh(Vbo vbo, Ebo vao, const VectorType scale = @@ -47,7 +47,7 @@ namespace omath::primitives 1, 1, }) - : m_vertex_buffer(std::move(vbo)), m_vertex_array_object(std::move(vao)), m_scale(std::move(scale)) + : 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) From 2ddf29b158c62423b20aa01f11a4b87f58d1045f Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 09:53:12 +0300 Subject: [PATCH 06/14] style fix --- include/omath/collision/epa_algorithm.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index 5b88149..e2bb72c 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -19,7 +19,7 @@ namespace omath::collision { a.cross(b) } -> std::same_as; { a.dot(b) } -> std::same_as; { -a } -> std::same_as; - { a* s } -> std::same_as; + { a * s } -> std::same_as; { a / s } -> std::same_as; }; @@ -198,10 +198,10 @@ namespace omath::collision [[nodiscard]] static Heap rebuild_heap(const std::pmr::vector& faces, auto& memory_resource) { - std::pmr::vector storage{ &memory_resource }; + std::pmr::vector storage{&memory_resource}; storage.reserve(faces.size()); // optional but recommended - Heap h{ HeapCmp{}, std::move(storage) }; + Heap h{HeapCmp{}, std::move(storage)}; for (int i = 0; i < static_cast(faces.size()); ++i) h.emplace(faces[i].d, i); From f3b74fe43399dfd7c5999ab2b15ea1d66a90b619 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 10:18:58 +0300 Subject: [PATCH 07/14] removed useless comment --- include/omath/collision/epa_algorithm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index e2bb72c..a009300 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -1,6 +1,6 @@ #pragma once #include "simplex.hpp" -#include // find_if +#include #include #include #include From b6ac0a1d612aafb3f15cf7f7348526ac926775d8 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 10:26:36 +0300 Subject: [PATCH 08/14] decomposed into method --- include/omath/collision/epa_algorithm.hpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index a009300..9427f26 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -45,7 +45,6 @@ namespace omath::collision int max_iterations{64}; float tolerance{1e-4f}; // absolute tolerance on distance growth }; - // Precondition: simplex.size()==4 and contains the origin. [[nodiscard]] static std::optional solve(const ColliderInterfaceType& a, const ColliderInterfaceType& b, @@ -59,12 +58,7 @@ namespace omath::collision vertexes.emplace_back(simplex[i]); // Initial tetra faces (windings corrected in make_face) - std::pmr::vector faces{&mem_resource}; - faces.reserve(4); - faces.emplace_back(make_face(vertexes, 0, 1, 2)); - faces.emplace_back(make_face(vertexes, 0, 2, 3)); - faces.emplace_back(make_face(vertexes, 0, 3, 1)); - faces.emplace_back(make_face(vertexes, 1, 3, 2)); + std::pmr::vector faces = create_initial_tetra_faces(mem_resource, vertexes); auto heap = rebuild_heap(faces, mem_resource); @@ -272,5 +266,16 @@ namespace omath::collision return d; return V{1, 0, 0}; } + static std::pmr::vector create_initial_tetra_faces(std::pmr::memory_resource& mem_resource, + const std::pmr::vector& vertexes) + { + std::pmr::vector faces{&mem_resource}; + faces.reserve(4); + faces.emplace_back(make_face(vertexes, 0, 1, 2)); + faces.emplace_back(make_face(vertexes, 0, 2, 3)); + faces.emplace_back(make_face(vertexes, 0, 3, 1)); + faces.emplace_back(make_face(vertexes, 1, 3, 2)); + return faces; + } }; } // namespace omath::collision From a94c78f834b30894a5be075b1e25454b61ee4f63 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 10:39:23 +0300 Subject: [PATCH 09/14] added nodiscard --- include/omath/collision/epa_algorithm.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index 9427f26..599b4d8 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -111,6 +111,7 @@ namespace omath::collision { if (to_delete[i]) continue; + if (visible_from(faces[i], p)) { const auto& rf = faces[i]; @@ -266,6 +267,7 @@ namespace omath::collision return d; return V{1, 0, 0}; } + [[nodiscard]] static std::pmr::vector create_initial_tetra_faces(std::pmr::memory_resource& mem_resource, const std::pmr::vector& vertexes) { From 257b06c552b632e73f627599152814037629539c Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 10:42:23 +0300 Subject: [PATCH 10/14] extracted to methdod --- include/omath/collision/epa_algorithm.hpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index 599b4d8..baaaa6d 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -52,10 +52,7 @@ namespace omath::collision std::pmr::memory_resource& mem_resource = *std::pmr::get_default_resource()) { // --- Build initial polytope from simplex (4 points) --- - std::pmr::vector vertexes{&mem_resource}; - vertexes.reserve(simplex.size()); - for (std::size_t i = 0; i < simplex.size(); ++i) - vertexes.emplace_back(simplex[i]); + std::pmr::vector vertexes = build_initial_polytope_from_simplex(simplex, mem_resource); // Initial tetra faces (windings corrected in make_face) std::pmr::vector faces = create_initial_tetra_faces(mem_resource, vertexes); @@ -279,5 +276,18 @@ namespace omath::collision faces.emplace_back(make_face(vertexes, 1, 3, 2)); return faces; } + + [[nodiscard]] + static std::pmr::vector build_initial_polytope_from_simplex(const Simplex& simplex, + std::pmr::memory_resource& mem_resource) + { + std::pmr::vector vertexes{&mem_resource}; + vertexes.reserve(simplex.size()); + + for (std::size_t i = 0; i < simplex.size(); ++i) + vertexes.emplace_back(simplex[i]); + + return vertexes; + } }; } // namespace omath::collision From adce4a808a109793b5babd0b4c8c7cb172345a4a Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 10:59:38 +0300 Subject: [PATCH 11/14] improved readability --- include/omath/collision/epa_algorithm.hpp | 71 +++++++++++++---------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index baaaa6d..c7517ac 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -99,33 +99,9 @@ namespace omath::collision const int new_idx = static_cast(vertexes.size()); vertexes.emplace_back(p); - // Mark faces visible from p and collect their horizon - std::pmr::vector to_delete(faces.size(), false, &mem_resource); // uses single bits - std::pmr::vector boundary{&mem_resource}; - boundary.reserve(faces.size() * 2); + auto [to_delete, boundary] = mark_visible_and_collect_horizon(faces, p); - for (int i = 0; i < static_cast(faces.size()); ++i) - { - if (to_delete[i]) - continue; - - if (visible_from(faces[i], p)) - { - const auto& rf = faces[i]; - to_delete[i] = true; - add_edge_boundary(boundary, rf.i0, rf.i1); - add_edge_boundary(boundary, rf.i1, rf.i2); - add_edge_boundary(boundary, rf.i2, rf.i0); - } - } - - // Remove visible faces - std::pmr::vector new_faces{&mem_resource}; - new_faces.reserve(faces.size() + boundary.size()); - for (int i = 0; i < static_cast(faces.size()); ++i) - if (!to_delete[i]) - new_faces.emplace_back(faces[i]); - faces.swap(new_faces); + erase_marked(faces, to_delete); // Stitch new faces around the horizon for (const auto& e : boundary) @@ -142,10 +118,8 @@ namespace omath::collision // Fallback: pick closest face as best-effort answer if (!faces.empty()) { - auto best = faces[0]; - for (const auto& f : faces) - if (f.d < best.d) - best = f; + const auto best = *std::ranges::min_element(faces, [](const auto& first, const auto& second) + { return first.d < second.d; }); out.normal = best.n; out.depth = best.d; out.num_vertices = static_cast(vertexes.size()); @@ -289,5 +263,42 @@ namespace omath::collision return vertexes; } + static void erase_marked(std::pmr::vector& faces, const std::pmr::vector& to_delete) + { + auto* mr = faces.get_allocator().resource(); // keep same resource + std::pmr::vector kept{mr}; + kept.reserve(faces.size()); + + for (std::size_t i = 0; i < faces.size(); ++i) + if (!to_delete[i]) + kept.emplace_back(faces[i]); + + faces.swap(kept); + } + struct Horizon + { + std::pmr::vector to_delete; + std::pmr::vector boundary; + }; + + static Horizon mark_visible_and_collect_horizon(const std::pmr::vector& faces, const VectorType& p) + { + auto* mr = faces.get_allocator().resource(); + + Horizon out{std::pmr::vector(faces.size(), false, mr), std::pmr::vector(mr)}; + out.boundary.reserve(faces.size() * 2); + + for (std::size_t i = 0; i < faces.size(); ++i) + if (visible_from(faces[i], p)) + { + const auto& rf = faces[i]; + out.to_delete[i] = true; + add_edge_boundary(out.boundary, rf.i0, rf.i1); + add_edge_boundary(out.boundary, rf.i1, rf.i2); + add_edge_boundary(out.boundary, rf.i2, rf.i0); + } + + return out; + } }; } // namespace omath::collision From 4ad44badb940033ec5366102610c036a9904717c Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 11:05:24 +0300 Subject: [PATCH 12/14] removed double size reserve --- include/omath/collision/epa_algorithm.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index c7517ac..7b5a678 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -285,20 +285,20 @@ namespace omath::collision { auto* mr = faces.get_allocator().resource(); - Horizon out{std::pmr::vector(faces.size(), false, mr), std::pmr::vector(mr)}; - out.boundary.reserve(faces.size() * 2); + Horizon horizon{std::pmr::vector(faces.size(), false, mr), std::pmr::vector(mr)}; + horizon.boundary.reserve(faces.size()); for (std::size_t i = 0; i < faces.size(); ++i) if (visible_from(faces[i], p)) { const auto& rf = faces[i]; - out.to_delete[i] = true; - add_edge_boundary(out.boundary, rf.i0, rf.i1); - add_edge_boundary(out.boundary, rf.i1, rf.i2); - add_edge_boundary(out.boundary, rf.i2, rf.i0); + horizon.to_delete[i] = true; + add_edge_boundary(horizon.boundary, rf.i0, rf.i1); + add_edge_boundary(horizon.boundary, rf.i1, rf.i2); + add_edge_boundary(horizon.boundary, rf.i2, rf.i0); } - return out; + return horizon; } }; } // namespace omath::collision From e10cbf935683f72f2b0ec893cb31a9da858630e2 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 11:06:15 +0300 Subject: [PATCH 13/14] added const --- include/omath/collision/epa_algorithm.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index 7b5a678..0496b87 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -99,7 +99,7 @@ namespace omath::collision const int new_idx = static_cast(vertexes.size()); vertexes.emplace_back(p); - auto [to_delete, boundary] = mark_visible_and_collect_horizon(faces, p); + const auto [to_delete, boundary] = mark_visible_and_collect_horizon(faces, p); erase_marked(faces, to_delete); From 90c4ea20364fce12688bba71f6a1903a92a2d544 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 14 Dec 2025 11:08:06 +0300 Subject: [PATCH 14/14] removed nesting --- include/omath/collision/epa_algorithm.hpp | 24 +++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/include/omath/collision/epa_algorithm.hpp b/include/omath/collision/epa_algorithm.hpp index 0496b87..cd5ed36 100644 --- a/include/omath/collision/epa_algorithm.hpp +++ b/include/omath/collision/epa_algorithm.hpp @@ -115,21 +115,19 @@ namespace omath::collision out.iterations = it + 1; } - // Fallback: pick closest face as best-effort answer - if (!faces.empty()) - { - const auto best = *std::ranges::min_element(faces, [](const auto& first, const auto& second) - { return first.d < second.d; }); - out.normal = best.n; - out.depth = best.d; - out.num_vertices = static_cast(vertexes.size()); - out.num_faces = static_cast(faces.size()); + if (faces.empty()) + return std::nullopt; - out.penetration_vector = out.normal * out.depth; + const auto best = *std::ranges::min_element(faces, [](const auto& first, const auto& second) + { return first.d < second.d; }); + out.normal = best.n; + out.depth = best.d; + out.num_vertices = static_cast(vertexes.size()); + out.num_faces = static_cast(faces.size()); - return out; - } - return std::nullopt; + out.penetration_vector = out.normal * out.depth; + + return out; } private: