mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Rename Plane
struct to HalfSpace
(#8744)
# Objective - Rename the `render::primitives::Plane` struct as to not confuse it with `bevy_render::mesh::shape::Plane` - Fixes https://github.com/bevyengine/bevy/issues/8730 ## Solution - Refactor the `render::primitives::Plane` struct to `render::primitives::HalfSpace` - Modify documentation to reflect this change ## Changelog - Renamed `Plane` to `HalfSpace` to more accurately represent it's use - Renamed `planes` member in `Frustum` to `half_spaces` to reflect changes ## Migration Guide - `Plane` has been renamed to `HalfSpace` - `planes` member in `Frustum` has been renamed to `half_spaces` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Nicola Papale <nicopap@users.noreply.github.com>
This commit is contained in:
parent
a78c4d78d5
commit
278daab6ae
2 changed files with 72 additions and 64 deletions
|
@ -8,7 +8,7 @@ use bevy_render::{
|
||||||
color::Color,
|
color::Color,
|
||||||
extract_resource::ExtractResource,
|
extract_resource::ExtractResource,
|
||||||
prelude::Projection,
|
prelude::Projection,
|
||||||
primitives::{Aabb, CascadesFrusta, CubemapFrusta, Frustum, Plane, Sphere},
|
primitives::{Aabb, CascadesFrusta, CubemapFrusta, Frustum, HalfSpace, Sphere},
|
||||||
render_resource::BufferBindingType,
|
render_resource::BufferBindingType,
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
view::{ComputedVisibility, RenderLayers, VisibleEntities},
|
view::{ComputedVisibility, RenderLayers, VisibleEntities},
|
||||||
|
@ -1457,7 +1457,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
let view_x = clip_to_view(inverse_projection, Vec4::new(x_pos, 0.0, 1.0, 1.0)).x;
|
let view_x = clip_to_view(inverse_projection, Vec4::new(x_pos, 0.0, 1.0, 1.0)).x;
|
||||||
let normal = Vec3::X;
|
let normal = Vec3::X;
|
||||||
let d = view_x * normal.x;
|
let d = view_x * normal.x;
|
||||||
x_planes.push(Plane::new(normal.extend(d)));
|
x_planes.push(HalfSpace::new(normal.extend(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let y_slices = clusters.dimensions.y as f32;
|
let y_slices = clusters.dimensions.y as f32;
|
||||||
|
@ -1467,7 +1467,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
let view_y = clip_to_view(inverse_projection, Vec4::new(0.0, y_pos, 1.0, 1.0)).y;
|
let view_y = clip_to_view(inverse_projection, Vec4::new(0.0, y_pos, 1.0, 1.0)).y;
|
||||||
let normal = Vec3::Y;
|
let normal = Vec3::Y;
|
||||||
let d = view_y * normal.y;
|
let d = view_y * normal.y;
|
||||||
y_planes.push(Plane::new(normal.extend(d)));
|
y_planes.push(HalfSpace::new(normal.extend(d)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let x_slices = clusters.dimensions.x as f32;
|
let x_slices = clusters.dimensions.x as f32;
|
||||||
|
@ -1478,7 +1478,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
let nt = clip_to_view(inverse_projection, Vec4::new(x_pos, 1.0, 1.0, 1.0)).xyz();
|
let nt = clip_to_view(inverse_projection, Vec4::new(x_pos, 1.0, 1.0, 1.0)).xyz();
|
||||||
let normal = nb.cross(nt);
|
let normal = nb.cross(nt);
|
||||||
let d = nb.dot(normal);
|
let d = nb.dot(normal);
|
||||||
x_planes.push(Plane::new(normal.extend(d)));
|
x_planes.push(HalfSpace::new(normal.extend(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let y_slices = clusters.dimensions.y as f32;
|
let y_slices = clusters.dimensions.y as f32;
|
||||||
|
@ -1489,7 +1489,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
let nr = clip_to_view(inverse_projection, Vec4::new(1.0, y_pos, 1.0, 1.0)).xyz();
|
let nr = clip_to_view(inverse_projection, Vec4::new(1.0, y_pos, 1.0, 1.0)).xyz();
|
||||||
let normal = nr.cross(nl);
|
let normal = nr.cross(nl);
|
||||||
let d = nr.dot(normal);
|
let d = nr.dot(normal);
|
||||||
y_planes.push(Plane::new(normal.extend(d)));
|
y_planes.push(HalfSpace::new(normal.extend(d)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1498,7 +1498,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
let view_z = z_slice_to_view_z(first_slice_depth, far_z, z_slices, z, is_orthographic);
|
let view_z = z_slice_to_view_z(first_slice_depth, far_z, z_slices, z, is_orthographic);
|
||||||
let normal = -Vec3::Z;
|
let normal = -Vec3::Z;
|
||||||
let d = view_z * normal.z;
|
let d = view_z * normal.z;
|
||||||
z_planes.push(Plane::new(normal.extend(d)));
|
z_planes.push(HalfSpace::new(normal.extend(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut update_from_light_intersections = |visible_lights: &mut Vec<Entity>| {
|
let mut update_from_light_intersections = |visible_lights: &mut Vec<Entity>| {
|
||||||
|
@ -1737,7 +1737,7 @@ pub(crate) fn assign_lights_to_clusters(
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This exploits the fact that a x-plane normal has only x and z components
|
// NOTE: This exploits the fact that a x-plane normal has only x and z components
|
||||||
fn get_distance_x(plane: Plane, point: Vec3A, is_orthographic: bool) -> f32 {
|
fn get_distance_x(plane: HalfSpace, point: Vec3A, is_orthographic: bool) -> f32 {
|
||||||
if is_orthographic {
|
if is_orthographic {
|
||||||
point.x - plane.d()
|
point.x - plane.d()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1750,7 +1750,7 @@ fn get_distance_x(plane: Plane, point: Vec3A, is_orthographic: bool) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This exploits the fact that a z-plane normal has only a z component
|
// NOTE: This exploits the fact that a z-plane normal has only a z component
|
||||||
fn project_to_plane_z(z_light: Sphere, z_plane: Plane) -> Option<Sphere> {
|
fn project_to_plane_z(z_light: Sphere, z_plane: HalfSpace) -> Option<Sphere> {
|
||||||
// p = sphere center
|
// p = sphere center
|
||||||
// n = plane normal
|
// n = plane normal
|
||||||
// d = n.p if p is in the plane
|
// d = n.p if p is in the plane
|
||||||
|
@ -1772,7 +1772,11 @@ fn project_to_plane_z(z_light: Sphere, z_plane: Plane) -> Option<Sphere> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This exploits the fact that a y-plane normal has only y and z components
|
// NOTE: This exploits the fact that a y-plane normal has only y and z components
|
||||||
fn project_to_plane_y(y_light: Sphere, y_plane: Plane, is_orthographic: bool) -> Option<Sphere> {
|
fn project_to_plane_y(
|
||||||
|
y_light: Sphere,
|
||||||
|
y_plane: HalfSpace,
|
||||||
|
is_orthographic: bool,
|
||||||
|
) -> Option<Sphere> {
|
||||||
let distance_to_plane = if is_orthographic {
|
let distance_to_plane = if is_orthographic {
|
||||||
y_plane.d() - y_light.center.y
|
y_plane.d() - y_light.center.y
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -81,21 +81,21 @@ impl Sphere {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A plane defined by a unit normal and distance from the origin along the normal
|
/// A bisecting plane that partitions 3D space into two regions.
|
||||||
/// 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
|
/// Each instance of this type is characterized by the bisecting plane's unit normal and distance from the origin along the normal.
|
||||||
/// the positive side (inside) of the plane.
|
/// 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)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct Plane {
|
pub struct HalfSpace {
|
||||||
normal_d: Vec4,
|
normal_d: Vec4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plane {
|
impl HalfSpace {
|
||||||
/// Constructs a `Plane` from a 4D vector whose first 3 components
|
/// Constructs a `HalfSpace` from a 4D vector whose first 3 components
|
||||||
/// are the normal and whose last component is the distance along the normal
|
/// represent the bisecting plane's unit normal, and the last component signifies
|
||||||
/// from the origin.
|
/// the distance from the origin to the plane along the normal.
|
||||||
/// This constructor ensures that the normal is normalized and the distance is
|
/// The constructor ensures the normal vector is normalized and the distance is appropriately scaled.
|
||||||
/// scaled accordingly so it represents the signed distance from the origin.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(normal_d: Vec4) -> Self {
|
pub fn new(normal_d: Vec4) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -103,35 +103,34 @@ impl Plane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Plane` unit normal
|
/// Returns the unit normal vector of the bisecting plane that characterizes the `HalfSpace`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normal(&self) -> Vec3A {
|
pub fn normal(&self) -> Vec3A {
|
||||||
Vec3A::from(self.normal_d)
|
Vec3A::from(self.normal_d)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signed distance from the origin along the unit normal such that n.p + d = 0 for point p in
|
/// Returns the distance from the origin to the bisecting plane along the plane's unit normal vector.
|
||||||
/// the `Plane`
|
/// This distance helps determine the position of a point `p` on the bisecting plane, as per the equation `n.p + d = 0`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn d(&self) -> f32 {
|
pub fn d(&self) -> f32 {
|
||||||
self.normal_d.w
|
self.normal_d.w
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Plane` unit normal and signed distance from the origin such that n.p + d = 0 for point p
|
/// Returns the bisecting plane's unit normal vector and the distance from the origin to the plane.
|
||||||
/// in the `Plane`
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normal_d(&self) -> Vec4 {
|
pub fn normal_d(&self) -> Vec4 {
|
||||||
self.normal_d
|
self.normal_d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A frustum defined by the 6 containing planes
|
/// A frustum made up of the 6 defining half spaces.
|
||||||
/// Planes are ordered left, right, top, bottom, near, far
|
/// Half spaces are ordered left, right, top, bottom, near, far.
|
||||||
/// Normals point into the contained volume
|
/// The normal vectors of the half spaces point towards the interior of the frustum.
|
||||||
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
|
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Frustum {
|
pub struct Frustum {
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
pub planes: [Plane; 6],
|
pub half_spaces: [HalfSpace; 6],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frustum {
|
impl Frustum {
|
||||||
|
@ -139,12 +138,12 @@ impl Frustum {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_view_projection(view_projection: &Mat4) -> Self {
|
pub fn from_view_projection(view_projection: &Mat4) -> Self {
|
||||||
let mut frustum = Frustum::from_view_projection_no_far(view_projection);
|
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
|
frustum
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a frustum derived from `view_projection`, but with a custom
|
/// Returns a frustum derived from `view_projection`,
|
||||||
/// far plane.
|
/// but with a custom far plane.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_view_projection_custom_far(
|
pub fn from_view_projection_custom_far(
|
||||||
view_projection: &Mat4,
|
view_projection: &Mat4,
|
||||||
|
@ -154,39 +153,44 @@ impl Frustum {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut frustum = Frustum::from_view_projection_no_far(view_projection);
|
let mut frustum = Frustum::from_view_projection_no_far(view_projection);
|
||||||
let far_center = *view_translation - far * *view_backward;
|
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
|
frustum
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This approach of extracting the frustum planes from the view
|
// NOTE: This approach of extracting the frustum half-space from the view
|
||||||
// projection matrix is from Foundations of Game Engine Development 2
|
// projection matrix is from Foundations of Game Engine Development 2
|
||||||
// Rendering by Lengyel.
|
// Rendering by Lengyel.
|
||||||
|
/// Returns a frustum derived from `view_projection`,
|
||||||
|
/// without a far plane.
|
||||||
fn from_view_projection_no_far(view_projection: &Mat4) -> Self {
|
fn from_view_projection_no_far(view_projection: &Mat4) -> Self {
|
||||||
let row3 = view_projection.row(3);
|
let row3 = view_projection.row(3);
|
||||||
let mut planes = [Plane::default(); 6];
|
let mut half_spaces = [HalfSpace::default(); 6];
|
||||||
for (i, plane) in planes.iter_mut().enumerate().take(5) {
|
for (i, half_space) in half_spaces.iter_mut().enumerate().take(5) {
|
||||||
let row = view_projection.row(i / 2);
|
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
|
row3 + row
|
||||||
} else {
|
} else {
|
||||||
row3 - row
|
row3 - row
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Self { planes }
|
Self { half_spaces }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if a sphere intersects the frustum.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersects_sphere(&self, sphere: &Sphere, intersect_far: bool) -> bool {
|
pub fn intersects_sphere(&self, sphere: &Sphere, intersect_far: bool) -> bool {
|
||||||
let sphere_center = sphere.center.extend(1.0);
|
let sphere_center = sphere.center.extend(1.0);
|
||||||
let max = if intersect_far { 6 } else { 5 };
|
let max = if intersect_far { 6 } else { 5 };
|
||||||
for plane in &self.planes[..max] {
|
for half_space in &self.half_spaces[..max] {
|
||||||
if plane.normal_d().dot(sphere_center) + sphere.radius <= 0.0 {
|
if half_space.normal_d().dot(sphere_center) + sphere.radius <= 0.0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if an Oriented Bounding Box (obb) intersects the frustum.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersects_obb(
|
pub fn intersects_obb(
|
||||||
&self,
|
&self,
|
||||||
|
@ -202,16 +206,16 @@ impl Frustum {
|
||||||
Vec3A::from(model_to_world.z_axis),
|
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 {
|
if idx == 4 && !intersect_near {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if idx == 5 && !intersect_far {
|
if idx == 5 && !intersect_far {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let p_normal = plane.normal();
|
let p_normal = half_space.normal();
|
||||||
let relative_radius = aabb.relative_radius(&p_normal, &axes);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,13 +253,13 @@ mod tests {
|
||||||
// A big, offset frustum
|
// A big, offset frustum
|
||||||
fn big_frustum() -> Frustum {
|
fn big_frustum() -> Frustum {
|
||||||
Frustum {
|
Frustum {
|
||||||
planes: [
|
half_spaces: [
|
||||||
Plane::new(Vec4::new(-0.9701, -0.2425, -0.0000, 7.7611)),
|
HalfSpace::new(Vec4::new(-0.9701, -0.2425, -0.0000, 7.7611)),
|
||||||
Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 4.0000)),
|
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 4.0000)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.2425, -0.9701, 2.9104)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.2425, -0.9701, 2.9104)),
|
||||||
Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 4.0000)),
|
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 4.0000)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.2425, 0.9701, 2.9104)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.2425, 0.9701, 2.9104)),
|
||||||
Plane::new(Vec4::new(0.9701, -0.2425, -0.0000, -1.9403)),
|
HalfSpace::new(Vec4::new(0.9701, -0.2425, -0.0000, -1.9403)),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,13 +289,13 @@ mod tests {
|
||||||
// A frustum
|
// A frustum
|
||||||
fn frustum() -> Frustum {
|
fn frustum() -> Frustum {
|
||||||
Frustum {
|
Frustum {
|
||||||
planes: [
|
half_spaces: [
|
||||||
Plane::new(Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276)),
|
HalfSpace::new(Vec4::new(-0.9701, -0.2425, -0.0000, 0.7276)),
|
||||||
Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000)),
|
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 1.0000)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.2425, -0.9701, 0.7276)),
|
||||||
Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000)),
|
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 1.0000)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.2425, 0.9701, 0.7276)),
|
||||||
Plane::new(Vec4::new(0.9701, -0.2425, -0.0000, 0.7276)),
|
HalfSpace::new(Vec4::new(0.9701, -0.2425, -0.0000, 0.7276)),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,13 +369,13 @@ mod tests {
|
||||||
// A long frustum.
|
// A long frustum.
|
||||||
fn long_frustum() -> Frustum {
|
fn long_frustum() -> Frustum {
|
||||||
Frustum {
|
Frustum {
|
||||||
planes: [
|
half_spaces: [
|
||||||
Plane::new(Vec4::new(-0.9998, -0.0222, -0.0000, -1.9543)),
|
HalfSpace::new(Vec4::new(-0.9998, -0.0222, -0.0000, -1.9543)),
|
||||||
Plane::new(Vec4::new(-0.0000, 1.0000, -0.0000, 45.1249)),
|
HalfSpace::new(Vec4::new(-0.0000, 1.0000, -0.0000, 45.1249)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.0168, -0.9999, 2.2718)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.0168, -0.9999, 2.2718)),
|
||||||
Plane::new(Vec4::new(-0.0000, -1.0000, -0.0000, 45.1249)),
|
HalfSpace::new(Vec4::new(-0.0000, -1.0000, -0.0000, 45.1249)),
|
||||||
Plane::new(Vec4::new(-0.0000, -0.0168, 0.9999, 2.2718)),
|
HalfSpace::new(Vec4::new(-0.0000, -0.0168, 0.9999, 2.2718)),
|
||||||
Plane::new(Vec4::new(0.9998, -0.0222, -0.0000, 7.9528)),
|
HalfSpace::new(Vec4::new(0.9998, -0.0222, -0.0000, 7.9528)),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue