-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Rename Plane
struct to HalfSpace
#8744
Merged
Merged
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
6c4f8aa
Refactor Plane struct
hate 4958bc8
Adjust HalfSpace documentation
hate ddde5ac
fmt
hate 5e12dff
Reword HalfSpace documentation
hate 9b1b92f
Update crates/bevy_render/src/primitives/mod.rs
hate 997a5bb
Add backticks
hate 576ac98
Update crates/bevy_render/src/primitives/mod.rs
hate dfc862b
remove line
hate d9469e7
Adjust Frustum documentation
hate cdbb26c
Grammar
hate 45b78e7
Rename planes member to half_spaces
hate d13eea9
Update crates/bevy_render/src/primitives/mod.rs
hate 478cbad
add missing documentation
hate File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,70 +81,69 @@ impl Sphere { | |
} | ||
} | ||
|
||
/// 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. | ||
/// A bisecting plane that partitions 3D space into two regions. | ||
/// | ||
/// Each instance of this type is characterized by the bisecting plane's unit normal and distance from the origin along the normal. | ||
/// Any point `p` is considered to be within the `HalfSpace` when the distance is positive, | ||
/// meaning: if the equation `n.p + d > 0` is satisfied. | ||
#[derive(Clone, Copy, Debug, Default)] | ||
pub struct Plane { | ||
pub struct HalfSpace { | ||
normal_d: Vec4, | ||
} | ||
|
||
impl Plane { | ||
/// 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. | ||
impl HalfSpace { | ||
/// Constructs a `HalfSpace` from a 4D vector whose first 3 components | ||
/// represent the bisecting plane's unit normal, and the last component signifies | ||
/// the distance from the origin to the plane along the normal. | ||
/// The constructor ensures the normal vector is normalized and the distance is appropriately scaled. | ||
#[inline] | ||
pub fn new(normal_d: Vec4) -> Self { | ||
Self { | ||
normal_d: normal_d * normal_d.xyz().length_recip(), | ||
} | ||
} | ||
|
||
/// `Plane` unit normal | ||
/// Returns the unit normal vector of the bisecting plane that characterizes the `HalfSpace`. | ||
#[inline] | ||
pub fn normal(&self) -> Vec3A { | ||
Vec3A::from(self.normal_d) | ||
} | ||
|
||
/// Signed distance from the origin along the unit normal such that n.p + d = 0 for point p in | ||
/// the `Plane` | ||
/// Returns the distance from the origin to the bisecting plane along the plane's unit normal vector. | ||
/// This distance helps determine the position of a point `p` on the bisecting plane, as per the equation `n.p + d = 0`. | ||
#[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` | ||
/// Returns the bisecting plane's unit normal vector and the distance from the origin to the plane. | ||
#[inline] | ||
pub fn normal_d(&self) -> Vec4 { | ||
self.normal_d | ||
} | ||
} | ||
|
||
/// A frustum defined by the 6 containing planes | ||
/// Planes are ordered left, right, top, bottom, near, far | ||
/// Normals point into the contained volume | ||
/// A frustum made up of the 6 defining half spaces. | ||
/// Half spaces are ordered left, right, top, bottom, near, far. | ||
/// The normal vectors of the half spaces point towards the interior of the frustum. | ||
#[derive(Component, Clone, Copy, Debug, Default, Reflect)] | ||
#[reflect(Component)] | ||
pub struct Frustum { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see the doc string for |
||
#[reflect(ignore)] | ||
pub planes: [Plane; 6], | ||
pub half_spaces: [HalfSpace; 6], | ||
} | ||
|
||
impl Frustum { | ||
/// Returns a frustum derived from `view_projection`. | ||
#[inline] | ||
pub fn from_view_projection(view_projection: &Mat4) -> Self { | ||
let mut frustum = Frustum::from_view_projection_no_far(view_projection); | ||
frustum.planes[5] = Plane::new(view_projection.row(2)); | ||
frustum.half_spaces[5] = HalfSpace::new(view_projection.row(2)); | ||
frustum | ||
} | ||
|
||
/// Returns a frustum derived from `view_projection`, but with a custom | ||
/// far plane. | ||
/// Returns a frustum derived from `view_projection`, | ||
/// but with a custom far plane. | ||
#[inline] | ||
pub fn from_view_projection_custom_far( | ||
view_projection: &Mat4, | ||
|
@@ -154,39 +153,42 @@ impl Frustum { | |
) -> Self { | ||
let mut frustum = Frustum::from_view_projection_no_far(view_projection); | ||
let far_center = *view_translation - far * *view_backward; | ||
frustum.planes[5] = Plane::new(view_backward.extend(-view_backward.dot(far_center))); | ||
frustum.half_spaces[5] = | ||
HalfSpace::new(view_backward.extend(-view_backward.dot(far_center))); | ||
frustum | ||
} | ||
|
||
// NOTE: This approach of extracting the frustum planes from the view | ||
// NOTE: This approach of extracting the frustum HalfSpaces from the view | ||
hate marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// projection matrix is from Foundations of Game Engine Development 2 | ||
// Rendering by Lengyel. | ||
fn from_view_projection_no_far(view_projection: &Mat4) -> Self { | ||
let row3 = view_projection.row(3); | ||
let mut planes = [Plane::default(); 6]; | ||
for (i, plane) in planes.iter_mut().enumerate().take(5) { | ||
let mut half_spaces = [HalfSpace::default(); 6]; | ||
for (i, half_space) in half_spaces.iter_mut().enumerate().take(5) { | ||
let row = view_projection.row(i / 2); | ||
*plane = Plane::new(if (i & 1) == 0 && i != 4 { | ||
*half_space = HalfSpace::new(if (i & 1) == 0 && i != 4 { | ||
row3 + row | ||
} else { | ||
row3 - row | ||
}); | ||
} | ||
Self { planes } | ||
Self { half_spaces } | ||
} | ||
|
||
/// Checks if a sphere intersects the frustum. | ||
#[inline] | ||
pub fn intersects_sphere(&self, sphere: &Sphere, intersect_far: bool) -> bool { | ||
let sphere_center = sphere.center.extend(1.0); | ||
let max = if intersect_far { 6 } else { 5 }; | ||
for plane in &self.planes[..max] { | ||
if plane.normal_d().dot(sphere_center) + sphere.radius <= 0.0 { | ||
for half_space in &self.half_spaces[..max] { | ||
if half_space.normal_d().dot(sphere_center) + sphere.radius <= 0.0 { | ||
return false; | ||
} | ||
} | ||
true | ||
} | ||
|
||
/// Checks if an Oriented Bounding Box (obb) intersects the frustum. | ||
#[inline] | ||
pub fn intersects_obb( | ||
&self, | ||
|
@@ -202,16 +204,16 @@ impl Frustum { | |
Vec3A::from(model_to_world.z_axis), | ||
]; | ||
|
||
for (idx, plane) in self.planes.into_iter().enumerate() { | ||
for (idx, half_space) in self.half_spaces.into_iter().enumerate() { | ||
if idx == 4 && !intersect_near { | ||
continue; | ||
} | ||
if idx == 5 && !intersect_far { | ||
continue; | ||
} | ||
let p_normal = plane.normal(); | ||
let p_normal = half_space.normal(); | ||
let relative_radius = aabb.relative_radius(&p_normal, &axes); | ||
if plane.normal_d().dot(aabb_center_world) + relative_radius <= 0.0 { | ||
if half_space.normal_d().dot(aabb_center_world) + relative_radius <= 0.0 { | ||
return false; | ||
} | ||
} | ||
|
@@ -249,13 +251,13 @@ mod tests { | |
// A big, offset frustum | ||
fn big_frustum() -> Frustum { | ||
Frustum { | ||
planes: [ | ||
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)), | ||
half_spaces: [ | ||
HalfSpace::new(Vec4::new(-0.9701, -0.2425, -0.0000, 7.7611)), | ||
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 4.0000)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.2425, -0.9701, 2.9104)), | ||
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 4.0000)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.2425, 0.9701, 2.9104)), | ||
HalfSpace::new(Vec4::new(0.9701, -0.2425, -0.0000, -1.9403)), | ||
], | ||
} | ||
} | ||
|
@@ -285,13 +287,13 @@ mod tests { | |
// A frustum | ||
fn frustum() -> Frustum { | ||
Frustum { | ||
planes: [ | ||
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)), | ||
half_spaces: [ | ||
HalfSpace::new(Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276)), | ||
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276)), | ||
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276)), | ||
HalfSpace::new(Vec4::new(0.9701, -0.2425, -0.0000, 0.7276)), | ||
], | ||
} | ||
} | ||
|
@@ -365,13 +367,13 @@ mod tests { | |
// A long frustum. | ||
fn long_frustum() -> Frustum { | ||
Frustum { | ||
planes: [ | ||
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)), | ||
half_spaces: [ | ||
HalfSpace::new(Vec4::new(-0.9998, -0.0222, -0.0000, -1.9543)), | ||
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 45.1249)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.0168, -0.9999, 2.2718)), | ||
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 45.1249)), | ||
HalfSpace::new(Vec4::new(-0.0000, -0.0168, 0.9999, 2.2718)), | ||
HalfSpace::new(Vec4::new(0.9998, -0.0222, -0.0000, 7.9528)), | ||
], | ||
} | ||
} | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Props to you, I like the phrasing 👍