1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
use crate::b2_math::*;
use crate::b2_settings::B2_MAX_MANIFOLD_POINTS;
use crate::b2_shape::*;
use crate::private::collision as private;
use crate::shapes::b2_circle_shape::*;
use crate::shapes::b2_edge_shape::*;
use crate::shapes::b2_polygon_shape::*;

/// @file
/// Structures and functions used for computing contact points, distance
/// queries, and TOI queries.

pub const B2_NULL_FEATURE: u8 = std::u8::MAX;

pub enum B2contactFeatureType {
    EVertex = 0,
    EFace = 1,
}

/// The features that intersect to form the contact point
/// This must be 4 bytes or less.
#[derive(Clone, Default, Copy, Debug, PartialEq)]
pub struct B2contactFeature {
    /// Feature index on shape_a
    pub index_a: u8,
    /// Feature index on shape_b
    pub index_b: u8,
    /// The feature type on shape_a
    pub type_a: u8,
    /// The feature type on shape_b
    pub type_b: u8,
}

/// Contact ids to facilitate warm starting.
#[derive(Clone, Default, Copy, Debug, PartialEq)]
pub struct B2contactId {
    pub cf: B2contactFeature,
}

/// A manifold point is a contact point belonging to a contact
/// manifold. It holds details related to the geometry and dynamics
/// of the contact points.
/// The local point usage depends on the manifold type:
/// -e_circles: the local center of circle_b
/// -e_faceA: the local center of cirlceB or the clip point of polygon_b
/// -e_faceB: the clip point of polygon_a
/// This structure is stored across time steps, so we keep it small.
/// Note: the impulses are used for internal caching and may not
/// provide reliable contact forces, especially for high speed collisions.
#[derive(Clone, Copy, Debug, Default)]
pub struct B2manifoldPoint {
    ///< usage depends on manifold type
    pub local_point: B2vec2,
    ///< the non-penetration impulse
    pub normal_impulse: f32,
    ///< the friction impulse
    pub tangent_impulse: f32,
    ///< uniquely identifies a contact point between two shapes
    pub id: B2contactId,
}

#[derive(Clone, Copy, Debug)]
pub enum B2manifoldType {
    ECircles,
    EFaceA,
    EFaceB,
}

impl Default for B2manifoldType {
    fn default() -> Self {
        return B2manifoldType::ECircles;
    }
}

impl Default for B2manifold {
    fn default() -> Self {
        return B2manifold {
            points: [B2manifoldPoint::default();B2_MAX_MANIFOLD_POINTS],
            local_normal: B2vec2::default(),
            local_point: B2vec2::default(),
            manifold_type: B2manifoldType::ECircles,
            point_count: 0,
        };
    }
}

/// A manifold for two touching convex shapes.
/// Box2D supports multiple types of contact:
/// - clip point versus plane with radius
/// - point versus point with radius (circles)
/// The local point usage depends on the manifold type:
/// -e_circles: the local center of circle_a
/// -e_faceA: the center of faceA
/// -e_faceB: the center of faceB
/// Similarly the local normal usage:
/// -e_circles: not used
/// -e_faceA: the normal on polygon_a
/// -e_faceB: the normal on polygon_b
/// We store contacts in this way so that position correction can
/// account for movement, which is critical for continuous physics.
/// All contact scenarios must be expressed in one of these types.
/// This structure is stored across time steps, so we keep it small.
#[derive(Clone, Copy, Debug)]
pub struct B2manifold {
    /// the points of contact
    pub points: [B2manifoldPoint; B2_MAX_MANIFOLD_POINTS],
    ///< not use for B2manifoldType::e_points
    pub local_normal: B2vec2,
    ///< usage depends on manifold type
    pub local_point: B2vec2,
    pub manifold_type: B2manifoldType,
    ///< the number of manifold points
    pub point_count: usize,
}

/// This is used to compute the current state of a contact manifold.
#[derive(Default, Clone, Copy, Debug)]
pub struct B2worldManifold {
    ///< world vector pointing from A to b
    pub normal: B2vec2,
    ///< world contact point (point of intersection)
    pub points: [B2vec2; B2_MAX_MANIFOLD_POINTS],
    ///< a negative value indicates overlap, in meters
    pub separations: [f32; B2_MAX_MANIFOLD_POINTS],
}

