Function directional_distance

Source
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>)>
where G1: ?Sized + SupportMap, G2: ?Sized + SupportMap,
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 implement SupportMap)
  • g2: The second shape (static target, must implement SupportMap)
  • dir: The direction vector to move shape 1 in (in local-space of shape 1)
  • simplex: A reusable simplex structure. Initialize with VoronoiSimplex::new().

§Returns

  • Some((distance, normal, witness1, witness2)): If contact would occur
    • distance: How far shape 1 can travel before touching shape 2
    • normal: The contact normal at the point of first contact
    • witness1: 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