Add Aabb2d::new and Aabb3d::new constructors (#11433)

# 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.
This commit is contained in:
Joona Aalto 2024-01-20 22:12:20 +02:00 committed by GitHub
parent 440bba80c4
commit c31f3aa128
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 44 additions and 60 deletions

View file

@ -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`.
///
@ -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.);

View file

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

View file

@ -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`.
///
@ -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 {

View file

@ -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 {
@ -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 {
@ -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 {
@ -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 {
@ -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(
@ -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 {
@ -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),
}
}
@ -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 {