impl B2worldManifold {
    /// evaluate the manifold with supplied transforms. This assumes
    /// modest motion from the original state. This does not change the
    /// point count, impulses, etc. The radii must come from the shapes
    /// that generated the manifold.
    pub fn initialize(
        &mut self,
        manifold: &B2manifold,
        xf_a: B2Transform,
        radius_a: f32,
        xf_b: B2Transform,
        radius_b: f32,
    ) {
        private::b2_collision::b2_world_manifold_initialize(
            self, manifold, xf_a, radius_a, xf_b, radius_b,
        );
    }
}

/// This is used for determining the state of contact points.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum B2pointState {
    ///< point does not exist
    B2NullState,
    ///< point was added in the update
    B2AddState,
    ///< point persisted across the update
    B2PersistState,
    ///< point was removed in the update
    B2RemoveState,
}

impl Default for B2pointState {
    fn default() -> Self {
        B2pointState::B2NullState
    }
}

/// Compute the point states given two manifolds. The states pertain to the transition from manifold1
/// to manifold2. So state1 is either persist or remove while state2 is either add or persist.
pub fn b2_get_point_states(
    state1: &mut [B2pointState; B2_MAX_MANIFOLD_POINTS],
    state2: &mut [B2pointState; B2_MAX_MANIFOLD_POINTS],
    manifold1: &B2manifold,
    manifold2: &B2manifold,
) {
    private::b2_collision::b2_get_point_states(state1, state2, manifold1, manifold2);
}

/// Used for computing contact manifolds.
#[derive(Clone, Default, Copy, Debug)]
pub struct B2clipVertex {
    pub v: B2vec2,
    pub id: B2contactId,
}

/// Ray-cast input data. The ray extends from p1 to p1 + max_fraction * (p2 - p1).
#[derive(Clone, Copy, Debug)]
pub struct B2rayCastInput {
    pub p1: B2vec2,
    pub p2: B2vec2,
    pub max_fraction: f32,
}

/// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2
/// come from b2RayCastInput.
#[derive(Default, Clone, Copy, Debug)]
pub struct B2rayCastOutput {
    pub normal: B2vec2,
    pub fraction: f32,
}

/// An axis aligned bounding box.
#[derive(Default, Clone, Copy, Debug)]
pub struct B2AABB {
    ///< the lower vertex
    pub lower_bound: B2vec2,
    ///< the upper vertex
    pub upper_bound: B2vec2,
}

impl B2AABB {
    /// Verify that the bounds are sorted.
    pub fn is_valid(self) -> bool {
        return b2_aabb_is_valid(self);
    }

    /// Get the center of the AABB.
    pub fn get_center(self) -> B2vec2 {
        return 0.5 * (self.lower_bound + self.upper_bound);
    }

    /// Get the extents of the AABB (half-widths).
    pub fn get_extents(self) -> B2vec2 {
        return 0.5 * (self.upper_bound - self.lower_bound);
    }

    /// Get the perimeter length
    pub fn get_perimeter(self) -> f32 {
        let wx = self.upper_bound.x - self.lower_bound.x;
        let wy = self.upper_bound.y - self.lower_bound.y;
        return 2.0 * (wx + wy);
    }

    /// Combine an AABB into this one.
    pub fn combine(&mut self, aabb: B2AABB) {
        self.lower_bound = b2_min_vec2(self.lower_bound, aabb.lower_bound);
        self.upper_bound = b2_max_vec2(self.upper_bound, aabb.upper_bound);
    }

    /// Combine two AABBs into this one.
    pub fn combine_two(&mut self, aabb1: B2AABB, aabb2: B2AABB) {
        self.lower_bound = b2_min_vec2(aabb1.lower_bound, aabb2.lower_bound);
        self.upper_bound = b2_max_vec2(aabb1.upper_bound, aabb2.upper_bound);
    }

    /// Does this aabb contain the provided AABB.
    pub fn contains(self, aabb: &B2AABB) -> bool {
        let mut result = true;
        result = result && self.lower_bound.x <= aabb.lower_bound.x;
        result = result && self.lower_bound.y <= aabb.lower_bound.y;
        result = result && aabb.upper_bound.x <= self.upper_bound.x;
        result = result && aabb.upper_bound.y <= self.upper_bound.y;
        return result;
    }

