Trait QueryDispatcher

Source
pub trait QueryDispatcher: Send + Sync {
    // Required methods
    fn intersection_test(
        &self,
        pos12: &Isometry<f32>,
        g1: &dyn Shape,
        g2: &dyn Shape,
    ) -> Result<bool, Unsupported>;
    fn distance(
        &self,
        pos12: &Isometry<f32>,
        g1: &dyn Shape,
        g2: &dyn Shape,
    ) -> Result<f32, Unsupported>;
    fn contact(
        &self,
        pos12: &Isometry<f32>,
        g1: &dyn Shape,
        g2: &dyn Shape,
        prediction: f32,
    ) -> Result<Option<Contact>, Unsupported>;
    fn closest_points(
        &self,
        pos12: &Isometry<f32>,
        g1: &dyn Shape,
        g2: &dyn Shape,
        max_dist: f32,
    ) -> Result<ClosestPoints, Unsupported>;
    fn cast_shapes(
        &self,
        pos12: &Isometry<f32>,
        local_vel12: &Vector<f32>,
        g1: &dyn Shape,
        g2: &dyn Shape,
        options: ShapeCastOptions,
    ) -> Result<Option<ShapeCastHit>, Unsupported>;
    fn cast_shapes_nonlinear(
        &self,
        motion1: &NonlinearRigidMotion,
        g1: &dyn Shape,
        motion2: &NonlinearRigidMotion,
        g2: &dyn Shape,
        start_time: f32,
        end_time: f32,
        stop_at_penetration: bool,
    ) -> Result<Option<ShapeCastHit>, Unsupported>;

    // Provided method
    fn chain<U: QueryDispatcher>(
        self,
        other: U,
    ) -> QueryDispatcherChain<Self, U>
       where Self: Sized { ... }
}
Expand description

Dispatcher for pairwise geometric queries between shapes.

This is the core trait for performing geometric queries (distance, intersection, contact, etc.) between pairs of shapes in Parry. It provides a uniform interface for querying different shape combinations.

§Purpose

The QueryDispatcher trait serves as an abstraction layer that:

  1. Decouples query algorithms from shape types: Different shape pairs may require different algorithms (e.g., sphere-sphere uses simple math, while convex-convex uses GJK/EPA).

  2. Enables extensibility: You can implement custom dispatchers to add support for custom shape types or specialized algorithms without modifying Parry’s core code.

  3. Provides fallback mechanisms: Dispatchers can be chained together using chain(), allowing graceful fallback when a query is not supported.

§The pos12 Parameter Convention

All query methods in this trait take a pos12 parameter, which represents the relative position of shape 2 (g2) in shape 1’s (g1) local coordinate frame:

pos12 = pos1.inverse() * pos2

This convention is used because:

  • It reduces redundant transformations during query execution
  • Many algorithms naturally work in one shape’s local space
  • It’s more efficient than passing two separate world-space positions

When using the high-level query functions, this transformation is done automatically.

§Query Methods Overview

The trait provides several categories of queries:

§Basic Queries

§Motion Queries (Time of Impact)

§Thread Safety

Query dispatchers must be Send + Sync because they’re often shared across threads in:

  • Parallel collision detection
  • Physics simulations with multi-threaded broad phase
  • Game engines with parallel scene queries

Ensure your custom dispatcher implementations are thread-safe or use appropriate synchronization.

§Error Handling with Unsupported

All query methods return Result<T, Unsupported>. The Unsupported error indicates:

  • The dispatcher doesn’t know how to handle the given shape pair
  • The shapes don’t support this type of query
  • The query is mathematically undefined for these shapes

When chaining dispatchers with chain(), returning Unsupported causes the next dispatcher in the chain to be tried.

§Example: Using the Default Dispatcher

use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
use parry3d::shape::{Ball, Cuboid};
use parry3d::na::{Isometry3, Vector3};

let dispatcher = DefaultQueryDispatcher;

let ball = Ball::new(1.0);
let cuboid = Cuboid::new(Vector3::new(2.0, 2.0, 2.0));

let pos1 = Isometry3::identity();
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);
let pos12 = pos1.inv_mul(&pos2);

