Skip to content

Commit

Permalink
Add Aabb2d::new and Aabb3d::new constructors (#11433)
Browse files Browse the repository at this point in the history
# Objective

Currently, the only way to create an AABB is to specify its `min` and
`max` coordinates. However, it's often more useful to use the center and
half-size instead.

## Solution

Add `new` constructors for `Aabb2d` and `Aabb3d`.

This:

```rust
let aabb = Aabb3d {
    min: center - half_size,
    max: center + half_size,
}
```

becomes this:

```rust
let aabb = Aabb3d::new(center, half_size);
```

I also made the usage of "half-extents" vs. "half-size" a bit more
consistent.
  • Loading branch information
Jondolf committed Jan 20, 2024
1 parent 440bba8 commit c31f3aa
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 60 deletions.
12 changes: 11 additions & 1 deletion crates/bevy_math/src/bounding/bounded2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ pub struct Aabb2d {
}

impl Aabb2d {
/// Constructs an AABB from its center and half-size.
#[inline(always)]
pub fn new(center: Vec2, half_size: Vec2) -> Self {
debug_assert!(half_size.x >= 0.0 && half_size.y >= 0.0);
Self {
min: center - half_size,
max: center + half_size,
}
}

/// Computes the smallest [`Aabb2d`] containing the given set of points,
/// transformed by `translation` and `rotation`.
///
Expand Down Expand Up @@ -248,7 +258,7 @@ pub struct BoundingCircle {
}

impl BoundingCircle {
/// Construct a bounding circle from its center and radius
/// Constructs a bounding circle from its center and radius.
#[inline(always)]
pub fn new(center: Vec2, radius: f32) -> Self {
debug_assert!(radius >= 0.);
Expand Down
34 changes: 8 additions & 26 deletions crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ use super::{Aabb2d, Bounded2d, BoundingCircle};

impl Bounded2d for Circle {
fn aabb_2d(&self, translation: Vec2, _rotation: f32) -> Aabb2d {
Aabb2d {
min: translation - Vec2::splat(self.radius),
max: translation + Vec2::splat(self.radius),
}
Aabb2d::new(translation, Vec2::splat(self.radius))
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand Down Expand Up @@ -47,12 +44,9 @@ impl Bounded2d for Ellipse {
let (ux, uy) = (hw * alpha_cos, hw * alpha_sin);
let (vx, vy) = (hh * beta_cos, hh * beta_sin);

let half_extents = Vec2::new(ux.hypot(vx), uy.hypot(vy));
let half_size = Vec2::new(ux.hypot(vx), uy.hypot(vy));

Aabb2d {
min: translation - half_extents,
max: translation + half_extents,
}
Aabb2d::new(translation, half_size)
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand All @@ -72,10 +66,7 @@ impl Bounded2d for Plane2d {
let half_height = if facing_y { 0.0 } else { f32::MAX / 2.0 };
let half_size = Vec2::new(half_width, half_height);

Aabb2d {
min: translation - half_size,
max: translation + half_size,
}
Aabb2d::new(translation, half_size)
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand All @@ -94,10 +85,7 @@ impl Bounded2d for Line2d {
let half_height = if direction.y == 0.0 { 0.0 } else { max };
let half_size = Vec2::new(half_width, half_height);

Aabb2d {
min: translation - half_size,
max: translation + half_size,
}
Aabb2d::new(translation, half_size)
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand All @@ -109,12 +97,9 @@ impl Bounded2d for Segment2d {
fn aabb_2d(&self, translation: Vec2, rotation: f32) -> Aabb2d {
// Rotate the segment by `rotation`
let direction = Mat2::from_angle(rotation) * *self.direction;
let half_extent = (self.half_length * direction).abs();
let half_size = (self.half_length * direction).abs();

Aabb2d {
min: translation - half_extent,
max: translation + half_extent,
}
Aabb2d::new(translation, half_size)
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand Down Expand Up @@ -195,10 +180,7 @@ impl Bounded2d for Rectangle {
let abs_rot_mat = Mat2::from_cols_array(&[cos.abs(), sin.abs(), sin.abs(), cos.abs()]);
let half_size = abs_rot_mat * self.half_size;

Aabb2d {
min: translation - half_size,
max: translation + half_size,
}
Aabb2d::new(translation, half_size)
}

fn bounding_circle(&self, translation: Vec2, _rotation: f32) -> BoundingCircle {
Expand Down
12 changes: 11 additions & 1 deletion crates/bevy_math/src/bounding/bounded3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ pub struct Aabb3d {
}

impl Aabb3d {
/// Constructs an AABB from its center and half-size.
#[inline(always)]
pub fn new(center: Vec3, half_size: Vec3) -> Self {
debug_assert!(half_size.x >= 0.0 && half_size.y >= 0.0 && half_size.z >= 0.0);
Self {
min: center - half_size,
max: center + half_size,
}
}

/// Computes the smallest [`Aabb3d`] containing the given set of points,
/// transformed by `translation` and `rotation`.
///
Expand Down Expand Up @@ -243,7 +253,7 @@ pub struct BoundingSphere {
}

impl BoundingSphere {
/// Construct a bounding sphere from its center and radius.
/// Constructs a bounding sphere from its center and radius.
pub fn new(center: Vec3, radius: f32) -> Self {
debug_assert!(radius >= 0.);
Self {
Expand Down
46 changes: 14 additions & 32 deletions crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ use super::{Aabb3d, Bounded3d, BoundingSphere};

impl Bounded3d for Sphere {
fn aabb_3d(&self, translation: Vec3, _rotation: Quat) -> Aabb3d {
Aabb3d {
min: translation - Vec3::splat(self.radius),
max: translation + Vec3::splat(self.radius),
}
Aabb3d::new(translation, Vec3::splat(self.radius))
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand All @@ -39,10 +36,7 @@ impl Bounded3d for Plane3d {
let half_depth = if facing_z { 0.0 } else { f32::MAX / 2.0 };
let half_size = Vec3::new(half_width, half_height, half_depth);

Aabb3d {
min: translation - half_size,
max: translation + half_size,
}
Aabb3d::new(translation, half_size)
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand All @@ -62,10 +56,7 @@ impl Bounded3d for Line3d {
let half_depth = if direction.z == 0.0 { 0.0 } else { max };
let half_size = Vec3::new(half_width, half_height, half_depth);

Aabb3d {
min: translation - half_size,
max: translation + half_size,
}
Aabb3d::new(translation, half_size)
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand All @@ -77,12 +68,9 @@ impl Bounded3d for Segment3d {
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
// Rotate the segment by `rotation`
let direction = rotation * *self.direction;
let half_extent = (self.half_length * direction).abs();
let half_size = (self.half_length * direction).abs();

Aabb3d {
min: translation - half_extent,
max: translation + half_extent,
}
Aabb3d::new(translation, half_size)
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand Down Expand Up @@ -112,7 +100,7 @@ impl Bounded3d for BoxedPolyline3d {

impl Bounded3d for Cuboid {
fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d {
// Compute the AABB of the rotated cuboid by transforming the half-extents
// Compute the AABB of the rotated cuboid by transforming the half-size
// by an absolute rotation matrix.
let rot_mat = Mat3::from_quat(rotation);
let abs_rot_mat = Mat3::from_cols(
Expand All @@ -122,10 +110,7 @@ impl Bounded3d for Cuboid {
);
let half_size = abs_rot_mat * self.half_size;

Aabb3d {
min: translation - half_size,
max: translation + half_size,
}
Aabb3d::new(translation, half_size)
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand All @@ -147,11 +132,11 @@ impl Bounded3d for Cylinder {
let bottom = -top;

let e = Vec3::ONE - segment_dir * segment_dir;
let half_extents = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let half_size = self.radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());

Aabb3d {
min: translation + (top - half_extents).min(bottom - half_extents),
max: translation + (top + half_extents).max(bottom + half_extents),
min: translation + (top - half_size).min(bottom - half_size),
max: translation + (top + half_size).max(bottom + half_size),
}
}

Expand Down Expand Up @@ -305,15 +290,12 @@ impl Bounded3d for Torus {
// Reference: http://iquilezles.org/articles/diskbbox/
let normal = rotation * Vec3::Y;
let e = 1.0 - normal * normal;
let disc_half_extents = self.major_radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let disc_half_size = self.major_radius * Vec3::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());

// Expand the disc by the minor radius to get the torus half extents
let half_extents = disc_half_extents + Vec3::splat(self.minor_radius);
// Expand the disc by the minor radius to get the torus half-size
let half_size = disc_half_size + Vec3::splat(self.minor_radius);

Aabb3d {
min: translation - half_extents,
max: translation + half_extents,
}
Aabb3d::new(translation, half_size)
}

fn bounding_sphere(&self, translation: Vec3, _rotation: Quat) -> BoundingSphere {
Expand Down

0 comments on commit c31f3aa

Please sign in to comment.