diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 074a9232e6b79..c9d07b38b49bd 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -626,7 +626,7 @@ where /// # use bevy_math::{bounding::Aabb3d, Vec3}; /// # use bevy_color::palettes::basic::GREEN; /// fn system(mut gizmos: Gizmos) { - /// gizmos.aabb_3d(Aabb3d::new(Vec3::ZERO, Vec3::ONE), Transform::IDENTITY, GREEN); + /// gizmos.aabb_3d(Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), Transform::IDENTITY, GREEN); /// } /// # bevy_ecs::system::assert_is_system(system); /// ``` diff --git a/crates/bevy_math/src/bounding/bounded3d/extrusion.rs b/crates/bevy_math/src/bounding/bounded3d/extrusion.rs index e37783576caac..3f92f1c2ee422 100644 --- a/crates/bevy_math/src/bounding/bounded3d/extrusion.rs +++ b/crates/bevy_math/src/bounding/bounded3d/extrusion.rs @@ -65,7 +65,7 @@ impl BoundedExtrusion for Ellipse { }); let half_size = Vec3A::new(max_x.x, max_y.y, max_z.z).abs() + (normal * half_depth).abs(); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } } @@ -82,7 +82,7 @@ impl BoundedExtrusion for Line2d { if dir.z == 0. { half_depth.z } else { max }, ); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } } @@ -92,7 +92,7 @@ impl BoundedExtrusion for Segment2d { let half_size = isometry.rotation * Vec3A::from(self.point1().extend(0.)); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); - Aabb3d::new(isometry.translation, half_size.abs() + depth.abs()) + Aabb3d::from_half_size(isometry.translation, half_size.abs() + depth.abs()) } } @@ -161,7 +161,7 @@ impl BoundedExtrusion for Capsule2d { let up = isometry.rotation * Vec3A::new(0., self.half_length, 0.); let half_size = aabb.max + up.abs(); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } } @@ -230,7 +230,7 @@ pub trait BoundedExtrusion: Primitive2d + Bounded2d { let cap_size = Vec3A::from_array(axis_values.map(|(max_val, _)| max_val)).abs(); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); - Aabb3d::new(isometry.translation - offset, cap_size + depth.abs()) + Aabb3d::from_half_size(isometry.translation - offset, cap_size + depth.abs()) } /// Get a bounding sphere for an extrusion of the `base_shape` with the given `half_depth` with the given translation and rotation diff --git a/crates/bevy_math/src/bounding/bounded3d/mod.rs b/crates/bevy_math/src/bounding/bounded3d/mod.rs index f973d464d3558..4904a0883ad1a 100644 --- a/crates/bevy_math/src/bounding/bounded3d/mod.rs +++ b/crates/bevy_math/src/bounding/bounded3d/mod.rs @@ -61,9 +61,17 @@ pub struct Aabb3d { } impl Aabb3d { + /// Constructs an AABB from the its minimum and maximum extent. + #[inline] + pub fn from_min_max(min: impl Into, max: impl Into) -> Self { + let (min, max) = (min.into(), max.into()); + debug_assert!(min.x <= max.x && min.y <= max.y && min.z <= max.z); + Self { min, max } + } + /// Constructs an AABB from its center and half-size. #[inline] - pub fn new(center: impl Into, half_size: impl Into) -> Self { + pub fn from_half_size(center: impl Into, half_size: impl Into) -> Self { let (center, half_size) = (center.into(), half_size.into()); debug_assert!(half_size.x >= 0.0 && half_size.y >= 0.0 && half_size.z >= 0.0); Self { @@ -261,7 +269,7 @@ impl BoundingVolume for Aabb3d { fn rotate_by(&mut self, rotation: impl Into) { let rot_mat = Mat3::from_quat(rotation.into()); let half_size = rot_mat.abs() * self.half_size(); - *self = Self::new(rot_mat * self.center(), half_size); + *self = Self::from_half_size(rot_mat * self.center(), half_size); } } diff --git a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs index 7cf118e4d97e8..e88ddbafe1b40 100644 --- a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs +++ b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs @@ -18,7 +18,7 @@ use super::{Aabb3d, Bounded3d, BoundingSphere}; impl Bounded3d for Sphere { fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { let isometry = isometry.into(); - Aabb3d::new(isometry.translation, Vec3::splat(self.radius)) + Aabb3d::from_half_size(isometry.translation, Vec3::splat(self.radius)) } fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { @@ -43,7 +43,7 @@ impl Bounded3d for InfinitePlane3d { let half_depth = if facing_z { 0.0 } else { f32::MAX / 2.0 }; let half_size = Vec3A::new(half_width, half_height, half_depth); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { @@ -65,7 +65,7 @@ impl Bounded3d for Line3d { let half_depth = if direction.z == 0.0 { 0.0 } else { max }; let half_size = Vec3A::new(half_width, half_height, half_depth); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { @@ -111,7 +111,7 @@ impl Bounded3d for Cuboid { ); let half_size = abs_rot_mat * self.half_size; - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { @@ -312,7 +312,7 @@ impl Bounded3d for Torus { // Expand the disc by the minor radius to get the torus half-size let half_size = disc_half_size + Vec3A::splat(self.minor_radius); - Aabb3d::new(isometry.translation, half_size) + Aabb3d::from_half_size(isometry.translation, half_size) } fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { @@ -337,7 +337,7 @@ impl Bounded3d for Triangle3d { let bounding_center = (max + min) / 2.0 + isometry.translation; let half_extents = (max - min) / 2.0; - Aabb3d::new(bounding_center, half_extents) + Aabb3d::from_half_size(bounding_center, half_extents) } /// Get the bounding sphere of the triangle. diff --git a/crates/bevy_math/src/bounding/raycast3d.rs b/crates/bevy_math/src/bounding/raycast3d.rs index 9086837f60bcc..3810fda4aabdd 100644 --- a/crates/bevy_math/src/bounding/raycast3d.rs +++ b/crates/bevy_math/src/bounding/raycast3d.rs @@ -315,37 +315,37 @@ mod tests { ( // Hit the center of a centered aabb RayCast3d::new(Vec3::Y * -5., Dir3::Y, 90.), - Aabb3d::new(Vec3::ZERO, Vec3::ONE), + Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), 4., ), ( // Hit the center of a centered aabb, but from the other side RayCast3d::new(Vec3::Y * 5., -Dir3::Y, 90.), - Aabb3d::new(Vec3::ZERO, Vec3::ONE), + Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), 4., ), ( // Hit the center of an offset aabb RayCast3d::new(Vec3::ZERO, Dir3::Y, 90.), - Aabb3d::new(Vec3::Y * 3., Vec3::splat(2.)), + Aabb3d::from_half_size(Vec3::Y * 3., Vec3::splat(2.)), 1., ), ( // Just barely hit the aabb before the max distance RayCast3d::new(Vec3::X, Dir3::Y, 1.), - Aabb3d::new(Vec3::new(1., 1., 0.), Vec3::splat(0.01)), + Aabb3d::from_half_size(Vec3::new(1., 1., 0.), Vec3::splat(0.01)), 0.99, ), ( // Hit an aabb off-center RayCast3d::new(Vec3::X, Dir3::Y, 90.), - Aabb3d::new(Vec3::Y * 5., Vec3::splat(2.)), + Aabb3d::from_half_size(Vec3::Y * 5., Vec3::splat(2.)), 3., ), ( // Barely hit an aabb on corner RayCast3d::new(Vec3::X * -0.001, Dir3::from_xyz(1., 1., 1.).unwrap(), 90.), - Aabb3d::new(Vec3::Y * 2., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 2., Vec3::ONE), 1.732, ), ] { @@ -373,17 +373,17 @@ mod tests { ( // The ray doesn't go in the right direction RayCast3d::new(Vec3::ZERO, Dir3::X, 90.), - Aabb3d::new(Vec3::Y * 2., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 2., Vec3::ONE), ), ( // Ray's alignment isn't enough to hit the aabb RayCast3d::new(Vec3::ZERO, Dir3::from_xyz(1., 0.99, 1.).unwrap(), 90.), - Aabb3d::new(Vec3::Y * 2., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 2., Vec3::ONE), ), ( // The ray's maximum distance isn't high enough RayCast3d::new(Vec3::ZERO, Dir3::Y, 0.5), - Aabb3d::new(Vec3::Y * 2., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 2., Vec3::ONE), ), ] { assert!( @@ -395,7 +395,7 @@ mod tests { #[test] fn test_ray_intersection_aabb_inside() { - let volume = Aabb3d::new(Vec3::splat(0.5), Vec3::ONE); + let volume = Aabb3d::from_half_size(Vec3::splat(0.5), Vec3::ONE); for origin in &[Vec3::X, Vec3::Y, Vec3::ONE, Vec3::ZERO] { for direction in &[Dir3::X, Dir3::Y, Dir3::Z, -Dir3::X, -Dir3::Y, -Dir3::Z] { for max in &[0., 1., 900.] { @@ -422,41 +422,46 @@ mod tests { for (test, volume, expected_distance) in &[ ( // Hit the center of the aabb, that a ray would've also hit - AabbCast3d::new(Aabb3d::new(Vec3::ZERO, Vec3::ONE), Vec3::ZERO, Dir3::Y, 90.), - Aabb3d::new(Vec3::Y * 5., Vec3::ONE), + AabbCast3d::new( + Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), + Vec3::ZERO, + Dir3::Y, + 90., + ), + Aabb3d::from_half_size(Vec3::Y * 5., Vec3::ONE), 3., ), ( // Hit the center of the aabb, but from the other side AabbCast3d::new( - Aabb3d::new(Vec3::ZERO, Vec3::ONE), + Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), Vec3::Y * 10., -Dir3::Y, 90., ), - Aabb3d::new(Vec3::Y * 5., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 5., Vec3::ONE), 3., ), ( // Hit the edge of the aabb, that a ray would've missed AabbCast3d::new( - Aabb3d::new(Vec3::ZERO, Vec3::ONE), + Aabb3d::from_half_size(Vec3::ZERO, Vec3::ONE), Vec3::X * 1.5, Dir3::Y, 90., ), - Aabb3d::new(Vec3::Y * 5., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 5., Vec3::ONE), 3., ), ( // Hit the edge of the aabb, by casting an off-center AABB AabbCast3d::new( - Aabb3d::new(Vec3::X * -2., Vec3::ONE), + Aabb3d::from_half_size(Vec3::X * -2., Vec3::ONE), Vec3::X * 3., Dir3::Y, 90., ), - Aabb3d::new(Vec3::Y * 5., Vec3::ONE), + Aabb3d::from_half_size(Vec3::Y * 5., Vec3::ONE), 3., ), ] { diff --git a/crates/bevy_mesh/src/mesh.rs b/crates/bevy_mesh/src/mesh.rs index ca224d6e286eb..ea6482b1421c8 100644 --- a/crates/bevy_mesh/src/mesh.rs +++ b/crates/bevy_mesh/src/mesh.rs @@ -2165,7 +2165,7 @@ impl Mesh { min = Vec3::min(min, v); max = Vec3::max(max, v); } - self.final_aabb = Some(Aabb3d::new(min, max)); + self.final_aabb = Some(Aabb3d::from_min_max(min, max)); } Ok(Self { @@ -2523,6 +2523,7 @@ mod tests { use crate::mesh::{Indices, MeshWindingInvertError, VertexAttributeValues}; use crate::PrimitiveTopology; use bevy_asset::RenderAssetUsages; + use bevy_math::bounding::Aabb3d; use bevy_math::primitives::Triangle3d; use bevy_math::Vec3; use bevy_transform::components::Transform; @@ -2878,6 +2879,29 @@ mod tests { ); } + #[test] + fn take_gpu_data_calculates_aabb() { + let mut mesh = Mesh::new( + PrimitiveTopology::TriangleList, + RenderAssetUsages::default(), + ); + mesh.insert_attribute( + Mesh::ATTRIBUTE_POSITION, + vec![ + [-0.5, 0., 0.], + [-1., 0., 0.], + [-1., -1., 0.], + [-0.5, -1., 0.], + ], + ); + mesh.insert_indices(Indices::U32(vec![0, 1, 2, 2, 3, 0])); + mesh = mesh.take_gpu_data().unwrap(); + assert_eq!( + mesh.final_aabb, + Some(Aabb3d::from_min_max([-1., -1., 0.], [-0.5, 0., 0.])) + ); + } + #[cfg(feature = "serialize")] #[test] fn serialize_deserialize_mesh() { diff --git a/crates/bevy_pbr/src/meshlet/from_mesh.rs b/crates/bevy_pbr/src/meshlet/from_mesh.rs index 23de97909404f..ed6a17a435e1d 100644 --- a/crates/bevy_pbr/src/meshlet/from_mesh.rs +++ b/crates/bevy_pbr/src/meshlet/from_mesh.rs @@ -892,7 +892,7 @@ impl BvhBuilder { break; } - aabb = aabb.merge(&Aabb3d::new( + aabb = aabb.merge(&Aabb3d::from_half_size( child.aabbs[i].center, child.aabbs[i].half_extent, )); @@ -963,7 +963,7 @@ impl BvhBuilder { break; } - aabb = aabb.merge(&Aabb3d::new( + aabb = aabb.merge(&Aabb3d::from_half_size( root.aabbs[i].center, root.aabbs[i].half_extent, )); diff --git a/crates/bevy_picking/src/mesh_picking/ray_cast/mod.rs b/crates/bevy_picking/src/mesh_picking/ray_cast/mod.rs index 5fbcc370e1e98..1bcef4bece1be 100644 --- a/crates/bevy_picking/src/mesh_picking/ray_cast/mod.rs +++ b/crates/bevy_picking/src/mesh_picking/ray_cast/mod.rs @@ -235,7 +235,7 @@ impl<'w, 's> MeshRayCast<'w, 's> { if should_ray_cast && let Some(distance) = ray_aabb_intersection_3d( ray, - &Aabb3d::new(aabb.center, aabb.half_extents), + &Aabb3d::from_half_size(aabb.center, aabb.half_extents), &transform.affine(), ) { diff --git a/release-content/migration-guides/aabb3d_new_renamed.md b/release-content/migration-guides/aabb3d_new_renamed.md new file mode 100644 index 0000000000000..5a8888a58b800 --- /dev/null +++ b/release-content/migration-guides/aabb3d_new_renamed.md @@ -0,0 +1,6 @@ +--- +title: "`Aabb3d::new` renamed to `Aabb3d::from_half_size`" +pull_requests: [22176] +--- + +`Aabb3d::new` has been renamed to `Aabb3d::from_half_size`, and a new constructor has been added `Aabb3d::from_min_max`.