Skip to main content

box2d_rust/distance/
types.rs

1// Distance-group types from include/box2d/collision.h.
2// SPDX-FileCopyrightText: 2023 Erin Catto
3// SPDX-License-Identifier: MIT
4
5use crate::hull::MAX_POLYGON_VERTICES;
6use crate::math_functions::{Rot, Transform, Vec2};
7
8/// A distance proxy used by the GJK algorithm. It encapsulates any shape.
9/// You can provide between 1 and [`MAX_POLYGON_VERTICES`] points and a radius.
10/// (b2ShapeProxy)
11#[derive(Debug, Clone, Copy, PartialEq)]
12pub struct ShapeProxy {
13    /// The point cloud
14    pub points: [Vec2; MAX_POLYGON_VERTICES],
15    /// The number of points. Must be greater than 0.
16    pub count: i32,
17    /// The external radius of the point cloud. May be zero.
18    pub radius: f32,
19}
20
21impl Default for ShapeProxy {
22    fn default() -> Self {
23        ShapeProxy {
24            points: [Vec2::default(); MAX_POLYGON_VERTICES],
25            count: 0,
26            radius: 0.0,
27        }
28    }
29}
30
31/// Result of computing the distance between two line segments.
32/// (b2SegmentDistanceResult)
33#[derive(Debug, Clone, Copy, PartialEq, Default)]
34pub struct SegmentDistanceResult {
35    /// The closest point on the first segment
36    pub closest1: Vec2,
37    /// The closest point on the second segment
38    pub closest2: Vec2,
39    /// The barycentric coordinate on the first segment
40    pub fraction1: f32,
41    /// The barycentric coordinate on the second segment
42    pub fraction2: f32,
43    /// The squared distance between the closest points
44    pub distance_squared: f32,
45}
46
47/// Used to warm start the GJK simplex. If you call this function multiple times
48/// with nearby transforms this might improve performance. Otherwise you can
49/// zero initialize this. (b2SimplexCache)
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
51pub struct SimplexCache {
52    /// The number of stored simplex points
53    pub count: u16,
54    /// The cached simplex indices on shape A
55    pub index_a: [u8; 3],
56    /// The cached simplex indices on shape B
57    pub index_b: [u8; 3],
58}
59
60/// Input for [`shape_distance`](crate::distance::shape_distance).
61/// (b2DistanceInput)
62#[derive(Debug, Clone, Copy, PartialEq)]
63pub struct DistanceInput {
64    /// The proxy for shape A
65    pub proxy_a: ShapeProxy,
66    /// The proxy for shape B
67    pub proxy_b: ShapeProxy,
68    /// Transform of shape B in shape A's frame, the relative pose B in A
69    /// (`inv_mul_transforms(world_a, world_b)`). The query is origin
70    /// independent and runs in frame A.
71    pub transform: Transform,
72    /// Should the proxy radius be considered?
73    pub use_radii: bool,
74}
75
76/// Output for [`shape_distance`](crate::distance::shape_distance).
77/// (b2DistanceOutput)
78#[derive(Debug, Clone, Copy, PartialEq, Default)]
79pub struct DistanceOutput {
80    /// Closest point on shape A, in shape A's frame
81    pub point_a: Vec2,
82    /// Closest point on shape B, in shape A's frame
83    pub point_b: Vec2,
84    /// A to B normal in shape A's frame. Invalid if distance is zero.
85    pub normal: Vec2,
86    /// The final distance, zero if overlapped
87    pub distance: f32,
88    /// Number of GJK iterations used
89    pub iterations: i32,
90    /// The number of simplexes stored in the simplex array
91    pub simplex_count: i32,
92}
93
94/// Simplex vertex for debugging the GJK algorithm. (b2SimplexVertex)
95#[derive(Debug, Clone, Copy, PartialEq, Default)]
96pub struct SimplexVertex {
97    /// support point in proxy A
98    pub w_a: Vec2,
99    /// support point in proxy B
100    pub w_b: Vec2,
101    /// w_b - w_a
102    pub w: Vec2,
103    /// barycentric coordinate for closest point
104    pub a: f32,
105    /// w_a index
106    pub index_a: i32,
107    /// w_b index
108    pub index_b: i32,
109}
110
111/// Simplex from the GJK algorithm. (b2Simplex)
112#[derive(Debug, Clone, Copy, PartialEq, Default)]
113pub struct Simplex {
114    /// vertices
115    pub v1: SimplexVertex,
116    pub v2: SimplexVertex,
117    pub v3: SimplexVertex,
118    /// number of valid vertices
119    pub count: i32,
120}
121
122impl Simplex {
123    /// The C code walks `b2SimplexVertex* vertices[] = {&v1, &v2, &v3}`; these
124    /// accessors are the borrow-checked equivalent.
125    pub(crate) fn vertex(&self, index: i32) -> &SimplexVertex {
126        match index {
127            0 => &self.v1,
128            1 => &self.v2,
129            _ => &self.v3,
130        }
131    }
132
133    pub(crate) fn vertex_mut(&mut self, index: i32) -> &mut SimplexVertex {
134        match index {
135            0 => &mut self.v1,
136            1 => &mut self.v2,
137            _ => &mut self.v3,
138        }
139    }
140}
141
142/// Input parameters for [`shape_cast`](crate::distance::shape_cast).
143/// (b2ShapeCastPairInput)
144#[derive(Debug, Clone, Copy, PartialEq)]
145pub struct ShapeCastPairInput {
146    /// The proxy for shape A
147    pub proxy_a: ShapeProxy,
148    /// The proxy for shape B
149    pub proxy_b: ShapeProxy,
150    /// Transform of shape B in shape A's frame, the relative pose B in A
151    pub transform: Transform,
152    /// The translation of shape B, in A's frame
153    pub translation_b: Vec2,
154    /// The fraction of the translation to consider, typically 1
155    pub max_fraction: f32,
156    /// Allows shapes with a radius to move slightly closer if already touching
157    pub can_encroach: bool,
158}
159
160/// This describes the motion of a body/shape for TOI computation. Shapes are
161/// defined with respect to the body origin, which may not coincide with the
162/// center of mass. However, to support dynamics we must interpolate the center
163/// of mass position. (b2Sweep)
164#[derive(Debug, Clone, Copy, PartialEq)]
165pub struct Sweep {
166    /// Local center of mass position
167    pub local_center: Vec2,
168    /// Starting center of mass world position
169    pub c1: Vec2,
170    /// Ending center of mass world position
171    pub c2: Vec2,
172    /// Starting world rotation
173    pub q1: Rot,
174    /// Ending world rotation
175    pub q2: Rot,
176}
177
178/// Time of impact input. (b2TOIInput)
179#[derive(Debug, Clone, Copy, PartialEq)]
180pub struct ToiInput {
181    /// The proxy for shape A
182    pub proxy_a: ShapeProxy,
183    /// The proxy for shape B
184    pub proxy_b: ShapeProxy,
185    /// The movement of shape A
186    pub sweep_a: Sweep,
187    /// The movement of shape B
188    pub sweep_b: Sweep,
189    /// Defines the sweep interval [0, max_fraction]
190    pub max_fraction: f32,
191}
192
193/// Describes the TOI output. (b2TOIState)
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
195pub enum ToiState {
196    #[default]
197    Unknown,
198    Failed,
199    Overlapped,
200    Hit,
201    Separated,
202}
203
204/// Time of impact output. (b2TOIOutput)
205#[derive(Debug, Clone, Copy, PartialEq, Default)]
206pub struct ToiOutput {
207    /// The type of result
208    pub state: ToiState,
209    /// The hit point
210    pub point: Vec2,
211    /// The hit normal
212    pub normal: Vec2,
213    /// The sweep time of the collision
214    pub fraction: f32,
215}