From 59ecc59507d084d4b5d48b75842d7033183e6c06 Mon Sep 17 00:00:00 2001 From: whatf0xx Date: Sun, 24 Mar 2024 12:25:04 +0100 Subject: [PATCH] Aabb wrt centre/issue #155 (#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * non-functional halfway modification, read the docs * Working and with a single unit test to verify * feat: simplify implementation of Aabb::scaled_wrt_center * chore: move Aabb::scaled_wirt_center test to the test dir. * chore: update changelog --------- Co-authored-by: whatf0xx Co-authored-by: Sébastien Crozet --- CHANGELOG.md | 4 ++++ crates/parry2d/tests/geometry/aabb_scale.rs | 16 ++++++++++++++++ crates/parry2d/tests/geometry/mod.rs | 1 + crates/parry3d/tests/geometry/aabb_scale.rs | 16 ++++++++++++++++ crates/parry3d/tests/geometry/mod.rs | 1 + src/bounding_volume/aabb.rs | 17 +++++++++++++++++ 6 files changed, 55 insertions(+) create mode 100644 crates/parry2d/tests/geometry/aabb_scale.rs create mode 100644 crates/parry3d/tests/geometry/aabb_scale.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a2264a2..4e1b4fc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ - Fix a crash in `Qbvh::refit` that results from the QBVH tree becoming increasingly imbalanced. +### Added + +- Add `Aabb::scaled_wrt_center` to scale an AABB while keeping its center unchanged. + ## v0.13.6 ### Fixed diff --git a/crates/parry2d/tests/geometry/aabb_scale.rs b/crates/parry2d/tests/geometry/aabb_scale.rs new file mode 100644 index 00000000..07c8bf8a --- /dev/null +++ b/crates/parry2d/tests/geometry/aabb_scale.rs @@ -0,0 +1,16 @@ +use na::{Point2, Vector2}; +use parry2d::bounding_volume::Aabb; + +#[test] +fn test_aabb_scale_wrt_center() { + let aabb = Aabb::from_half_extents(Point2::new(1.0, 2.0), Vector2::new(4.0, 5.0)); + let scale = Vector2::new(10.0, -20.0); + let scaled_aabb = aabb.scaled_wrt_center(&scale); + let scaled_aabb_neg = aabb.scaled_wrt_center(&-scale); + let scaled_aabb_abs = aabb.scaled_wrt_center(&scale.abs()); + + assert_eq!(&scaled_aabb, &scaled_aabb_neg); + assert_eq!(&scaled_aabb, &scaled_aabb_abs); + assert_eq!(aabb.center(), scaled_aabb.center()); + assert_eq!(scaled_aabb.half_extents(), Vector2::new(40.0, 100.0)); +} diff --git a/crates/parry2d/tests/geometry/mod.rs b/crates/parry2d/tests/geometry/mod.rs index 5d9c653c..d3ca21e6 100644 --- a/crates/parry2d/tests/geometry/mod.rs +++ b/crates/parry2d/tests/geometry/mod.rs @@ -1,3 +1,4 @@ +mod aabb_scale; mod ball_ball_toi; mod ball_cuboid_contact; mod epa2; diff --git a/crates/parry3d/tests/geometry/aabb_scale.rs b/crates/parry3d/tests/geometry/aabb_scale.rs new file mode 100644 index 00000000..30e6c384 --- /dev/null +++ b/crates/parry3d/tests/geometry/aabb_scale.rs @@ -0,0 +1,16 @@ +use na::{Point3, Vector3}; +use parry3d::bounding_volume::Aabb; + +#[test] +fn test_aabb_scale_wrt_center() { + let aabb = Aabb::from_half_extents(Point3::new(1.0, 2.0, 3.0), Vector3::new(4.0, 5.0, 6.0)); + let scale = Vector3::new(10.0, -20.0, 50.0); + let scaled_aabb = aabb.scaled_wrt_center(&scale); + let scaled_aabb_neg = aabb.scaled_wrt_center(&-scale); + let scaled_aabb_abs = aabb.scaled_wrt_center(&scale.abs()); + + assert_eq!(&scaled_aabb, &scaled_aabb_neg); + assert_eq!(&scaled_aabb, &scaled_aabb_abs); + assert_eq!(aabb.center(), scaled_aabb.center()); + assert_eq!(scaled_aabb.half_extents(), Vector3::new(40.0, 100.0, 300.0)); +} diff --git a/crates/parry3d/tests/geometry/mod.rs b/crates/parry3d/tests/geometry/mod.rs index 912181ca..25a4e755 100644 --- a/crates/parry3d/tests/geometry/mod.rs +++ b/crates/parry3d/tests/geometry/mod.rs @@ -1,3 +1,4 @@ +mod aabb_scale; mod ball_ball_toi; mod ball_triangle_toi; mod convex_hull; diff --git a/src/bounding_volume/aabb.rs b/src/bounding_volume/aabb.rs index c038dd28..f8b93d84 100644 --- a/src/bounding_volume/aabb.rs +++ b/src/bounding_volume/aabb.rs @@ -176,6 +176,23 @@ impl Aabb { } } + /// Returns an AABB with the same center as `self` but with extents scaled by `scale`. + /// + /// # Parameters + /// - `scale`: the scaling factor. It can be non-uniform and/or negative. The AABB being + /// symmetric wrt. its center, a negative scale value has the same effect as scaling + /// by its absolute value. + #[inline] + #[must_use] + pub fn scaled_wrt_center(self, scale: &Vector) -> Self { + let center = self.center(); + // Multiply the extents by the scale. Negative scaling might modify the half-extent + // sign, so we take the absolute value. The AABB being symmetric that absolute value + // is valid. + let half_extents = self.half_extents().component_mul(scale).abs(); + Self::from_half_extents(center, half_extents) + } + /// The smallest bounding sphere containing this `Aabb`. #[inline] pub fn bounding_sphere(&self) -> BoundingSphere {