box2d_rs/
b2_distance.rs

1use crate::b2_math::*;
2use crate::b2_common::*;
3use crate::b2_shape::*;
4use crate::private::collision::b2_distance as private;
5
6use std::sync::atomic::AtomicUsize;
7
8pub static B2_GJK_CALLS: AtomicUsize = AtomicUsize::new(0);
9pub static B2_GJK_ITERS: AtomicUsize = AtomicUsize::new(0);
10pub static B2_GJK_MAX_ITERS: AtomicUsize = AtomicUsize::new(0);
11
12/// A distance proxy is used by the GJK algorithm.
13/// It encapsulates any shape.
14#[derive(Default, Clone, Debug)]
15pub struct B2distanceProxy {
16    pub m_buffer: [B2vec2; 2],
17    //box2d-rs: reference to shape vertices replaced by copy, because of borrowing/lifetime problems
18    pub m_vertices: Vec<B2vec2>,
19    //const b2Vec2* m_vertices;
20    pub m_radius: f32,
21}
22
23impl B2distanceProxy {
24    /// initialize the proxy using the given shape. The shape
25    /// must remain in scope while the proxy is in use.
26    pub fn set_shape(&mut self, shape: ShapePtr, index: usize) {
27        private::set_shape(self, shape, index);
28    }
29
30    /// initialize the proxy using a vertex cloud and radius. The vertices
31    /// must remain in scope while the proxy is in use.
32    pub fn set_vertices(&mut self, vertices: &[B2vec2], radius: f32) {
33        private::set_vertices(self, vertices, radius);
34    }
35
36    /// Get the supporting vertex index in the given direction.
37    pub fn get_support(&self, d: B2vec2) -> usize {
38        return inline::get_support(self, d);
39    }
40
41    /// Get the supporting vertex in the given direction.
42    pub fn get_support_vertex(&self, d: B2vec2) -> B2vec2 {
43        return inline::get_support_vertex(self, d);
44    }
45
46    /// Get the vertex count.
47    pub fn get_vertex_count(&self) -> usize {
48        return inline::get_vertex_count(self);
49    }
50
51    /// Get a vertex by index. Used by b2Distance.
52    pub fn get_vertex(&self, index: usize) -> B2vec2 {
53        return inline::get_vertex(self, index);
54    }
55}
56
57/// Used to warm start b2Distance.
58/// Set count to zero on first call.
59#[derive(Default, Clone, Copy, Debug)]
60pub struct B2simplexCache {
61    ///< length or area
62    pub metric: f32,
63    pub count: u16,
64    ///< vertices on shape A
65    pub index_a: [u8; 3],
66    ///< vertices on shape b
67    pub index_b: [u8; 3],
68}
69
70/// Input for b2Distance.
71/// You have to option to use the shape radii
72/// in the computation. Even
73#[derive(Default, Clone, Debug)]
74pub struct B2distanceInput {
75    pub proxy_a: B2distanceProxy,
76    pub proxy_b: B2distanceProxy,
77    pub transform_a: B2Transform,
78    pub transform_b: B2Transform,
79    pub use_radii: bool,
80}
81
82/// Output for b2Distance.
83#[derive(Default, Clone, Copy, Debug)]
84pub struct B2distanceOutput {
85    ///< closest point on shape_a
86    pub point_a: B2vec2,
87    ///< closest point on shape_b
88    pub point_b: B2vec2,
89    pub distance: f32,
90    ///< number of GJK iterations used
91    pub iterations: i32,
92}
93
94/// Compute the closest points between two shapes. Supports any combination of:
95/// B2circleShape, B2polygonShape, B2edgeShape. The simplex cache is input/output.
96/// On the first call set B2simplexCache.count to zero.
97pub fn b2_distance_fn(
98    output: &mut B2distanceOutput,
99    cache: &mut B2simplexCache,
100    input: &B2distanceInput,
101) {
102    private::b2_distance_fn(output, cache, input);
103}
104
105/// Input parameters for b2ShapeCast
106#[derive(Default, Clone, Debug)]
107pub struct B2shapeCastInput {
108    pub proxy_a: B2distanceProxy,
109    pub proxy_b: B2distanceProxy,
110    pub transform_a: B2Transform,
111    pub transform_b: B2Transform,
112    pub translation_b: B2vec2,
113}
114
115/// Output results for b2ShapeCast
116#[derive(Default, Clone, Copy, Debug)]
117pub struct B2shapeCastOutput {
118    pub point: B2vec2,
119    pub normal: B2vec2,
120    pub lambda: f32,
121    pub iterations: i32,
122}
123
124/// Perform a linear shape cast of shape b moving and shape A fixed. Determines the hit point, normal, and translation fraction.
125/// 
126/// @returns true if hit, false if there is no hit or an initial overlap
127pub fn b2_shape_cast(output: &mut B2shapeCastOutput, input: B2shapeCastInput) -> bool {
128    return private::b2_shape_cast(output, input);
129}
130
131mod inline {
132    use super::*;
133
134    pub fn get_vertex_count(self_: &B2distanceProxy) -> usize {
135        return self_.m_vertices.len();
136    }
137
138    pub fn get_vertex(self_: &B2distanceProxy, index: usize) -> B2vec2 {
139        b2_assert(index < self_.m_vertices.len());
140        return self_.m_vertices[index];
141    }
142
143    pub fn get_support(self_: &B2distanceProxy, d: B2vec2) -> usize {
144        let mut best_index: usize = 0;
145        let mut best_value: f32 = b2_dot(self_.m_vertices[0], d);
146        for i in 1..self_.m_vertices.len() {
147            let value: f32 = b2_dot(self_.m_vertices[i], d);
148            if value > best_value {
149                best_index = i;
150                best_value = value;
151            }
152        }
153
154        return best_index;
155    }
156
157    pub fn get_support_vertex(self_: &B2distanceProxy, d: B2vec2) -> B2vec2 {
158        let mut best_index: usize = 0;
159        let mut best_value: f32 = b2_dot(self_.m_vertices[0], d);
160        for i in 1..self_.m_vertices.len() {
161            let value: f32 = b2_dot(self_.m_vertices[i], d);
162            if value > best_value {
163                best_index = i;
164                best_value = value;
165            }
166        }
167
168        return self_.m_vertices[best_index];
169    }
170}