diff --git a/scenes/engine/AABB.c b/scenes/engine/AABB.c index 1c25f82..7f03951 100644 --- a/scenes/engine/AABB.c +++ b/scenes/engine/AABB.c @@ -49,3 +49,45 @@ bool point_in_AABB(Vector2 point, Rectangle box) && point.y < box.y + box.height ); } + +bool line_in_AABB(Vector2 p1, Vector2 p2, Rectangle box) +{ + float A = p2.y - p1.y; + float B = p1.x - p2.x; + float C = (p2.x * p1.y) - (p1.x * p2.y); + + Vector2 corners[3] = + { + {box.x + box.width - 1, box.y}, + {box.x + box.width - 1, box.y + box.height - 1}, + {box.x, box.y + box.height - 1}, + }; + + float F = (A * box.x + B * box.y + C); + uint8_t last_mode = 0; + if (fabs(F) < 1e-3) + { + last_mode = 0; + } + else + { + last_mode = (F > 0) ? 1 : 2; + } + for (uint8_t i = 0; i < 3; ++i) + { + + F = (A * corners[i].x + B * corners[i].y + C); + uint8_t mode = 0; + if (fabs(F) < 1e-3) + { + mode = 0; + } + else + { + mode = (F > 0) ? 1 : 2; + } + if (mode != last_mode) return true; + last_mode = mode; + } + return false; +} diff --git a/scenes/engine/AABB.h b/scenes/engine/AABB.h index fadc2be..f0d2f14 100644 --- a/scenes/engine/AABB.h +++ b/scenes/engine/AABB.h @@ -6,4 +6,5 @@ uint8_t find_1D_overlap(Vector2 l1, Vector2 l2, float* overlap); uint8_t find_AABB_overlap(const Vector2 tl1, const Vector2 sz1, const Vector2 tl2, const Vector2 sz2, Vector2* overlap); bool point_in_AABB(Vector2 point, Rectangle box); +bool line_in_AABB(Vector2 p1, Vector2 p2, Rectangle box); #endif // __AABB_H diff --git a/tests/test_AABB.c b/tests/test_AABB.c index 6c5b071..4b99f15 100644 --- a/tests/test_AABB.c +++ b/tests/test_AABB.c @@ -6,6 +6,44 @@ #include #include +static void test_line_AABB(void **state) +{ + (void) state; + + Vector2 p1 = {0, 0}; + Vector2 p2 = {20, 20}; + + Rectangle box = {5, 0, 10, 20}; + assert_true(line_in_AABB(p1, p2, box)); + + p1.y = 20; + assert_false(line_in_AABB(p1, p2, box)); + + p1.y = 19; + p2 = (Vector2){19, 19}; + assert_true(line_in_AABB(p1, p2, box)); + + p1.y = 0; + p2.y = 0; + assert_true(line_in_AABB(p1, p2, box)); + + p1 = (Vector2){5, 0}; + p2 = (Vector2){5, 10}; + assert_true(line_in_AABB(p1, p2, box)); + + p1 = (Vector2){14, 0}; + p2 = (Vector2){14, 10}; + assert_true(line_in_AABB(p1, p2, box)); + + p1 = (Vector2){15, 0}; + p2 = (Vector2){15, 10}; + assert_false(line_in_AABB(p1, p2, box)); + + p1 = (Vector2){0, 30}; + p2 = (Vector2){6, 35}; + assert_false(line_in_AABB(p1, p2, box)); +} + static void test_point_AABB(void **state) { (void) state; @@ -86,6 +124,7 @@ int main(void) cmocka_unit_test(test_1D_overlap), cmocka_unit_test(test_AABB_overlap), cmocka_unit_test(test_point_AABB), + cmocka_unit_test(test_line_AABB), }; return cmocka_run_group_tests(tests, NULL, NULL);