    pub fn ray_cast(self, output: &mut B2rayCastOutput, input: &B2rayCastInput) -> bool {
        return private::b2_collision::b2_aabb_ray_cast(self, output, input);
    }
}

/// Compute the collision manifold between two circles.
pub fn b2_collide_circles(
    manifold: &mut B2manifold,
    circle_a: &B2circleShape,
    xf_a: &B2Transform,
    circle_b: &B2circleShape,
    xf_b: &B2Transform,
) {
    private::b2_collide_circle::b2_collide_circles(manifold, circle_a, xf_a, circle_b, xf_b);
}

/// Compute the collision manifold between a polygon and a circle.
pub fn b2_collide_polygon_and_circle(
    manifold: &mut B2manifold,
    polygon_a: &B2polygonShape,
    xf_a: &B2Transform,
    circle_b: &B2circleShape,
    xf_b: &B2Transform,
) {
    private::b2_collide_circle::b2_collide_polygon_and_circle(
        manifold, polygon_a, xf_a, circle_b, xf_b,
    );
}

/// Compute the collision manifold between two polygons.
pub fn b2_collide_polygons(
    manifold: &mut B2manifold,
    polygon_a: &B2polygonShape,
    xf_a: &B2Transform,
    polygon_b: &B2polygonShape,
    xf_b: &B2Transform,
) {
    private::b2_collide_polygon::b2_collide_polygons(
        manifold, *polygon_a, *xf_a, *polygon_b, *xf_b,
    );
}

/// Compute the collision manifold between an edge and a circle.
pub fn b2_collide_edge_and_circle(
    manifold: &mut B2manifold,
    edge_a: &B2edgeShape,
    xf_a: &B2Transform,
    circle_b: &B2circleShape,
    xf_b: &B2Transform,
) {
    private::b2_collide_edge::b2_collide_edge_and_circle(manifold, edge_a, xf_a, circle_b, xf_b);
}

/// Compute the collision manifold between an edge and a polygon.
pub fn b2_collide_edge_and_polygon(
    manifold: &mut B2manifold,
    edge_a: &B2edgeShape,
    xf_a: &B2Transform,
    polygon_b: &B2polygonShape,
    xf_b: &B2Transform,
) {
    private::b2_collide_edge::b2_collide_edge_and_polygon(manifold, edge_a, xf_a, polygon_b, xf_b);
}

// /// Clipping for contact manifolds.
pub fn b2_clip_segment_to_line(
    v_out: &mut [B2clipVertex; 2],
    v_in: [B2clipVertex; 2],
    normal: B2vec2,
    offset: f32,
    vertex_index_a: usize,
) -> usize {
    return private::b2_collision::b2_clip_segment_to_line(
        v_out,
        v_in,
        normal,
        offset,
        vertex_index_a,
    );
}

/// Determine if two generic shapes overlap.
pub fn b2_test_overlap_shapes(
    shape_a: ShapePtr,
    index_a: usize,
    shape_b: ShapePtr,
    index_b: usize,
    xf_a: B2Transform,
    xf_b: B2Transform,
) -> bool {
    return private::b2_collision::b2_test_overlap(shape_a, index_a, shape_b, index_b, xf_a, xf_b);
}

// ---------------- Inline Functions ------------------------------------------

pub fn b2_aabb_is_valid(this: B2AABB) -> bool {
    let d: B2vec2 = this.upper_bound - this.lower_bound;
    let mut valid: bool = d.x >= 0.0 && d.y >= 0.0;
    valid = valid && this.lower_bound.is_valid() && this.upper_bound.is_valid();
    return valid;
}

pub fn b2_test_overlap(a: B2AABB, b: B2AABB) -> bool {
    let d1 = b.lower_bound - a.upper_bound;
    let d2 = a.lower_bound - b.upper_bound;

    if d1.x > 0.0 || d1.y > 0.0 {
        return false;
    }

    if d2.x > 0.0 || d2.y > 0.0 {
        return false;
    }

    return true;
}