diff --git a/crates/bevy_gizmos/src/arcs.rs b/crates/bevy_gizmos/src/arcs.rs index cc4934398db06..ce57450f2d5d6 100644 --- a/crates/bevy_gizmos/src/arcs.rs +++ b/crates/bevy_gizmos/src/arcs.rs @@ -50,14 +50,14 @@ where #[inline] pub fn arc_2d( &mut self, - isometry: Isometry2d, + isometry: impl Into, arc_angle: f32, radius: f32, color: impl Into, ) -> Arc2dBuilder<'_, 'w, 's, Config, Clear> { Arc2dBuilder { gizmos: self, - isometry, + isometry: isometry.into(), arc_angle, radius, color: color.into(), @@ -176,13 +176,13 @@ where &mut self, angle: f32, radius: f32, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> { Arc3dBuilder { gizmos: self, start_vertex: Vec3::X, - isometry, + isometry: isometry.into(), angle, radius, color: color.into(), diff --git a/crates/bevy_gizmos/src/circles.rs b/crates/bevy_gizmos/src/circles.rs index 7b0a5e82890a8..6cd11e5381822 100644 --- a/crates/bevy_gizmos/src/circles.rs +++ b/crates/bevy_gizmos/src/circles.rs @@ -51,13 +51,13 @@ where #[inline] pub fn ellipse( &mut self, - isometry: Isometry3d, + isometry: impl Into, half_size: Vec2, color: impl Into, ) -> EllipseBuilder<'_, 'w, 's, Config, Clear> { EllipseBuilder { gizmos: self, - isometry, + isometry: isometry.into(), half_size, color: color.into(), resolution: DEFAULT_CIRCLE_RESOLUTION, @@ -92,13 +92,13 @@ where #[inline] pub fn ellipse_2d( &mut self, - isometry: Isometry2d, + isometry: impl Into, half_size: Vec2, color: impl Into, ) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> { Ellipse2dBuilder { gizmos: self, - isometry, + isometry: isometry.into(), half_size, color: color.into(), resolution: DEFAULT_CIRCLE_RESOLUTION, @@ -131,13 +131,13 @@ where #[inline] pub fn circle( &mut self, - isometry: Isometry3d, + isometry: impl Into, radius: f32, color: impl Into, ) -> EllipseBuilder<'_, 'w, 's, Config, Clear> { EllipseBuilder { gizmos: self, - isometry, + isometry: isometry.into(), half_size: Vec2::splat(radius), color: color.into(), resolution: DEFAULT_CIRCLE_RESOLUTION, @@ -172,13 +172,13 @@ where #[inline] pub fn circle_2d( &mut self, - isometry: Isometry2d, + isometry: impl Into, radius: f32, color: impl Into, ) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> { Ellipse2dBuilder { gizmos: self, - isometry, + isometry: isometry.into(), half_size: Vec2::splat(radius), color: color.into(), resolution: DEFAULT_CIRCLE_RESOLUTION, @@ -214,14 +214,14 @@ where #[inline] pub fn sphere( &mut self, - isometry: Isometry3d, + isometry: impl Into, radius: f32, color: impl Into, ) -> SphereBuilder<'_, 'w, 's, Config, Clear> { SphereBuilder { gizmos: self, radius, - isometry, + isometry: isometry.into(), color: color.into(), resolution: DEFAULT_CIRCLE_RESOLUTION, } diff --git a/crates/bevy_gizmos/src/cross.rs b/crates/bevy_gizmos/src/cross.rs index 710aa71e9a982..d08e2ddb8dcff 100644 --- a/crates/bevy_gizmos/src/cross.rs +++ b/crates/bevy_gizmos/src/cross.rs @@ -30,7 +30,13 @@ where /// } /// # bevy_ecs::system::assert_is_system(system); /// ``` - pub fn cross(&mut self, isometry: Isometry3d, half_size: f32, color: impl Into) { + pub fn cross( + &mut self, + isometry: impl Into, + half_size: f32, + color: impl Into, + ) { + let isometry = isometry.into(); let color: Color = color.into(); [Vec3::X, Vec3::Y, Vec3::Z] .map(|axis| axis * half_size) @@ -59,7 +65,13 @@ where /// } /// # bevy_ecs::system::assert_is_system(system); /// ``` - pub fn cross_2d(&mut self, isometry: Isometry2d, half_size: f32, color: impl Into) { + pub fn cross_2d( + &mut self, + isometry: impl Into, + half_size: f32, + color: impl Into, + ) { + let isometry = isometry.into(); let color: Color = color.into(); [Vec2::X, Vec2::Y] .map(|axis| axis * half_size) diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 86df15333949f..508cd5519c2bd 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -482,10 +482,11 @@ where /// # bevy_ecs::system::assert_is_system(system); /// ``` #[inline] - pub fn rect(&mut self, isometry: Isometry3d, size: Vec2, color: impl Into) { + pub fn rect(&mut self, isometry: impl Into, size: Vec2, color: impl Into) { if !self.enabled { return; } + let isometry = isometry.into(); let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2.extend(0.)); self.linestrip([tl, tr, br, bl, tl], color); } @@ -709,10 +710,16 @@ where /// # bevy_ecs::system::assert_is_system(system); /// ``` #[inline] - pub fn rect_2d(&mut self, isometry: Isometry2d, size: Vec2, color: impl Into) { + pub fn rect_2d( + &mut self, + isometry: impl Into, + size: Vec2, + color: impl Into, + ) { if !self.enabled { return; } + let isometry = isometry.into(); let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2); self.linestrip_2d([tl, tr, br, bl, tl], color); } diff --git a/crates/bevy_gizmos/src/grid.rs b/crates/bevy_gizmos/src/grid.rs index 55e611d767874..20cb4e115b023 100644 --- a/crates/bevy_gizmos/src/grid.rs +++ b/crates/bevy_gizmos/src/grid.rs @@ -218,14 +218,14 @@ where /// ``` pub fn grid( &mut self, - isometry: Isometry3d, + isometry: impl Into, cell_count: UVec2, spacing: Vec2, color: impl Into, ) -> GridBuilder2d<'_, 'w, 's, Config, Clear> { GridBuilder2d { gizmos: self, - isometry, + isometry: isometry.into(), spacing, cell_count, skew: Vec2::ZERO, @@ -272,14 +272,14 @@ where /// ``` pub fn grid_3d( &mut self, - isometry: Isometry3d, + isometry: impl Into, cell_count: UVec3, spacing: Vec3, color: impl Into, ) -> GridBuilder3d<'_, 'w, 's, Config, Clear> { GridBuilder3d { gizmos: self, - isometry, + isometry: isometry.into(), spacing, cell_count, skew: Vec3::ZERO, @@ -326,11 +326,12 @@ where /// ``` pub fn grid_2d( &mut self, - isometry: Isometry2d, + isometry: impl Into, cell_count: UVec2, spacing: Vec2, color: impl Into, ) -> GridBuilder2d<'_, 'w, 's, Config, Clear> { + let isometry = isometry.into(); GridBuilder2d { gizmos: self, isometry: Isometry3d::new( diff --git a/crates/bevy_gizmos/src/light.rs b/crates/bevy_gizmos/src/light.rs index 615f1e8753cbf..9a618ac85acc7 100644 --- a/crates/bevy_gizmos/src/light.rs +++ b/crates/bevy_gizmos/src/light.rs @@ -41,20 +41,10 @@ fn point_light_gizmo( ) { let position = transform.translation(); gizmos - .primitive_3d( - &Sphere { - radius: point_light.radius, - }, - Isometry3d::from_translation(position), - color, - ) + .primitive_3d(&Sphere::new(point_light.radius), position, color) .resolution(16); gizmos - .sphere( - Isometry3d::from_translation(position), - point_light.range, - color, - ) + .sphere(position, point_light.range, color) .resolution(32); } @@ -68,13 +58,7 @@ fn spot_light_gizmo( ) { let (_, rotation, translation) = transform.to_scale_rotation_translation(); gizmos - .primitive_3d( - &Sphere { - radius: spot_light.radius, - }, - Isometry3d::from_translation(translation), - color, - ) + .primitive_3d(&Sphere::new(spot_light.radius), translation, color) .resolution(16); // Offset the tip of the cone to the light position. diff --git a/crates/bevy_gizmos/src/primitives/dim2.rs b/crates/bevy_gizmos/src/primitives/dim2.rs index 732eba0c019d8..0c3b44cd67dee 100644 --- a/crates/bevy_gizmos/src/primitives/dim2.rs +++ b/crates/bevy_gizmos/src/primitives/dim2.rs @@ -33,7 +33,7 @@ pub trait GizmoPrimitive2d { fn primitive_2d( &mut self, primitive: &P, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_>; } @@ -53,12 +53,13 @@ where fn primitive_2d( &mut self, primitive: &Dir2, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let start = Vec2::ZERO; let end = *primitive * MIN_LINE_LEN; self.arrow_2d(isometry * start, isometry * end, color); @@ -80,13 +81,14 @@ where fn primitive_2d( &mut self, primitive: &Arc2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let start_iso = isometry * Isometry2d::from_rotation(Rot2::radians(-primitive.half_angle)); self.arc_2d( @@ -113,7 +115,7 @@ where fn primitive_2d( &mut self, primitive: &Circle, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { self.circle_2d(isometry, primitive.radius, color) @@ -135,13 +137,14 @@ where fn primitive_2d( &mut self, primitive: &CircularSector, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let color = color.into(); let start_iso = @@ -177,13 +180,14 @@ where fn primitive_2d( &mut self, primitive: &CircularSegment, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let color = color.into(); let start_iso = @@ -218,7 +222,7 @@ where fn primitive_2d<'a>( &mut self, primitive: &Ellipse, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { self.ellipse_2d(isometry, primitive.half_size, color) @@ -280,12 +284,12 @@ where fn primitive_2d( &mut self, primitive: &Annulus, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Annulus2dBuilder { gizmos: self, - isometry, + isometry: isometry.into(), inner_radius: primitive.inner_circle.radius, outer_radius: primitive.outer_circle.radius, color: color.into(), @@ -340,12 +344,13 @@ where fn primitive_2d( &mut self, primitive: &Rhombus, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; }; + let isometry = isometry.into(); let [a, b, c, d] = [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| { Vec2::new( @@ -373,9 +378,10 @@ where fn primitive_2d( &mut self, primitive: &Capsule2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { + let isometry = isometry.into(); let polymorphic_color: Color = color.into(); if !self.enabled { @@ -465,13 +471,13 @@ where fn primitive_2d( &mut self, primitive: &Line2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Line2dBuilder { gizmos: self, direction: primitive.direction, - isometry, + isometry: isometry.into(), color: color.into(), draw_arrow: false, } @@ -523,9 +529,10 @@ where fn primitive_2d( &mut self, primitive: &Plane2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { + let isometry = isometry.into(); let polymorphic_color: Color = color.into(); if !self.enabled { @@ -604,7 +611,7 @@ where fn primitive_2d( &mut self, primitive: &Segment2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Segment2dBuilder { @@ -612,7 +619,7 @@ where direction: primitive.direction, half_length: primitive.half_length, - isometry, + isometry: isometry.into(), color: color.into(), draw_arrow: Default::default(), @@ -658,13 +665,15 @@ where fn primitive_2d( &mut self, primitive: &Polyline2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + self.linestrip_2d( primitive .vertices @@ -691,13 +700,15 @@ where fn primitive_2d( &mut self, primitive: &BoxedPolyline2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + self.linestrip_2d( primitive .vertices @@ -724,12 +735,15 @@ where fn primitive_2d( &mut self, primitive: &Triangle2d, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + + let isometry = isometry.into(); + let [a, b, c] = primitive.vertices; let positions = [a, b, c, a].map(|vec2| isometry * vec2); self.linestrip_2d(positions, color); @@ -751,13 +765,15 @@ where fn primitive_2d( &mut self, primitive: &Rectangle, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + let [a, b, c, d] = [(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0)].map(|(sign_x, sign_y)| { Vec2::new( @@ -786,13 +802,15 @@ where fn primitive_2d( &mut self, primitive: &Polygon, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + // Check if the polygon needs a closing point let closing_point = { let first = primitive.vertices.first(); @@ -829,13 +847,15 @@ where fn primitive_2d( &mut self, primitive: &BoxedPolygon, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + let closing_point = { let first = primitive.vertices.first(); (primitive.vertices.last() != first) @@ -870,13 +890,15 @@ where fn primitive_2d( &mut self, primitive: &RegularPolygon, - isometry: Isometry2d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + let points = (0..=primitive.sides) .map(|n| single_circle_coordinate(primitive.circumcircle.radius, primitive.sides, n)) .map(|vec2| isometry * vec2); diff --git a/crates/bevy_gizmos/src/primitives/dim3.rs b/crates/bevy_gizmos/src/primitives/dim3.rs index 5ed99314f7633..4c11628246878 100644 --- a/crates/bevy_gizmos/src/primitives/dim3.rs +++ b/crates/bevy_gizmos/src/primitives/dim3.rs @@ -31,7 +31,7 @@ pub trait GizmoPrimitive3d { fn primitive_3d( &mut self, primitive: &P, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_>; } @@ -51,9 +51,10 @@ where fn primitive_3d( &mut self, primitive: &Dir3, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { + let isometry = isometry.into(); let start = Vec3::ZERO; let end = primitive.as_vec3(); self.arrow(isometry * start, isometry * end, color); @@ -75,7 +76,7 @@ where fn primitive_3d( &mut self, primitive: &Sphere, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { self.sphere(isometry, primitive.radius, color) @@ -136,13 +137,13 @@ where fn primitive_3d( &mut self, primitive: &Plane3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Plane3dBuilder { gizmos: self, normal: primitive.normal, - isometry, + isometry: isometry.into(), color: color.into(), cell_count: UVec2::splat(3), spacing: Vec2::splat(1.0), @@ -188,13 +189,14 @@ where fn primitive_3d( &mut self, primitive: &Line3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let color = color.into(); let direction = primitive.direction.as_vec3(); self.arrow(isometry * Vec3::ZERO, isometry * direction, color); @@ -222,13 +224,14 @@ where fn primitive_3d( &mut self, primitive: &Segment3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let direction = primitive.direction.as_vec3(); self.line(isometry * direction, isometry * (-direction), color); } @@ -250,13 +253,14 @@ where fn primitive_3d( &mut self, primitive: &Polyline3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); self.linestrip(primitive.vertices.map(|vec3| isometry * vec3), color); } } @@ -276,13 +280,14 @@ where fn primitive_3d( &mut self, primitive: &BoxedPolyline3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); self.linestrip( primitive .vertices @@ -309,13 +314,14 @@ where fn primitive_3d( &mut self, primitive: &Triangle3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); let [a, b, c] = primitive.vertices; self.linestrip([a, b, c, a].map(|vec3| isometry * vec3), color); } @@ -336,13 +342,15 @@ where fn primitive_3d( &mut self, primitive: &Cuboid, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + // transform the points from the reference unit cube to the cuboid coords let vertices @ [a, b, c, d, e, f, g, h] = [ [1.0, 1.0, 1.0], @@ -429,14 +437,14 @@ where fn primitive_3d( &mut self, primitive: &Cylinder, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Cylinder3dBuilder { gizmos: self, radius: primitive.radius, half_height: primitive.half_height, - isometry, + isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, } @@ -515,14 +523,14 @@ where fn primitive_3d( &mut self, primitive: &Capsule3d, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Capsule3dBuilder { gizmos: self, radius: primitive.radius, half_length: primitive.half_length, - isometry, + isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, } @@ -655,14 +663,14 @@ where fn primitive_3d( &mut self, primitive: &Cone, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Cone3dBuilder { gizmos: self, radius: primitive.radius, height: primitive.height, - isometry, + isometry: isometry.into(), color: color.into(), base_resolution: DEFAULT_RESOLUTION, height_resolution: DEFAULT_RESOLUTION, @@ -757,7 +765,7 @@ where fn primitive_3d( &mut self, primitive: &ConicalFrustum, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { ConicalFrustum3dBuilder { @@ -765,7 +773,7 @@ where radius_top: primitive.radius_top, radius_bottom: primitive.radius_bottom, height: primitive.height, - isometry, + isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, } @@ -861,14 +869,14 @@ where fn primitive_3d( &mut self, primitive: &Torus, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { Torus3dBuilder { gizmos: self, minor_radius: primitive.minor_radius, major_radius: primitive.major_radius, - isometry, + isometry: isometry.into(), color: color.into(), minor_resolution: DEFAULT_RESOLUTION, major_resolution: DEFAULT_RESOLUTION, @@ -937,13 +945,15 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, ' fn primitive_3d( &mut self, primitive: &Tetrahedron, - isometry: Isometry3d, + isometry: impl Into, color: impl Into, ) -> Self::Output<'_> { if !self.enabled { return; } + let isometry = isometry.into(); + let [a, b, c, d] = primitive.vertices.map(|vec3| isometry * vec3); let lines = [(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)]; diff --git a/crates/bevy_gizmos/src/rounded_box.rs b/crates/bevy_gizmos/src/rounded_box.rs index 70ee09b64d01d..2b107dbcf52c8 100644 --- a/crates/bevy_gizmos/src/rounded_box.rs +++ b/crates/bevy_gizmos/src/rounded_box.rs @@ -240,7 +240,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { /// ``` pub fn rounded_rect( &mut self, - isometry: Isometry3d, + isometry: impl Into, size: Vec2, color: impl Into, ) -> RoundedRectBuilder<'_, 'w, 's, T> { @@ -248,7 +248,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { RoundedRectBuilder { gizmos: self, config: RoundedBoxConfig { - isometry, + isometry: isometry.into(), color: color.into(), corner_radius, arc_resolution: DEFAULT_ARC_RESOLUTION, @@ -294,10 +294,11 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { /// ``` pub fn rounded_rect_2d( &mut self, - isometry: Isometry2d, + isometry: impl Into, size: Vec2, color: impl Into, ) -> RoundedRectBuilder<'_, 'w, 's, T> { + let isometry = isometry.into(); let corner_radius = size.min_element() * DEFAULT_CORNER_RADIUS; RoundedRectBuilder { gizmos: self, @@ -351,7 +352,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { /// ``` pub fn rounded_cuboid( &mut self, - isometry: Isometry3d, + isometry: impl Into, size: Vec3, color: impl Into, ) -> RoundedCuboidBuilder<'_, 'w, 's, T> { @@ -359,7 +360,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { RoundedCuboidBuilder { gizmos: self, config: RoundedBoxConfig { - isometry, + isometry: isometry.into(), color: color.into(), corner_radius, arc_resolution: DEFAULT_ARC_RESOLUTION, diff --git a/crates/bevy_math/src/bounding/bounded2d/mod.rs b/crates/bevy_math/src/bounding/bounded2d/mod.rs index 8f6812bc27247..7e824101bc790 100644 --- a/crates/bevy_math/src/bounding/bounded2d/mod.rs +++ b/crates/bevy_math/src/bounding/bounded2d/mod.rs @@ -24,9 +24,9 @@ fn point_cloud_2d_center(points: &[Vec2]) -> Vec2 { /// A trait with methods that return 2D bounding volumes for a shape. pub trait Bounded2d { /// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry. - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d; + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d; /// Get a bounding circle for the shape translated and rotated by the given isometry. - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle; + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle; } /// A 2D axis-aligned bounding box, or bounding rectangle @@ -58,7 +58,9 @@ impl Aabb2d { /// /// Panics if the given set of points is empty. #[inline(always)] - pub fn from_point_cloud(isometry: Isometry2d, points: &[Vec2]) -> Aabb2d { + pub fn from_point_cloud(isometry: impl Into, points: &[Vec2]) -> Aabb2d { + let isometry = isometry.into(); + // Transform all points by rotation let mut iter = points.iter().map(|point| isometry.rotation * *point); @@ -472,7 +474,9 @@ impl BoundingCircle { /// /// The bounding circle is not guaranteed to be the smallest possible. #[inline(always)] - pub fn from_point_cloud(isometry: Isometry2d, points: &[Vec2]) -> BoundingCircle { + pub fn from_point_cloud(isometry: impl Into, points: &[Vec2]) -> BoundingCircle { + let isometry = isometry.into(); + let center = point_cloud_2d_center(points); let mut radius_squared = 0.0; diff --git a/crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs b/crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs index 1d6b67b0d6aa7..d4d211cd127a5 100644 --- a/crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs +++ b/crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs @@ -16,11 +16,13 @@ use smallvec::SmallVec; use super::{Aabb2d, Bounded2d, BoundingCircle}; impl Bounded2d for Circle { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); Aabb2d::new(isometry.translation, Vec2::splat(self.radius)) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.radius) } } @@ -58,19 +60,23 @@ fn arc_bounding_points(arc: Arc2d, rotation: impl Into) -> SmallVec<[Vec2; } impl Bounded2d for Arc2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { // If our arc covers more than a circle, just return the bounding box of the circle. if self.half_angle >= PI { return Circle::new(self.radius).aabb_2d(isometry); } + let isometry = isometry.into(); + Aabb2d::from_point_cloud( Isometry2d::from_translation(isometry.translation), &arc_bounding_points(*self, isometry.rotation), ) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); + // There are two possibilities for the bounding circle. if self.is_major() { // If the arc is major, then the widest distance between two points is a diameter of the arc's circle; @@ -86,7 +92,9 @@ impl Bounded2d for Arc2d { } impl Bounded2d for CircularSector { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + // If our sector covers more than a circle, just return the bounding box of the circle. if self.half_angle() >= PI { return Circle::new(self.radius()).aabb_2d(isometry); @@ -99,8 +107,10 @@ impl Bounded2d for CircularSector { Aabb2d::from_point_cloud(Isometry2d::from_translation(isometry.translation), &bounds) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { if self.arc.is_major() { + let isometry = isometry.into(); + // If the arc is major, that is, greater than a semicircle, // then bounding circle is just the circle defining the sector. BoundingCircle::new(isometry.translation, self.arc.radius) @@ -121,17 +131,19 @@ impl Bounded2d for CircularSector { } impl Bounded2d for CircularSegment { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { self.arc.aabb_2d(isometry) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { self.arc.bounding_circle(isometry) } } impl Bounded2d for Ellipse { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + // V = (hh * cos(beta), hh * sin(beta)) // #####*##### // ### | ### @@ -160,23 +172,28 @@ impl Bounded2d for Ellipse { Aabb2d::new(isometry.translation, half_size) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.semi_major()) } } impl Bounded2d for Annulus { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); Aabb2d::new(isometry.translation, Vec2::splat(self.outer_circle.radius)) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.outer_circle.radius) } } impl Bounded2d for Rhombus { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [ isometry.rotation * Vec2::new(self.half_diagonals.x, 0.0), isometry.rotation * Vec2::new(0.0, self.half_diagonals.y), @@ -191,13 +208,16 @@ impl Bounded2d for Rhombus { } } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.circumradius()) } } impl Bounded2d for Plane2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + let normal = isometry.rotation * *self.normal; let facing_x = normal == Vec2::X || normal == Vec2::NEG_X; let facing_y = normal == Vec2::Y || normal == Vec2::NEG_Y; @@ -211,13 +231,16 @@ impl Bounded2d for Plane2d { Aabb2d::new(isometry.translation, half_size) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, f32::MAX / 2.0) } } impl Bounded2d for Line2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + let direction = isometry.rotation * *self.direction; // Dividing `f32::MAX` by 2.0 is helpful so that we can do operations @@ -230,13 +253,16 @@ impl Bounded2d for Line2d { Aabb2d::new(isometry.translation, half_size) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, f32::MAX / 2.0) } } impl Bounded2d for Segment2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + // Rotate the segment by `rotation` let direction = isometry.rotation * *self.direction; let half_size = (self.half_length * direction).abs(); @@ -244,33 +270,35 @@ impl Bounded2d for Segment2d { Aabb2d::new(isometry.translation, half_size) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.half_length) } } impl Bounded2d for Polyline2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { Aabb2d::from_point_cloud(isometry, &self.vertices) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { BoundingCircle::from_point_cloud(isometry, &self.vertices) } } impl Bounded2d for BoxedPolyline2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { Aabb2d::from_point_cloud(isometry, &self.vertices) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { BoundingCircle::from_point_cloud(isometry, &self.vertices) } } impl Bounded2d for Triangle2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); let [a, b, c] = self.vertices.map(|vtx| isometry.rotation * vtx); let min = Vec2::new(a.x.min(b.x).min(c.x), a.y.min(b.y).min(c.y)); @@ -282,7 +310,8 @@ impl Bounded2d for Triangle2d { } } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); let [a, b, c] = self.vertices; // The points of the segment opposite to the obtuse or right angle if one exists @@ -313,7 +342,9 @@ impl Bounded2d for Triangle2d { } impl Bounded2d for Rectangle { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + // Compute the AABB of the rotated rectangle by transforming the half-extents // by an absolute rotation matrix. let (sin, cos) = isometry.rotation.sin_cos(); @@ -323,34 +354,37 @@ impl Bounded2d for Rectangle { Aabb2d::new(isometry.translation, half_size) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); let radius = self.half_size.length(); BoundingCircle::new(isometry.translation, radius) } } impl Bounded2d for Polygon { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { Aabb2d::from_point_cloud(isometry, &self.vertices) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { BoundingCircle::from_point_cloud(isometry, &self.vertices) } } impl Bounded2d for BoxedPolygon { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { Aabb2d::from_point_cloud(isometry, &self.vertices) } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { BoundingCircle::from_point_cloud(isometry, &self.vertices) } } impl Bounded2d for RegularPolygon { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + let mut min = Vec2::ZERO; let mut max = Vec2::ZERO; @@ -365,13 +399,16 @@ impl Bounded2d for RegularPolygon { } } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.circumcircle.radius) } } impl Bounded2d for Capsule2d { - fn aabb_2d(&self, isometry: Isometry2d) -> Aabb2d { + fn aabb_2d(&self, isometry: impl Into) -> Aabb2d { + let isometry = isometry.into(); + // Get the line segment between the hemicircles of the rotated capsule let segment = Segment2d { // Multiplying a normalized vector (Vec2::Y) with a rotation returns a normalized vector. @@ -390,7 +427,8 @@ impl Bounded2d for Capsule2d { } } - fn bounding_circle(&self, isometry: Isometry2d) -> BoundingCircle { + fn bounding_circle(&self, isometry: impl Into) -> BoundingCircle { + let isometry = isometry.into(); BoundingCircle::new(isometry.translation, self.radius + self.half_length) } } diff --git a/crates/bevy_math/src/bounding/bounded3d/extrusion.rs b/crates/bevy_math/src/bounding/bounded3d/extrusion.rs index 8784a3286ecfd..8eb3eb9791795 100644 --- a/crates/bevy_math/src/bounding/bounded3d/extrusion.rs +++ b/crates/bevy_math/src/bounding/bounded3d/extrusion.rs @@ -17,9 +17,11 @@ use crate::{bounding::Bounded2d, primitives::Circle}; use super::{Aabb3d, Bounded3d, BoundingSphere}; impl BoundedExtrusion for Circle { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { // Reference: http://iquilezles.org/articles/diskbbox/ + let isometry = isometry.into(); + let segment_dir = isometry.rotation * Vec3A::Z; let top = (segment_dir * half_depth).abs(); @@ -34,7 +36,8 @@ impl BoundedExtrusion for Circle { } impl BoundedExtrusion for Ellipse { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let Vec2 { x: a, y: b } = self.half_size; let normal = isometry.rotation * Vec3A::Z; let conjugate_rot = isometry.rotation.conjugate(); @@ -64,7 +67,8 @@ impl BoundedExtrusion for Ellipse { } impl BoundedExtrusion for Line2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let dir = isometry.rotation * Vec3A::from(self.direction.extend(0.)); let half_depth = (isometry.rotation * Vec3A::new(0., 0., half_depth)).abs(); @@ -80,7 +84,8 @@ impl BoundedExtrusion for Line2d { } impl BoundedExtrusion for Segment2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let half_size = isometry.rotation * Vec3A::from(self.point1().extend(0.)); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -89,7 +94,8 @@ impl BoundedExtrusion for Segment2d { } impl BoundedExtrusion for Polyline2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter()); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -99,7 +105,8 @@ impl BoundedExtrusion for Polyline2d { } impl BoundedExtrusion for BoxedPolyline2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.))); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -108,7 +115,8 @@ impl BoundedExtrusion for BoxedPolyline2d { } impl BoundedExtrusion for Triangle2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.))); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -117,7 +125,7 @@ impl BoundedExtrusion for Triangle2d { } impl BoundedExtrusion for Rectangle { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { Cuboid { half_size: self.half_size.extend(half_depth), } @@ -126,7 +134,8 @@ impl BoundedExtrusion for Rectangle { } impl BoundedExtrusion for Polygon { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.map(|v| v.extend(0.)).into_iter()); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -136,7 +145,8 @@ impl BoundedExtrusion for Polygon { } impl BoundedExtrusion for BoxedPolygon { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud(isometry, self.vertices.iter().map(|v| v.extend(0.))); let depth = isometry.rotation * Vec3A::new(0., 0., half_depth); @@ -145,7 +155,8 @@ impl BoundedExtrusion for BoxedPolygon { } impl BoundedExtrusion for RegularPolygon { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Aabb3d::from_point_cloud( isometry, self.vertices(0.).into_iter().map(|v| v.extend(0.)), @@ -157,14 +168,13 @@ impl BoundedExtrusion for RegularPolygon { } impl BoundedExtrusion for Capsule2d { - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let aabb = Cylinder { half_height: half_depth, radius: self.radius, } - .aabb_3d(Isometry3d::from_rotation( - isometry.rotation * Quat::from_rotation_x(FRAC_PI_2), - )); + .aabb_3d(isometry.rotation * Quat::from_rotation_x(FRAC_PI_2)); let up = isometry.rotation * Vec3A::new(0., self.half_length, 0.); let half_size = aabb.max + up.abs(); @@ -173,11 +183,11 @@ impl BoundedExtrusion for Capsule2d { } impl Bounded3d for Extrusion { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { self.base_shape.extrusion_aabb_3d(self.half_depth, isometry) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { self.base_shape .extrusion_bounding_sphere(self.half_depth, isometry) } @@ -191,7 +201,8 @@ impl Bounded3d for Extrusion { /// `impl BoundedExtrusion for MyShape {}` pub trait BoundedExtrusion: Primitive2d + Bounded2d { /// Get an axis-aligned bounding box for an extrusion with this shape as a base and the given `half_depth`, transformed by the given `translation` and `rotation`. - fn extrusion_aabb_3d(&self, half_depth: f32, isometry: Isometry3d) -> Aabb3d { + fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let cap_normal = isometry.rotation * Vec3A::Z; let conjugate_rot = isometry.rotation.conjugate(); @@ -213,7 +224,7 @@ pub trait BoundedExtrusion: Primitive2d + Bounded2d { // Calculate the `Aabb2d` of the base shape. The shape is rotated so that the line of intersection is parallel to the Y axis in the `Aabb2d` calculations. // This guarantees that the X value of the `Aabb2d` is closest to the `ax` plane - let aabb2d = self.aabb_2d(Isometry2d::from_rotation(Rot2::radians(angle))); + let aabb2d = self.aabb_2d(Rot2::radians(angle)); (aabb2d.half_size().x * scale, aabb2d.center().x * scale) }); @@ -225,7 +236,13 @@ pub trait BoundedExtrusion: Primitive2d + Bounded2d { } /// Get a bounding sphere for an extrusion of the `base_shape` with the given `half_depth` with the given translation and rotation - fn extrusion_bounding_sphere(&self, half_depth: f32, isometry: Isometry3d) -> BoundingSphere { + fn extrusion_bounding_sphere( + &self, + half_depth: f32, + isometry: impl Into, + ) -> BoundingSphere { + let isometry = isometry.into(); + // We calculate the bounding circle of the base shape. // Since each of the extrusions bases will have the same distance from its center, // and they are just shifted along the Z-axis, the minimum bounding sphere will be the bounding sphere @@ -261,13 +278,12 @@ mod tests { fn circle() { let cylinder = Extrusion::new(Circle::new(0.5), 2.0); let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = cylinder.aabb_3d(isometry); + let aabb = cylinder.aabb_3d(translation); assert_eq!(aabb.center(), Vec3A::from(translation)); assert_eq!(aabb.half_size(), Vec3A::new(0.5, 0.5, 1.0)); - let bounding_sphere = cylinder.bounding_sphere(isometry); + let bounding_sphere = cylinder.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5)); } diff --git a/crates/bevy_math/src/bounding/bounded3d/mod.rs b/crates/bevy_math/src/bounding/bounded3d/mod.rs index 81edbe8a57d4f..38460fc08e09f 100644 --- a/crates/bevy_math/src/bounding/bounded3d/mod.rs +++ b/crates/bevy_math/src/bounding/bounded3d/mod.rs @@ -27,9 +27,9 @@ fn point_cloud_3d_center(points: impl Iterator>) -> Vec3 /// A trait with methods that return 3D bounding volumes for a shape. pub trait Bounded3d { /// Get an axis-aligned bounding box for the shape translated and rotated by the given isometry. - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d; + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d; /// Get a bounding sphere for the shape translated and rotated by the given isometry. - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere; + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere; } /// A 3D axis-aligned bounding box @@ -62,9 +62,11 @@ impl Aabb3d { /// Panics if the given set of points is empty. #[inline(always)] pub fn from_point_cloud( - isometry: Isometry3d, + isometry: impl Into, points: impl Iterator>, ) -> Aabb3d { + let isometry = isometry.into(); + // Transform all points by rotation let mut iter = points.map(|point| isometry.rotation * point.into()); @@ -476,9 +478,11 @@ impl BoundingSphere { /// The bounding sphere is not guaranteed to be the smallest possible. #[inline(always)] pub fn from_point_cloud( - isometry: Isometry3d, + isometry: impl Into, points: &[impl Copy + Into], ) -> BoundingSphere { + let isometry = isometry.into(); + let center = point_cloud_3d_center(points.iter().map(|v| Into::::into(*v))); let mut radius_squared: f32 = 0.0; diff --git a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs index bb6a6a5a12c37..3871ac07490ae 100644 --- a/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs +++ b/crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs @@ -15,17 +15,21 @@ use crate::{ use super::{Aabb3d, Bounded3d, BoundingSphere}; impl Bounded3d for Sphere { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); Aabb3d::new(isometry.translation, Vec3::splat(self.radius)) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, self.radius) } } impl Bounded3d for InfinitePlane3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); + let normal = isometry.rotation * *self.normal; let facing_x = normal == Vec3::X || normal == Vec3::NEG_X; let facing_y = normal == Vec3::Y || normal == Vec3::NEG_Y; @@ -41,13 +45,15 @@ impl Bounded3d for InfinitePlane3d { Aabb3d::new(isometry.translation, half_size) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, f32::MAX / 2.0) } } impl Bounded3d for Line3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let direction = isometry.rotation * *self.direction; // Dividing `f32::MAX` by 2.0 is helpful so that we can do operations @@ -61,13 +67,16 @@ impl Bounded3d for Line3d { Aabb3d::new(isometry.translation, half_size) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, f32::MAX / 2.0) } } impl Bounded3d for Segment3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); + // Rotate the segment by `rotation` let direction = isometry.rotation * *self.direction; let half_size = (self.half_length * direction).abs(); @@ -75,33 +84,36 @@ impl Bounded3d for Segment3d { Aabb3d::new(isometry.translation, half_size) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, self.half_length) } } impl Bounded3d for Polyline3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied()) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { BoundingSphere::from_point_cloud(isometry, &self.vertices) } } impl Bounded3d for BoxedPolyline3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied()) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { BoundingSphere::from_point_cloud(isometry, &self.vertices) } } impl Bounded3d for Cuboid { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); + // Compute the AABB of the rotated cuboid by transforming the half-size // by an absolute rotation matrix. let rot_mat = Mat3::from_quat(isometry.rotation); @@ -115,15 +127,18 @@ impl Bounded3d for Cuboid { Aabb3d::new(isometry.translation, half_size) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, self.half_size.length()) } } impl Bounded3d for Cylinder { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { // Reference: http://iquilezles.org/articles/diskbbox/ + let isometry = isometry.into(); + let segment_dir = isometry.rotation * Vec3A::Y; let top = segment_dir * self.half_height; let bottom = -top; @@ -137,14 +152,17 @@ impl Bounded3d for Cylinder { } } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); let radius = ops::hypot(self.radius, self.half_height); BoundingSphere::new(isometry.translation, radius) } } impl Bounded3d for Capsule3d { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); + // Get the line segment between the hemispheres of the rotated capsule let segment_dir = isometry.rotation * Vec3A::Y; let top = segment_dir * self.half_length; @@ -160,15 +178,18 @@ impl Bounded3d for Capsule3d { } } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, self.radius + self.half_length) } } impl Bounded3d for Cone { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { // Reference: http://iquilezles.org/articles/diskbbox/ + let isometry = isometry.into(); + let segment_dir = isometry.rotation * Vec3A::Y; let top = segment_dir * 0.5 * self.height; let bottom = -top; @@ -182,7 +203,9 @@ impl Bounded3d for Cone { } } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); + // Get the triangular cross-section of the cone. let half_height = 0.5 * self.height; let triangle = Triangle2d::new( @@ -203,9 +226,11 @@ impl Bounded3d for Cone { } impl Bounded3d for ConicalFrustum { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { // Reference: http://iquilezles.org/articles/diskbbox/ + let isometry = isometry.into(); + let segment_dir = isometry.rotation * Vec3A::Y; let top = segment_dir * 0.5 * self.height; let bottom = -top; @@ -223,7 +248,8 @@ impl Bounded3d for ConicalFrustum { } } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); let half_height = 0.5 * self.height; // To compute the bounding sphere, we'll get the center and radius of the circumcircle @@ -286,7 +312,9 @@ impl Bounded3d for ConicalFrustum { } impl Bounded3d for Torus { - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); + // Compute the AABB of a flat disc with the major radius of the torus. // Reference: http://iquilezles.org/articles/diskbbox/ let normal = isometry.rotation * Vec3A::Y; @@ -299,14 +327,16 @@ impl Bounded3d for Torus { Aabb3d::new(isometry.translation, half_size) } - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); BoundingSphere::new(isometry.translation, self.outer_radius()) } } impl Bounded3d for Triangle3d { /// Get the bounding box of the triangle. - fn aabb_3d(&self, isometry: Isometry3d) -> Aabb3d { + fn aabb_3d(&self, isometry: impl Into) -> Aabb3d { + let isometry = isometry.into(); let [a, b, c] = self.vertices; let a = isometry.rotation * a; @@ -327,7 +357,9 @@ impl Bounded3d for Triangle3d { /// The [`Triangle3d`] implements the minimal bounding sphere calculation. For acute triangles, the circumcenter is used as /// the center of the sphere. For the others, the bounding sphere is the minimal sphere /// that contains the largest side of the triangle. - fn bounding_sphere(&self, isometry: Isometry3d) -> BoundingSphere { + fn bounding_sphere(&self, isometry: impl Into) -> BoundingSphere { + let isometry = isometry.into(); + if self.is_degenerate() || self.is_obtuse() { let (p1, p2) = self.largest_side(); let (p1, p2) = (Vec3A::from(p1), Vec3A::from(p2)); @@ -362,13 +394,12 @@ mod tests { fn sphere() { let sphere = Sphere { radius: 1.0 }; let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = sphere.aabb_3d(isometry); + let aabb = sphere.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0)); assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0)); - let bounding_sphere = sphere.bounding_sphere(isometry); + let bounding_sphere = sphere.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), 1.0); } @@ -376,25 +407,24 @@ mod tests { #[test] fn plane() { let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb1 = InfinitePlane3d::new(Vec3::X).aabb_3d(isometry); + let aabb1 = InfinitePlane3d::new(Vec3::X).aabb_3d(translation); assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, -f32::MAX / 2.0)); assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, f32::MAX / 2.0)); - let aabb2 = InfinitePlane3d::new(Vec3::Y).aabb_3d(isometry); + let aabb2 = InfinitePlane3d::new(Vec3::Y).aabb_3d(translation); assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, -f32::MAX / 2.0)); assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, f32::MAX / 2.0)); - let aabb3 = InfinitePlane3d::new(Vec3::Z).aabb_3d(isometry); + let aabb3 = InfinitePlane3d::new(Vec3::Z).aabb_3d(translation); assert_eq!(aabb3.min, Vec3A::new(-f32::MAX / 2.0, -f32::MAX / 2.0, 0.0)); assert_eq!(aabb3.max, Vec3A::new(f32::MAX / 2.0, f32::MAX / 2.0, 0.0)); - let aabb4 = InfinitePlane3d::new(Vec3::ONE).aabb_3d(isometry); + let aabb4 = InfinitePlane3d::new(Vec3::ONE).aabb_3d(translation); assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0)); assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0)); - let bounding_sphere = InfinitePlane3d::new(Vec3::Y).bounding_sphere(isometry); + let bounding_sphere = InfinitePlane3d::new(Vec3::Y).bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0); } @@ -402,28 +432,27 @@ mod tests { #[test] fn line() { let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb1 = Line3d { direction: Dir3::Y }.aabb_3d(isometry); + let aabb1 = Line3d { direction: Dir3::Y }.aabb_3d(translation); assert_eq!(aabb1.min, Vec3A::new(2.0, -f32::MAX / 2.0, 0.0)); assert_eq!(aabb1.max, Vec3A::new(2.0, f32::MAX / 2.0, 0.0)); - let aabb2 = Line3d { direction: Dir3::X }.aabb_3d(isometry); + let aabb2 = Line3d { direction: Dir3::X }.aabb_3d(translation); assert_eq!(aabb2.min, Vec3A::new(-f32::MAX / 2.0, 1.0, 0.0)); assert_eq!(aabb2.max, Vec3A::new(f32::MAX / 2.0, 1.0, 0.0)); - let aabb3 = Line3d { direction: Dir3::Z }.aabb_3d(isometry); + let aabb3 = Line3d { direction: Dir3::Z }.aabb_3d(translation); assert_eq!(aabb3.min, Vec3A::new(2.0, 1.0, -f32::MAX / 2.0)); assert_eq!(aabb3.max, Vec3A::new(2.0, 1.0, f32::MAX / 2.0)); let aabb4 = Line3d { direction: Dir3::from_xyz(1.0, 1.0, 1.0).unwrap(), } - .aabb_3d(isometry); + .aabb_3d(translation); assert_eq!(aabb4.min, Vec3A::splat(-f32::MAX / 2.0)); assert_eq!(aabb4.max, Vec3A::splat(f32::MAX / 2.0)); - let bounding_sphere = Line3d { direction: Dir3::Y }.bounding_sphere(isometry); + let bounding_sphere = Line3d { direction: Dir3::Y }.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0); } @@ -431,16 +460,15 @@ mod tests { #[test] fn segment() { let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); let segment = Segment3d::from_points(Vec3::new(-1.0, -0.5, 0.0), Vec3::new(1.0, 0.5, 0.0)).0; - let aabb = segment.aabb_3d(isometry); + let aabb = segment.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(1.0, 0.5, 0.0)); assert_eq!(aabb.max, Vec3A::new(3.0, 1.5, 0.0)); - let bounding_sphere = segment.bounding_sphere(isometry); + let bounding_sphere = segment.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5)); } @@ -454,13 +482,12 @@ mod tests { Vec3::new(1.0, -1.0, -1.0), ]); let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = polyline.aabb_3d(isometry); + let aabb = polyline.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0)); assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0)); - let bounding_sphere = polyline.bounding_sphere(isometry); + let bounding_sphere = polyline.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!( bounding_sphere.radius(), @@ -481,7 +508,7 @@ mod tests { assert_eq!(aabb.min, Vec3A::from(translation) - expected_half_size); assert_eq!(aabb.max, Vec3A::from(translation) + expected_half_size); - let bounding_sphere = cuboid.bounding_sphere(Isometry3d::from_translation(translation)); + let bounding_sphere = cuboid.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!( bounding_sphere.radius(), @@ -493,9 +520,8 @@ mod tests { fn cylinder() { let cylinder = Cylinder::new(0.5, 2.0); let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = cylinder.aabb_3d(isometry); + let aabb = cylinder.aabb_3d(translation); assert_eq!( aabb.min, Vec3A::from(translation) - Vec3A::new(0.5, 1.0, 0.5) @@ -505,7 +531,7 @@ mod tests { Vec3A::from(translation) + Vec3A::new(0.5, 1.0, 0.5) ); - let bounding_sphere = cylinder.bounding_sphere(isometry); + let bounding_sphere = cylinder.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), ops::hypot(1.0, 0.5)); } @@ -514,9 +540,8 @@ mod tests { fn capsule() { let capsule = Capsule3d::new(0.5, 2.0); let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = capsule.aabb_3d(isometry); + let aabb = capsule.aabb_3d(translation); assert_eq!( aabb.min, Vec3A::from(translation) - Vec3A::new(0.5, 1.5, 0.5) @@ -526,7 +551,7 @@ mod tests { Vec3A::from(translation) + Vec3A::new(0.5, 1.5, 0.5) ); - let bounding_sphere = capsule.bounding_sphere(isometry); + let bounding_sphere = capsule.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), 1.5); } @@ -538,13 +563,12 @@ mod tests { height: 2.0, }; let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = cone.aabb_3d(isometry); + let aabb = cone.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0)); assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0)); - let bounding_sphere = cone.bounding_sphere(isometry); + let bounding_sphere = cone.bounding_sphere(translation); assert_eq!( bounding_sphere.center, Vec3A::from(translation) + Vec3A::NEG_Y * 0.25 @@ -560,13 +584,12 @@ mod tests { height: 2.0, }; let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = conical_frustum.aabb_3d(isometry); + let aabb = conical_frustum.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(1.0, 0.0, -1.0)); assert_eq!(aabb.max, Vec3A::new(3.0, 2.0, 1.0)); - let bounding_sphere = conical_frustum.bounding_sphere(isometry); + let bounding_sphere = conical_frustum.bounding_sphere(translation); assert_eq!( bounding_sphere.center, Vec3A::from(translation) + Vec3A::NEG_Y * 0.1875 @@ -582,15 +605,14 @@ mod tests { height: 1.0, }; let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = conical_frustum.aabb_3d(isometry); + let aabb = conical_frustum.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(-3.0, 0.5, -5.0)); assert_eq!(aabb.max, Vec3A::new(7.0, 1.5, 5.0)); // For wide conical frusta like this, the circumcenter can be outside the frustum, // so the center and radius should be clamped to the longest side. - let bounding_sphere = conical_frustum.bounding_sphere(isometry); + let bounding_sphere = conical_frustum.bounding_sphere(translation); assert_eq!( bounding_sphere.center, Vec3A::from(translation) + Vec3A::NEG_Y * 0.5 @@ -605,13 +627,12 @@ mod tests { major_radius: 1.0, }; let translation = Vec3::new(2.0, 1.0, 0.0); - let isometry = Isometry3d::from_translation(translation); - let aabb = torus.aabb_3d(isometry); + let aabb = torus.aabb_3d(translation); assert_eq!(aabb.min, Vec3A::new(0.5, 0.5, -1.5)); assert_eq!(aabb.max, Vec3A::new(3.5, 1.5, 1.5)); - let bounding_sphere = torus.bounding_sphere(isometry); + let bounding_sphere = torus.bounding_sphere(translation); assert_eq!(bounding_sphere.center, translation.into()); assert_eq!(bounding_sphere.radius(), 1.5); } diff --git a/crates/bevy_math/src/isometry.rs b/crates/bevy_math/src/isometry.rs index 356b78738db05..e01a8cd713661 100644 --- a/crates/bevy_math/src/isometry.rs +++ b/crates/bevy_math/src/isometry.rs @@ -192,6 +192,20 @@ impl From for Affine2 { } } +impl From for Isometry2d { + #[inline] + fn from(translation: Vec2) -> Self { + Isometry2d::from_translation(translation) + } +} + +impl From for Isometry2d { + #[inline] + fn from(rotation: Rot2) -> Self { + Isometry2d::from_rotation(rotation) + } +} + impl Mul for Isometry2d { type Output = Self; @@ -466,6 +480,27 @@ impl From for Affine3A { } } +impl From for Isometry3d { + #[inline] + fn from(translation: Vec3) -> Self { + Isometry3d::from_translation(translation) + } +} + +impl From for Isometry3d { + #[inline] + fn from(translation: Vec3A) -> Self { + Isometry3d::from_translation(translation) + } +} + +impl From for Isometry3d { + #[inline] + fn from(rotation: Quat) -> Self { + Isometry3d::from_rotation(rotation) + } +} + impl Mul for Isometry3d { type Output = Self; diff --git a/crates/bevy_math/src/primitives/dim3.rs b/crates/bevy_math/src/primitives/dim3.rs index d3761455d8cf2..cd1b5013e6b72 100644 --- a/crates/bevy_math/src/primitives/dim3.rs +++ b/crates/bevy_math/src/primitives/dim3.rs @@ -220,7 +220,8 @@ impl InfinitePlane3d { /// `point`. The result is a signed value; it's positive if the point lies in the half-space /// that the plane's normal vector points towards. #[inline] - pub fn signed_distance(&self, isometry: Isometry3d, point: Vec3) -> f32 { + pub fn signed_distance(&self, isometry: impl Into, point: Vec3) -> f32 { + let isometry = isometry.into(); self.normal.dot(isometry.inverse() * point) } @@ -228,7 +229,7 @@ impl InfinitePlane3d { /// /// This projects the point orthogonally along the shortest path onto the plane. #[inline] - pub fn project_point(&self, isometry: Isometry3d, point: Vec3) -> Vec3 { + pub fn project_point(&self, isometry: impl Into, point: Vec3) -> Vec3 { point - self.normal * self.signed_distance(isometry, point) } @@ -1374,36 +1375,36 @@ mod tests { let point_in_plane = Vec3::X + Vec3::Z; assert_eq!( - plane.signed_distance(Isometry3d::from_translation(origin), point_in_plane), + plane.signed_distance(origin, point_in_plane), 0.0, "incorrect distance" ); assert_eq!( - plane.project_point(Isometry3d::from_translation(origin), point_in_plane), + plane.project_point(origin, point_in_plane), point_in_plane, "incorrect point" ); let point_outside = Vec3::Y; assert_eq!( - plane.signed_distance(Isometry3d::from_translation(origin), point_outside), + plane.signed_distance(origin, point_outside), -1.0, "incorrect distance" ); assert_eq!( - plane.project_point(Isometry3d::from_translation(origin), point_outside), + plane.project_point(origin, point_outside), Vec3::ZERO, "incorrect point" ); let point_outside = Vec3::NEG_Y; assert_eq!( - plane.signed_distance(Isometry3d::from_translation(origin), point_outside), + plane.signed_distance(origin, point_outside), 1.0, "incorrect distance" ); assert_eq!( - plane.project_point(Isometry3d::from_translation(origin), point_outside), + plane.project_point(origin, point_outside), Vec3::ZERO, "incorrect point" ); diff --git a/examples/2d/2d_viewport_to_world.rs b/examples/2d/2d_viewport_to_world.rs index 193fc281290a1..5648f30e87211 100644 --- a/examples/2d/2d_viewport_to_world.rs +++ b/examples/2d/2d_viewport_to_world.rs @@ -1,6 +1,6 @@ //! This example demonstrates how to use the `Camera::viewport_to_world_2d` method. -use bevy::{color::palettes::basic::WHITE, math::Isometry2d, prelude::*}; +use bevy::{color::palettes::basic::WHITE, prelude::*}; fn main() { App::new() @@ -30,7 +30,7 @@ fn draw_cursor( return; }; - gizmos.circle_2d(Isometry2d::from_translation(point), 10., WHITE); + gizmos.circle_2d(point, 10., WHITE); } fn setup(mut commands: Commands) { diff --git a/examples/2d/bounding_2d.rs b/examples/2d/bounding_2d.rs index 0a44c6ae686fb..ac71c4b8b9112 100644 --- a/examples/2d/bounding_2d.rs +++ b/examples/2d/bounding_2d.rs @@ -186,14 +186,10 @@ fn render_volumes(mut gizmos: Gizmos, query: Query<(&CurrentVolume, &Intersects) let color = if **intersects { AQUA } else { ORANGE_RED }; match volume { CurrentVolume::Aabb(a) => { - gizmos.rect_2d( - Isometry2d::from_translation(a.center()), - a.half_size() * 2., - color, - ); + gizmos.rect_2d(a.center(), a.half_size() * 2., color); } CurrentVolume::Circle(c) => { - gizmos.circle_2d(Isometry2d::from_translation(c.center()), c.radius(), color); + gizmos.circle_2d(c.center(), c.radius(), color); } } } @@ -288,7 +284,7 @@ fn setup(mut commands: Commands) { fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) { for r in [1., 2., 3.] { - gizmos.circle_2d(Isometry2d::from_translation(position), r, color); + gizmos.circle_2d(position, r, color); } } @@ -361,9 +357,7 @@ fn aabb_cast_system( **intersects = toi.is_some(); if let Some(toi) = toi { gizmos.rect_2d( - Isometry2d::from_translation( - aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi, - ), + aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi, aabb_cast.aabb.half_size() * 2., LIME, ); @@ -391,9 +385,7 @@ fn bounding_circle_cast_system( **intersects = toi.is_some(); if let Some(toi) = toi { gizmos.circle_2d( - Isometry2d::from_translation( - circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi, - ), + circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi, circle_cast.circle.radius(), LIME, ); @@ -414,11 +406,7 @@ fn aabb_intersection_system( ) { let center = get_intersection_position(&time); let aabb = Aabb2d::new(center, Vec2::splat(50.)); - gizmos.rect_2d( - Isometry2d::from_translation(center), - aabb.half_size() * 2., - YELLOW, - ); + gizmos.rect_2d(center, aabb.half_size() * 2., YELLOW); for (volume, mut intersects) in volumes.iter_mut() { let hit = match volume { @@ -437,11 +425,7 @@ fn circle_intersection_system( ) { let center = get_intersection_position(&time); let circle = BoundingCircle::new(center, 50.); - gizmos.circle_2d( - Isometry2d::from_translation(center), - circle.radius(), - YELLOW, - ); + gizmos.circle_2d(center, circle.radius(), YELLOW); for (volume, mut intersects) in volumes.iter_mut() { let hit = match volume { diff --git a/examples/2d/mesh2d_arcs.rs b/examples/2d/mesh2d_arcs.rs index 975cc2cf8bbf0..e1b2f604359e5 100644 --- a/examples/2d/mesh2d_arcs.rs +++ b/examples/2d/mesh2d_arcs.rs @@ -114,17 +114,9 @@ fn draw_bounds( let isometry = Isometry2d::new(translation, Rot2::radians(rotation)); let aabb = shape.0.aabb_2d(isometry); - gizmos.rect_2d( - Isometry2d::from_translation(aabb.center()), - aabb.half_size() * 2.0, - RED, - ); + gizmos.rect_2d(aabb.center(), aabb.half_size() * 2.0, RED); let bounding_circle = shape.0.bounding_circle(isometry); - gizmos.circle_2d( - Isometry2d::from_translation(bounding_circle.center), - bounding_circle.radius(), - BLUE, - ); + gizmos.circle_2d(bounding_circle.center, bounding_circle.radius(), BLUE); } } diff --git a/examples/ecs/observers.rs b/examples/ecs/observers.rs index 5b4d8b0b81129..58b5e4e13959d 100644 --- a/examples/ecs/observers.rs +++ b/examples/ecs/observers.rs @@ -1,7 +1,6 @@ //! Demonstrates how to observe life-cycle triggers as well as define custom ones. use bevy::{ - math::Isometry2d, prelude::*, utils::{HashMap, HashSet}, }; @@ -166,7 +165,7 @@ fn explode_mine(trigger: Trigger, query: Query<&Mine>, mut commands: Co fn draw_shapes(mut gizmos: Gizmos, mines: Query<&Mine>) { for mine in &mines { gizmos.circle_2d( - Isometry2d::from_translation(mine.pos), + mine.pos, mine.size, Color::hsl((mine.size - 4.0) / 16.0 * 360.0, 1.0, 0.8), ); diff --git a/examples/gizmos/2d_gizmos.rs b/examples/gizmos/2d_gizmos.rs index 929ec47e3788e..45f31ceb3c4e4 100644 --- a/examples/gizmos/2d_gizmos.rs +++ b/examples/gizmos/2d_gizmos.rs @@ -67,11 +67,7 @@ fn draw_example_collection( gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK); - gizmos.cross_2d( - Isometry2d::from_translation(Vec2::new(-160., 120.)), - 12., - FUCHSIA, - ); + gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA); let domain = Interval::EVERYWHERE; let curve = function_curve(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0)); @@ -89,11 +85,11 @@ fn draw_example_collection( // Circles have 32 line-segments by default. // You may want to increase this for larger circles. my_gizmos - .circle_2d(Isometry2d::from_translation(Vec2::ZERO), 300., NAVY) + .circle_2d(Isometry2d::IDENTITY, 300., NAVY) .resolution(64); my_gizmos.ellipse_2d( - Isometry2d::new(Vec2::ZERO, Rot2::radians(time.elapsed_seconds() % TAU)), + Rot2::radians(time.elapsed_seconds() % TAU), Vec2::new(100., 200.), YELLOW_GREEN, ); @@ -101,7 +97,7 @@ fn draw_example_collection( // Arcs default resolution is linearly interpolated between // 1 and 32, using the arc length as scalar. my_gizmos.arc_2d( - Isometry2d::from_rotation(Rot2::radians(sin_t_scaled / 10.)), + Rot2::radians(sin_t_scaled / 10.), FRAC_PI_2, 310., ORANGE_RED, diff --git a/examples/gizmos/3d_gizmos.rs b/examples/gizmos/3d_gizmos.rs index 6da3db4110e2f..7a95d6e9a50c3 100644 --- a/examples/gizmos/3d_gizmos.rs +++ b/examples/gizmos/3d_gizmos.rs @@ -78,19 +78,19 @@ fn draw_example_collection( time: Res