2
0
Эх сурвалжийг харах

Simplify and fix Rect2/AABB get_support function

Aaron Franke 1 жил өмнө
parent
commit
7db24a9ad5

+ 13 - 10
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 {

+ 9 - 7
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 {

+ 2 - 1
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());

+ 1 - 1
doc/classes/AABB.xml

@@ -206,7 +206,7 @@
 		</method>
 		<method name="get_support" qualifiers="const">
 			<return type="Vector3" />
-			<param index="0" name="dir" type="Vector3" />
+			<param index="0" name="direction" type="Vector3" />
 			<description>
 				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.
 			</description>

+ 7 - 0
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].
 			</description>
 		</method>
+		<method name="get_support" qualifiers="const">
+			<return type="Vector2" />
+			<param index="0" name="direction" type="Vector2" />
+			<description>
+				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.
+			</description>
+		</method>
 		<method name="grow" qualifiers="const">
 			<return type="Rect2" />
 			<param index="0" name="amount" type="float" />

+ 1 - 1
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;

+ 14 - 7
modules/mono/glue/GodotSharp/GodotSharp/Core/Aabb.cs

@@ -314,13 +314,20 @@ namespace Godot
         /// <returns>A vector representing the support.</returns>
         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;
         }
 
         /// <summary>

+ 20 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs

@@ -171,6 +171,26 @@ namespace Godot
             return _position + (_size * 0.5f);
         }
 
+        /// <summary>
+        /// Returns the support point in a given direction.
+        /// This is useful for collision detection algorithms.
+        /// </summary>
+        /// <param name="direction">The direction to find support for.</param>
+        /// <returns>A vector representing the support.</returns>
+        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;
+        }
+
         /// <summary>
         /// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
         /// on all sides.

+ 1 - 1
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;

+ 7 - 7
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") {

+ 22 - 0
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)),