Skip to main content

box3d_rust/distance/
mod.rs

1// Port of box3d-cpp-reference/src/distance.c and the distance/query group of
2// include/box3d/collision.h and types.h.
3//
4// Split to satisfy the 800-line file limit:
5// - types.rs    — proxies, simplex cache, distance/cast/TOI inputs and outputs
6// - simplex.rs  — barycentric coords and simplex region solvers
7// - gjk.rs      — GJK distance (b3ShapeDistance) and support functions
8// - cast.rs     — linear shape cast and sweep evaluation
9// - toi.rs      — time of impact via local separating axes
10//
11// ShapeProxy owns its point buffer (C holds a const pointer). Use [`make_proxy`]
12// to build one from a slice.
13//
14// SPDX-FileCopyrightText: 2026 Erin Catto
15// SPDX-License-Identifier: MIT
16
17mod cast;
18mod gjk;
19mod simplex;
20mod toi;
21mod types;
22
23pub use cast::{get_sweep_transform, shape_cast};
24pub use gjk::{get_point_support, get_proxy_support, shape_distance};
25pub use toi::time_of_impact;
26pub use types::{
27    CastOutput, DistanceInput, DistanceOutput, ShapeCastPairInput, ShapeProxy, Simplex,
28    SimplexCache, SimplexVertex, Sweep, ToiInput, ToiOutput, ToiState,
29};
30
31use crate::constants::MAX_SHAPE_CAST_POINTS;
32use crate::math_functions::{
33    add, invert_transform, make_aabb, make_matrix_from_quat, min_int, mul_mv, Aabb, Transform, Vec3,
34};
35
36/// Make a proxy for use in overlap, shape cast, and related functions. This is
37/// a deep copy of the points. (box2d-style helper; C uses a pointer in
38/// `b3ShapeProxy`)
39pub fn make_proxy(points: &[Vec3], radius: f32) -> ShapeProxy {
40    let count = min_int(points.len() as i32, MAX_SHAPE_CAST_POINTS as i32);
41    let mut proxy = ShapeProxy {
42        count,
43        radius,
44        ..Default::default()
45    };
46    proxy.points[..count as usize].copy_from_slice(&points[..count as usize]);
47    proxy
48}
49
50/// Transform a proxy into the local frame of `transform`.
51/// (shape.c: b3MakeLocalProxy)
52pub fn make_local_proxy(proxy: &ShapeProxy, transform: Transform) -> ShapeProxy {
53    let inv_transform = invert_transform(transform);
54    let r = make_matrix_from_quat(inv_transform.q);
55
56    let count = min_int(proxy.count, MAX_SHAPE_CAST_POINTS as i32);
57    let mut local = ShapeProxy {
58        count,
59        radius: proxy.radius,
60        ..Default::default()
61    };
62    for i in 0..count as usize {
63        local.points[i] = add(mul_mv(r, proxy.points[i]), inv_transform.p);
64    }
65    local
66}
67
68/// Compute the AABB of a shape proxy. (shape.c: b3ComputeProxyAABB)
69pub fn compute_proxy_aabb(proxy: &ShapeProxy) -> Aabb {
70    debug_assert!(proxy.count > 0);
71    make_aabb(&proxy.points[..proxy.count as usize], proxy.radius)
72}