Skip to content

Commit

Permalink
Follow-up fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Bromeon committed Jun 17, 2023
1 parent 2eeff84 commit 0a53448
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 107 deletions.
37 changes: 27 additions & 10 deletions godot-core/src/builtin/aabb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,12 @@ impl Aabb {
/// Create a new `Aabb` with the first corner at `position` and opposite corner at `end`.
#[inline]
pub fn from_corners(position: Vector3, end: Vector3) -> Self {
Self {
position,
size: position + end,
}
// Cannot use floating point arithmetic in const functions.
Self::new(position, end - position)
}

/// Returns an AABB with equivalent position and size,
/// modified so that the most-negative corner is the origin and the size is positive.
/// Returns an AABB with the same geometry, with most-negative corner as `position` and non-negative `size`.
#[inline]
pub fn abs(&self) -> Self {
Aabb {
position: self.position + self.size.coord_min(Vector3::ZERO),
Expand Down Expand Up @@ -141,6 +139,7 @@ impl Aabb {
}

/// Returns true if the AABB has a volume, and false if the AABB is flat, linear, empty, or has a negative size.
#[inline]
pub fn has_volume(&self) -> bool {
self.size.x > 0.0 && self.size.y > 0.0 && self.size.z > 0.0
}
Expand Down Expand Up @@ -168,6 +167,7 @@ impl Aabb {
}

/// Returns `true` if this AABB is finite, by calling `@GlobalScope.is_finite` on each component.
#[inline]
pub fn is_finite(&self) -> bool {
self.position.is_finite() && self.size.is_finite()
}
Expand All @@ -187,6 +187,7 @@ impl Aabb {
}

/// Returns the normalized longest axis of the AABB.
#[inline]
pub fn longest_axis(&self) -> Vector3 {
match self.longest_axis_index() {
Vector3Axis::X => Vector3::RIGHT,
Expand All @@ -196,16 +197,19 @@ impl Aabb {
}

/// Returns the index of the longest axis of the AABB (according to Vector3's AXIS_* constants).
#[inline]
pub fn longest_axis_index(&self) -> Vector3Axis {
self.size.max_axis_index()
}

/// Returns the scalar length of the longest axis of the AABB.
#[inline]
pub fn longest_axis_size(&self) -> real {
self.size.x.max(self.size.y.max(self.size.z))
}

/// Returns the normalized shortest axis of the AABB.
#[inline]
pub fn shortest_axis(&self) -> Vector3 {
match self.shortest_axis_index() {
Vector3Axis::X => Vector3::RIGHT,
Expand All @@ -215,16 +219,19 @@ impl Aabb {
}

/// Returns the index of the shortest axis of the AABB (according to Vector3::AXIS* enum).
#[inline]
pub fn shortest_axis_index(&self) -> Vector3Axis {
self.size.min_axis_index()
}

/// Returns the scalar length of the shortest axis of the AABB.
#[inline]
pub fn shortest_axis_size(&self) -> real {
self.size.x.min(self.size.y.min(self.size.z))
}

/// Returns the support point in a given direction. This is useful for collision detection algorithms.
#[inline]
pub fn support(&self, dir: Vector3) -> Vector3 {
let half_extents = self.size * 0.5;
let relative_center_point = self.position + half_extents;
Expand All @@ -238,9 +245,12 @@ impl Aabb {
half_extents * signs + relative_center_point
}

/// Returns `true` if the AABB overlaps with `b` (i.e. they have at least one point in common).
/// Checks whether two AABBs have at least one point in common.
///
/// _Godot equivalent: `AABB.intersects(AABB b, bool include_borders = false)`_
/// Also returns `true` if the AABBs only touch each other (share a point/edge/face).
/// See [`intersects_exclude_borders`][Self::intersects_exclude_borders] if you want to return `false` in that case.
///
/// _Godot equivalent: `AABB.intersects(AABB b, bool include_borders = true)`_
#[inline]
pub fn intersects(&self, b: &Aabb) -> bool {
let end = self.end();
Expand All @@ -253,9 +263,13 @@ impl Aabb {
&& self.position.z <= end_b.z
}

/// Returns `true` if the AABB overlaps with `b` (i.e. they have at least one inner point in common).
/// Checks whether two AABBs have at least one _inner_ point in common (not on the borders).
///
/// _Godot equivalent: `AABB.intersects(AABB b, bool include_borders = true)`_
/// Returns `false` if the AABBs only touch each other (share a point/edge/face).
/// See [`intersects`][Self::intersects] if you want to return `true` in that case.
///
/// _Godot equivalent: `AABB.intersects(AABB b, bool include_borders = false)`_
#[inline]
pub fn intersects_exclude_borders(&self, &b: &Aabb) -> bool {
let end = self.end();
let end_b = b.end();
Expand All @@ -269,6 +283,7 @@ impl Aabb {
}

/// Returns `true` if the AABB is on both sides of a plane.
#[inline]
pub fn intersects_plane(&self, plane: &Plane) -> bool {
// The set of the edges of the AABB.
let points = [
Expand Down Expand Up @@ -301,6 +316,7 @@ impl Aabb {
///
/// # Panics
/// If `self.size` is negative.
#[inline]
pub fn intersects_ray(&self, from: Vector3, dir: Vector3) -> bool {
self.assert_nonnegative();

Expand All @@ -320,6 +336,7 @@ impl Aabb {
///
/// # Panics
/// If `self.size` is negative.
#[inline]
pub fn intersects_segment(&self, from: Vector3, to: Vector3) -> bool {
self.assert_nonnegative();

Expand Down
80 changes: 45 additions & 35 deletions godot-core/src/builtin/rect2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ impl Rect2 {
Self { position, size }
}

/// Create a new `Rect2` with the first corner at `position` and the opposite corner at `end`.
#[inline]
pub fn from_corners(position: Vector2, end: Vector2) -> Self {
// Cannot use floating point arithmetic in const functions.
Self::new(position, end - position)
}

/// Create a new `Rect2` from four reals representing position `(x,y)` and size `(width,height)`.
///
/// _Godot equivalent: `Rect2(float x, float y, float width, float height)`_
Expand All @@ -46,6 +53,17 @@ impl Rect2 {
}
}

/// Create a new `Rect2` from a `Rect2i`, using `as` for `i32` to `real` conversions.
///
/// _Godot equivalent: `Rect2(Rect2i from)`_
#[inline]
pub const fn from_rect2i(rect: Rect2i) -> Self {
Self {
position: Vector2::from_vector2i(rect.position),
size: Vector2::from_vector2i(rect.size),
}
}

/// Returns a rectangle with the same geometry, with top-left corner as `position` and non-negative size.
///
/// _Godot equivalent: `Rect2.abs()`_
Expand Down Expand Up @@ -180,7 +198,7 @@ impl Rect2 {
/// _Godot equivalent: `Rect2.intersection(Rect2 b)`_
#[inline]
pub fn intersection(&self, b: Self) -> Option<Self> {
if !self.intersects(b, true) {
if !self.intersects(b) {
return None;
}

Expand All @@ -194,54 +212,46 @@ impl Rect2 {
Some(rect)
}

/// Returns `true` if the Rect2 overlaps with `b` (i.e. they have at least one point in common).
/// Checks whether two rectangles have at least one point in common.
///
/// If `include_borders` is `true`, they will also be considered overlapping if their borders touch, even without intersection.
/// Also returns `true` if the rects only touch each other (share a point/edge).
/// See [`intersects_exclude_borders`][Self::intersects_exclude_borders] if you want to return `false` in that case.
///
/// _Godot equivalent: `Rect2.intersects(Rect2 b, bool include_borders)`_
/// _Godot equivalent: `Rect2.intersects(Rect2 b, bool include_borders = true)`_
#[inline]
pub fn intersects(&self, b: Self, include_borders: bool) -> bool {
pub fn intersects(&self, b: Self) -> bool {
let end = self.end();
let end_b = b.end();

if include_borders {
self.position.x <= end_b.x
&& end.x >= b.position.x
&& self.position.y <= end_b.y
&& end.y >= b.position.y
} else {
self.position.x < end_b.x
&& end.x > b.position.x
&& self.position.y < end_b.y
&& end.y > b.position.y
}
self.position.x <= end_b.x
&& end.x >= b.position.x
&& self.position.y <= end_b.y
&& end.y >= b.position.y
}

/// Returns `true` if this Rect2 is finite, by calling `@GlobalScope.is_finite` on each component.
/// Checks whether two rectangles have at least one _inner_ point in common (not on the borders).
///
/// _Godot equivalent: `Rect2.is_finite()`_
pub fn is_finite(&self) -> bool {
self.position.is_finite() && self.size.is_finite()
}

/// Create a new `Rect2` from a `Rect2i`, using `as` for `i32` to `real` conversions.
/// Returns `false` if the rects only touch each other (share a point/edge).
/// See [`intersects`][Self::intersects] if you want to return `true` in that case.
///
/// _Godot equivalent: `Rect2(Rect2i from)`_
/// _Godot equivalent: `Rect2.intersects(AABB b, bool include_borders = false)`_
#[inline]
pub const fn from_rect2i(rect: Rect2i) -> Self {
Self {
position: Vector2::from_vector2i(rect.position),
size: Vector2::from_vector2i(rect.size),
}
pub fn intersects_exclude_borders(&self, b: Self) -> bool {
let end = self.end();
let end_b = b.end();

self.position.x < end_b.x
&& end.x > b.position.x
&& self.position.y < end_b.y
&& end.y > b.position.y
}

/// Create a new `Rect2` with the first corner at `position` and the opposite corner at `end`.
/// Returns `true` if this Rect2 is finite, by calling `@GlobalScope.is_finite` on each component.
///
/// _Godot equivalent: `Rect2.is_finite()`_
#[inline]
pub fn from_corners(position: Vector2, end: Vector2) -> Self {
Self {
position,
size: end - position,
}
pub fn is_finite(&self) -> bool {
self.position.is_finite() && self.size.is_finite()
}

/// The end of the `Rect2` calculated as `position + size`.
Expand Down
Loading

0 comments on commit 0a53448

Please sign in to comment.