From 16bb5b762e8772cf5c478889a06329e0d0ab9d51 Mon Sep 17 00:00:00 2001 From: Joshua Ani Date: Fri, 25 Feb 2022 02:22:10 -0500 Subject: [PATCH 1/5] Fixed the frustum-sphere collision and added tests --- crates/bevy_render/src/primitives/mod.rs | 180 ++++++++++++++++++++++- 1 file changed, 178 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 623abd0d1801c..e62ba2100724d 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -74,7 +74,7 @@ impl Sphere { /// A plane defined by a normal and distance value along the normal /// Any point p is in the plane if n.p = d -/// For planes defining half-spaces such as for frusta, if n.p > d then p is on the positive side of the plane. +/// For planes defining half-spaces such as for frusta, if n.p > d then p is on the positive side (inside) of the plane. #[derive(Clone, Copy, Debug, Default)] pub struct Plane { pub normal_d: Vec4, @@ -118,7 +118,10 @@ impl Frustum { pub fn intersects_sphere(&self, sphere: &Sphere) -> bool { for plane in &self.planes { - if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius <= 0.0 { + // The formula `normal . center + d + radius <= 0` relies on `normal` being normalized, + // which is not necessarily the case. + let factor = (plane.normal_d.truncate().length_squared() / plane.normal_d.length_squared()).sqrt(); + if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius * factor <= 0.0 { return false; } } @@ -159,3 +162,176 @@ impl CubemapFrusta { self.frusta.iter_mut() } } + +#[cfg(test)] +mod tests { + use super::*; + + fn big_frustum() -> Frustum { + Frustum { planes: [ + Plane { normal_d: Vec4::new(-0.2425, -0.0606, -0.0000, 1.9403).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, 0.2500, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.0606, -0.2425, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.2500, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.0606, 0.2425, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(0.2425, -0.0606, -0.0000, -0.4851).normalize() }, + ]} + } + + #[test] + fn intersects_sphere_big_frustum_outside() { + // Sphere outside frustum + let frustum = big_frustum(); + let sphere = Sphere { + center: Vec3::new(0.9167, 0.0000, 0.0000), + radius: 0.7500, + }; + assert!(!frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_big_frustum_intersect() { + // Sphere intersects frustum boundary + let frustum = big_frustum(); + let sphere = Sphere { + center: Vec3::new(7.9288, 0.0000, 2.9728), + radius: 2.0000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + // A frustum + fn frustum() -> Frustum { + Frustum { planes: [ + Plane { normal_d: Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(0.9701, -0.2425, -0.0000, 0.7276).normalize() }, + ]} + } + + #[test] + fn intersects_sphere_frustum_surrounding() { + // Sphere surrounds frustum + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(0.0000, 0.0000, 0.0000), + radius: 3.0000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_frustum_contained() { + // Sphere is contained in frustum + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(0.0000, 0.0000, 0.0000), + radius: 0.7000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_frustum_intersects_plane() { + // Sphere intersects a plane + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(0.0000, 0.0000, 0.9695), + radius: 0.7000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_frustum_intersects_2_planes() { + // Sphere intersects 2 planes + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(1.2037, 0.0000, 0.9695), + radius: 0.7000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_frustum_intersects_3_planes() { + // Sphere intersects 3 planes + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(1.2037, -1.0988, 0.9695), + radius: 0.7000, + }; + assert!(frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_frustum_dodges_1_plane() { + // Sphere avoids intersecting the frustum by 1 plane + let frustum = frustum(); + let sphere = Sphere { + center: Vec3::new(-1.7020, 0.0000, 0.0000), + radius: 0.7000, + }; + assert!(!frustum.intersects_sphere(&sphere)); + } + + // These tests are not handled, and it may not be worth handling them. + //#[test] + //fn intersects_sphere_frustum_dodges_2_planes() { + // // Sphere avoids intersecting the frustum by a combination of 2 planes + // let frustum = frustum(); + // let sphere = Sphere { + // center: Vec3::new(-1.6048, -1.5564, 0.0000), + // radius: 0.7000, + // }; + // assert!(!frustum.intersects_sphere(&sphere)); + //} + + //#[test] + //fn intersects_sphere_frustum_dodges_3_planes() { + // // Sphere avoids intersecting the frustum by a combination of 3 planes + // let frustum = frustum(); + // let sphere = Sphere { + // center: Vec3::new(-1.3059, -1.5564, -1.4264), + // radius: 0.7000, + // }; + // assert!(!frustum.intersects_sphere(&sphere)); + //} + + // A long frustum. + fn long_frustum() -> Frustum { + Frustum { planes: [ + Plane { normal_d: Vec4::new(-0.2425, -0.0054, -0.0000, -0.4741).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, 0.0222, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.0054, -0.3202, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.0222, -0.0000, 1.0000).normalize() }, + Plane { normal_d: Vec4::new(-0.0000, -0.0054, 0.3202, 0.7276).normalize() }, + Plane { normal_d: Vec4::new(0.2425, -0.0054, -0.0000, 1.9293).normalize() }, + ]} + } + + #[test] + fn intersects_sphere_long_frustum_outside() { + // Sphere outside frustum + let frustum = long_frustum(); + let sphere = Sphere { + center: Vec3::new(-4.4889, 46.9021, 0.0000), + radius: 0.7500, + }; + assert!(!frustum.intersects_sphere(&sphere)); + } + + #[test] + fn intersects_sphere_long_frustum_intersect() { + // Sphere intersects frustum boundary + let frustum = long_frustum(); + let sphere = Sphere { + center: Vec3::new(-4.9957, 0.0000, -0.7396), + radius: 4.4094, + }; + assert!(frustum.intersects_sphere(&sphere)); + } +} \ No newline at end of file From 881db8672fc19e0beb608af29c53cf29ded320e6 Mon Sep 17 00:00:00 2001 From: Joshua Ani Date: Fri, 25 Feb 2022 02:35:24 -0500 Subject: [PATCH 2/5] Formatting --- crates/bevy_render/src/primitives/mod.rs | 96 +++++++++++++++++------- 1 file changed, 70 insertions(+), 26 deletions(-) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index e62ba2100724d..9ee07ca94c28d 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -120,7 +120,9 @@ impl Frustum { for plane in &self.planes { // The formula `normal . center + d + radius <= 0` relies on `normal` being normalized, // which is not necessarily the case. - let factor = (plane.normal_d.truncate().length_squared() / plane.normal_d.length_squared()).sqrt(); + let factor = (plane.normal_d.truncate().length_squared() + / plane.normal_d.length_squared()) + .sqrt(); if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius * factor <= 0.0 { return false; } @@ -168,14 +170,28 @@ mod tests { use super::*; fn big_frustum() -> Frustum { - Frustum { planes: [ - Plane { normal_d: Vec4::new(-0.2425, -0.0606, -0.0000, 1.9403).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, 0.2500, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.0606, -0.2425, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.2500, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.0606, 0.2425, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(0.2425, -0.0606, -0.0000, -0.4851).normalize() }, - ]} + Frustum { + planes: [ + Plane { + normal_d: Vec4::new(-0.2425, -0.0606, -0.0000, 1.9403).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, 0.2500, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.0606, -0.2425, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.2500, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.0606, 0.2425, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(0.2425, -0.0606, -0.0000, -0.4851).normalize(), + }, + ], + } } #[test] @@ -202,14 +218,28 @@ mod tests { // A frustum fn frustum() -> Frustum { - Frustum { planes: [ - Plane { normal_d: Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(0.9701, -0.2425, -0.0000, 0.7276).normalize() }, - ]} + Frustum { + planes: [ + Plane { + normal_d: Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(0.9701, -0.2425, -0.0000, 0.7276).normalize(), + }, + ], + } } #[test] @@ -303,14 +333,28 @@ mod tests { // A long frustum. fn long_frustum() -> Frustum { - Frustum { planes: [ - Plane { normal_d: Vec4::new(-0.2425, -0.0054, -0.0000, -0.4741).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, 0.0222, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.0054, -0.3202, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.0222, -0.0000, 1.0000).normalize() }, - Plane { normal_d: Vec4::new(-0.0000, -0.0054, 0.3202, 0.7276).normalize() }, - Plane { normal_d: Vec4::new(0.2425, -0.0054, -0.0000, 1.9293).normalize() }, - ]} + Frustum { + planes: [ + Plane { + normal_d: Vec4::new(-0.2425, -0.0054, -0.0000, -0.4741).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, 0.0222, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.0054, -0.3202, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.0222, -0.0000, 1.0000).normalize(), + }, + Plane { + normal_d: Vec4::new(-0.0000, -0.0054, 0.3202, 0.7276).normalize(), + }, + Plane { + normal_d: Vec4::new(0.2425, -0.0054, -0.0000, 1.9293).normalize(), + }, + ], + } } #[test] @@ -334,4 +378,4 @@ mod tests { }; assert!(frustum.intersects_sphere(&sphere)); } -} \ No newline at end of file +} From ce787f6e8196949962c196c20507c5dfe9d579a9 Mon Sep 17 00:00:00 2001 From: Joshua Ani Date: Fri, 25 Feb 2022 12:28:06 -0500 Subject: [PATCH 3/5] Added constructor that normalizes normal --- crates/bevy_render/src/primitives/mod.rs | 128 +++++++---------------- 1 file changed, 37 insertions(+), 91 deletions(-) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 9ee07ca94c28d..5d87707e3d0d2 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -1,5 +1,5 @@ use bevy_ecs::{component::Component, reflect::ReflectComponent}; -use bevy_math::{Mat4, Vec3, Vec3A, Vec4}; +use bevy_math::{Mat4, Vec3, Vec3A, Vec4, Vec4Swizzles}; use bevy_reflect::Reflect; /// An Axis-Aligned Bounding Box @@ -72,7 +72,7 @@ impl Sphere { } } -/// A plane defined by a normal and distance value along the normal +/// A plane defined by a normalized normal and distance value along the normal /// Any point p is in the plane if n.p = d /// For planes defining half-spaces such as for frusta, if n.p > d then p is on the positive side (inside) of the plane. #[derive(Clone, Copy, Debug, Default)] @@ -80,6 +80,18 @@ pub struct Plane { pub normal_d: Vec4, } +impl Plane { + /// Constructs a `Plane` from a 4D vector whose first 3 components + /// are the normal and whose last component is d. + /// Ensures that the normal is normalized and d is scaled accordingly + /// so it represents the signed distance from the origin. + fn new(normal_d: Vec4) -> Self { + Self { + normal_d: normal_d * normal_d.xyz().length_recip(), + } + } +} + #[derive(Component, Clone, Copy, Debug, Default, Reflect)] #[reflect(Component)] pub struct Frustum { @@ -102,28 +114,20 @@ impl Frustum { let mut planes = [Plane::default(); 6]; for (i, plane) in planes.iter_mut().enumerate().take(5) { let row = view_projection.row(i / 2); - plane.normal_d = if (i & 1) == 0 && i != 4 { + *plane = Plane::new(if (i & 1) == 0 && i != 4 { row3 + row } else { row3 - row - } - .normalize(); + }); } let far_center = *view_translation - far * *view_backward; - planes[5].normal_d = view_backward - .extend(-view_backward.dot(far_center)) - .normalize(); + planes[5] = Plane::new(view_backward.extend(-view_backward.dot(far_center))); Self { planes } } pub fn intersects_sphere(&self, sphere: &Sphere) -> bool { for plane in &self.planes { - // The formula `normal . center + d + radius <= 0` relies on `normal` being normalized, - // which is not necessarily the case. - let factor = (plane.normal_d.truncate().length_squared() - / plane.normal_d.length_squared()) - .sqrt(); - if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius * factor <= 0.0 { + if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius <= 0.0 { return false; } } @@ -169,27 +173,16 @@ impl CubemapFrusta { mod tests { use super::*; + // A big, offset frustum fn big_frustum() -> Frustum { Frustum { planes: [ - Plane { - normal_d: Vec4::new(-0.2425, -0.0606, -0.0000, 1.9403).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, 0.2500, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.0606, -0.2425, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.2500, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.0606, 0.2425, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(0.2425, -0.0606, -0.0000, -0.4851).normalize(), - }, + Plane::new(Vec4::new(-0.9701, -0.2425, -0.0000, 7.7611)), + Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 4.0000)), + Plane::new(Vec4::new(-0.0000, -0.2425, -0.9701, 2.9104)), + Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 4.0000)), + Plane::new(Vec4::new(-0.0000, -0.2425, 0.9701, 2.9104)), + Plane::new(Vec4::new(0.9701, -0.2425, -0.0000, -1.9403)), ], } } @@ -220,24 +213,12 @@ mod tests { fn frustum() -> Frustum { Frustum { planes: [ - Plane { - normal_d: Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(0.9701, -0.2425, -0.0000, 0.7276).normalize(), - }, + Plane::new(Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276)), + Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000)), + Plane::new(Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276)), + Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000)), + Plane::new(Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276)), + Plane::new(Vec4::new(0.9701, -0.2425, -0.0000, 0.7276)), ], } } @@ -308,51 +289,16 @@ mod tests { assert!(!frustum.intersects_sphere(&sphere)); } - // These tests are not handled, and it may not be worth handling them. - //#[test] - //fn intersects_sphere_frustum_dodges_2_planes() { - // // Sphere avoids intersecting the frustum by a combination of 2 planes - // let frustum = frustum(); - // let sphere = Sphere { - // center: Vec3::new(-1.6048, -1.5564, 0.0000), - // radius: 0.7000, - // }; - // assert!(!frustum.intersects_sphere(&sphere)); - //} - - //#[test] - //fn intersects_sphere_frustum_dodges_3_planes() { - // // Sphere avoids intersecting the frustum by a combination of 3 planes - // let frustum = frustum(); - // let sphere = Sphere { - // center: Vec3::new(-1.3059, -1.5564, -1.4264), - // radius: 0.7000, - // }; - // assert!(!frustum.intersects_sphere(&sphere)); - //} - // A long frustum. fn long_frustum() -> Frustum { Frustum { planes: [ - Plane { - normal_d: Vec4::new(-0.2425, -0.0054, -0.0000, -0.4741).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, 0.0222, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.0054, -0.3202, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.0222, -0.0000, 1.0000).normalize(), - }, - Plane { - normal_d: Vec4::new(-0.0000, -0.0054, 0.3202, 0.7276).normalize(), - }, - Plane { - normal_d: Vec4::new(0.2425, -0.0054, -0.0000, 1.9293).normalize(), - }, + Plane::new(Vec4::new(-0.9998, -0.0222, -0.0000, -1.9543)), + Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 45.1249)), + Plane::new(Vec4::new(-0.0000, -0.0168, -0.9999, 2.2718)), + Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 45.1249)), + Plane::new(Vec4::new(-0.0000, -0.0168, 0.9999, 2.2718)), + Plane::new(Vec4::new(0.9998, -0.0222, -0.0000, 7.9528)), ], } } From 3507530b048a0c717d7b9864f3333fc1bdc7b4f3 Mon Sep 17 00:00:00 2001 From: Joshua Ani Date: Wed, 2 Mar 2022 23:09:17 -0500 Subject: [PATCH 4/5] Applied suggestions --- crates/bevy_render/src/primitives/mod.rs | 44 ++++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 5d87707e3d0d2..32a60200edebe 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -72,24 +72,46 @@ impl Sphere { } } -/// A plane defined by a normalized normal and distance value along the normal -/// Any point p is in the plane if n.p = d -/// For planes defining half-spaces such as for frusta, if n.p > d then p is on the positive side (inside) of the plane. +/// A plane defined by a unit normal and distance from the origin along the normal +/// Any point p is in the plane if n.p + d = 0 +/// For planes defining half-spaces such as for frusta, if n.p + d > 0 then p is on +/// the positive side (inside) of the plane. #[derive(Clone, Copy, Debug, Default)] pub struct Plane { - pub normal_d: Vec4, + normal_d: Vec4, } impl Plane { /// Constructs a `Plane` from a 4D vector whose first 3 components - /// are the normal and whose last component is d. - /// Ensures that the normal is normalized and d is scaled accordingly - /// so it represents the signed distance from the origin. - fn new(normal_d: Vec4) -> Self { + /// are the normal and whose last component is the distance along the normal + /// from the origin. + /// This constructor ensures that the normal is normalized and the distance is + /// scaled accordingly so it represents the signed distance from the origin. + pub fn new(normal_d: Vec4) -> Self { Self { normal_d: normal_d * normal_d.xyz().length_recip(), } } + + /// `Plane` unit normal + #[inline] + pub fn normal(&self) -> Vec3 { + self.normal_d.xyz() + } + + /// Signed distance from the origin along the unit normal such that n.p + d = 0 for point p in + /// the `Plane` + #[inline] + pub fn d(&self) -> f32 { + self.normal_d.w + } + + /// `Plane` unit normal and signed distance from the origin such that n.p + d = 0 for point p + /// in the `Plane` + #[inline] + pub fn normal_d(&self) -> Vec4 { + self.normal_d + } } #[derive(Component, Clone, Copy, Debug, Default, Reflect)] @@ -127,7 +149,7 @@ impl Frustum { pub fn intersects_sphere(&self, sphere: &Sphere) -> bool { for plane in &self.planes { - if plane.normal_d.dot(sphere.center.extend(1.0)) + sphere.radius <= 0.0 { + if plane.normal_d().dot(sphere.center.extend(1.0)) + sphere.radius <= 0.0 { return false; } } @@ -143,9 +165,9 @@ impl Frustum { ]; for plane in &self.planes { - let p_normal = Vec3A::from(plane.normal_d); + let p_normal = Vec3A::from(plane.normal_d()); let relative_radius = aabb.relative_radius(&p_normal, &axes); - if plane.normal_d.dot(aabb_center_world) + relative_radius <= 0.0 { + if plane.normal_d().dot(aabb_center_world) + relative_radius <= 0.0 { return false; } } From a46ea9f0340af286c17cb97de2bbf3da35918c44 Mon Sep 17 00:00:00 2001 From: Joshua Ani Date: Mon, 7 Mar 2022 01:58:29 -0500 Subject: [PATCH 5/5] Inlined constructor of Plane --- crates/bevy_render/src/primitives/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 32a60200edebe..161e8c24fd75a 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -87,6 +87,7 @@ impl Plane { /// from the origin. /// This constructor ensures that the normal is normalized and the distance is /// scaled accordingly so it represents the signed distance from the origin. + #[inline] pub fn new(normal_d: Vec4) -> Self { Self { normal_d: normal_d * normal_d.xyz().length_recip(),