From 7db24a9ad59aeae3e9f8945c518074f76ef80820 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 19 Aug 2024 00:28:48 -0700 Subject: [PATCH] Simplify and fix Rect2/AABB get_support function --- core/math/aabb.h | 23 +++++++++++-------- core/math/rect2.h | 16 +++++++------ core/variant/variant_call.cpp | 3 ++- doc/classes/AABB.xml | 2 +- doc/classes/Rect2.xml | 7 ++++++ drivers/gles3/rasterizer_canvas_gles3.cpp | 2 +- .../glue/GodotSharp/GodotSharp/Core/Aabb.cs | 21 +++++++++++------ .../glue/GodotSharp/GodotSharp/Core/Rect2.cs | 20 ++++++++++++++++ .../renderer_rd/renderer_canvas_render_rd.cpp | 2 +- tests/core/math/test_aabb.h | 14 +++++------ tests/core/math/test_rect2.h | 22 ++++++++++++++++++ 11 files changed, 97 insertions(+), 35 deletions(-) diff --git a/core/math/aabb.h b/core/math/aabb.h index cb358ca7efc..7a5581b5d45 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -85,7 +85,7 @@ struct [[nodiscard]] AABB { bool intersects_plane(const Plane &p_plane) const; _FORCE_INLINE_ bool has_point(const Vector3 &p_point) const; - _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_normal) const; + _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_direction) const; Vector3 get_longest_axis() const; int get_longest_axis_index() const; @@ -212,15 +212,18 @@ inline bool AABB::encloses(const AABB &p_aabb) const { (src_max.z >= dst_max.z)); } -Vector3 AABB::get_support(const Vector3 &p_normal) const { - Vector3 half_extents = size * 0.5f; - Vector3 ofs = position + half_extents; - - return Vector3( - (p_normal.x > 0) ? half_extents.x : -half_extents.x, - (p_normal.y > 0) ? half_extents.y : -half_extents.y, - (p_normal.z > 0) ? half_extents.z : -half_extents.z) + - ofs; +Vector3 AABB::get_support(const Vector3 &p_direction) const { + Vector3 support = position; + if (p_direction.x > 0.0f) { + support.x += size.x; + } + if (p_direction.y > 0.0f) { + support.y += size.y; + } + if (p_direction.z > 0.0f) { + support.z += size.z; + } + return support; } Vector3 AABB::get_endpoint(int p_point) const { diff --git a/core/math/rect2.h b/core/math/rect2.h index 9cb341b6894..817923c1348 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -285,13 +285,15 @@ struct [[nodiscard]] Rect2 { return Rect2(position.round(), size.round()); } - Vector2 get_support(const Vector2 &p_normal) const { - Vector2 half_extents = size * 0.5f; - Vector2 ofs = position + half_extents; - return Vector2( - (p_normal.x > 0) ? -half_extents.x : half_extents.x, - (p_normal.y > 0) ? -half_extents.y : half_extents.y) + - ofs; + Vector2 get_support(const Vector2 &p_direction) const { + Vector2 support = position; + if (p_direction.x > 0.0f) { + support.x += size.x; + } + if (p_direction.y > 0.0f) { + support.y += size.y; + } + return support; } _FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const { diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 5e402937cf9..695ad23bf5c 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1849,6 +1849,7 @@ static void _register_variant_builtin_methods_math() { bind_method(Rect2, intersection, sarray("b"), varray()); bind_method(Rect2, merge, sarray("b"), varray()); bind_method(Rect2, expand, sarray("to"), varray()); + bind_method(Rect2, get_support, sarray("direction"), varray()); bind_method(Rect2, grow, sarray("amount"), varray()); bind_methodv(Rect2, grow_side, &Rect2::grow_side_bind, sarray("side", "amount"), varray()); bind_method(Rect2, grow_individual, sarray("left", "top", "right", "bottom"), varray()); @@ -2185,7 +2186,7 @@ static void _register_variant_builtin_methods_misc() { bind_method(AABB, merge, sarray("with"), varray()); bind_method(AABB, expand, sarray("to_point"), varray()); bind_method(AABB, grow, sarray("by"), varray()); - bind_method(AABB, get_support, sarray("dir"), varray()); + bind_method(AABB, get_support, sarray("direction"), varray()); bind_method(AABB, get_longest_axis, sarray(), varray()); bind_method(AABB, get_longest_axis_index, sarray(), varray()); bind_method(AABB, get_longest_axis_size, sarray(), varray()); diff --git a/doc/classes/AABB.xml b/doc/classes/AABB.xml index 77c74e17da7..188d9652a8c 100644 --- a/doc/classes/AABB.xml +++ b/doc/classes/AABB.xml @@ -206,7 +206,7 @@ - + Returns the vertex's position of this bounding box that's the farthest in the given direction. This point is commonly known as the support point in collision detection algorithms. diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml index ba7dcab2d76..f2c0b017bce 100644 --- a/doc/classes/Rect2.xml +++ b/doc/classes/Rect2.xml @@ -112,6 +112,13 @@ Returns the center point of the rectangle. This is the same as [code]position + (size / 2.0)[/code]. + + + + + Returns the vertex's position of this rect that's the farthest in the given direction. This point is commonly known as the support point in collision detection algorithms. + + diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 7a6df3d2a43..b9206f310e8 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1734,7 +1734,7 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha Vector2 center = p_clip_rect.get_center(); - float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center)); + float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(-light_dir)) - light_dir.dot(center)); Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance); float distance = to_edge_distance * 2.0 + p_cull_distance; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs index 33f0850a8d5..ef550eab0d4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs @@ -314,13 +314,20 @@ namespace Godot /// A vector representing the support. public readonly Vector3 GetSupport(Vector3 dir) { - Vector3 halfExtents = _size * 0.5f; - Vector3 ofs = _position + halfExtents; - - return ofs + new Vector3( - dir.X > 0f ? halfExtents.X : -halfExtents.X, - dir.Y > 0f ? halfExtents.Y : -halfExtents.Y, - dir.Z > 0f ? halfExtents.Z : -halfExtents.Z); + Vector3 support = _position; + if (dir.X > 0.0f) + { + support.X += _size.X; + } + if (dir.Y > 0.0f) + { + support.Y += _size.Y; + } + if (dir.Z > 0.0f) + { + support.Z += _size.Z; + } + return support; } /// diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index 19721b6ccaf..4f606cc6b3b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -171,6 +171,26 @@ namespace Godot return _position + (_size * 0.5f); } + /// + /// Returns the support point in a given direction. + /// This is useful for collision detection algorithms. + /// + /// The direction to find support for. + /// A vector representing the support. + public readonly Vector2 GetSupport(Vector2 direction) + { + Vector2 support = _position; + if (direction.X > 0.0f) + { + support.X += _size.X; + } + if (direction.Y > 0.0f) + { + support.Y += _size.Y; + } + return support; + } + /// /// Returns a copy of the grown by the specified amount /// on all sides. diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 5e4721dfb51..51fec8c206a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1823,7 +1823,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh Vector2 center = p_clip_rect.get_center(); - float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center)); + float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(-light_dir)) - light_dir.dot(center)); Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance); float distance = to_edge_distance * 2.0 + p_cull_distance; diff --git a/tests/core/math/test_aabb.h b/tests/core/math/test_aabb.h index dbc62bc2486..741e6af5d47 100644 --- a/tests/core/math/test_aabb.h +++ b/tests/core/math/test_aabb.h @@ -377,23 +377,23 @@ TEST_CASE("[AABB] Get longest/shortest axis") { TEST_CASE("[AABB] Get support") { const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6)); CHECK_MESSAGE( - aabb.get_support(Vector3(1, 0, 0)).is_equal_approx(Vector3(2.5, 2, -2.5)), + aabb.get_support(Vector3(1, 0, 0)) == Vector3(2.5, 2, -2.5), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0.5, 1, 0)).is_equal_approx(Vector3(2.5, 7, -2.5)), + aabb.get_support(Vector3(0.5, 1, 1)) == Vector3(2.5, 7, 3.5), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0.5, 1, -400)).is_equal_approx(Vector3(2.5, 7, -2.5)), + aabb.get_support(Vector3(0.5, 1, -400)) == Vector3(2.5, 7, -2.5), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0, -1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)), + aabb.get_support(Vector3(0, -1, 0)) == Vector3(-1.5, 2, -2.5), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3(0, -0.1, 0)).is_equal_approx(Vector3(-1.5, 2, -2.5)), + aabb.get_support(Vector3(0, -0.1, 0)) == Vector3(-1.5, 2, -2.5), "get_support() should return the expected value."); CHECK_MESSAGE( - aabb.get_support(Vector3()).is_equal_approx(Vector3(-1.5, 2, -2.5)), - "get_support() should return the expected value with a null vector."); + aabb.get_support(Vector3()) == Vector3(-1.5, 2, -2.5), + "get_support() should return the AABB position when given a zero vector."); } TEST_CASE("[AABB] Grow") { diff --git a/tests/core/math/test_rect2.h b/tests/core/math/test_rect2.h index 26ab185aa2f..c4368808a6b 100644 --- a/tests/core/math/test_rect2.h +++ b/tests/core/math/test_rect2.h @@ -180,6 +180,28 @@ TEST_CASE("[Rect2] Expanding") { "expand() with non-contained Vector2 should return the expected result."); } +TEST_CASE("[Rect2] Get support") { + const Rect2 rect = Rect2(Vector2(-1.5, 2), Vector2(4, 5)); + CHECK_MESSAGE( + rect.get_support(Vector2(1, 0)) == Vector2(2.5, 2), + "get_support() should return the expected value."); + CHECK_MESSAGE( + rect.get_support(Vector2(0.5, 1)) == Vector2(2.5, 7), + "get_support() should return the expected value."); + CHECK_MESSAGE( + rect.get_support(Vector2(0.5, 1)) == Vector2(2.5, 7), + "get_support() should return the expected value."); + CHECK_MESSAGE( + rect.get_support(Vector2(0, -1)) == Vector2(-1.5, 2), + "get_support() should return the expected value."); + CHECK_MESSAGE( + rect.get_support(Vector2(0, -0.1)) == Vector2(-1.5, 2), + "get_support() should return the expected value."); + CHECK_MESSAGE( + rect.get_support(Vector2()) == Vector2(-1.5, 2), + "get_support() should return the Rect2 position when given a zero vector."); +} + TEST_CASE("[Rect2] Growing") { CHECK_MESSAGE( Rect2(0, 100, 1280, 720).grow(100).is_equal_approx(Rect2(-100, 0, 1480, 920)),