-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Merged by Bors] - Fixed the frustum-sphere collision and added tests #4035
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a review on the code quality itself, not the correctness of it.
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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split up this statement. It's hard to read in it's current state.
I fixed this yesterday and was going to make a PR: superdump@34d134d I was thinking of making a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made a few suggestions for further changes for how I think the API should be after a bit more thought. Hopefully the suggested changes are all correct and there's not too much to fix elsewhere.
@@ -72,14 +72,26 @@ 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// A plane defined by a normalized normal and distance value along the normal | |
/// A plane defined by a unit normal and distance from the origin along the normal |
@@ -72,14 +72,26 @@ 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Any point p is in the plane if n.p = d | |
/// Any point p is in the plane if n.p + d = 0 |
/// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// For planes defining half-spaces such as for frusta, if n.p > d then p is on the positive side (inside) of the plane. | |
/// 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. |
/// 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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub normal_d: Vec4, | |
normal_d: Vec4, |
And then update other code that uses Plane
to use Plane::new
for construction.
/// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// 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. | |
/// Constructs a `Plane` from a 4D vector whose first 3 components | |
/// 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. |
/// 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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn new(normal_d: Vec4) -> Self { | |
pub fn new(normal_d: Vec4) -> Self { |
Self { | ||
normal_d: normal_d * normal_d.xyz().length_recip(), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
} | |
/// `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 | |
} |
And then use these in the Frustum
intersects sphere/obb functions below.
Thanks for writing the tests by the way. With the suggestions, I would likely approve this and try to prioritise it being merged. |
/// 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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this one be inline too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it could be. I haven’t tested it. I’m just using Cart’s of using online for accessors. But I don’t think we tend to use them for constructors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems the constructor is used a few time during from_view_projection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made the suggestion. I'm leaving it as approved as it's too minor to block on imo.
/// 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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn new(normal_d: Vec4) -> Self { | |
#[inline] | |
pub fn new(normal_d: Vec4) -> Self { |
bors r+ |
# Objective Fixes #3744 ## Solution The old code used the formula `normal . center + d + radius <= 0` to determine if the sphere with center `center` and radius `radius` is outside the plane with normal `normal` and distance from origin `d`. This only works if `normal` is normalized, which is not necessarily the case. Instead, `normal` and `d` are both multiplied by some factor that `radius` isn't multiplied by. So the additional code multiplied `radius` by that factor.
# Objective Fixes bevyengine#3744 ## Solution The old code used the formula `normal . center + d + radius <= 0` to determine if the sphere with center `center` and radius `radius` is outside the plane with normal `normal` and distance from origin `d`. This only works if `normal` is normalized, which is not necessarily the case. Instead, `normal` and `d` are both multiplied by some factor that `radius` isn't multiplied by. So the additional code multiplied `radius` by that factor.
# Objective Fixes bevyengine#3744 ## Solution The old code used the formula `normal . center + d + radius <= 0` to determine if the sphere with center `center` and radius `radius` is outside the plane with normal `normal` and distance from origin `d`. This only works if `normal` is normalized, which is not necessarily the case. Instead, `normal` and `d` are both multiplied by some factor that `radius` isn't multiplied by. So the additional code multiplied `radius` by that factor.
# Objective Fixes bevyengine#3744 ## Solution The old code used the formula `normal . center + d + radius <= 0` to determine if the sphere with center `center` and radius `radius` is outside the plane with normal `normal` and distance from origin `d`. This only works if `normal` is normalized, which is not necessarily the case. Instead, `normal` and `d` are both multiplied by some factor that `radius` isn't multiplied by. So the additional code multiplied `radius` by that factor.
Objective
Fixes #3744
Solution
The old code used the formula
normal . center + d + radius <= 0
to determine if the sphere with centercenter
and radiusradius
is outside the plane with normalnormal
and distance from origind
. This only works ifnormal
is normalized, which is not necessarily the case. Instead,normal
andd
are both multiplied by some factor thatradius
isn't multiplied by. So the additional code multipliedradius
by that factor.