pub fn directional_distance<G1, G2>(
pos12: &Isometry<f32>,
g1: &G1,
g2: &G2,
dir: &Vector<f32>,
simplex: &mut VoronoiSimplex,
) -> Option<(f32, Vector<f32>, Point<f32>, Point<f32>)>Expand description
Computes how far a shape can move in a direction before touching another shape.
This function answers the question: “If I move shape 1 along this direction, how far can it travel before it touches shape 2?” This is useful for:
- Continuous collision detection (CCD)
- Movement planning and obstacle avoidance
- Computing time-of-impact for moving objects
- Safe navigation distances
§How It Works
The function casts shape 1 along the given direction vector and finds the first point where it would contact shape 2. It returns:
- The distance that can be traveled
- The contact normal at the point of first contact
- The witness points (closest points) on both shapes at contact
§Parameters
pos12: The relative position of shape 2 with respect to shape 1 (isometry from shape 1’s space to shape 2’s space)g1: The first shape being moved (must implementSupportMap)g2: The second shape (static target, must implementSupportMap)dir: The direction vector to move shape 1 in (in local-space of shape 1)simplex: A reusable simplex structure. Initialize withVoronoiSimplex::new().
§Returns
Some((distance, normal, witness1, witness2)): If contact would occurdistance: How far shape 1 can travel before touching shape 2normal: The contact normal at the point of first contactwitness1: The contact point on shape 1 (in local-space of shape 1)witness2: The contact point on shape 2 (in local-space of shape 1)
None: If no contact would occur (shapes don’t intersect along this direction)
§Example
use parry3d::shape::Ball;
use parry3d::query::gjk::{directional_distance, VoronoiSimplex};
use parry3d::math::{Isometry, Vector};
// Two balls: one at origin, one at (10, 0, 0)
let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);
let pos12 = Isometry::translation(10.0, 0.0, 0.0);
// Move ball1 toward ball2 along the +X axis
let direction = Vector::new(1.0, 0.0, 0.0);
let mut simplex = VoronoiSimplex::new();
if let Some((distance, normal, w1, w2)) = directional_distance(
&pos12,
&ball1,
&ball2,
&direction,
&mut simplex
) {
println!("Ball1 can move {} units before contact", distance);
println!("Contact normal: {:?}", normal);
println!("Contact point on ball1: {:?}", w1);
println!("Contact point on ball2: {:?}", w2);
// Expected: distance ≈ 8.0 (10.0 - 1.0 - 1.0)
}§Use Cases
1. Continuous Collision Detection:
ⓘ
let movement_dir = velocity * time_step;
if let Some((toi, normal, _, _)) = directional_distance(...) {
if toi < 1.0 {
// Collision will occur during this timestep
let collision_time = toi * time_step;
}
}2. Safe Movement Distance:
ⓘ
let desired_movement = Vector::new(5.0, 0.0, 0.0);
if let Some((max_safe_dist, _, _, _)) = directional_distance(...) {
let actual_movement = desired_movement.normalize() * max_safe_dist.min(5.0);
}§Notes
- All inputs and outputs are in the local-space of shape 1
- If the shapes are already intersecting, the returned distance is 0.0 and witness points are undefined (set to origin)
- The direction vector does not need to be normalized
- This function internally uses GJK raycasting on the Minkowski difference