Merge pull request #95790 from aaronfranke/rect-aabb-support

Simplify Rect2/AABB `get_support` function
This commit is contained in:
Rémi Verschelde 2024-08-22 00:10:39 +02:00
commit 39b77ea04e
No known key found for this signature in database
GPG Key ID: C3336907360768E1
11 changed files with 97 additions and 35 deletions

View File

@ -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 {

View File

@ -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 {

View File

@ -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());

View File

@ -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>

View File

@ -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" />

View File

@ -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;

View File

@ -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>

View File

@ -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.

View File

@ -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;

View File

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

View File

@ -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)),