#[repr(C)]pub struct HalfSpace {
pub normal: Unit<Vector<f32>>,
}Expand description
A half-space delimited by an infinite plane.
§What is a HalfSpace?
A half-space represents an infinite region of space on one side of a plane. It divides space into two regions:
- The “inside” region (where the normal vector points away from)
- The “outside” region (where the normal vector points toward)
The plane itself passes through the origin of the shape’s coordinate system and is defined by its outward normal vector. All points in the direction opposite to the normal are considered “inside” the half-space.
§When to Use HalfSpace
Half-spaces are useful for representing:
- Ground planes: A flat, infinite floor for collision detection
- Walls: Infinite vertical barriers
- Bounding regions: Constraining objects to one side of a plane
- Clipping planes: Cutting off geometry in one direction
Because half-spaces are infinite, they are very efficient for collision detection and don’t require complex shape representations.
§Coordinate System
The plane always passes through the origin (0, 0) in 2D or (0, 0, 0) in 3D of the
half-space’s local coordinate system. To position the plane elsewhere in your world,
use an Isometry transformation when performing queries.
§Examples
§Creating a Ground Plane (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Create a horizontal ground plane with normal pointing up (positive Y-axis)
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
// The ground plane is at Y = 0 in local coordinates
// Everything below (negative Y) is "inside" the half-space§Vertical Wall (2D)
use parry2d::shape::HalfSpace;
use parry2d::na::{Vector2, Unit};
// Create a vertical wall with normal pointing right (positive X-axis)
let wall = HalfSpace::new(Unit::new_normalize(Vector2::x()));
// The wall is at X = 0 in local coordinates
// Everything to the left (negative X) is "inside" the half-space§Collision Detection with a Ball (3D)
use parry3d::shape::{HalfSpace, Ball};
use parry3d::query;
use parry3d::na::{Isometry3, Vector3, Unit};
// Create a ground plane at Y = 0, normal pointing up
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
let ground_pos = Isometry3::identity();
// Create a ball with radius 1.0 at position (0, 0.5, 0)
// The ball is resting on the ground, just touching it
let ball = Ball::new(1.0);
let ball_pos = Isometry3::translation(0.0, 0.5, 0.0);
// Check if they're in contact (with a small prediction distance)
let contact = query::contact(
&ground_pos,
&ground,
&ball_pos,
&ball,
0.1
);
assert!(contact.unwrap().is_some());§Positioned Ground Plane (3D)
use parry3d::shape::HalfSpace;
use parry3d::query::{PointQuery};
use parry3d::na::{Isometry3, Vector3, Point3, Unit};
// Create a ground plane with normal pointing up
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
// Position the plane at Y = 5.0 using an isometry
let ground_pos = Isometry3::translation(0.0, 5.0, 0.0);
// Check if a point is below the ground (inside the half-space)
let point = Point3::new(0.0, 3.0, 0.0); // Point at Y = 3.0 (below the plane)
// Project the point onto the ground plane
let proj = ground.project_point(&ground_pos, &point, true);
// The point is below the ground (inside the half-space)
assert!(proj.is_inside);§Tilted Plane (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Create a plane tilted at 45 degrees
// Normal points up and to the right
let normal = Vector3::new(1.0, 1.0, 0.0);
let tilted_plane = HalfSpace::new(Unit::new_normalize(normal));
// This plane passes through the origin and divides space diagonallyFields§
§normal: Unit<Vector<f32>>The halfspace planar boundary’s outward normal.
This unit vector points in the direction considered “outside” the half-space. All points in the direction opposite to this normal (when measured from the plane at the origin) are considered “inside” the half-space.
§Example
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
// The normal points up (positive Y direction)
assert_eq!(*ground.normal, Vector3::y());Implementations§
Source§impl HalfSpace
impl HalfSpace
Sourcepub fn bounding_sphere(&self, pos: &Isometry<f32>) -> BoundingSphere
pub fn bounding_sphere(&self, pos: &Isometry<f32>) -> BoundingSphere
Computes the world-space bounding sphere of this half-space, transformed by pos.
Sourcepub fn local_bounding_sphere(&self) -> BoundingSphere
pub fn local_bounding_sphere(&self) -> BoundingSphere
Computes the local-space bounding sphere of this half-space.
Source§impl HalfSpace
impl HalfSpace
Sourcepub fn new(normal: Unit<Vector<f32>>) -> HalfSpace
pub fn new(normal: Unit<Vector<f32>>) -> HalfSpace
Builds a new half-space from its outward normal vector.
The plane defining the half-space passes through the origin of the local coordinate system and is perpendicular to the given normal vector. The normal points toward the “outside” region, while the opposite direction is considered “inside.”
§Parameters
normal- A unit vector defining the plane’s outward normal direction. This must be a normalized vector (useUnit::new_normalizeto create one from any vector).
§Examples
§Creating a Horizontal Ground Plane (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Ground plane with normal pointing up
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));§Creating a Vertical Wall (2D)
use parry2d::shape::HalfSpace;
use parry2d::na::{Vector2, Unit};
// Wall with normal pointing to the right
let wall = HalfSpace::new(Unit::new_normalize(Vector2::x()));§Custom Normal Direction (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Plane with normal at 45-degree angle
let custom_normal = Vector3::new(1.0, 1.0, 0.0);
let plane = HalfSpace::new(Unit::new_normalize(custom_normal));
// Verify the normal is normalized
assert!((plane.normal.norm() - 1.0).abs() < 1e-5);Sourcepub fn scaled(self, scale: &Vector<f32>) -> Option<Self>
pub fn scaled(self, scale: &Vector<f32>) -> Option<Self>
Computes a scaled version of this half-space.
Scaling a half-space applies non-uniform scaling to its normal vector. This is useful when transforming shapes in a scaled coordinate system. The resulting normal is re-normalized to maintain the half-space’s validity.
§Parameters
scale- A vector containing the scaling factors for each axis. For example,Vector3::new(2.0, 1.0, 1.0)doubles the X-axis scaling.
§Returns
Some(HalfSpace)- The scaled half-space with the transformed normalNone- If the scaled normal becomes zero (degenerate case), meaning the half-space cannot be represented after scaling
§When This Returns None
The method returns None when any component of the normal becomes zero after
scaling AND that component was the only non-zero component. For example:
- A horizontal plane (normal =
[0, 1, 0]) scaled by[1, 0, 1]→None - A diagonal plane (normal =
[0.7, 0.7, 0]) scaled by[1, 0, 1]→Some(...)
§Examples
§Uniform Scaling (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
// Uniform scaling doesn't change the normal direction
let scaled = ground.scaled(&Vector3::new(2.0, 2.0, 2.0)).unwrap();
assert_eq!(*scaled.normal, Vector3::y());§Non-Uniform Scaling (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Diagonal plane
let plane = HalfSpace::new(
Unit::new_normalize(Vector3::new(1.0, 1.0, 0.0))
);
// Scale X-axis by 2.0, Y-axis stays 1.0
let scaled = plane.scaled(&Vector3::new(2.0, 1.0, 1.0)).unwrap();
// The normal changes direction due to non-uniform scaling
// It's no longer at 45 degrees
assert!(scaled.normal.x != scaled.normal.y);§Degenerate Case (3D)
use parry3d::shape::HalfSpace;
use parry3d::na::{Vector3, Unit};
// Horizontal ground plane
let ground = HalfSpace::new(Unit::new_normalize(Vector3::y()));
// Scaling Y to zero makes the normal degenerate
let scaled = ground.scaled(&Vector3::new(1.0, 0.0, 1.0));
assert!(scaled.is_none()); // Returns None because normal becomes zero§Practical Use Case (2D)
use parry2d::shape::HalfSpace;
use parry2d::na::{Vector2, Unit};
// Create a wall in a 2D platformer
let wall = HalfSpace::new(Unit::new_normalize(Vector2::x()));
// Apply level scaling (e.g., for pixel-perfect rendering)
let pixel_scale = Vector2::new(16.0, 16.0);
if let Some(scaled_wall) = wall.scaled(&pixel_scale) {
// Use the scaled wall for collision detection
}Trait Implementations§
Source§impl PointQuery for HalfSpace
impl PointQuery for HalfSpace
Source§fn project_local_point(&self, pt: &Point<f32>, solid: bool) -> PointProjection
fn project_local_point(&self, pt: &Point<f32>, solid: bool) -> PointProjection
self. Read moreSource§fn project_local_point_and_get_feature(
&self,
pt: &Point<f32>,
) -> (PointProjection, FeatureId)
fn project_local_point_and_get_feature( &self, pt: &Point<f32>, ) -> (PointProjection, FeatureId)
self and returns the id of the
feature the point was projected on.Source§fn distance_to_local_point(&self, pt: &Point<f32>, solid: bool) -> f32
fn distance_to_local_point(&self, pt: &Point<f32>, solid: bool) -> f32
self.Source§fn contains_local_point(&self, pt: &Point<f32>) -> bool
fn contains_local_point(&self, pt: &Point<f32>) -> bool
self.Source§fn project_local_point_with_max_dist(
&self,
pt: &Point<f32>,
solid: bool,
max_dist: f32,
) -> Option<PointProjection>
fn project_local_point_with_max_dist( &self, pt: &Point<f32>, solid: bool, max_dist: f32, ) -> Option<PointProjection>
Source§fn project_point_with_max_dist(
&self,
m: &Isometry<f32>,
pt: &Point<f32>,
solid: bool,
max_dist: f32,
) -> Option<PointProjection>
fn project_point_with_max_dist( &self, m: &Isometry<f32>, pt: &Point<f32>, solid: bool, max_dist: f32, ) -> Option<PointProjection>
self transformed by m, unless the projection lies further than the given max distance.Source§fn project_point(
&self,
m: &Isometry<f32>,
pt: &Point<f32>,
solid: bool,
) -> PointProjection
fn project_point( &self, m: &Isometry<f32>, pt: &Point<f32>, solid: bool, ) -> PointProjection
self transformed by m.Source§fn distance_to_point(
&self,
m: &Isometry<f32>,
pt: &Point<f32>,
solid: bool,
) -> f32
fn distance_to_point( &self, m: &Isometry<f32>, pt: &Point<f32>, solid: bool, ) -> f32
self transformed by m.Source§fn project_point_and_get_feature(
&self,
m: &Isometry<f32>,
pt: &Point<f32>,
) -> (PointProjection, FeatureId)
fn project_point_and_get_feature( &self, m: &Isometry<f32>, pt: &Point<f32>, ) -> (PointProjection, FeatureId)
self transformed by m and returns the id of the
feature the point was projected on.Source§impl RayCast for HalfSpace
impl RayCast for HalfSpace
Source§fn cast_local_ray_and_get_normal(
&self,
ray: &Ray,
max_time_of_impact: f32,
solid: bool,
) -> Option<RayIntersection>
fn cast_local_ray_and_get_normal( &self, ray: &Ray, max_time_of_impact: f32, solid: bool, ) -> Option<RayIntersection>
Source§fn cast_local_ray(
&self,
ray: &Ray,
max_time_of_impact: f32,
solid: bool,
) -> Option<f32>
fn cast_local_ray( &self, ray: &Ray, max_time_of_impact: f32, solid: bool, ) -> Option<f32>
Source§fn intersects_local_ray(&self, ray: &Ray, max_time_of_impact: f32) -> bool
fn intersects_local_ray(&self, ray: &Ray, max_time_of_impact: f32) -> bool
Source§fn cast_ray(
&self,
m: &Isometry<f32>,
ray: &Ray,
max_time_of_impact: f32,
solid: bool,
) -> Option<f32>
fn cast_ray( &self, m: &Isometry<f32>, ray: &Ray, max_time_of_impact: f32, solid: bool, ) -> Option<f32>
Source§fn cast_ray_and_get_normal(
&self,
m: &Isometry<f32>,
ray: &Ray,
max_time_of_impact: f32,
solid: bool,
) -> Option<RayIntersection>
fn cast_ray_and_get_normal( &self, m: &Isometry<f32>, ray: &Ray, max_time_of_impact: f32, solid: bool, ) -> Option<RayIntersection>
Source§impl Shape for HalfSpace
impl Shape for HalfSpace
Source§fn scale_dyn(
&self,
scale: &Vector<f32>,
_num_subdivisions: u32,
) -> Option<Box<dyn Shape>>
fn scale_dyn( &self, scale: &Vector<f32>, _num_subdivisions: u32, ) -> Option<Box<dyn Shape>>
scale into a boxed trait-object. Read moreSource§fn compute_local_aabb(&self) -> Aabb
fn compute_local_aabb(&self) -> Aabb
Aabb of this shape.Source§fn compute_local_bounding_sphere(&self) -> BoundingSphere
fn compute_local_bounding_sphere(&self) -> BoundingSphere
Source§fn compute_aabb(&self, position: &Isometry<f32>) -> Aabb
fn compute_aabb(&self, position: &Isometry<f32>) -> Aabb
Aabb of this shape with the given position.fn ccd_thickness(&self) -> f32
fn ccd_angular_thickness(&self) -> f32
Source§fn mass_properties(&self, _: f32) -> MassProperties
fn mass_properties(&self, _: f32) -> MassProperties
Source§fn shape_type(&self) -> ShapeType
fn shape_type(&self) -> ShapeType
Source§fn as_typed_shape(&self) -> TypedShape<'_>
fn as_typed_shape(&self) -> TypedShape<'_>
Source§fn clone_box(&self) -> Box<dyn Shape>
fn clone_box(&self) -> Box<dyn Shape>
clone_dynSource§fn compute_bounding_sphere(&self, position: &Isometry<f32>) -> BoundingSphere
fn compute_bounding_sphere(&self, position: &Isometry<f32>) -> BoundingSphere
Source§fn as_support_map(&self) -> Option<&dyn SupportMap>
fn as_support_map(&self) -> Option<&dyn SupportMap>
fn as_composite_shape(&self) -> Option<&dyn CompositeShape>
Source§fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, f32)>
fn as_polygonal_feature_map(&self) -> Option<(&dyn PolygonalFeatureMap, f32)>
impl Copy for HalfSpace
impl StructuralPartialEq for HalfSpace
Auto Trait Implementations§
impl Freeze for HalfSpace
impl RefUnwindSafe for HalfSpace
impl Send for HalfSpace
impl Sync for HalfSpace
impl Unpin for HalfSpace
impl UnwindSafe for HalfSpace
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.