c2_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5/* automatically generated by rust-bindgen */
6
7pub const C2_MAX_POLYGON_VERTS: u32 = 8;
8
9#[derive(Debug, Copy, Clone)]
10pub struct c2v {
11    pub x: f32,
12    pub y: f32,
13}
14
15#[derive(Debug, Copy, Clone)]
16pub struct c2r {
17    pub c: f32,
18    pub s: f32,
19}
20
21#[derive(Debug, Copy, Clone)]
22pub struct c2m {
23    pub x: c2v,
24    pub y: c2v,
25}
26
27#[derive(Debug, Copy, Clone)]
28pub struct c2x {
29    pub p: c2v,
30    pub r: c2r,
31}
32
33#[derive(Debug, Copy, Clone)]
34pub struct c2h {
35    pub n: c2v,
36    pub d: f32,
37}
38
39#[derive(Debug, Copy, Clone)]
40pub struct c2Circle {
41    pub p: c2v,
42    pub r: f32,
43}
44
45#[derive(Debug, Copy, Clone)]
46pub struct c2AABB {
47    pub min: c2v,
48    pub max: c2v,
49}
50
51#[derive(Debug, Copy, Clone)]
52pub struct c2Capsule {
53    pub a: c2v,
54    pub b: c2v,
55    pub r: f32,
56}
57
58#[derive(Debug, Copy, Clone)]
59pub struct c2Poly {
60    pub count: ::std::os::raw::c_int,
61    pub verts: [c2v; 8usize],
62    pub norms: [c2v; 8usize],
63}
64
65#[derive(Debug, Copy, Clone)]
66pub struct c2Ray {
67    pub p: c2v,
68    pub d: c2v,
69    pub t: f32,
70}
71
72#[derive(Debug, Copy, Clone)]
73pub struct c2Raycast {
74    pub t: f32,
75    pub n: c2v,
76}
77
78#[derive(Debug, Copy, Clone)]
79pub struct c2Manifold {
80    pub count: ::std::os::raw::c_int,
81    pub depths: [f32; 2usize],
82    pub contact_points: [c2v; 2usize],
83    pub n: c2v,
84}
85
86fn c2Sub(mut a: c2v, b: c2v) -> c2v {
87    a.x -= b.x;
88    a.y -= b.y;
89    a
90}
91
92fn c2Dot(a: c2v, b: c2v) -> f32 {
93    a.x * b.x + a.y * b.y
94}
95
96pub unsafe fn c2CircletoCircle(A: c2Circle, B: c2Circle) -> ::std::os::raw::c_int {
97    let c: c2v = c2Sub(B.p, A.p);
98    let d2: f32 = c2Dot(c, c);
99    let mut r2: f32 = A.r + B.r;
100    r2 = r2 * r2;
101    if d2 < r2 {
102        1
103    } else {
104        0
105    }
106}
107
108fn c2V(x: f32, y: f32) -> c2v {
109    c2v { x, y }
110}
111
112fn c2Minv(a: c2v, b: c2v) -> c2v {
113    c2V(a.x.min(b.x), a.y.min(b.y))
114}
115fn c2Maxv(a: c2v, b: c2v) -> c2v {
116    c2V(a.x.max(b.x), a.y.max(b.y))
117}
118
119fn c2Clampv(a: c2v, lo: c2v, hi: c2v) -> c2v {
120    c2Maxv(lo, c2Minv(a, hi))
121}
122
123pub unsafe fn c2CircletoAABB(A: c2Circle, B: c2AABB) -> ::std::os::raw::c_int {
124    let L: c2v = c2Clampv(A.p, B.min, B.max);
125    let ab: c2v = c2Sub(A.p, L);
126    let d2: f32 = c2Dot(ab, ab);
127    let r2: f32 = A.r * A.r;
128    if d2 < r2 {
129        1
130    } else {
131        0
132    }
133}
134
135fn c2Mulvs(mut a: c2v, b: f32) -> c2v {
136    a.x *= b;
137    a.y *= b;
138    a
139}
140
141pub unsafe fn c2CircletoCapsule(A: c2Circle, B: c2Capsule) -> ::std::os::raw::c_int {
142    let n: c2v = c2Sub(B.b, B.a);
143    let ap = c2Sub(A.p, B.a);
144    let da = c2Dot(ap, n);
145    let d2: f32;
146
147    if da < 0.0 {
148        d2 = c2Dot(ap, ap);
149    } else {
150        let db = c2Dot(c2Sub(A.p, B.b), n);
151        if db < 0.0 {
152            let e = c2Sub(ap, c2Mulvs(n, da / c2Dot(n, n)));
153            d2 = c2Dot(e, e);
154        } else {
155            let bp = c2Sub(A.p, B.b);
156            d2 = c2Dot(bp, bp);
157        }
158    }
159
160    let r = A.r + B.r;
161    if d2 < r * r {
162        1
163    } else {
164        0
165    }
166}
167
168pub unsafe fn c2AABBtoAABB(A: c2AABB, B: c2AABB) -> ::std::os::raw::c_int {
169    let d0 = B.max.x < A.min.x;
170    let d1 = A.max.x < B.min.x;
171    let d2 = B.max.y < A.min.y;
172    let d3 = A.max.y < B.min.y;
173    if !(d0 | d1 | d2 | d3) {
174        1
175    } else {
176        0
177    }
178}
179
180fn c2AABBtoPoint(A: c2AABB, B: c2v) -> ::std::os::raw::c_int {
181    let d0 = B.x < A.min.x;
182    let d1 = B.y < A.min.y;
183    let d2 = B.x > A.max.x;
184    let d3 = B.y > A.max.y;
185    if !(d0 | d1 | d2 | d3) {
186        1
187    } else {
188        0
189    }
190}
191
192fn c2CircleToPoint(A: c2Circle, B: c2v) -> ::std::os::raw::c_int {
193    let n = c2Sub(A.p, B);
194    let d2 = c2Dot(n, n);
195    if d2 < A.r * A.r {
196        1
197    } else {
198        0
199    }
200}
201
202pub unsafe fn c2AABBtoCapsule(A: c2AABB, B: c2Capsule) -> ::std::os::raw::c_int {
203    if c2GJK(
204        &A as *const _ as *const std::os::raw::c_void,
205        C2_TYPE_C2_TYPE_AABB,
206        std::ptr::null(),
207        &B as *const _ as *const std::os::raw::c_void,
208        C2_TYPE_C2_TYPE_CAPSULE,
209        std::ptr::null(),
210        std::ptr::null_mut(),
211        std::ptr::null_mut(),
212        1,
213        std::ptr::null_mut(),
214        std::ptr::null_mut(),
215    ) != 0.0
216    {
217        return 0;
218    }
219    return 1;
220}
221
222pub unsafe fn c2CapsuletoCapsule(A: c2Capsule, B: c2Capsule) -> ::std::os::raw::c_int {
223    if c2GJK(
224        &A as *const _ as *const std::os::raw::c_void,
225        C2_TYPE_C2_TYPE_CAPSULE,
226        std::ptr::null(),
227        &B as *const _ as *const std::os::raw::c_void,
228        C2_TYPE_C2_TYPE_CAPSULE,
229        std::ptr::null(),
230        std::ptr::null_mut(),
231        std::ptr::null_mut(),
232        1,
233        std::ptr::null_mut(),
234        std::ptr::null_mut(),
235    ) != 0.0
236    {
237        return 0;
238    }
239    return 1;
240}
241
242pub unsafe fn c2CircletoPoly(
243    A: c2Circle,
244    B: *const c2Poly,
245    bx: *const c2x,
246) -> ::std::os::raw::c_int {
247    if c2GJK(
248        &A as *const _ as *const std::os::raw::c_void,
249        C2_TYPE_C2_TYPE_CIRCLE,
250        std::ptr::null(),
251        B as *const _ as *const std::os::raw::c_void,
252        C2_TYPE_C2_TYPE_POLY,
253        bx,
254        std::ptr::null_mut(),
255        std::ptr::null_mut(),
256        1,
257        std::ptr::null_mut(),
258        std::ptr::null_mut(),
259    ) != 0.0
260    {
261        return 0;
262    }
263    return 1;
264}
265
266pub unsafe fn c2AABBtoPoly(A: c2AABB, B: *const c2Poly, bx: *const c2x) -> ::std::os::raw::c_int {
267    if c2GJK(
268        &A as *const _ as *const std::os::raw::c_void,
269        C2_TYPE_C2_TYPE_AABB,
270        std::ptr::null(),
271        B as *const _ as *const std::os::raw::c_void,
272        C2_TYPE_C2_TYPE_POLY,
273        bx,
274        std::ptr::null_mut(),
275        std::ptr::null_mut(),
276        1,
277        std::ptr::null_mut(),
278        std::ptr::null_mut(),
279    ) != 0.0
280    {
281        return 0;
282    }
283    return 1;
284}
285
286pub unsafe fn c2CapsuletoPoly(
287    A: c2Capsule,
288    B: *const c2Poly,
289    bx: *const c2x,
290) -> ::std::os::raw::c_int {
291    if c2GJK(
292        &A as *const _ as *const std::os::raw::c_void,
293        C2_TYPE_C2_TYPE_CAPSULE,
294        std::ptr::null(),
295        B as *const _ as *const std::os::raw::c_void,
296        C2_TYPE_C2_TYPE_POLY,
297        bx,
298        std::ptr::null_mut(),
299        std::ptr::null_mut(),
300        1,
301        std::ptr::null_mut(),
302        std::ptr::null_mut(),
303    ) != 0.0
304    {
305        return 0;
306    }
307    return 1;
308}
309
310pub unsafe fn c2PolytoPoly(
311    A: *const c2Poly,
312    ax: *const c2x,
313    B: *const c2Poly,
314    bx: *const c2x,
315) -> ::std::os::raw::c_int {
316    if c2GJK(
317        A as *const _ as *const std::os::raw::c_void,
318        C2_TYPE_C2_TYPE_POLY,
319        ax,
320        B as *const _ as *const std::os::raw::c_void,
321        C2_TYPE_C2_TYPE_POLY,
322        bx,
323        std::ptr::null_mut(),
324        std::ptr::null_mut(),
325        1,
326        std::ptr::null_mut(),
327        std::ptr::null_mut(),
328    ) != 0.0
329    {
330        return 0;
331    }
332    return 1;
333}
334
335fn c2Impact(ray: c2Ray, t: f32) -> c2v {
336    c2Add(ray.p, c2Mulvs(ray.d, t))
337}
338
339pub unsafe fn c2RaytoCircle(A: c2Ray, B: c2Circle, out: *mut c2Raycast) -> ::std::os::raw::c_int {
340    let p = B.p;
341    let m = c2Sub(A.p, p);
342    let c = c2Dot(m, m) - B.r * B.r;
343    let b = c2Dot(m, A.d);
344    let disc = b * b - c;
345    if disc < 0.0 {
346        return 0;
347    }
348
349    let t = -b - disc.sqrt();
350    if t >= 0.0 && t <= A.t {
351        (*out).t = t;
352        let impact = c2Impact(A, t);
353        (*out).n = c2Norm(c2Sub(impact, p));
354        return 1;
355    }
356    return 0;
357}
358
359pub unsafe fn c2RaytoAABB(A: c2Ray, B: c2AABB, out: *mut c2Raycast) -> ::std::os::raw::c_int {
360    let p0 = A.p;
361    let p1 = c2Impact(A, A.t);
362    let a_box = c2AABB {
363        min: c2Minv(p0, p1),
364        max: c2Maxv(p0, p1),
365    };
366
367    // Test B's axes.
368    if c2AABBtoAABB(a_box, B) == 0 {
369        return 0;
370    }
371
372    // Test the ray's axes (along the segment's normal).
373    let ab = c2Sub(p1, p0);
374    let n = c2Skew(ab);
375    let abs_n = c2Absv(n);
376    let half_extents = c2Mulvs(c2Sub(B.max, B.min), 0.5);
377    let center_of_b_box = c2Mulvs(c2Add(B.min, B.max), 0.5);
378    let d = c2Dot(n, c2Sub(p0, center_of_b_box)).abs() - c2Dot(abs_n, half_extents);
379    if d > 0.0 {
380        return 0;
381    }
382
383    // Calculate intermediate values up-front.
384    // This should play well with superscalar architecture.
385    let da0 = c2SignedDistPointToPlane_OneDimensional(p0.x, -1.0, B.min.x);
386    let db0 = c2SignedDistPointToPlane_OneDimensional(p1.x, -1.0, B.min.x);
387    let da1 = c2SignedDistPointToPlane_OneDimensional(p0.x, 1.0, B.max.x);
388    let db1 = c2SignedDistPointToPlane_OneDimensional(p1.x, 1.0, B.max.x);
389    let da2 = c2SignedDistPointToPlane_OneDimensional(p0.y, -1.0, B.min.y);
390    let db2 = c2SignedDistPointToPlane_OneDimensional(p1.y, -1.0, B.min.y);
391    let da3 = c2SignedDistPointToPlane_OneDimensional(p0.y, 1.0, B.max.y);
392    let db3 = c2SignedDistPointToPlane_OneDimensional(p1.y, 1.0, B.max.y);
393    let mut t0 = c2RayToPlane_OneDimensional(da0, db0);
394    let mut t1 = c2RayToPlane_OneDimensional(da1, db1);
395    let mut t2 = c2RayToPlane_OneDimensional(da2, db2);
396    let mut t3 = c2RayToPlane_OneDimensional(da3, db3);
397
398    // Calculate hit predicate, no branching.
399    let hit0 = t0 < 1.0;
400    let hit1 = t1 < 1.0;
401    let hit2 = t2 < 1.0;
402    let hit3 = t3 < 1.0;
403    let hit = hit0 | hit1 | hit2 | hit3;
404
405    if hit {
406        // Remap t's within 0-1 range, where >= 1 is treated as 0.
407        t0 = hit0 as i32 as f32 * t0;
408        t1 = hit1 as i32 as f32 * t1;
409        t2 = hit2 as i32 as f32 * t2;
410        t3 = hit3 as i32 as f32 * t3;
411
412        // Sort output by finding largest t to deduce the normal.
413        if t0 >= t1 && t0 >= t2 && t0 >= t3 {
414            (*out).t = t0 * A.t;
415            (*out).n = c2V(-1.0, 0.0);
416        } else if t1 >= t0 && t1 >= t2 && t1 >= t3 {
417            (*out).t = t1 * A.t;
418            (*out).n = c2V(1.0, 0.0);
419        } else if t2 >= t0 && t2 >= t1 && t2 >= t3 {
420            (*out).t = t2 * A.t;
421            (*out).n = c2V(0.0, -1.0);
422        } else {
423            (*out).t = t3 * A.t;
424            (*out).n = c2V(0.0, 1.0);
425        }
426
427        return 1;
428    } else {
429        return 0;
430    } // This can still numerically happen.
431}
432
433fn c2SignedDistPointToPlane_OneDimensional(p: f32, n: f32, d: f32) -> f32 {
434    p * n - d * n
435}
436
437fn c2RayToPlane_OneDimensional(da: f32, db: f32) -> f32 {
438    if da < 0.0 {
439        return 0.0;
440    }
441    // Ray started behind plane.
442    else if da * db >= 0.0 {
443        return 1.0;
444    }
445    // Ray starts and ends on the same of the plane.
446    else
447    // Ray starts and ends on opposite sides of the plane (or directly on the plane).
448    {
449        let d = da - db;
450        if d != 0.0 {
451            return da / d;
452        } else {
453            // Special case for super tiny ray, or AABB.
454            return 0.0;
455        }
456    }
457}
458
459fn c2MulmvT(a: c2m, b: c2v) -> c2v {
460    c2v {
461        x: a.x.x * b.x + a.x.y * b.y,
462        y: a.y.x * b.x + a.y.y * b.y,
463    }
464}
465
466pub unsafe fn c2RaytoCapsule(A: c2Ray, B: c2Capsule, out: *mut c2Raycast) -> ::std::os::raw::c_int {
467    let M = {
468        let y = c2Norm(c2Sub(B.b, B.a));
469        c2m { x: c2CCW90(y), y }
470    };
471
472    // rotate capsule to origin, along Y axis
473    // rotate the ray same way
474    let cap_n = c2Sub(B.b, B.a);
475    let yBb = c2MulmvT(M, cap_n);
476    let yAp = c2MulmvT(M, c2Sub(A.p, B.a));
477    let yAd = c2MulmvT(M, A.d);
478    let yAe = c2Add(yAp, c2Mulvs(yAd, A.t));
479
480    let capsule_bb = c2AABB {
481        min: c2V(-B.r, 0.0),
482        max: c2V(B.r, yBb.y),
483    };
484
485    (*out).n = c2Norm(cap_n);
486    (*out).t = 0.0;
487
488    // check and see if ray starts within the capsule
489    if c2AABBtoPoint(capsule_bb, yAp) != 0 {
490        return 1;
491    } else {
492        let capsule_a = c2Circle { p: B.a, r: B.r };
493        let capsule_b = c2Circle { p: B.b, r: B.r };
494
495        if c2CircleToPoint(capsule_a, A.p) != 0 {
496            return 1;
497        } else if c2CircleToPoint(capsule_b, A.p) != 0 {
498            return 1;
499        }
500    }
501
502    if yAe.x * yAp.x < 0.0 || yAe.x.abs().min(yAp.x.abs()) < B.r {
503        let Ca = c2Circle { p: B.a, r: B.r };
504        let Cb = c2Circle { p: B.b, r: B.r };
505
506        // ray starts inside capsule prism -- must hit one of the semi-circles
507        if yAp.x.abs() < B.r {
508            if yAp.y < 0.0 {
509                return c2RaytoCircle(A, Ca, out);
510            } else {
511                return c2RaytoCircle(A, Cb, out);
512            }
513        }
514        // hit the capsule prism
515        else {
516            let c = if yAp.x > 0.0 { B.r } else { -B.r };
517            let d = yAe.x - yAp.x;
518            let t = (c - yAp.x) / d;
519            let y = yAp.y + (yAe.y - yAp.y) * t;
520            if y <= 0.0 {
521                return c2RaytoCircle(A, Ca, out);
522            }
523            if y >= yBb.y {
524                return c2RaytoCircle(A, Cb, out);
525            } else {
526                (*out).n = if c > 0.0 { M.x } else { c2Skew(M.y) };
527                (*out).t = t * A.t;
528                return 1;
529            }
530        }
531    }
532
533    return 0;
534}
535
536pub unsafe fn c2RaytoPoly(
537    A: c2Ray,
538    B: *const c2Poly,
539    bx_ptr: *const c2x,
540    out: *mut c2Raycast,
541) -> ::std::os::raw::c_int {
542    let bx = if !bx_ptr.is_null() {
543        *bx_ptr
544    } else {
545        c2xIdentity()
546    };
547    let p = c2MulxvT(bx, A.p);
548    let d = c2MulrvT(bx.r, A.d);
549    let mut lo = 0.0;
550    let mut hi = A.t;
551    let mut index = !0;
552
553    // test ray to each plane, tracking lo/hi times of intersection
554    for i in 0..(*B).count as usize {
555        let num = c2Dot((*B).norms[i], c2Sub((*B).verts[i], p));
556        let den = c2Dot((*B).norms[i], d);
557        if den == 0.0 && num < 0.0 {
558            return 0;
559        } else {
560            if den < 0.0 && num < lo * den {
561                lo = num / den;
562                index = i;
563            } else if den > 0.0 && num < hi * den {
564                hi = num / den;
565            }
566        }
567        if hi < lo {
568            return 0;
569        }
570    }
571
572    if index != !0 {
573        (*out).t = lo;
574        (*out).n = c2Mulrv(bx.r, (*B).norms[index]);
575        return 1;
576    }
577
578    return 0;
579}
580
581pub unsafe fn c2CircletoCircleManifold(A: c2Circle, B: c2Circle, m: *mut c2Manifold) {
582    (*m).count = 0;
583    let d = c2Sub(B.p, A.p);
584    let d2 = c2Dot(d, d);
585    let r = A.r + B.r;
586    if d2 < r * r {
587        let l = d2.sqrt();
588        let n = if l != 0.0 {
589            c2Mulvs(d, 1.0 / l)
590        } else {
591            c2V(0.0, 1.0)
592        };
593        (*m).count = 1;
594        (*m).depths[0] = r - l;
595        (*m).contact_points[0] = c2Sub(B.p, c2Mulvs(n, B.r));
596        (*m).n = n;
597    }
598}
599
600fn c2Absv(a: c2v) -> c2v {
601    return c2V(a.x.abs(), a.y.abs());
602}
603
604pub unsafe fn c2CircletoAABBManifold(A: c2Circle, B: c2AABB, m: *mut c2Manifold) {
605    (*m).count = 0;
606    let L = c2Clampv(A.p, B.min, B.max);
607    let ab = c2Sub(L, A.p);
608    let d2 = c2Dot(ab, ab);
609    let r2 = A.r * A.r;
610    if d2 < r2 {
611        // shallow (center of circle not inside of AABB)
612        if d2 != 0.0 {
613            let d = d2.sqrt();
614            let n = c2Norm(ab);
615            (*m).count = 1;
616            (*m).depths[0] = A.r - d;
617            (*m).contact_points[0] = c2Add(A.p, c2Mulvs(n, d));
618            (*m).n = n;
619        }
620        // deep (center of circle inside of AABB)
621        // clamp circle's center to edge of AABB, then form the manifold
622        else {
623            let mid = c2Mulvs(c2Add(B.min, B.max), 0.5);
624            let e = c2Mulvs(c2Sub(B.max, B.min), 0.5);
625            let d = c2Sub(A.p, mid);
626            let abs_d = c2Absv(d);
627
628            let x_overlap = e.x - abs_d.x;
629            let y_overlap = e.y - abs_d.y;
630
631            let depth;
632            let mut n;
633
634            if x_overlap < y_overlap {
635                depth = x_overlap;
636                n = c2V(1.0, 0.0);
637                n = c2Mulvs(n, if d.x < 0.0 { 1.0 } else { -1.0 });
638            } else {
639                depth = y_overlap;
640                n = c2V(0.0, 1.0);
641                n = c2Mulvs(n, if d.y < 0.0 { 1.0 } else { -1.0 });
642            }
643
644            (*m).count = 1;
645            (*m).depths[0] = A.r + depth;
646            (*m).contact_points[0] = c2Sub(A.p, c2Mulvs(n, depth));
647            (*m).n = n;
648        }
649    }
650}
651
652pub unsafe fn c2CircletoCapsuleManifold(A: c2Circle, B: c2Capsule, m: *mut c2Manifold) {
653    (*m).count = 0;
654    let mut a = c2V(0.0, 0.0);
655    let mut b = c2V(0.0, 0.0);
656    let r = A.r + B.r;
657    let d = c2GJK(
658        &A as *const _ as *const std::os::raw::c_void,
659        C2_TYPE_C2_TYPE_CIRCLE,
660        std::ptr::null_mut(),
661        &B as *const _ as *const std::os::raw::c_void,
662        C2_TYPE_C2_TYPE_CAPSULE,
663        std::ptr::null_mut(),
664        &mut a,
665        &mut b,
666        0,
667        std::ptr::null_mut(),
668        std::ptr::null_mut(),
669    );
670    if d < r {
671        let n;
672        if d == 0.0 {
673            n = c2Norm(c2Skew(c2Sub(B.b, B.a)));
674        } else {
675            n = c2Norm(c2Sub(b, a));
676        }
677
678        (*m).count = 1;
679        (*m).depths[0] = r - d;
680        (*m).contact_points[0] = c2Sub(b, c2Mulvs(n, B.r));
681        (*m).n = n;
682    }
683}
684
685pub unsafe fn c2AABBtoAABBManifold(A: c2AABB, B: c2AABB, m: *mut c2Manifold) {
686    (*m).count = 0;
687    let mid_a = c2Mulvs(c2Add(A.min, A.max), 0.5);
688    let mid_b = c2Mulvs(c2Add(B.min, B.max), 0.5);
689    let eA = c2Absv(c2Mulvs(c2Sub(A.max, A.min), 0.5));
690    let eB = c2Absv(c2Mulvs(c2Sub(B.max, B.min), 0.5));
691    let d = c2Sub(mid_b, mid_a);
692
693    // calc overlap on x and y axes
694    let dx = eA.x + eB.x - d.x.abs();
695    if dx < 0.0 {
696        return;
697    }
698    let dy = eA.y + eB.y - d.y.abs();
699    if dy < 0.0 {
700        return;
701    }
702
703    let n;
704    let depth;
705    let p;
706
707    // x axis overlap is smaller
708    if dx < dy {
709        depth = dx;
710        if d.x < 0.0 {
711            n = c2V(-1.0, 0.0);
712            p = c2Sub(mid_a, c2V(eA.x, 0.0));
713        } else {
714            n = c2V(1.0, 0.0);
715            p = c2Add(mid_a, c2V(eA.x, 0.0));
716        }
717    }
718    // y axis overlap is smaller
719    else {
720        depth = dy;
721        if d.y < 0.0 {
722            n = c2V(0.0, -1.0);
723            p = c2Sub(mid_a, c2V(0.0, eA.y));
724        } else {
725            n = c2V(0.0, 1.0);
726            p = c2Add(mid_a, c2V(0.0, eA.y));
727        }
728    }
729
730    (*m).count = 1;
731    (*m).contact_points[0] = p;
732    (*m).depths[0] = depth;
733    (*m).n = n;
734}
735
736pub unsafe fn c2AABBtoCapsuleManifold(A: c2AABB, B: c2Capsule, m: *mut c2Manifold) {
737    (*m).count = 0;
738    let mut p = c2Poly {
739        count: 0,
740        verts: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
741        norms: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
742    };
743    c2BBVerts(&mut p.verts, &A);
744    p.count = 4;
745    c2Norms(&mut p.verts, &mut p.norms, 4);
746    c2CapsuletoPolyManifold(B, &p, std::ptr::null(), m);
747    (*m).n = c2Neg((*m).n);
748}
749
750pub unsafe fn c2CapsuletoCapsuleManifold(A: c2Capsule, B: c2Capsule, m: *mut c2Manifold) {
751    {
752        (*m).count = 0;
753        let mut a = c2V(0.0, 0.0);
754        let mut b = c2V(0.0, 0.0);
755        let r = A.r + B.r;
756        let d = c2GJK(
757            &A as *const _ as *const std::os::raw::c_void,
758            C2_TYPE_C2_TYPE_CAPSULE,
759            std::ptr::null_mut(),
760            &B as *const _ as *const std::os::raw::c_void,
761            C2_TYPE_C2_TYPE_CAPSULE,
762            std::ptr::null_mut(),
763            &mut a,
764            &mut b,
765            0,
766            std::ptr::null_mut(),
767            std::ptr::null_mut(),
768        );
769        if d < r {
770            let n;
771            if d == 0.0 {
772                n = c2Norm(c2Skew(c2Sub(A.b, A.a)));
773            } else {
774                n = c2Norm(c2Sub(b, a));
775            }
776
777            (*m).count = 1;
778            (*m).depths[0] = r - d;
779            (*m).contact_points[0] = c2Sub(b, c2Mulvs(n, B.r));
780            (*m).n = n;
781        }
782    }
783}
784
785fn c2MulxvT(a: c2x, b: c2v) -> c2v {
786    return c2MulrvT(a.r, c2Sub(b, a.p));
787}
788
789fn c2MulrvT(a: c2r, b: c2v) -> c2v {
790    return c2V(a.c * b.x + a.s * b.y, -a.s * b.x + a.c * b.y);
791}
792
793unsafe fn c2PlaneAt(p: *const c2Poly, i: i32) -> c2h {
794    c2h {
795        n: (*p).norms[i as usize],
796        d: c2Dot((*p).norms[i as usize], (*p).verts[i as usize]),
797    }
798}
799
800fn c2Dist(h: c2h, p: c2v) -> f32 {
801    return c2Dot(h.n, p) - h.d;
802}
803
804fn c2Project(h: c2h, p: c2v) -> c2v {
805    return c2Sub(p, c2Mulvs(h.n, c2Dist(h, p)));
806}
807
808pub unsafe fn c2CircletoPolyManifold(
809    A: c2Circle,
810    B: *const c2Poly,
811    bx_tr: *const c2x,
812    m: *mut c2Manifold,
813) {
814    (*m).count = 0;
815    let mut a = c2V(0.0, 0.0);
816    let mut b = c2V(0.0, 0.0);
817    let mut d = c2GJK(
818        &A as *const _ as *const std::os::raw::c_void,
819        C2_TYPE_C2_TYPE_CIRCLE,
820        std::ptr::null_mut(),
821        B as *const _ as *const std::os::raw::c_void,
822        C2_TYPE_C2_TYPE_POLY,
823        bx_tr,
824        &mut a,
825        &mut b,
826        0,
827        std::ptr::null_mut(),
828        std::ptr::null_mut(),
829    );
830
831    // shallow, the circle center did not hit the polygon
832    // just use a and b from GJK to define the collision
833    if d != 0.0 {
834        let n = c2Sub(b, a);
835        let mut l = c2Dot(n, n);
836        if l < A.r * A.r {
837            l = l.sqrt();
838            (*m).count = 1;
839            (*m).contact_points[0] = b;
840            (*m).depths[0] = A.r - l;
841            (*m).n = c2Mulvs(n, 1.0 / l);
842        }
843    }
844    // Circle center is inside the polygon
845    // find the face closest to circle center to form manifold
846    else {
847        let bx = if !bx_tr.is_null() {
848            *bx_tr
849        } else {
850            c2xIdentity()
851        };
852        let mut sep = -std::f32::MAX;
853        let mut index = !0;
854        let local = c2MulxvT(bx, A.p);
855
856        for i in 0..(*B).count {
857            {
858                let h = c2PlaneAt(B, i);
859                d = c2Dist(h, local);
860                if d > A.r {
861                    return;
862                }
863                if d > sep {
864                    sep = d;
865                    index = i;
866                }
867            }
868
869            let h = c2PlaneAt(B, index);
870            let p = c2Project(h, local);
871            (*m).count = 1;
872            (*m).contact_points[0] = c2Mulxv(bx, p);
873            (*m).depths[0] = A.r - sep;
874            (*m).n = c2Neg(c2Mulrv(bx.r, (*B).norms[index as usize]));
875        }
876    }
877}
878
879pub unsafe fn c2AABBtoPolyManifold(
880    A: c2AABB,
881    B: *const c2Poly,
882    bx: *const c2x,
883    m: *mut c2Manifold,
884) {
885    (*m).count = 0;
886    let mut p = c2Poly {
887        count: 0,
888        verts: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
889        norms: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
890    };
891    c2BBVerts(&mut p.verts, &A);
892    p.count = 4;
893    c2Norms(&mut p.verts, &mut p.norms, 4);
894    c2PolytoPolyManifold(&p, std::ptr::null(), B, bx, m);
895}
896
897unsafe fn c2SidePlanesFromPoly(
898    seg: &mut [c2v; 2],
899    x: c2x,
900    p: *const c2Poly,
901    e: i32,
902    h: *mut c2h,
903) -> i32 {
904    let ra = c2Mulxv(x, (*p).verts[e as usize]);
905    let rb = c2Mulxv(
906        x,
907        (*p).verts[if e + 1 == if (*p).count != 0 { 0 } else { e + 1 } {
908            1
909        } else {
910            0
911        }],
912    );
913    return c2SidePlanes(seg, ra, rb, h);
914}
915
916// clip a segment to a plane
917unsafe fn c2Clip(seg: &mut [c2v; 2], h: c2h) -> i32 {
918    let mut out: [c2v; 2] = [c2V(0.0, 0.0); 2];
919    let mut sp = 0;
920    let d0: f32;
921    let d1: f32;
922    d0 = c2Dist(h, seg[0]);
923    if (d0) < 0.0 {
924        out[sp] = seg[0];
925        sp += 1;
926    }
927    d1 = c2Dist(h, seg[1]);
928    if (d1) < 0.0 {
929        out[sp] = seg[1];
930        sp += 1
931    }
932    if d0 == 0.0 && d1 == 0.0 {
933        out[sp] = seg[0];
934        sp += 1;
935        out[sp] = seg[1];
936        sp += 1;
937    } else if d0 * d1 <= 0.0 {
938        out[sp] = c2Intersect(seg[0], seg[1], d0, d1);
939        sp += 1;
940    }
941    seg[0] = out[0];
942    seg[1] = out[1];
943    return sp as i32;
944}
945
946fn c2Intersect(a: c2v, b: c2v, da: f32, db: f32) -> c2v {
947    return c2Add(a, c2Mulvs(c2Sub(b, a), da / (da - db)));
948}
949
950unsafe fn c2SidePlanes(seg: &mut [c2v; 2], ra: c2v, rb: c2v, h: *mut c2h) -> i32 {
951    let _in = c2Norm(c2Sub(rb, ra));
952    let left = c2h {
953        n: c2Neg(_in),
954        d: c2Dot(c2Neg(_in), ra),
955    };
956    let right = c2h {
957        n: _in,
958        d: c2Dot(_in, rb),
959    };
960    if c2Clip(seg, left) < 2 {
961        return 0;
962    }
963    if c2Clip(seg, right) < 2 {
964        return 0;
965    }
966    if !h.is_null() {
967        (*h).n = c2CCW90(_in);
968        (*h).d = c2Dot(c2CCW90(_in), ra);
969    }
970    return 1;
971}
972
973unsafe fn c2KeepDeep(seg: &mut [c2v; 2], h: c2h, m: *mut c2Manifold) {
974    let mut cp = 0;
975    for i in 0..2 {
976        let p = seg[i];
977        let d = c2Dist(h, p);
978        if d <= 0.0 {
979            (*m).contact_points[cp] = p;
980            (*m).depths[cp] = -d;
981            cp += 1;
982        }
983    }
984    (*m).count = cp as i32;
985    (*m).n = h.n;
986}
987
988unsafe fn c2Incident(
989    incident: &mut [c2v; 2],
990    ip: *const c2Poly,
991    ix: c2x,
992    rn_in_incident_space: c2v,
993) {
994    let mut index: i32 = !0;
995    let mut min_dot = std::f32::MAX;
996    for i in 0..(*ip).count {
997        let dot = c2Dot(rn_in_incident_space, (*ip).norms[i as usize]);
998        if dot < min_dot {
999            min_dot = dot;
1000            index = i;
1001        }
1002    }
1003    incident[0] = c2Mulxv(ix, (*ip).verts[index as usize]);
1004    incident[1] = c2Mulxv(
1005        ix,
1006        (*ip).verts[(index + 1 == if (*ip).count != 0 { 0 } else { index + 1 }) as usize],
1007    );
1008}
1009
1010pub unsafe fn c2CapsuletoPolyManifold(
1011    A: c2Capsule,
1012    B: *const c2Poly,
1013    bx_ptr: *const c2x,
1014    m: *mut c2Manifold,
1015) {
1016    (*m).count = 0;
1017    let mut a = c2V(0.0, 0.0);
1018    let mut b = c2V(0.0, 0.0);
1019    let d = c2GJK(
1020        &A as *const _ as *const std::os::raw::c_void,
1021        C2_TYPE_C2_TYPE_CAPSULE,
1022        std::ptr::null_mut(),
1023        B as *const _ as *const std::os::raw::c_void,
1024        C2_TYPE_C2_TYPE_POLY,
1025        bx_ptr,
1026        &mut a,
1027        &mut b,
1028        0,
1029        std::ptr::null_mut(),
1030        std::ptr::null_mut(),
1031    );
1032
1033    // deep, treat as segment to poly collision
1034    if d < 1.0e-6 {
1035        let bx = if !bx_ptr.is_null() {
1036            *bx_ptr
1037        } else {
1038            c2xIdentity()
1039        };
1040        let mut A_in_B = c2Capsule {
1041            a: c2V(0.0, 0.0),
1042            b: c2V(0.0, 0.0),
1043            r: 0.0,
1044        };
1045        A_in_B.a = c2MulxvT(bx, A.a);
1046        A_in_B.b = c2MulxvT(bx, A.b);
1047        let ab = c2Norm(c2Sub(A_in_B.a, A_in_B.b));
1048
1049        // test capsule axes
1050        let mut ab_h0 = c2h {
1051            n: c2V(0.0, 0.0),
1052            d: 0.0,
1053        };
1054        ab_h0.n = c2CCW90(ab);
1055        ab_h0.d = c2Dot(A_in_B.a, ab_h0.n);
1056        let v0 = c2Support((*B).verts, (*B).count, c2Neg(ab_h0.n));
1057        let s0 = c2Dist(ab_h0, (*B).verts[v0 as usize]);
1058
1059        let mut ab_h1 = c2h {
1060            n: c2V(0.0, 0.0),
1061            d: 0.0,
1062        };
1063        ab_h1.n = c2Skew(ab);
1064        ab_h1.d = c2Dot(A_in_B.a, ab_h1.n);
1065        let v1 = c2Support((*B).verts, (*B).count, c2Neg(ab_h1.n));
1066        let s1 = c2Dist(ab_h1, (*B).verts[v1 as usize]);
1067
1068        // test poly axes
1069        let mut index = !0;
1070        let mut sep = -std::f32::MAX;
1071        let mut code = 0;
1072        for i in 0..(*B).count {
1073            let h = c2PlaneAt(B, i);
1074            let da = c2Dot(A_in_B.a, c2Neg(h.n));
1075            let db = c2Dot(A_in_B.b, c2Neg(h.n));
1076            let d;
1077            if da > db {
1078                d = c2Dist(h, A_in_B.a);
1079            } else {
1080                d = c2Dist(h, A_in_B.b);
1081            }
1082            if d > sep {
1083                sep = d;
1084                index = i;
1085            }
1086        }
1087
1088        // track axis of minimum separation
1089        if s0 > sep {
1090            sep = s0;
1091            index = v0;
1092            code = 1;
1093        }
1094
1095        if s1 > sep {
1096            index = v1;
1097            code = 2;
1098        }
1099
1100        match code {
1101            // poly face
1102            0 => {
1103                let mut seg: [c2v; 2] = [A.a, A.b];
1104                let mut h = c2h {
1105                    n: c2V(0.0, 0.0),
1106                    d: 0.0,
1107                };
1108                if c2SidePlanesFromPoly(&mut seg, bx, B, index, &mut h) == 0 {
1109                    return;
1110                }
1111                c2KeepDeep(&mut seg, h, m);
1112                (*m).n = c2Neg((*m).n);
1113            }
1114
1115            1 =>
1116            // side 0 of capsule segment
1117            {
1118                let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
1119                c2Incident(&mut incident, B, bx, ab_h0.n);
1120                let mut h = c2h {
1121                    n: c2V(0.0, 0.0),
1122                    d: 0.0,
1123                };
1124                if c2SidePlanes(&mut incident, A_in_B.b, A_in_B.a, &mut h) == 0 {
1125                    return;
1126                }
1127                c2KeepDeep(&mut incident, h, m);
1128            }
1129
1130            2 =>
1131            // side 1 of capsule segment
1132            {
1133                let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
1134                c2Incident(&mut incident, B, bx, ab_h1.n);
1135                let mut h = c2h {
1136                    n: c2V(0.0, 0.0),
1137                    d: 0.0,
1138                };
1139                if c2SidePlanes(&mut incident, A_in_B.a, A_in_B.b, &mut h) == 0 {
1140                    return;
1141                }
1142                c2KeepDeep(&mut incident, h, m);
1143            }
1144
1145            _ => {
1146                // should never happen.
1147                return;
1148            }
1149        }
1150
1151        for i in 0..(*m).count {
1152            (*m).depths[i as usize] += A.r;
1153        }
1154    }
1155    // shallow, use GJK results a and b to define manifold
1156    else if d < A.r {
1157        (*m).count = 1;
1158        (*m).n = c2Norm(c2Sub(b, a));
1159        (*m).contact_points[0] = c2Add(a, c2Mulvs((*m).n, A.r));
1160        (*m).depths[0] = A.r - d;
1161    }
1162}
1163
1164fn c2MulrrT(a: c2r, b: c2r) -> c2r {
1165    c2r {
1166        c: a.c * b.c + a.s * b.s,
1167        s: a.c * b.s - a.s * b.c,
1168    }
1169}
1170
1171fn c2MulxxT(a: c2x, b: c2x) -> c2x {
1172    c2x {
1173        r: c2MulrrT(a.r, b.r),
1174        p: c2MulrvT(a.r, c2Sub(b.p, a.p)),
1175    }
1176}
1177
1178unsafe fn c2CheckFaces(
1179    A: *const c2Poly,
1180    ax: c2x,
1181    B: *const c2Poly,
1182    bx: c2x,
1183    face_index: &mut i32,
1184) -> f32 {
1185    let b_in_a = c2MulxxT(ax, bx);
1186    let a_in_b = c2MulxxT(bx, ax);
1187    let mut sep = -std::f32::MAX;
1188    let mut index = !0;
1189
1190    for i in 0..(*A).count {
1191        let h = c2PlaneAt(A, i);
1192        let idx = c2Support((*B).verts, (*B).count, c2Mulrv(a_in_b.r, c2Neg(h.n)));
1193        let p = c2Mulxv(b_in_a, (*B).verts[idx as usize]);
1194        let d = c2Dist(h, p);
1195        if d > sep {
1196            sep = d;
1197            index = i;
1198        }
1199    }
1200
1201    *face_index = index;
1202    return sep;
1203}
1204
1205pub unsafe fn c2PolytoPolyManifold(
1206    A: *const c2Poly,
1207    ax_ptr: *const c2x,
1208    B: *const c2Poly,
1209    bx_ptr: *const c2x,
1210    m: *mut c2Manifold,
1211) {
1212    (*m).count = 0;
1213    let ax = if !ax_ptr.is_null() {
1214        *ax_ptr
1215    } else {
1216        c2xIdentity()
1217    };
1218    let bx = if !bx_ptr.is_null() {
1219        *bx_ptr
1220    } else {
1221        c2xIdentity()
1222    };
1223    let mut ea: i32 = 0;
1224    let mut eb: i32 = 0;
1225    let sa = c2CheckFaces(A, ax, B, bx, &mut ea);
1226    let sb = c2CheckFaces(B, bx, A, ax, &mut eb);
1227    if sa >= 0.0 {
1228        return;
1229    }
1230    if sb >= 0.0 {
1231        return;
1232    }
1233
1234    let rp: *const c2Poly;
1235    let ip: *const c2Poly;
1236    let rx: c2x;
1237    let ix: c2x;
1238    let re: i32;
1239    let kRelTol = 0.95;
1240    let kAbsTol = 0.01;
1241    let flip: i32;
1242    if sa * kRelTol > sb + kAbsTol {
1243        rp = A;
1244        rx = ax;
1245        ip = B;
1246        ix = bx;
1247        re = ea;
1248        flip = 0;
1249    } else {
1250        rp = B;
1251        rx = bx;
1252        ip = A;
1253        ix = ax;
1254        re = eb;
1255        flip = 1;
1256    }
1257
1258    let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
1259    c2Incident(
1260        &mut incident,
1261        ip,
1262        ix,
1263        c2MulrvT(ix.r, c2Mulrv(rx.r, (*rp).norms[re as usize])),
1264    );
1265    let mut rh = c2h {
1266        n: c2V(0.0, 0.0),
1267        d: 0.0,
1268    };
1269    if c2SidePlanesFromPoly(&mut incident, rx, rp, re, &mut rh) == 0 {
1270        return;
1271    }
1272    c2KeepDeep(&mut incident, rh, m);
1273    if flip != 0 {
1274        (*m).n = c2Neg((*m).n);
1275    }
1276}
1277
1278pub const C2_TYPE_C2_TYPE_NONE: C2_TYPE = 0;
1279pub const C2_TYPE_C2_TYPE_CIRCLE: C2_TYPE = 1;
1280pub const C2_TYPE_C2_TYPE_AABB: C2_TYPE = 2;
1281pub const C2_TYPE_C2_TYPE_CAPSULE: C2_TYPE = 3;
1282pub const C2_TYPE_C2_TYPE_POLY: C2_TYPE = 4;
1283pub type C2_TYPE = u32;
1284
1285#[derive(Debug, Copy, Clone)]
1286pub struct c2GJKCache {
1287    pub metric: f32,
1288    pub count: ::std::os::raw::c_int,
1289    pub iA: [::std::os::raw::c_int; 3usize],
1290    pub iB: [::std::os::raw::c_int; 3usize],
1291    pub div: f32,
1292}
1293
1294#[derive(Debug, Copy, Clone)]
1295struct c2Proxy {
1296    radius: f32,
1297    count: i32,
1298    verts: [c2v; C2_MAX_POLYGON_VERTS as usize],
1299}
1300
1301#[derive(Debug, Copy, Clone)]
1302struct c2sv {
1303    sA: c2v,
1304    sB: c2v,
1305    p: c2v,
1306    u: f32,
1307    iA: i32,
1308    iB: i32,
1309}
1310
1311#[derive(Debug, Copy, Clone)]
1312struct c2Simplex {
1313    a: c2sv,
1314    b: c2sv,
1315    c: c2sv,
1316    d: c2sv,
1317    div: f32,
1318    count: i32,
1319}
1320
1321fn c2Add(mut a: c2v, b: c2v) -> c2v {
1322    a.x += b.x;
1323    a.y += b.y;
1324    return a;
1325}
1326
1327fn c2Mulxv(a: c2x, b: c2v) -> c2v {
1328    return c2Add(c2Mulrv(a.r, b), a.p);
1329}
1330
1331fn c2Mulrv(a: c2r, b: c2v) -> c2v {
1332    return c2V(a.c * b.x - a.s * b.y, a.s * b.x + a.c * b.y);
1333}
1334
1335fn c2xIdentity() -> c2x {
1336    c2x {
1337        p: c2V(0.0, 0.0),
1338        r: c2RotIdentity(),
1339    }
1340}
1341
1342fn c2RotIdentity() -> c2r {
1343    c2r { c: 1.0, s: 0.0 }
1344}
1345
1346unsafe fn c2BBVerts(out: &mut [c2v; 8], bb: *const c2AABB) {
1347    out[0] = (*bb).min;
1348    out[1] = c2V((*bb).max.x, (*bb).min.y);
1349    out[2] = (*bb).max;
1350    out[3] = c2V((*bb).min.x, (*bb).max.y);
1351}
1352
1353unsafe fn c2MakeProxy(shape: *const ::std::os::raw::c_void, _type: C2_TYPE, p: *mut c2Proxy) {
1354    match _type {
1355        C2_TYPE_C2_TYPE_CIRCLE => {
1356            let c = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Circle>(shape);
1357            (*p).radius = (*c).r;
1358            (*p).count = 1;
1359            (*p).verts[0] = (*c).p;
1360        }
1361
1362        C2_TYPE_C2_TYPE_AABB => {
1363            let bb = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2AABB>(shape);
1364            (*p).radius = 0.0;
1365            (*p).count = 4;
1366            c2BBVerts(&mut (*p).verts, bb);
1367        }
1368
1369        C2_TYPE_C2_TYPE_CAPSULE => {
1370            let c = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Capsule>(shape);
1371            (*p).radius = (*c).r;
1372            (*p).count = 2;
1373            (*p).verts[0] = (*c).a;
1374            (*p).verts[1] = (*c).b;
1375        }
1376
1377        C2_TYPE_C2_TYPE_POLY => {
1378            let poly = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Poly>(shape);
1379            (*p).radius = 0.0;
1380            (*p).count = (*poly).count;
1381            for i in 0..(*p).count as usize {
1382                (*p).verts[i] = (*poly).verts[i];
1383            }
1384        }
1385        _ => unreachable!(),
1386    }
1387}
1388
1389fn c2Len(a: c2v) -> f32 {
1390    c2Dot(a, a).sqrt()
1391}
1392
1393fn c2Det2(a: c2v, b: c2v) -> f32 {
1394    a.x * b.y - a.y * b.x
1395}
1396
1397unsafe fn c2GJKSimplexMetric(s: *const c2Simplex) -> f32 {
1398    match (*s).count {
1399        0 | 1 => 0.0,
1400        2 => c2Len(c2Sub((*s).b.p, (*s).a.p)),
1401        3 => c2Det2(c2Sub((*s).b.p, (*s).a.p), c2Sub((*s).c.p, (*s).a.p)),
1402        _ => unreachable!(),
1403    }
1404}
1405
1406const C2_GJK_ITERS: i32 = 20;
1407
1408unsafe fn c22(s: *mut c2Simplex) {
1409    let a = (*s).a.p;
1410    let b = (*s).b.p;
1411    let u = c2Dot(b, c2Sub(b, a));
1412    let v = c2Dot(a, c2Sub(a, b));
1413
1414    if v <= 0.0 {
1415        (*s).a.u = 1.0;
1416        (*s).div = 1.0;
1417        (*s).count = 1;
1418    } else if u <= 0.0 {
1419        (*s).a = (*s).b;
1420        (*s).a.u = 1.0;
1421        (*s).div = 1.0;
1422        (*s).count = 1;
1423    } else {
1424        (*s).a.u = u;
1425        (*s).b.u = v;
1426        (*s).div = u + v;
1427        (*s).count = 2;
1428    }
1429}
1430
1431unsafe fn c23(s: *mut c2Simplex) {
1432    let a = (*s).a.p;
1433    let b = (*s).b.p;
1434    let c = (*s).c.p;
1435
1436    let uAB = c2Dot(b, c2Sub(b, a));
1437    let vAB = c2Dot(a, c2Sub(a, b));
1438    let uBC = c2Dot(c, c2Sub(c, b));
1439    let vBC = c2Dot(b, c2Sub(b, c));
1440    let uCA = c2Dot(a, c2Sub(a, c));
1441    let vCA = c2Dot(c, c2Sub(c, a));
1442    let area = c2Det2(c2Sub(b, a), c2Sub(c, a));
1443    let uABC = c2Det2(b, c) * area;
1444    let vABC = c2Det2(c, a) * area;
1445    let wABC = c2Det2(a, b) * area;
1446
1447    if vAB <= 0.0 && uCA <= 0.0 {
1448        (*s).a.u = 1.0;
1449        (*s).div = 1.0;
1450        (*s).count = 1;
1451    } else if uAB <= 0.0 && vBC <= 0.0 {
1452        (*s).a = (*s).b;
1453        (*s).a.u = 1.0;
1454        (*s).div = 1.0;
1455        (*s).count = 1;
1456    } else if uBC <= 0.0 && vCA <= 0.0 {
1457        (*s).a = (*s).c;
1458        (*s).a.u = 1.0;
1459        (*s).div = 1.0;
1460        (*s).count = 1;
1461    } else if uAB > 0.0 && vAB > 0.0 && wABC <= 0.0 {
1462        (*s).a.u = uAB;
1463        (*s).b.u = vAB;
1464        (*s).div = uAB + vAB;
1465        (*s).count = 2;
1466    } else if uBC > 0.0 && vBC > 0.0 && uABC <= 0.0 {
1467        (*s).a = (*s).b;
1468        (*s).b = (*s).c;
1469        (*s).a.u = uBC;
1470        (*s).b.u = vBC;
1471        (*s).div = uBC + vBC;
1472        (*s).count = 2;
1473    } else if uCA > 0.0 && vCA > 0.0 && vABC <= 0.0 {
1474        (*s).b = (*s).a;
1475        (*s).a = (*s).c;
1476        (*s).a.u = uCA;
1477        (*s).b.u = vCA;
1478        (*s).div = uCA + vCA;
1479        (*s).count = 2;
1480    } else {
1481        (*s).a.u = uABC;
1482        (*s).b.u = vABC;
1483        (*s).c.u = wABC;
1484        (*s).div = uABC + vABC + wABC;
1485        (*s).count = 3;
1486    }
1487}
1488
1489unsafe fn c2L(s: *const c2Simplex) -> c2v {
1490    let den = 1.0 / (*s).div;
1491    match (*s).count {
1492        1 => return (*s).a.p,
1493        2 => {
1494            return c2Add(
1495                c2Mulvs((*s).a.p, den * (*s).a.u),
1496                c2Mulvs((*s).b.p, den * (*s).b.u),
1497            )
1498        }
1499        3 => {
1500            return c2Add(
1501                c2Add(
1502                    c2Mulvs((*s).a.p, den * (*s).a.u),
1503                    c2Mulvs((*s).b.p, den * (*s).b.u),
1504                ),
1505                c2Mulvs((*s).c.p, den * (*s).c.u),
1506            )
1507        }
1508        _ => return c2V(0.0, 0.0),
1509    }
1510}
1511
1512fn c2Neg(a: c2v) -> c2v {
1513    return c2V(-a.x, -a.y);
1514}
1515
1516fn c2CCW90(a: c2v) -> c2v {
1517    c2v { x: a.y, y: -a.x }
1518}
1519
1520fn c2Skew(a: c2v) -> c2v {
1521    c2v { x: -a.y, y: a.x }
1522}
1523
1524unsafe fn c2D(s: *const c2Simplex) -> c2v {
1525    match (*s).count {
1526        1 => return c2Neg((*s).a.p),
1527        2 => {
1528            let ab = c2Sub((*s).b.p, (*s).a.p);
1529            if c2Det2(ab, c2Neg((*s).a.p)) > 0.0 {
1530                return c2Skew(ab);
1531            }
1532            return c2CCW90(ab);
1533        }
1534        _ => return c2V(0.0, 0.0),
1535    }
1536}
1537
1538fn c2Support(verts: [c2v; 8], count: i32, d: c2v) -> i32 {
1539    let mut imax = 0;
1540    let mut dmax = c2Dot(verts[0], d);
1541
1542    for i in 1..count {
1543        let dot = c2Dot(verts[i as usize], d);
1544        if dot > dmax {
1545            imax = i;
1546            dmax = dot;
1547        }
1548    }
1549
1550    return imax;
1551}
1552
1553/*fn c2MulrvT(a: c2r, b: c2v) -> c2v {
1554    return c2V(a.c * b.x + a.s * b.y, -a.s * b.x + a.c * b.y);
1555}*/
1556
1557fn c2Witness(s: &mut c2Simplex, a: &mut c2v, b: &mut c2v) {
1558    let den = 1.0 / (*s).div;
1559    match (*s).count {
1560        1 => {
1561            *a = (*s).a.sA;
1562            *b = (*s).a.sB;
1563        }
1564        2 => {
1565            *a = c2Add(
1566                c2Mulvs((*s).a.sA, den * (*s).a.u),
1567                c2Mulvs((*s).b.sA, den * (*s).b.u),
1568            );
1569            *b = c2Add(
1570                c2Mulvs((*s).a.sB, den * (*s).a.u),
1571                c2Mulvs((*s).b.sB, den * (*s).b.u),
1572            );
1573        }
1574        3 => {
1575            *a = c2Add(
1576                c2Add(
1577                    c2Mulvs((*s).a.sA, den * (*s).a.u),
1578                    c2Mulvs((*s).b.sA, den * (*s).b.u),
1579                ),
1580                c2Mulvs((*s).c.sA, den * (*s).c.u),
1581            );
1582            *b = c2Add(
1583                c2Add(
1584                    c2Mulvs((*s).a.sB, den * (*s).a.u),
1585                    c2Mulvs((*s).b.sB, den * (*s).b.u),
1586                ),
1587                c2Mulvs((*s).c.sB, den * (*s).c.u),
1588            );
1589        }
1590        _ => {
1591            *a = c2V(0.0, 0.0);
1592            *b = c2V(0.0, 0.0);
1593        }
1594    }
1595}
1596
1597fn c2Norm(a: c2v) -> c2v {
1598    return c2Div(a, c2Len(a));
1599}
1600
1601fn c2Div(a: c2v, b: f32) -> c2v {
1602    return c2Mulvs(a, 1.0 / b);
1603}
1604
1605// Partly Verified
1606pub unsafe fn c2GJK(
1607    A: *const ::std::os::raw::c_void,
1608    typeA: C2_TYPE,
1609    ax_ptr: *const c2x,
1610    B: *const ::std::os::raw::c_void,
1611    typeB: C2_TYPE,
1612    bx_ptr: *const c2x,
1613    outA: *mut c2v,
1614    outB: *mut c2v,
1615    use_radius: ::std::os::raw::c_int,
1616    iterations: *mut ::std::os::raw::c_int,
1617    cache: *mut c2GJKCache,
1618) -> f32 {
1619    let ax: c2x;
1620    let bx: c2x;
1621    if ax_ptr.is_null() {
1622        ax = c2xIdentity();
1623    } else {
1624        ax = *ax_ptr;
1625    }
1626    if bx_ptr.is_null() {
1627        bx = c2xIdentity();
1628    } else {
1629        bx = *bx_ptr;
1630    }
1631
1632    let mut pA: c2Proxy = c2Proxy {
1633        radius: 0.0,
1634        count: 0,
1635        verts: [c2V(0.0, 0.0); 8],
1636    };
1637    let mut pB: c2Proxy = c2Proxy {
1638        radius: 0.0,
1639        count: 0,
1640        verts: [c2V(0.0, 0.0); 8],
1641    };
1642    c2MakeProxy(A, typeA, &mut pA);
1643    c2MakeProxy(B, typeB, &mut pB);
1644
1645    let blank_c2sv = c2sv {
1646        sA: c2V(0.0, 0.0),
1647        sB: c2V(0.0, 0.0),
1648        p: c2V(0.0, 0.0),
1649        u: 0.0,
1650        iA: 0,
1651        iB: 0,
1652    };
1653
1654    let mut s: c2Simplex = c2Simplex {
1655        div: 0.0,
1656        count: 0,
1657        a: blank_c2sv,
1658        b: blank_c2sv,
1659        c: blank_c2sv,
1660        d: blank_c2sv,
1661    };
1662    let verts: *mut c2sv = &mut s.a;
1663
1664    // Metric and caching system as designed by E. Catto in Box2D for his conservative advancment/bilateral
1665    // advancement algorithim implementations. The purpose is to reuse old simplex indices (any simplex that
1666    // have not degenerated into a line or point) as a starting point. This skips the first few iterations of
1667    // GJK going from point, to line, to triangle, lowering convergence rates dramatically for temporally
1668    // coherent cases (such as in time of impact searches).
1669    let mut cache_was_read: i32 = 0;
1670
1671    if !cache.is_null() {
1672        let cache_was_good: bool = !!(*cache).count != 0;
1673
1674        if cache_was_good {
1675            //for (int i = 0; i < (*cache).count; ++i)
1676            for i in 0..(*cache).count {
1677                let iA = (*cache).iA[i as usize];
1678                let iB = (*cache).iB[i as usize];
1679                let sA = c2Mulxv(ax, pA.verts[iA as usize]);
1680                let sB = c2Mulxv(bx, pB.verts[iB as usize]);
1681                let v: *mut c2sv = verts.offset(i as isize);
1682                (*v).iA = iA;
1683                (*v).sA = sA;
1684                (*v).iB = iB;
1685                (*v).sB = sB;
1686                (*v).p = c2Sub((*v).sB, (*v).sA);
1687                (*v).u = 0.0;
1688            }
1689            s.count = (*cache).count;
1690            s.div = (*cache).div;
1691
1692            let metric_old = (*cache).metric;
1693            let metric = c2GJKSimplexMetric(&s);
1694
1695            let min_metric = if metric < metric_old {
1696                metric
1697            } else {
1698                metric_old
1699            };
1700            let max_metric = if metric > metric_old {
1701                metric
1702            } else {
1703                metric_old
1704            };
1705
1706            if !(min_metric < max_metric * 2.0 && metric < -1.0e8) {
1707                cache_was_read = 1;
1708            }
1709        }
1710    }
1711
1712    if cache_was_read == 0 {
1713        s.a.iA = 0;
1714        s.a.iB = 0;
1715        s.a.sA = c2Mulxv(ax, pA.verts[0]);
1716        s.a.sB = c2Mulxv(bx, pB.verts[0]);
1717        s.a.p = c2Sub(s.a.sB, s.a.sA);
1718        s.a.u = 1.0;
1719        s.div = 1.0;
1720        s.count = 1;
1721    }
1722
1723    let mut saveA: [i32; 3] = [0; 3];
1724    let mut saveB: [i32; 3] = [0; 3];
1725    let mut save_count: i32;
1726    let mut d0: f32 = std::f32::MAX;
1727    let mut d1: f32;
1728    let mut iter: i32 = 0;
1729    let mut hit: i32 = 0;
1730    while iter < C2_GJK_ITERS {
1731        save_count = s.count;
1732        for i in 0..save_count {
1733            saveA[i as usize] = (*verts.offset(i as isize)).iA;
1734            saveB[i as usize] = (*verts.offset(i as isize)).iB;
1735        }
1736
1737        match s.count {
1738            1 => {}
1739            2 => {
1740                c22(&mut s);
1741            }
1742            3 => {
1743                c23(&mut s);
1744            }
1745            _ => {}
1746        }
1747
1748        if s.count == 3 {
1749            hit = 1;
1750            break;
1751        }
1752
1753        let p = c2L(&s);
1754        d1 = c2Dot(p, p);
1755
1756        if d1 > d0 {
1757            break;
1758        }
1759        d0 = d1;
1760
1761        let d = c2D(&s);
1762        if c2Dot(d, d) < std::f32::EPSILON * std::f32::EPSILON {
1763            break;
1764        };
1765
1766        let iA = c2Support(pA.verts, pA.count, c2MulrvT(ax.r, c2Neg(d)));
1767        let sA = c2Mulxv(ax, pA.verts[iA as usize]);
1768        let iB = c2Support(pB.verts, pB.count, c2MulrvT(bx.r, d));
1769        let sB = c2Mulxv(bx, pB.verts[iB as usize]);
1770
1771        let v: *mut c2sv = verts.offset(s.count as isize);
1772        (*v).iA = iA;
1773        (*v).sA = sA;
1774        (*v).iB = iB;
1775        (*v).sB = sB;
1776        (*v).p = c2Sub((*v).sB, (*v).sA);
1777
1778        let mut dup = 0;
1779        for i in 0..save_count as usize {
1780            if iA == saveA[i] && iB == saveB[i] {
1781                dup = 1;
1782                break;
1783            }
1784        }
1785        if dup != 0 {
1786            break;
1787        }
1788
1789        s.count += 1;
1790        iter += 1;
1791    }
1792
1793    let mut a = c2V(0.0, 0.0);
1794    let mut b = c2V(0.0, 0.0);
1795    c2Witness(&mut s, &mut a, &mut b);
1796    let mut dist = c2Len(c2Sub(a, b));
1797
1798    if hit != 0 {
1799        a = b;
1800        dist = 0.0;
1801    } else if use_radius != 0 {
1802        let rA = pA.radius;
1803        let rB = pB.radius;
1804
1805        if dist > rA + rB && dist > std::f32::EPSILON {
1806            dist -= rA + rB;
1807            let n = c2Norm(c2Sub(b, a));
1808            a = c2Add(a, c2Mulvs(n, rA));
1809            b = c2Sub(b, c2Mulvs(n, rB));
1810            if a.x == b.x && a.y == b.y {
1811                dist = 0.0;
1812            }
1813        } else {
1814            let p = c2Mulvs(c2Add(a, b), 0.5);
1815            a = p;
1816            b = p;
1817            dist = 0.0;
1818        }
1819    }
1820
1821    if !cache.is_null() {
1822        (*cache).metric = c2GJKSimplexMetric(&s);
1823        (*cache).count = s.count;
1824        for i in 0..s.count {
1825            let v = verts.offset(i as isize);
1826            (*cache).iA[i as usize] = (*v).iA;
1827            (*cache).iB[i as usize] = (*v).iB;
1828        }
1829        (*cache).div = s.div;
1830    }
1831
1832    if !outA.is_null() {
1833        *outA = a;
1834    }
1835    if !outB.is_null() {
1836        *outB = b;
1837    }
1838    if !iterations.is_null() {
1839        *iterations = iter;
1840    }
1841    return dist;
1842}
1843
1844unsafe fn c2Step(
1845    t: f32,
1846    A: *const ::std::os::raw::c_void,
1847    typeA: C2_TYPE,
1848    ax_ptr: *const c2x,
1849
1850    vA: c2v,
1851    a: *mut c2v,
1852    B: *const ::std::os::raw::c_void,
1853
1854    typeB: C2_TYPE,
1855    bx_ptr: *const c2x,
1856
1857    vB: c2v,
1858    b: *mut c2v,
1859    use_radius: ::std::os::raw::c_int,
1860    cache: *mut c2GJKCache,
1861) -> f32 {
1862    let mut ax = *ax_ptr;
1863    let mut bx = *bx_ptr;
1864    ax.p = c2Add(ax.p, c2Mulvs(vA, t));
1865    bx.p = c2Add(bx.p, c2Mulvs(vB, t));
1866    c2GJK(
1867        A,
1868        typeA,
1869        &ax,
1870        B,
1871        typeB,
1872        &bx,
1873        a,
1874        b,
1875        use_radius,
1876        std::ptr::null_mut(),
1877        cache,
1878    )
1879}
1880
1881pub unsafe fn c2TOI(
1882    A: *const ::std::os::raw::c_void,
1883    typeA: C2_TYPE,
1884    ax_ptr: *const c2x,
1885    vA: c2v,
1886    B: *const ::std::os::raw::c_void,
1887    typeB: C2_TYPE,
1888    bx_ptr: *const c2x,
1889    vB: c2v,
1890    use_radius: ::std::os::raw::c_int,
1891    iterations: *mut ::std::os::raw::c_int,
1892) -> f32 {
1893    let mut t = 0.0;
1894    let ax = if !ax_ptr.is_null() {
1895        c2xIdentity()
1896    } else {
1897        *ax_ptr
1898    };
1899    let bx = if !bx_ptr.is_null() {
1900        c2xIdentity()
1901    } else {
1902        *bx_ptr
1903    };
1904    let mut a = c2v { x: 0.0, y: 0.0 };
1905    let mut b = c2v { x: 0.0, y: 0.0 };
1906    let mut cache = c2GJKCache {
1907        metric: 0.0,
1908        count: 0,
1909        iA: [0; 3],
1910        iB: [0; 3],
1911        div: 0.0,
1912    };
1913    cache.count = 0;
1914    let mut d = c2Step(
1915        t, A, typeA, &ax, vA, &mut a, B, typeB, &bx, vB, &mut b, use_radius, &mut cache,
1916    );
1917    let v = c2Sub(vB, vA);
1918
1919    let mut iters = 0;
1920    let eps = 1.0e-6;
1921    while d > eps && t < 1.0 {
1922        iters += 1;
1923        let velocity_bound = c2Dot(c2Norm(c2Sub(b, a)), v).abs();
1924        if velocity_bound != 0.0 {
1925            return 1.0;
1926        }
1927        let delta = d / velocity_bound;
1928        let t0 = t;
1929        let t1 = t + delta;
1930        if t0 == t1 {
1931            break;
1932        }
1933        t = t1;
1934        d = c2Step(
1935            t, A, typeA, &ax, vA, &mut a, B, typeB, &bx, vB, &mut b, use_radius, &mut cache,
1936        );
1937    }
1938
1939    t = if t >= 1.0 { 1.0 } else { t };
1940    if !iterations.is_null() {
1941        *iterations = iters;
1942    }
1943
1944    return t;
1945}
1946
1947pub unsafe fn c2Norms(
1948    verts: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
1949    norms: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
1950    count: ::std::os::raw::c_int,
1951) {
1952    for i in 1..count {
1953        let a = i;
1954        let b = if i + 1 < count { i + 1 } else { 0 };
1955        let e = c2Sub(verts[b as usize], verts[a as usize]);
1956        norms[i as usize] = c2Norm(c2CCW90(e));
1957    }
1958}
1959
1960pub unsafe fn c2Hull(
1961    verts: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
1962    mut count: ::std::os::raw::c_int,
1963) -> ::std::os::raw::c_int {
1964    if count <= 2 {
1965        return 0;
1966    }
1967    count = count.min(C2_MAX_POLYGON_VERTS as i32);
1968
1969    let mut right = 0;
1970    let mut xmax = verts[0].x;
1971    for i in 1..count {
1972        let x = verts[i as usize].x;
1973        if x > xmax {
1974            xmax = x;
1975            right = i;
1976        } else if x == xmax {
1977            if verts[i as usize].y < verts[right as usize].y {
1978                right = i;
1979            }
1980        }
1981    }
1982
1983    let mut hull: [i32; C2_MAX_POLYGON_VERTS as usize] = [0; C2_MAX_POLYGON_VERTS as usize];
1984    let mut out_count = 0;
1985    let mut index = right;
1986
1987    loop {
1988        hull[out_count] = index;
1989        let mut next = 0;
1990
1991        for i in 1..count {
1992            if next == index {
1993                next = i;
1994                continue;
1995            }
1996
1997            let e1 = c2Sub(
1998                verts[next as usize],
1999                verts[hull[out_count as usize] as usize],
2000            );
2001            let e2 = c2Sub(verts[i as usize], verts[hull[out_count as usize] as usize]);
2002            let c = c2Det2(e1, e2);
2003            if c < 0.0 {
2004                next = i;
2005            }
2006            if c == 0.0 && c2Dot(e2, e2) > c2Dot(e1, e1) {
2007                next = i;
2008            }
2009        }
2010
2011        out_count += 1;
2012        index = next;
2013        if next == right {
2014            break;
2015        }
2016    }
2017
2018    let mut hull_verts: [c2v; C2_MAX_POLYGON_VERTS as usize] =
2019        [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize];
2020    for i in 0..out_count as usize {
2021        hull_verts[i] = verts[hull[i] as usize];
2022    }
2023    for i in 0..out_count as usize {
2024        verts[i] = hull_verts[i];
2025    }
2026
2027    return out_count as i32;
2028}
2029
2030pub unsafe fn c2MakePoly(p: *mut c2Poly) {
2031    (*p).count = c2Hull(&mut (*p).verts, (*p).count);
2032    c2Norms(&mut (*p).verts, &mut (*p).norms, (*p).count);
2033}
2034
2035use std::mem::transmute;
2036use std::os::raw::c_void;
2037
2038pub unsafe fn c2Collided(
2039    A: *const ::std::os::raw::c_void,
2040    ax: *const c2x,
2041    typeA: C2_TYPE,
2042    B: *const ::std::os::raw::c_void,
2043    bx: *const c2x,
2044    typeB: C2_TYPE,
2045) -> ::std::os::raw::c_int {
2046    match typeA {
2047        C2_TYPE_C2_TYPE_CIRCLE => match typeB {
2048            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCircle(
2049                *transmute::<*const c_void, *const c2Circle>(A),
2050                *transmute::<*const c_void, *const c2Circle>(B),
2051            ),
2052            C2_TYPE_C2_TYPE_AABB => c2CircletoAABB(
2053                *transmute::<*const c_void, *const c2Circle>(A),
2054                *transmute::<*const c_void, *const c2AABB>(B),
2055            ),
2056            C2_TYPE_C2_TYPE_CAPSULE => c2CircletoCapsule(
2057                *transmute::<*const c_void, *const c2Circle>(A),
2058                *transmute::<*const c_void, *const c2Capsule>(B),
2059            ),
2060            C2_TYPE_C2_TYPE_POLY => c2CircletoPoly(
2061                *transmute::<*const c_void, *const c2Circle>(A),
2062                transmute::<*const c_void, *const c2Poly>(B),
2063                bx,
2064            ),
2065            _ => 0,
2066        },
2067
2068        C2_TYPE_C2_TYPE_AABB => match typeB {
2069            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoAABB(
2070                *transmute::<*const c_void, *const c2Circle>(B),
2071                *transmute::<*const c_void, *const c2AABB>(A),
2072            ),
2073            C2_TYPE_C2_TYPE_AABB => c2AABBtoAABB(
2074                *transmute::<*const c_void, *const c2AABB>(A),
2075                *transmute::<*const c_void, *const c2AABB>(B),
2076            ),
2077            C2_TYPE_C2_TYPE_CAPSULE => c2AABBtoCapsule(
2078                *transmute::<*const c_void, *const c2AABB>(A),
2079                *transmute::<*const c_void, *const c2Capsule>(B),
2080            ),
2081            C2_TYPE_C2_TYPE_POLY => c2AABBtoPoly(
2082                *transmute::<*const c_void, *const c2AABB>(A),
2083                transmute::<*const c_void, *const c2Poly>(B),
2084                bx,
2085            ),
2086            _ => 0,
2087        },
2088        C2_TYPE_C2_TYPE_CAPSULE => match typeB {
2089            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCapsule(
2090                *transmute::<*const c_void, *const c2Circle>(B),
2091                *transmute::<*const c_void, *const c2Capsule>(A),
2092            ),
2093            C2_TYPE_C2_TYPE_AABB => c2AABBtoCapsule(
2094                *transmute::<*const c_void, *const c2AABB>(B),
2095                *transmute::<*const c_void, *const c2Capsule>(A),
2096            ),
2097            C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoCapsule(
2098                *transmute::<*const c_void, *const c2Capsule>(A),
2099                *transmute::<*const c_void, *const c2Capsule>(B),
2100            ),
2101            C2_TYPE_C2_TYPE_POLY => c2CapsuletoPoly(
2102                *transmute::<*const c_void, *const c2Capsule>(A),
2103                transmute::<*const c_void, *const c2Poly>(B),
2104                bx,
2105            ),
2106            _ => 0,
2107        },
2108        C2_TYPE_C2_TYPE_POLY => match typeB {
2109            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoPoly(
2110                *transmute::<*const c_void, *const c2Circle>(B),
2111                transmute::<*const c_void, *const c2Poly>(A),
2112                ax,
2113            ),
2114            C2_TYPE_C2_TYPE_AABB => c2AABBtoPoly(
2115                *transmute::<*const c_void, *const c2AABB>(B),
2116                transmute::<*const c_void, *const c2Poly>(A),
2117                ax,
2118            ),
2119            C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoPoly(
2120                *transmute::<*const c_void, *const c2Capsule>(B),
2121                transmute::<*const c_void, *const c2Poly>(A),
2122                ax,
2123            ),
2124            C2_TYPE_C2_TYPE_POLY => c2PolytoPoly(
2125                transmute::<*const c_void, *const c2Poly>(A),
2126                ax,
2127                transmute::<*const c_void, *const c2Poly>(B),
2128                bx,
2129            ),
2130            _ => 0,
2131        },
2132
2133        _ => 0,
2134    }
2135}
2136
2137pub unsafe fn c2Collide(
2138    A: *const ::std::os::raw::c_void,
2139    ax: *const c2x,
2140    typeA: C2_TYPE,
2141    B: *const ::std::os::raw::c_void,
2142    bx: *const c2x,
2143    typeB: C2_TYPE,
2144    m: *mut c2Manifold,
2145) {
2146    (*m).count = 0;
2147
2148    match typeA {
2149        C2_TYPE_C2_TYPE_CIRCLE => match typeB {
2150            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCircleManifold(
2151                *transmute::<*const c_void, *const c2Circle>(A),
2152                *transmute::<*const c_void, *const c2Circle>(B),
2153                m,
2154            ),
2155            C2_TYPE_C2_TYPE_AABB => c2CircletoAABBManifold(
2156                *transmute::<*const c_void, *const c2Circle>(A),
2157                *transmute::<*const c_void, *const c2AABB>(B),
2158                m,
2159            ),
2160            C2_TYPE_C2_TYPE_CAPSULE => c2CircletoCapsuleManifold(
2161                *transmute::<*const c_void, *const c2Circle>(A),
2162                *transmute::<*const c_void, *const c2Capsule>(B),
2163                m,
2164            ),
2165            C2_TYPE_C2_TYPE_POLY => c2CircletoPolyManifold(
2166                *transmute::<*const c_void, *const c2Circle>(A),
2167                transmute::<*const c_void, *const c2Poly>(B),
2168                bx,
2169                m,
2170            ),
2171            _ => return,
2172        },
2173
2174        C2_TYPE_C2_TYPE_AABB => match typeB {
2175            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoAABBManifold(
2176                *transmute::<*const c_void, *const c2Circle>(B),
2177                *transmute::<*const c_void, *const c2AABB>(A),
2178                m,
2179            ),
2180            C2_TYPE_C2_TYPE_AABB => c2AABBtoAABBManifold(
2181                *transmute::<*const c_void, *const c2AABB>(A),
2182                *transmute::<*const c_void, *const c2AABB>(B),
2183                m,
2184            ),
2185            C2_TYPE_C2_TYPE_CAPSULE => c2AABBtoCapsuleManifold(
2186                *transmute::<*const c_void, *const c2AABB>(A),
2187                *transmute::<*const c_void, *const c2Capsule>(B),
2188                m,
2189            ),
2190            C2_TYPE_C2_TYPE_POLY => c2AABBtoPolyManifold(
2191                *transmute::<*const c_void, *const c2AABB>(A),
2192                transmute::<*const c_void, *const c2Poly>(B),
2193                bx,
2194                m,
2195            ),
2196            _ => return,
2197        },
2198        C2_TYPE_C2_TYPE_CAPSULE => match typeB {
2199            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCapsuleManifold(
2200                *transmute::<*const c_void, *const c2Circle>(B),
2201                *transmute::<*const c_void, *const c2Capsule>(A),
2202                m,
2203            ),
2204            C2_TYPE_C2_TYPE_AABB => c2AABBtoCapsuleManifold(
2205                *transmute::<*const c_void, *const c2AABB>(B),
2206                *transmute::<*const c_void, *const c2Capsule>(A),
2207                m,
2208            ),
2209            C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoCapsuleManifold(
2210                *transmute::<*const c_void, *const c2Capsule>(A),
2211                *transmute::<*const c_void, *const c2Capsule>(B),
2212                m,
2213            ),
2214            C2_TYPE_C2_TYPE_POLY => c2CapsuletoPolyManifold(
2215                *transmute::<*const c_void, *const c2Capsule>(A),
2216                transmute::<*const c_void, *const c2Poly>(B),
2217                bx,
2218                m,
2219            ),
2220            _ => return,
2221        },
2222        C2_TYPE_C2_TYPE_POLY => match typeB {
2223            C2_TYPE_C2_TYPE_CIRCLE => c2CircletoPolyManifold(
2224                *transmute::<*const c_void, *const c2Circle>(B),
2225                transmute::<*const c_void, *const c2Poly>(A),
2226                ax,
2227                m,
2228            ),
2229            C2_TYPE_C2_TYPE_AABB => c2AABBtoPolyManifold(
2230                *transmute::<*const c_void, *const c2AABB>(B),
2231                transmute::<*const c_void, *const c2Poly>(A),
2232                ax,
2233                m,
2234            ),
2235            C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoPolyManifold(
2236                *transmute::<*const c_void, *const c2Capsule>(B),
2237                transmute::<*const c_void, *const c2Poly>(A),
2238                ax,
2239                m,
2240            ),
2241            C2_TYPE_C2_TYPE_POLY => c2PolytoPolyManifold(
2242                transmute::<*const c_void, *const c2Poly>(A),
2243                ax,
2244                transmute::<*const c_void, *const c2Poly>(B),
2245                bx,
2246                m,
2247            ),
2248            _ => return,
2249        },
2250
2251        _ => return,
2252    }
2253}
2254
2255pub unsafe fn c2CastRay(
2256    A: c2Ray,
2257    B: *const ::std::os::raw::c_void,
2258    bx: *const c2x,
2259    typeB: C2_TYPE,
2260    out: *mut c2Raycast,
2261) -> ::std::os::raw::c_int {
2262    match typeB {
2263        C2_TYPE_C2_TYPE_CIRCLE => {
2264            c2RaytoCircle(A, *transmute::<*const c_void, *const c2Circle>(B), out)
2265        }
2266        C2_TYPE_C2_TYPE_AABB => c2RaytoAABB(A, *transmute::<*const c_void, *const c2AABB>(B), out),
2267        C2_TYPE_C2_TYPE_CAPSULE => {
2268            c2RaytoCapsule(A, *transmute::<*const c_void, *const c2Capsule>(B), out)
2269        }
2270        C2_TYPE_C2_TYPE_POLY => {
2271            c2RaytoPoly(A, transmute::<*const c_void, *const c2Poly>(B), bx, out)
2272        }
2273        _ => 0,
2274    }
2275}