// Test intersection
let intersects = dispatcher.intersection_test(&pos12, &ball, &cuboid).unwrap();

// Compute distance
let dist = dispatcher.distance(&pos12, &ball, &cuboid).unwrap();

println!("Intersects: {}, Distance: {}", intersects, dist);

§Example: Chaining Dispatchers

use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};

struct MyCustomDispatcher;

impl QueryDispatcher for MyCustomDispatcher {
    fn distance(
        &self,
        pos12: &Isometry<Real>,
        g1: &dyn Shape,
        g2: &dyn Shape,
    ) -> Result<Real, Unsupported> {
        // Handle custom shape types
        if let Some(my_shape) = g1.as_any().downcast_ref::<MyShape>() {
            // ... custom distance computation
            Ok(computed_distance)
        } else {
            // Don't know how to handle this, let the next dispatcher try
            Err(Unsupported)
        }
    }

    // ... implement other methods
}

// Chain custom dispatcher with default as fallback
let dispatcher = MyCustomDispatcher.chain(DefaultQueryDispatcher);

// Now all queries try custom dispatcher first, then default
let dist = dispatcher.distance(&pos12, shape1, shape2)?;

§See Also

Required Methods§

Source

fn intersection_test( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, ) -> Result<bool, Unsupported>

Tests whether two shapes are intersecting.

Source

fn distance( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, ) -> Result<f32, Unsupported>

Computes the minimum distance separating two shapes.

Returns 0.0 if the objects are touching or penetrating.

Source

fn contact( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, prediction: f32, ) -> Result<Option<Contact>, Unsupported>

Computes one pair of contact points point between two shapes.

Returns None if the objects are separated by a distance greater than prediction.

Source

fn closest_points( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, max_dist: f32, ) -> Result<ClosestPoints, Unsupported>

Computes the pair of closest points between two shapes.

Returns ClosestPoints::Disjoint if the objects are separated by a distance greater than max_dist.

Source

fn cast_shapes( &self, pos12: &Isometry<f32>, local_vel12: &Vector<f32>, g1: &dyn Shape, g2: &dyn Shape, options: ShapeCastOptions, ) -> Result<Option<ShapeCastHit>, Unsupported>

Computes the smallest time when two shapes under translational movement are separated by a distance smaller or equal to distance.

Returns 0.0 if the objects are touching or penetrating.

§Parameters
  • pos12: the position of the second shape relative to the first shape.
  • local_vel12: the relative velocity between the two shapes, expressed in the local-space of the first shape. In other world: pos1.inverse() * (vel2 - vel1).
  • g1: the first shape involved in the shape-cast.
  • g2: the second shape involved in the shape-cast.
  • target_dist: a hit will be returned as soon as the two shapes get closer than target_dist.
  • max_time_of_impact: the maximum allowed travel time. This method returns None if the time-of-impact detected is theater than this value.
Source

fn cast_shapes_nonlinear( &self, motion1: &NonlinearRigidMotion, g1: &dyn Shape, motion2: &NonlinearRigidMotion, g2: &dyn Shape, start_time: f32, end_time: f32, stop_at_penetration: bool, ) -> Result<Option<ShapeCastHit>, Unsupported>

Computes the smallest time of impact of two shapes under translational and rotational movement.

§Parameters
  • motion1 - The motion of the first shape.
  • g1 - The first shape involved in the query.
  • motion2 - The motion of the second shape.
  • g2 - The second shape involved in the query.
  • start_time - The starting time of the interval where the motion takes place.
  • end_time - The end time of the interval where the motion takes place.
  • stop_at_penetration - If the casted shape starts in a penetration state with any collider, two results are possible. If stop_at_penetration is true then, the result will have a time_of_impact equal to start_time. If stop_at_penetration is false then the nonlinear shape-casting will see if further motion wrt. the penetration normal would result in tunnelling. If it does not (i.e. we have a separating velocity along that normal) then the nonlinear shape-casting will attempt to find another impact, at a time > start_time that could result in tunnelling.

Provided Methods§

Source

fn chain<U: QueryDispatcher>(self, other: U) -> QueryDispatcherChain<Self, U>
where Self: Sized,

Construct a QueryDispatcher that falls back on other for cases not handled by self

Implementors§