From c0937a48153c593592473b9cc54deae6aa0b9612 Mon Sep 17 00:00:00 2001 From: Gelis Date: Mon, 5 Feb 2024 14:26:43 +0200 Subject: [PATCH] Added ray ray collision (collision(q,q)) --- TEST_Geometry2D.cpp | 7 +++++++ olcUTIL_Geometry2D.h | 47 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index fbdb6ee..91150da 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -373,6 +373,13 @@ class Test_Geometry2D : public olc::PixelGameEngine { DrawShape(ray1, olc::CYAN); DrawShape(ray2, olc::CYAN); + Ray rayTest1 = { Ray{{ { 10.0f, 10.0f }, olc::vf2d(GetMousePos())} }}; + Ray rayTest2 = { Ray{{ { float(ScreenWidth() - 10), 10.0f }, olc::vf2d(GetMousePos())} }}; + const auto RayCol = collision(make_internal(rayTest1), make_internal(rayTest2)); + if(RayCol.has_value()){ + FillCircle(RayCol.value().first, 5, olc::WHITE); + DrawLine(RayCol.value().first, RayCol.value().first + RayCol.value().second * 40, olc::RED); + } } // Laser beam diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index cedf02a..f4f7985 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -2219,6 +2219,51 @@ namespace olc::utils::geom2d return std::nullopt; } + // collision(q,q) + // optionally returns collision point and collision normal of ray and a ray, if it collides + template + inline std::optional, olc::v_2d>> collision(const ray& q1, const ray& q2) + { + //ray1 : y = ax + b + float Slope1 = q1.direction.y / q1.direction.x; + //line offset + float b1 = q1.origin.y - Slope1*q1.origin.x; + //ray2 : y = ax + b + float Slope2 = q2.direction.y / q2.direction.x; + //line offset + float b2 = q2.origin.y - Slope2*q2.origin.x; + if(q1.direction.x == 0){ + //ray1 is vertical. + olc::v_2d Point; + Point.x = q1.origin.x; + Point.y = Slope2 * Point.x + b2; + + olc::v_2d Normal(1, 0); + return { {Point, Normal.norm()} }; + } + if(q2.direction.x == 0){ + //ray2 is vertical. + olc::v_2d Point; + Point.x = q2.origin.x; + Point.y = Slope1 * Point.x + b2; + + olc::v_2d Normal(Slope1, -1); + return { {Point, Normal.norm()} }; + } + if(Slope1 == Slope2){ + //Lines are parallel so no intersection. + return std::nullopt; + } + + //Solve the ray equations to find the intersection. + olc::v_2d Point; + Point.x = (b2 - b1)/(Slope1 - Slope2); + Point.y = Slope1 * Point.x + b1; + + olc::v_2d Normal(Slope1, -1); + return { {Point, Normal.norm()} }; + } + // reflect(q,l) // optionally returns a ray reflected off a line segement if collision occurs template @@ -2243,7 +2288,7 @@ namespace olc::utils::geom2d } // collision(q,r) - // optionally returns collision point and collision normal of ray and a line segment, if it collides + // optionally returns collision point and collision normal of ray and a rectangle, if it collides template inline std::optional, olc::v_2d>> collision(const ray& q, const rect& r) {