Fix rotate_by implementation for Aabb2d (#19015)

# Objective

Fixes #18969 

## Solution

Also updated `Aabb3d` implementation for consistency.

## Testing

Added tests for `Aabb2d` and `Aabb3d` to verify correct rotation
behavior for angles greater than 90 degrees.
This commit is contained in:
Innokentiy Popov 2025-05-04 18:05:27 +05:00 committed by François Mockers
parent 227e1bbf34
commit 92cda8b0bb
2 changed files with 32 additions and 13 deletions

View File

@ -243,13 +243,9 @@ impl BoundingVolume for Aabb2d {
/// and consider storing the original AABB and rotating that every time instead.
#[inline(always)]
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
let rotation: Rot2 = rotation.into();
let abs_rot_mat = Mat2::from_cols(
Vec2::new(rotation.cos, rotation.sin),
Vec2::new(rotation.sin, rotation.cos),
);
let half_size = abs_rot_mat * self.half_size();
*self = Self::new(rotation * self.center(), half_size);
let rot_mat = Mat2::from(rotation.into());
let half_size = rot_mat.abs() * self.half_size();
*self = Self::new(rot_mat * self.center(), half_size);
}
}
@ -274,6 +270,8 @@ impl IntersectsVolume<BoundingCircle> for Aabb2d {
#[cfg(test)]
mod aabb2d_tests {
use approx::assert_relative_eq;
use super::Aabb2d;
use crate::{
bounding::{BoundingCircle, BoundingVolume, IntersectsVolume},
@ -394,6 +392,17 @@ mod aabb2d_tests {
assert!(scaled.contains(&a));
}
#[test]
fn rotate() {
let a = Aabb2d {
min: Vec2::new(-2.0, -2.0),
max: Vec2::new(2.0, 2.0),
};
let rotated = a.rotated_by(core::f32::consts::PI);
assert_relative_eq!(rotated.min, a.min);
assert_relative_eq!(rotated.max, a.max);
}
#[test]
fn transform() {
let a = Aabb2d {

View File

@ -250,12 +250,7 @@ impl BoundingVolume for Aabb3d {
#[inline(always)]
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
let rot_mat = Mat3::from_quat(rotation.into());
let abs_rot_mat = Mat3::from_cols(
rot_mat.x_axis.abs(),
rot_mat.y_axis.abs(),
rot_mat.z_axis.abs(),
);
let half_size = abs_rot_mat * self.half_size();
let half_size = rot_mat.abs() * self.half_size();
*self = Self::new(rot_mat * self.center(), half_size);
}
}
@ -279,6 +274,8 @@ impl IntersectsVolume<BoundingSphere> for Aabb3d {
#[cfg(test)]
mod aabb3d_tests {
use approx::assert_relative_eq;
use super::Aabb3d;
use crate::{
bounding::{BoundingSphere, BoundingVolume, IntersectsVolume},
@ -398,6 +395,19 @@ mod aabb3d_tests {
assert!(scaled.contains(&a));
}
#[test]
fn rotate() {
use core::f32::consts::PI;
let a = Aabb3d {
min: Vec3A::new(-2.0, -2.0, -2.0),
max: Vec3A::new(2.0, 2.0, 2.0),
};
let rotation = Quat::from_euler(glam::EulerRot::XYZ, PI, PI, 0.0);
let rotated = a.rotated_by(rotation);
assert_relative_eq!(rotated.min, a.min);
assert_relative_eq!(rotated.max, a.max);
}
#[test]
fn transform() {
let a = Aabb3d {