#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub const C2_MAX_POLYGON_VERTS: u32 = 8;
#[derive(Debug, Copy, Clone)]
pub struct c2v {
pub x: f32,
pub y: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2r {
pub c: f32,
pub s: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2m {
pub x: c2v,
pub y: c2v,
}
#[derive(Debug, Copy, Clone)]
pub struct c2x {
pub p: c2v,
pub r: c2r,
}
#[derive(Debug, Copy, Clone)]
pub struct c2h {
pub n: c2v,
pub d: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2Circle {
pub p: c2v,
pub r: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2AABB {
pub min: c2v,
pub max: c2v,
}
#[derive(Debug, Copy, Clone)]
pub struct c2Capsule {
pub a: c2v,
pub b: c2v,
pub r: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2Poly {
pub count: ::std::os::raw::c_int,
pub verts: [c2v; 8usize],
pub norms: [c2v; 8usize],
}
#[derive(Debug, Copy, Clone)]
pub struct c2Ray {
pub p: c2v,
pub d: c2v,
pub t: f32,
}
#[derive(Debug, Copy, Clone)]
pub struct c2Raycast {
pub t: f32,
pub n: c2v,
}
#[derive(Debug, Copy, Clone)]
pub struct c2Manifold {
pub count: ::std::os::raw::c_int,
pub depths: [f32; 2usize],
pub contact_points: [c2v; 2usize],
pub n: c2v,
}
fn c2Sub(mut a: c2v, b: c2v) -> c2v {
a.x -= b.x;
a.y -= b.y;
a
}
fn c2Dot(a: c2v, b: c2v) -> f32 {
a.x * b.x + a.y * b.y
}
pub unsafe fn c2CircletoCircle(A: c2Circle, B: c2Circle) -> ::std::os::raw::c_int {
let c: c2v = c2Sub(B.p, A.p);
let d2: f32 = c2Dot(c, c);
let mut r2: f32 = A.r + B.r;
r2 = r2 * r2;
if d2 < r2 {
1
} else {
0
}
}
fn c2V(x: f32, y: f32) -> c2v {
c2v { x, y }
}
fn c2Minv(a: c2v, b: c2v) -> c2v {
c2V(a.x.min(b.x), a.y.min(b.y))
}
fn c2Maxv(a: c2v, b: c2v) -> c2v {
c2V(a.x.max(b.x), a.y.max(b.y))
}
fn c2Clampv(a: c2v, lo: c2v, hi: c2v) -> c2v {
c2Maxv(lo, c2Minv(a, hi))
}
pub unsafe fn c2CircletoAABB(A: c2Circle, B: c2AABB) -> ::std::os::raw::c_int {
let L: c2v = c2Clampv(A.p, B.min, B.max);
let ab: c2v = c2Sub(A.p, L);
let d2: f32 = c2Dot(ab, ab);
let r2: f32 = A.r * A.r;
if d2 < r2 {
1
} else {
0
}
}
fn c2Mulvs(mut a: c2v, b: f32) -> c2v {
a.x *= b;
a.y *= b;
a
}
pub unsafe fn c2CircletoCapsule(A: c2Circle, B: c2Capsule) -> ::std::os::raw::c_int {
let n: c2v = c2Sub(B.b, B.a);
let ap = c2Sub(A.p, B.a);
let da = c2Dot(ap, n);
let d2: f32;
if da < 0.0 {
d2 = c2Dot(ap, ap);
} else {
let db = c2Dot(c2Sub(A.p, B.b), n);
if db < 0.0 {
let e = c2Sub(ap, c2Mulvs(n, da / c2Dot(n, n)));
d2 = c2Dot(e, e);
} else {
let bp = c2Sub(A.p, B.b);
d2 = c2Dot(bp, bp);
}
}
let r = A.r + B.r;
if d2 < r * r {
1
} else {
0
}
}
pub unsafe fn c2AABBtoAABB(A: c2AABB, B: c2AABB) -> ::std::os::raw::c_int {
let d0 = B.max.x < A.min.x;
let d1 = A.max.x < B.min.x;
let d2 = B.max.y < A.min.y;
let d3 = A.max.y < B.min.y;
if !(d0 | d1 | d2 | d3) {
1
} else {
0
}
}
fn c2AABBtoPoint(A: c2AABB, B: c2v) -> ::std::os::raw::c_int {
let d0 = B.x < A.min.x;
let d1 = B.y < A.min.y;
let d2 = B.x > A.max.x;
let d3 = B.y > A.max.y;
if !(d0 | d1 | d2 | d3) {
1
} else {
0
}
}
fn c2CircleToPoint(A: c2Circle, B: c2v) -> ::std::os::raw::c_int {
let n = c2Sub(A.p, B);
let d2 = c2Dot(n, n);
if d2 < A.r * A.r {
1
} else {
0
}
}
pub unsafe fn c2AABBtoCapsule(A: c2AABB, B: c2Capsule) -> ::std::os::raw::c_int {
if c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_AABB,
std::ptr::null(),
&B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null(),
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
pub unsafe fn c2CapsuletoCapsule(A: c2Capsule, B: c2Capsule) -> ::std::os::raw::c_int {
if c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null(),
&B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null(),
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
pub unsafe fn c2CircletoPoly(
A: c2Circle,
B: *const c2Poly,
bx: *const c2x,
) -> ::std::os::raw::c_int {
if c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CIRCLE,
std::ptr::null(),
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx,
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
pub unsafe fn c2AABBtoPoly(A: c2AABB, B: *const c2Poly, bx: *const c2x) -> ::std::os::raw::c_int {
if c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_AABB,
std::ptr::null(),
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx,
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
pub unsafe fn c2CapsuletoPoly(
A: c2Capsule,
B: *const c2Poly,
bx: *const c2x,
) -> ::std::os::raw::c_int {
if c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null(),
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx,
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
pub unsafe fn c2PolytoPoly(
A: *const c2Poly,
ax: *const c2x,
B: *const c2Poly,
bx: *const c2x,
) -> ::std::os::raw::c_int {
if c2GJK(
A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
ax,
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx,
std::ptr::null_mut(),
std::ptr::null_mut(),
1,
std::ptr::null_mut(),
std::ptr::null_mut(),
) != 0.0
{
return 0;
}
return 1;
}
fn c2Impact(ray: c2Ray, t: f32) -> c2v {
c2Add(ray.p, c2Mulvs(ray.d, t))
}
pub unsafe fn c2RaytoCircle(A: c2Ray, B: c2Circle, out: *mut c2Raycast) -> ::std::os::raw::c_int {
let p = B.p;
let m = c2Sub(A.p, p);
let c = c2Dot(m, m) - B.r * B.r;
let b = c2Dot(m, A.d);
let disc = b * b - c;
if disc < 0.0 {
return 0;
}
let t = -b - disc.sqrt();
if t >= 0.0 && t <= A.t {
(*out).t = t;
let impact = c2Impact(A, t);
(*out).n = c2Norm(c2Sub(impact, p));
return 1;
}
return 0;
}
pub unsafe fn c2RaytoAABB(A: c2Ray, B: c2AABB, out: *mut c2Raycast) -> ::std::os::raw::c_int {
let p0 = A.p;
let p1 = c2Impact(A, A.t);
let a_box = c2AABB {
min: c2Minv(p0, p1),
max: c2Maxv(p0, p1),
};
if c2AABBtoAABB(a_box, B) == 0 {
return 0;
}
let ab = c2Sub(p1, p0);
let n = c2Skew(ab);
let abs_n = c2Absv(n);
let half_extents = c2Mulvs(c2Sub(B.max, B.min), 0.5);
let center_of_b_box = c2Mulvs(c2Add(B.min, B.max), 0.5);
let d = c2Dot(n, c2Sub(p0, center_of_b_box)).abs() - c2Dot(abs_n, half_extents);
if d > 0.0 {
return 0;
}
let da0 = c2SignedDistPointToPlane_OneDimensional(p0.x, -1.0, B.min.x);
let db0 = c2SignedDistPointToPlane_OneDimensional(p1.x, -1.0, B.min.x);
let da1 = c2SignedDistPointToPlane_OneDimensional(p0.x, 1.0, B.max.x);
let db1 = c2SignedDistPointToPlane_OneDimensional(p1.x, 1.0, B.max.x);
let da2 = c2SignedDistPointToPlane_OneDimensional(p0.y, -1.0, B.min.y);
let db2 = c2SignedDistPointToPlane_OneDimensional(p1.y, -1.0, B.min.y);
let da3 = c2SignedDistPointToPlane_OneDimensional(p0.y, 1.0, B.max.y);
let db3 = c2SignedDistPointToPlane_OneDimensional(p1.y, 1.0, B.max.y);
let mut t0 = c2RayToPlane_OneDimensional(da0, db0);
let mut t1 = c2RayToPlane_OneDimensional(da1, db1);
let mut t2 = c2RayToPlane_OneDimensional(da2, db2);
let mut t3 = c2RayToPlane_OneDimensional(da3, db3);
let hit0 = t0 < 1.0;
let hit1 = t1 < 1.0;
let hit2 = t2 < 1.0;
let hit3 = t3 < 1.0;
let hit = hit0 | hit1 | hit2 | hit3;
if hit {
t0 = hit0 as i32 as f32 * t0;
t1 = hit1 as i32 as f32 * t1;
t2 = hit2 as i32 as f32 * t2;
t3 = hit3 as i32 as f32 * t3;
if t0 >= t1 && t0 >= t2 && t0 >= t3 {
(*out).t = t0 * A.t;
(*out).n = c2V(-1.0, 0.0);
} else if t1 >= t0 && t1 >= t2 && t1 >= t3 {
(*out).t = t1 * A.t;
(*out).n = c2V(1.0, 0.0);
} else if t2 >= t0 && t2 >= t1 && t2 >= t3 {
(*out).t = t2 * A.t;
(*out).n = c2V(0.0, -1.0);
} else {
(*out).t = t3 * A.t;
(*out).n = c2V(0.0, 1.0);
}
return 1;
} else {
return 0;
} }
fn c2SignedDistPointToPlane_OneDimensional(p: f32, n: f32, d: f32) -> f32 {
p * n - d * n
}
fn c2RayToPlane_OneDimensional(da: f32, db: f32) -> f32 {
if da < 0.0 {
return 0.0;
}
else if da * db >= 0.0 {
return 1.0;
}
else
{
let d = da - db;
if d != 0.0 {
return da / d;
} else {
return 0.0;
}
}
}
fn c2MulmvT(a: c2m, b: c2v) -> c2v {
c2v {
x: a.x.x * b.x + a.x.y * b.y,
y: a.y.x * b.x + a.y.y * b.y,
}
}
pub unsafe fn c2RaytoCapsule(A: c2Ray, B: c2Capsule, out: *mut c2Raycast) -> ::std::os::raw::c_int {
let M = {
let y = c2Norm(c2Sub(B.b, B.a));
c2m { x: c2CCW90(y), y }
};
let cap_n = c2Sub(B.b, B.a);
let yBb = c2MulmvT(M, cap_n);
let yAp = c2MulmvT(M, c2Sub(A.p, B.a));
let yAd = c2MulmvT(M, A.d);
let yAe = c2Add(yAp, c2Mulvs(yAd, A.t));
let capsule_bb = c2AABB {
min: c2V(-B.r, 0.0),
max: c2V(B.r, yBb.y),
};
(*out).n = c2Norm(cap_n);
(*out).t = 0.0;
if c2AABBtoPoint(capsule_bb, yAp) != 0 {
return 1;
} else {
let capsule_a = c2Circle { p: B.a, r: B.r };
let capsule_b = c2Circle { p: B.b, r: B.r };
if c2CircleToPoint(capsule_a, A.p) != 0 {
return 1;
} else if c2CircleToPoint(capsule_b, A.p) != 0 {
return 1;
}
}
if yAe.x * yAp.x < 0.0 || yAe.x.abs().min(yAp.x.abs()) < B.r {
let Ca = c2Circle { p: B.a, r: B.r };
let Cb = c2Circle { p: B.b, r: B.r };
if yAp.x.abs() < B.r {
if yAp.y < 0.0 {
return c2RaytoCircle(A, Ca, out);
} else {
return c2RaytoCircle(A, Cb, out);
}
}
else {
let c = if yAp.x > 0.0 { B.r } else { -B.r };
let d = yAe.x - yAp.x;
let t = (c - yAp.x) / d;
let y = yAp.y + (yAe.y - yAp.y) * t;
if y <= 0.0 {
return c2RaytoCircle(A, Ca, out);
}
if y >= yBb.y {
return c2RaytoCircle(A, Cb, out);
} else {
(*out).n = if c > 0.0 { M.x } else { c2Skew(M.y) };
(*out).t = t * A.t;
return 1;
}
}
}
return 0;
}
pub unsafe fn c2RaytoPoly(
A: c2Ray,
B: *const c2Poly,
bx_ptr: *const c2x,
out: *mut c2Raycast,
) -> ::std::os::raw::c_int {
let bx = if !bx_ptr.is_null() {
*bx_ptr
} else {
c2xIdentity()
};
let p = c2MulxvT(bx, A.p);
let d = c2MulrvT(bx.r, A.d);
let mut lo = 0.0;
let mut hi = A.t;
let mut index = !0;
for i in 0..(*B).count as usize {
let num = c2Dot((*B).norms[i], c2Sub((*B).verts[i], p));
let den = c2Dot((*B).norms[i], d);
if den == 0.0 && num < 0.0 {
return 0;
} else {
if den < 0.0 && num < lo * den {
lo = num / den;
index = i;
} else if den > 0.0 && num < hi * den {
hi = num / den;
}
}
if hi < lo {
return 0;
}
}
if index != !0 {
(*out).t = lo;
(*out).n = c2Mulrv(bx.r, (*B).norms[index]);
return 1;
}
return 0;
}
pub unsafe fn c2CircletoCircleManifold(A: c2Circle, B: c2Circle, m: *mut c2Manifold) {
(*m).count = 0;
let d = c2Sub(B.p, A.p);
let d2 = c2Dot(d, d);
let r = A.r + B.r;
if d2 < r * r {
let l = d2.sqrt();
let n = if l != 0.0 {
c2Mulvs(d, 1.0 / l)
} else {
c2V(0.0, 1.0)
};
(*m).count = 1;
(*m).depths[0] = r - l;
(*m).contact_points[0] = c2Sub(B.p, c2Mulvs(n, B.r));
(*m).n = n;
}
}
fn c2Absv(a: c2v) -> c2v {
return c2V(a.x.abs(), a.y.abs());
}
pub unsafe fn c2CircletoAABBManifold(A: c2Circle, B: c2AABB, m: *mut c2Manifold) {
(*m).count = 0;
let L = c2Clampv(A.p, B.min, B.max);
let ab = c2Sub(L, A.p);
let d2 = c2Dot(ab, ab);
let r2 = A.r * A.r;
if d2 < r2 {
if d2 != 0.0 {
let d = d2.sqrt();
let n = c2Norm(ab);
(*m).count = 1;
(*m).depths[0] = A.r - d;
(*m).contact_points[0] = c2Add(A.p, c2Mulvs(n, d));
(*m).n = n;
}
else {
let mid = c2Mulvs(c2Add(B.min, B.max), 0.5);
let e = c2Mulvs(c2Sub(B.max, B.min), 0.5);
let d = c2Sub(A.p, mid);
let abs_d = c2Absv(d);
let x_overlap = e.x - abs_d.x;
let y_overlap = e.y - abs_d.y;
let depth;
let mut n;
if x_overlap < y_overlap {
depth = x_overlap;
n = c2V(1.0, 0.0);
n = c2Mulvs(n, if d.x < 0.0 { 1.0 } else { -1.0 });
} else {
depth = y_overlap;
n = c2V(0.0, 1.0);
n = c2Mulvs(n, if d.y < 0.0 { 1.0 } else { -1.0 });
}
(*m).count = 1;
(*m).depths[0] = A.r + depth;
(*m).contact_points[0] = c2Sub(A.p, c2Mulvs(n, depth));
(*m).n = n;
}
}
}
pub unsafe fn c2CircletoCapsuleManifold(A: c2Circle, B: c2Capsule, m: *mut c2Manifold) {
(*m).count = 0;
let mut a = c2V(0.0, 0.0);
let mut b = c2V(0.0, 0.0);
let r = A.r + B.r;
let d = c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CIRCLE,
std::ptr::null_mut(),
&B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null_mut(),
&mut a,
&mut b,
0,
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if d < r {
let n;
if d == 0.0 {
n = c2Norm(c2Skew(c2Sub(B.b, B.a)));
} else {
n = c2Norm(c2Sub(b, a));
}
(*m).count = 1;
(*m).depths[0] = r - d;
(*m).contact_points[0] = c2Sub(b, c2Mulvs(n, B.r));
(*m).n = n;
}
}
pub unsafe fn c2AABBtoAABBManifold(A: c2AABB, B: c2AABB, m: *mut c2Manifold) {
(*m).count = 0;
let mid_a = c2Mulvs(c2Add(A.min, A.max), 0.5);
let mid_b = c2Mulvs(c2Add(B.min, B.max), 0.5);
let eA = c2Absv(c2Mulvs(c2Sub(A.max, A.min), 0.5));
let eB = c2Absv(c2Mulvs(c2Sub(B.max, B.min), 0.5));
let d = c2Sub(mid_b, mid_a);
let dx = eA.x + eB.x - d.x.abs();
if dx < 0.0 {
return;
}
let dy = eA.y + eB.y - d.y.abs();
if dy < 0.0 {
return;
}
let n;
let depth;
let p;
if dx < dy {
depth = dx;
if d.x < 0.0 {
n = c2V(-1.0, 0.0);
p = c2Sub(mid_a, c2V(eA.x, 0.0));
} else {
n = c2V(1.0, 0.0);
p = c2Add(mid_a, c2V(eA.x, 0.0));
}
}
else {
depth = dy;
if d.y < 0.0 {
n = c2V(0.0, -1.0);
p = c2Sub(mid_a, c2V(0.0, eA.y));
} else {
n = c2V(0.0, 1.0);
p = c2Add(mid_a, c2V(0.0, eA.y));
}
}
(*m).count = 1;
(*m).contact_points[0] = p;
(*m).depths[0] = depth;
(*m).n = n;
}
pub unsafe fn c2AABBtoCapsuleManifold(A: c2AABB, B: c2Capsule, m: *mut c2Manifold) {
(*m).count = 0;
let mut p = c2Poly {
count: 0,
verts: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
norms: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
};
c2BBVerts(&mut p.verts, &A);
p.count = 4;
c2Norms(&mut p.verts, &mut p.norms, 4);
c2CapsuletoPolyManifold(B, &p, std::ptr::null(), m);
(*m).n = c2Neg((*m).n);
}
pub unsafe fn c2CapsuletoCapsuleManifold(A: c2Capsule, B: c2Capsule, m: *mut c2Manifold) {
{
(*m).count = 0;
let mut a = c2V(0.0, 0.0);
let mut b = c2V(0.0, 0.0);
let r = A.r + B.r;
let d = c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null_mut(),
&B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null_mut(),
&mut a,
&mut b,
0,
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if d < r {
let n;
if d == 0.0 {
n = c2Norm(c2Skew(c2Sub(A.b, A.a)));
} else {
n = c2Norm(c2Sub(b, a));
}
(*m).count = 1;
(*m).depths[0] = r - d;
(*m).contact_points[0] = c2Sub(b, c2Mulvs(n, B.r));
(*m).n = n;
}
}
}
fn c2MulxvT(a: c2x, b: c2v) -> c2v {
return c2MulrvT(a.r, c2Sub(b, a.p));
}
fn c2MulrvT(a: c2r, b: c2v) -> c2v {
return c2V(a.c * b.x + a.s * b.y, -a.s * b.x + a.c * b.y);
}
unsafe fn c2PlaneAt(p: *const c2Poly, i: i32) -> c2h {
c2h {
n: (*p).norms[i as usize],
d: c2Dot((*p).norms[i as usize], (*p).verts[i as usize]),
}
}
fn c2Dist(h: c2h, p: c2v) -> f32 {
return c2Dot(h.n, p) - h.d;
}
fn c2Project(h: c2h, p: c2v) -> c2v {
return c2Sub(p, c2Mulvs(h.n, c2Dist(h, p)));
}
pub unsafe fn c2CircletoPolyManifold(
A: c2Circle,
B: *const c2Poly,
bx_tr: *const c2x,
m: *mut c2Manifold,
) {
(*m).count = 0;
let mut a = c2V(0.0, 0.0);
let mut b = c2V(0.0, 0.0);
let mut d = c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CIRCLE,
std::ptr::null_mut(),
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx_tr,
&mut a,
&mut b,
0,
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if d != 0.0 {
let n = c2Sub(b, a);
let mut l = c2Dot(n, n);
if l < A.r * A.r {
l = l.sqrt();
(*m).count = 1;
(*m).contact_points[0] = b;
(*m).depths[0] = A.r - l;
(*m).n = c2Mulvs(n, 1.0 / l);
}
}
else {
let bx = if !bx_tr.is_null() {
*bx_tr
} else {
c2xIdentity()
};
let mut sep = -std::f32::MAX;
let mut index = !0;
let local = c2MulxvT(bx, A.p);
for i in 0..(*B).count {
{
let h = c2PlaneAt(B, i);
d = c2Dist(h, local);
if d > A.r {
return;
}
if d > sep {
sep = d;
index = i;
}
}
let h = c2PlaneAt(B, index);
let p = c2Project(h, local);
(*m).count = 1;
(*m).contact_points[0] = c2Mulxv(bx, p);
(*m).depths[0] = A.r - sep;
(*m).n = c2Neg(c2Mulrv(bx.r, (*B).norms[index as usize]));
}
}
}
pub unsafe fn c2AABBtoPolyManifold(
A: c2AABB,
B: *const c2Poly,
bx: *const c2x,
m: *mut c2Manifold,
) {
(*m).count = 0;
let mut p = c2Poly {
count: 0,
verts: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
norms: [c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize],
};
c2BBVerts(&mut p.verts, &A);
p.count = 4;
c2Norms(&mut p.verts, &mut p.norms, 4);
c2PolytoPolyManifold(&p, std::ptr::null(), B, bx, m);
}
unsafe fn c2SidePlanesFromPoly(
seg: &mut [c2v; 2],
x: c2x,
p: *const c2Poly,
e: i32,
h: *mut c2h,
) -> i32 {
let ra = c2Mulxv(x, (*p).verts[e as usize]);
let rb = c2Mulxv(
x,
(*p).verts[if e + 1 == if (*p).count != 0 { 0 } else { e + 1 } {
1
} else {
0
}],
);
return c2SidePlanes(seg, ra, rb, h);
}
unsafe fn c2Clip(seg: &mut [c2v; 2], h: c2h) -> i32 {
let mut out: [c2v; 2] = [c2V(0.0, 0.0); 2];
let mut sp = 0;
let d0: f32;
let d1: f32;
d0 = c2Dist(h, seg[0]);
if (d0) < 0.0 {
out[sp] = seg[0];
sp += 1;
}
d1 = c2Dist(h, seg[1]);
if (d1) < 0.0 {
out[sp] = seg[1];
sp += 1
}
if d0 == 0.0 && d1 == 0.0 {
out[sp] = seg[0];
sp += 1;
out[sp] = seg[1];
sp += 1;
} else if d0 * d1 <= 0.0 {
out[sp] = c2Intersect(seg[0], seg[1], d0, d1);
sp += 1;
}
seg[0] = out[0];
seg[1] = out[1];
return sp as i32;
}
fn c2Intersect(a: c2v, b: c2v, da: f32, db: f32) -> c2v {
return c2Add(a, c2Mulvs(c2Sub(b, a), da / (da - db)));
}
unsafe fn c2SidePlanes(seg: &mut [c2v; 2], ra: c2v, rb: c2v, h: *mut c2h) -> i32 {
let _in = c2Norm(c2Sub(rb, ra));
let left = c2h {
n: c2Neg(_in),
d: c2Dot(c2Neg(_in), ra),
};
let right = c2h {
n: _in,
d: c2Dot(_in, rb),
};
if c2Clip(seg, left) < 2 {
return 0;
}
if c2Clip(seg, right) < 2 {
return 0;
}
if !h.is_null() {
(*h).n = c2CCW90(_in);
(*h).d = c2Dot(c2CCW90(_in), ra);
}
return 1;
}
unsafe fn c2KeepDeep(seg: &mut [c2v; 2], h: c2h, m: *mut c2Manifold) {
let mut cp = 0;
for i in 0..2 {
let p = seg[i];
let d = c2Dist(h, p);
if d <= 0.0 {
(*m).contact_points[cp] = p;
(*m).depths[cp] = -d;
cp += 1;
}
}
(*m).count = cp as i32;
(*m).n = h.n;
}
unsafe fn c2Incident(
incident: &mut [c2v; 2],
ip: *const c2Poly,
ix: c2x,
rn_in_incident_space: c2v,
) {
let mut index: i32 = !0;
let mut min_dot = std::f32::MAX;
for i in 0..(*ip).count {
let dot = c2Dot(rn_in_incident_space, (*ip).norms[i as usize]);
if dot < min_dot {
min_dot = dot;
index = i;
}
}
incident[0] = c2Mulxv(ix, (*ip).verts[index as usize]);
incident[1] = c2Mulxv(
ix,
(*ip).verts[(index + 1 == if (*ip).count != 0 { 0 } else { index + 1 }) as usize],
);
}
pub unsafe fn c2CapsuletoPolyManifold(
A: c2Capsule,
B: *const c2Poly,
bx_ptr: *const c2x,
m: *mut c2Manifold,
) {
(*m).count = 0;
let mut a = c2V(0.0, 0.0);
let mut b = c2V(0.0, 0.0);
let d = c2GJK(
&A as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_CAPSULE,
std::ptr::null_mut(),
B as *const _ as *const std::os::raw::c_void,
C2_TYPE_C2_TYPE_POLY,
bx_ptr,
&mut a,
&mut b,
0,
std::ptr::null_mut(),
std::ptr::null_mut(),
);
if d < 1.0e-6 {
let bx = if !bx_ptr.is_null() {
*bx_ptr
} else {
c2xIdentity()
};
let mut A_in_B = c2Capsule {
a: c2V(0.0, 0.0),
b: c2V(0.0, 0.0),
r: 0.0,
};
A_in_B.a = c2MulxvT(bx, A.a);
A_in_B.b = c2MulxvT(bx, A.b);
let ab = c2Norm(c2Sub(A_in_B.a, A_in_B.b));
let mut ab_h0 = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
ab_h0.n = c2CCW90(ab);
ab_h0.d = c2Dot(A_in_B.a, ab_h0.n);
let v0 = c2Support((*B).verts, (*B).count, c2Neg(ab_h0.n));
let s0 = c2Dist(ab_h0, (*B).verts[v0 as usize]);
let mut ab_h1 = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
ab_h1.n = c2Skew(ab);
ab_h1.d = c2Dot(A_in_B.a, ab_h1.n);
let v1 = c2Support((*B).verts, (*B).count, c2Neg(ab_h1.n));
let s1 = c2Dist(ab_h1, (*B).verts[v1 as usize]);
let mut index = !0;
let mut sep = -std::f32::MAX;
let mut code = 0;
for i in 0..(*B).count {
let h = c2PlaneAt(B, i);
let da = c2Dot(A_in_B.a, c2Neg(h.n));
let db = c2Dot(A_in_B.b, c2Neg(h.n));
let d;
if da > db {
d = c2Dist(h, A_in_B.a);
} else {
d = c2Dist(h, A_in_B.b);
}
if d > sep {
sep = d;
index = i;
}
}
if s0 > sep {
sep = s0;
index = v0;
code = 1;
}
if s1 > sep {
index = v1;
code = 2;
}
match code {
0 => {
let mut seg: [c2v; 2] = [A.a, A.b];
let mut h = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
if c2SidePlanesFromPoly(&mut seg, bx, B, index, &mut h) == 0 {
return;
}
c2KeepDeep(&mut seg, h, m);
(*m).n = c2Neg((*m).n);
}
1 =>
{
let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
c2Incident(&mut incident, B, bx, ab_h0.n);
let mut h = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
if c2SidePlanes(&mut incident, A_in_B.b, A_in_B.a, &mut h) == 0 {
return;
}
c2KeepDeep(&mut incident, h, m);
}
2 =>
{
let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
c2Incident(&mut incident, B, bx, ab_h1.n);
let mut h = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
if c2SidePlanes(&mut incident, A_in_B.a, A_in_B.b, &mut h) == 0 {
return;
}
c2KeepDeep(&mut incident, h, m);
}
_ => {
return;
}
}
for i in 0..(*m).count {
(*m).depths[i as usize] += A.r;
}
}
else if d < A.r {
(*m).count = 1;
(*m).n = c2Norm(c2Sub(b, a));
(*m).contact_points[0] = c2Add(a, c2Mulvs((*m).n, A.r));
(*m).depths[0] = A.r - d;
}
}
fn c2MulrrT(a: c2r, b: c2r) -> c2r {
c2r {
c: a.c * b.c + a.s * b.s,
s: a.c * b.s - a.s * b.c,
}
}
fn c2MulxxT(a: c2x, b: c2x) -> c2x {
c2x {
r: c2MulrrT(a.r, b.r),
p: c2MulrvT(a.r, c2Sub(b.p, a.p)),
}
}
unsafe fn c2CheckFaces(
A: *const c2Poly,
ax: c2x,
B: *const c2Poly,
bx: c2x,
face_index: &mut i32,
) -> f32 {
let b_in_a = c2MulxxT(ax, bx);
let a_in_b = c2MulxxT(bx, ax);
let mut sep = -std::f32::MAX;
let mut index = !0;
for i in 0..(*A).count {
let h = c2PlaneAt(A, i);
let idx = c2Support((*B).verts, (*B).count, c2Mulrv(a_in_b.r, c2Neg(h.n)));
let p = c2Mulxv(b_in_a, (*B).verts[idx as usize]);
let d = c2Dist(h, p);
if d > sep {
sep = d;
index = i;
}
}
*face_index = index;
return sep;
}
pub unsafe fn c2PolytoPolyManifold(
A: *const c2Poly,
ax_ptr: *const c2x,
B: *const c2Poly,
bx_ptr: *const c2x,
m: *mut c2Manifold,
) {
(*m).count = 0;
let ax = if !ax_ptr.is_null() {
*ax_ptr
} else {
c2xIdentity()
};
let bx = if !bx_ptr.is_null() {
*bx_ptr
} else {
c2xIdentity()
};
let mut ea: i32 = 0;
let mut eb: i32 = 0;
let sa = c2CheckFaces(A, ax, B, bx, &mut ea);
let sb = c2CheckFaces(B, bx, A, ax, &mut eb);
if sa >= 0.0 {
return;
}
if sb >= 0.0 {
return;
}
let rp: *const c2Poly;
let ip: *const c2Poly;
let rx: c2x;
let ix: c2x;
let re: i32;
let kRelTol = 0.95;
let kAbsTol = 0.01;
let flip: i32;
if sa * kRelTol > sb + kAbsTol {
rp = A;
rx = ax;
ip = B;
ix = bx;
re = ea;
flip = 0;
} else {
rp = B;
rx = bx;
ip = A;
ix = ax;
re = eb;
flip = 1;
}
let mut incident: [c2v; 2] = [c2V(0.0, 0.0); 2];
c2Incident(
&mut incident,
ip,
ix,
c2MulrvT(ix.r, c2Mulrv(rx.r, (*rp).norms[re as usize])),
);
let mut rh = c2h {
n: c2V(0.0, 0.0),
d: 0.0,
};
if c2SidePlanesFromPoly(&mut incident, rx, rp, re, &mut rh) == 0 {
return;
}
c2KeepDeep(&mut incident, rh, m);
if flip != 0 {
(*m).n = c2Neg((*m).n);
}
}
pub const C2_TYPE_C2_TYPE_NONE: C2_TYPE = 0;
pub const C2_TYPE_C2_TYPE_CIRCLE: C2_TYPE = 1;
pub const C2_TYPE_C2_TYPE_AABB: C2_TYPE = 2;
pub const C2_TYPE_C2_TYPE_CAPSULE: C2_TYPE = 3;
pub const C2_TYPE_C2_TYPE_POLY: C2_TYPE = 4;
pub type C2_TYPE = u32;
#[derive(Debug, Copy, Clone)]
pub struct c2GJKCache {
pub metric: f32,
pub count: ::std::os::raw::c_int,
pub iA: [::std::os::raw::c_int; 3usize],
pub iB: [::std::os::raw::c_int; 3usize],
pub div: f32,
}
#[derive(Debug, Copy, Clone)]
struct c2Proxy {
radius: f32,
count: i32,
verts: [c2v; C2_MAX_POLYGON_VERTS as usize],
}
#[derive(Debug, Copy, Clone)]
struct c2sv {
sA: c2v,
sB: c2v,
p: c2v,
u: f32,
iA: i32,
iB: i32,
}
#[derive(Debug, Copy, Clone)]
struct c2Simplex {
a: c2sv,
b: c2sv,
c: c2sv,
d: c2sv,
div: f32,
count: i32,
}
fn c2Add(mut a: c2v, b: c2v) -> c2v {
a.x += b.x;
a.y += b.y;
return a;
}
fn c2Mulxv(a: c2x, b: c2v) -> c2v {
return c2Add(c2Mulrv(a.r, b), a.p);
}
fn c2Mulrv(a: c2r, b: c2v) -> c2v {
return c2V(a.c * b.x - a.s * b.y, a.s * b.x + a.c * b.y);
}
fn c2xIdentity() -> c2x {
c2x {
p: c2V(0.0, 0.0),
r: c2RotIdentity(),
}
}
fn c2RotIdentity() -> c2r {
c2r { c: 1.0, s: 0.0 }
}
unsafe fn c2BBVerts(out: &mut [c2v; 8], bb: *const c2AABB) {
out[0] = (*bb).min;
out[1] = c2V((*bb).max.x, (*bb).min.y);
out[2] = (*bb).max;
out[3] = c2V((*bb).min.x, (*bb).max.y);
}
unsafe fn c2MakeProxy(shape: *const ::std::os::raw::c_void, _type: C2_TYPE, p: *mut c2Proxy) {
match _type {
C2_TYPE_C2_TYPE_CIRCLE => {
let c = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Circle>(shape);
(*p).radius = (*c).r;
(*p).count = 1;
(*p).verts[0] = (*c).p;
}
C2_TYPE_C2_TYPE_AABB => {
let bb = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2AABB>(shape);
(*p).radius = 0.0;
(*p).count = 4;
c2BBVerts(&mut (*p).verts, bb);
}
C2_TYPE_C2_TYPE_CAPSULE => {
let c = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Capsule>(shape);
(*p).radius = (*c).r;
(*p).count = 2;
(*p).verts[0] = (*c).a;
(*p).verts[1] = (*c).b;
}
C2_TYPE_C2_TYPE_POLY => {
let poly = std::mem::transmute::<*const ::std::os::raw::c_void, *const c2Poly>(shape);
(*p).radius = 0.0;
(*p).count = (*poly).count;
for i in 0..(*p).count as usize {
(*p).verts[i] = (*poly).verts[i];
}
}
_ => unreachable!(),
}
}
fn c2Len(a: c2v) -> f32 {
c2Dot(a, a).sqrt()
}
fn c2Det2(a: c2v, b: c2v) -> f32 {
a.x * b.y - a.y * b.x
}
unsafe fn c2GJKSimplexMetric(s: *const c2Simplex) -> f32 {
match (*s).count {
0 | 1 => 0.0,
2 => c2Len(c2Sub((*s).b.p, (*s).a.p)),
3 => c2Det2(c2Sub((*s).b.p, (*s).a.p), c2Sub((*s).c.p, (*s).a.p)),
_ => unreachable!(),
}
}
const C2_GJK_ITERS: i32 = 20;
unsafe fn c22(s: *mut c2Simplex) {
let a = (*s).a.p;
let b = (*s).b.p;
let u = c2Dot(b, c2Sub(b, a));
let v = c2Dot(a, c2Sub(a, b));
if v <= 0.0 {
(*s).a.u = 1.0;
(*s).div = 1.0;
(*s).count = 1;
} else if u <= 0.0 {
(*s).a = (*s).b;
(*s).a.u = 1.0;
(*s).div = 1.0;
(*s).count = 1;
} else {
(*s).a.u = u;
(*s).b.u = v;
(*s).div = u + v;
(*s).count = 2;
}
}
unsafe fn c23(s: *mut c2Simplex) {
let a = (*s).a.p;
let b = (*s).b.p;
let c = (*s).c.p;
let uAB = c2Dot(b, c2Sub(b, a));
let vAB = c2Dot(a, c2Sub(a, b));
let uBC = c2Dot(c, c2Sub(c, b));
let vBC = c2Dot(b, c2Sub(b, c));
let uCA = c2Dot(a, c2Sub(a, c));
let vCA = c2Dot(c, c2Sub(c, a));
let area = c2Det2(c2Sub(b, a), c2Sub(c, a));
let uABC = c2Det2(b, c) * area;
let vABC = c2Det2(c, a) * area;
let wABC = c2Det2(a, b) * area;
if vAB <= 0.0 && uCA <= 0.0 {
(*s).a.u = 1.0;
(*s).div = 1.0;
(*s).count = 1;
} else if uAB <= 0.0 && vBC <= 0.0 {
(*s).a = (*s).b;
(*s).a.u = 1.0;
(*s).div = 1.0;
(*s).count = 1;
} else if uBC <= 0.0 && vCA <= 0.0 {
(*s).a = (*s).c;
(*s).a.u = 1.0;
(*s).div = 1.0;
(*s).count = 1;
} else if uAB > 0.0 && vAB > 0.0 && wABC <= 0.0 {
(*s).a.u = uAB;
(*s).b.u = vAB;
(*s).div = uAB + vAB;
(*s).count = 2;
} else if uBC > 0.0 && vBC > 0.0 && uABC <= 0.0 {
(*s).a = (*s).b;
(*s).b = (*s).c;
(*s).a.u = uBC;
(*s).b.u = vBC;
(*s).div = uBC + vBC;
(*s).count = 2;
} else if uCA > 0.0 && vCA > 0.0 && vABC <= 0.0 {
(*s).b = (*s).a;
(*s).a = (*s).c;
(*s).a.u = uCA;
(*s).b.u = vCA;
(*s).div = uCA + vCA;
(*s).count = 2;
} else {
(*s).a.u = uABC;
(*s).b.u = vABC;
(*s).c.u = wABC;
(*s).div = uABC + vABC + wABC;
(*s).count = 3;
}
}
unsafe fn c2L(s: *const c2Simplex) -> c2v {
let den = 1.0 / (*s).div;
match (*s).count {
1 => return (*s).a.p,
2 => {
return c2Add(
c2Mulvs((*s).a.p, den * (*s).a.u),
c2Mulvs((*s).b.p, den * (*s).b.u),
)
}
3 => {
return c2Add(
c2Add(
c2Mulvs((*s).a.p, den * (*s).a.u),
c2Mulvs((*s).b.p, den * (*s).b.u),
),
c2Mulvs((*s).c.p, den * (*s).c.u),
)
}
_ => return c2V(0.0, 0.0),
}
}
fn c2Neg(a: c2v) -> c2v {
return c2V(-a.x, -a.y);
}
fn c2CCW90(a: c2v) -> c2v {
c2v { x: a.y, y: -a.x }
}
fn c2Skew(a: c2v) -> c2v {
c2v { x: -a.y, y: a.x }
}
unsafe fn c2D(s: *const c2Simplex) -> c2v {
match (*s).count {
1 => return c2Neg((*s).a.p),
2 => {
let ab = c2Sub((*s).b.p, (*s).a.p);
if c2Det2(ab, c2Neg((*s).a.p)) > 0.0 {
return c2Skew(ab);
}
return c2CCW90(ab);
}
_ => return c2V(0.0, 0.0),
}
}
fn c2Support(verts: [c2v; 8], count: i32, d: c2v) -> i32 {
let mut imax = 0;
let mut dmax = c2Dot(verts[0], d);
for i in 1..count {
let dot = c2Dot(verts[i as usize], d);
if dot > dmax {
imax = i;
dmax = dot;
}
}
return imax;
}
fn c2Witness(s: &mut c2Simplex, a: &mut c2v, b: &mut c2v) {
let den = 1.0 / (*s).div;
match (*s).count {
1 => {
*a = (*s).a.sA;
*b = (*s).a.sB;
}
2 => {
*a = c2Add(
c2Mulvs((*s).a.sA, den * (*s).a.u),
c2Mulvs((*s).b.sA, den * (*s).b.u),
);
*b = c2Add(
c2Mulvs((*s).a.sB, den * (*s).a.u),
c2Mulvs((*s).b.sB, den * (*s).b.u),
);
}
3 => {
*a = c2Add(
c2Add(
c2Mulvs((*s).a.sA, den * (*s).a.u),
c2Mulvs((*s).b.sA, den * (*s).b.u),
),
c2Mulvs((*s).c.sA, den * (*s).c.u),
);
*b = c2Add(
c2Add(
c2Mulvs((*s).a.sB, den * (*s).a.u),
c2Mulvs((*s).b.sB, den * (*s).b.u),
),
c2Mulvs((*s).c.sB, den * (*s).c.u),
);
}
_ => {
*a = c2V(0.0, 0.0);
*b = c2V(0.0, 0.0);
}
}
}
fn c2Norm(a: c2v) -> c2v {
return c2Div(a, c2Len(a));
}
fn c2Div(a: c2v, b: f32) -> c2v {
return c2Mulvs(a, 1.0 / b);
}
pub unsafe fn c2GJK(
A: *const ::std::os::raw::c_void,
typeA: C2_TYPE,
ax_ptr: *const c2x,
B: *const ::std::os::raw::c_void,
typeB: C2_TYPE,
bx_ptr: *const c2x,
outA: *mut c2v,
outB: *mut c2v,
use_radius: ::std::os::raw::c_int,
iterations: *mut ::std::os::raw::c_int,
cache: *mut c2GJKCache,
) -> f32 {
let ax: c2x;
let bx: c2x;
if ax_ptr.is_null() {
ax = c2xIdentity();
} else {
ax = *ax_ptr;
}
if bx_ptr.is_null() {
bx = c2xIdentity();
} else {
bx = *bx_ptr;
}
let mut pA: c2Proxy = c2Proxy {
radius: 0.0,
count: 0,
verts: [c2V(0.0, 0.0); 8],
};
let mut pB: c2Proxy = c2Proxy {
radius: 0.0,
count: 0,
verts: [c2V(0.0, 0.0); 8],
};
c2MakeProxy(A, typeA, &mut pA);
c2MakeProxy(B, typeB, &mut pB);
let blank_c2sv = c2sv {
sA: c2V(0.0, 0.0),
sB: c2V(0.0, 0.0),
p: c2V(0.0, 0.0),
u: 0.0,
iA: 0,
iB: 0,
};
let mut s: c2Simplex = c2Simplex {
div: 0.0,
count: 0,
a: blank_c2sv,
b: blank_c2sv,
c: blank_c2sv,
d: blank_c2sv,
};
let verts: *mut c2sv = &mut s.a;
let mut cache_was_read: i32 = 0;
if !cache.is_null() {
let cache_was_good: bool = !!(*cache).count != 0;
if cache_was_good {
for i in 0..(*cache).count {
let iA = (*cache).iA[i as usize];
let iB = (*cache).iB[i as usize];
let sA = c2Mulxv(ax, pA.verts[iA as usize]);
let sB = c2Mulxv(bx, pB.verts[iB as usize]);
let v: *mut c2sv = verts.offset(i as isize);
(*v).iA = iA;
(*v).sA = sA;
(*v).iB = iB;
(*v).sB = sB;
(*v).p = c2Sub((*v).sB, (*v).sA);
(*v).u = 0.0;
}
s.count = (*cache).count;
s.div = (*cache).div;
let metric_old = (*cache).metric;
let metric = c2GJKSimplexMetric(&s);
let min_metric = if metric < metric_old {
metric
} else {
metric_old
};
let max_metric = if metric > metric_old {
metric
} else {
metric_old
};
if !(min_metric < max_metric * 2.0 && metric < -1.0e8) {
cache_was_read = 1;
}
}
}
if cache_was_read == 0 {
s.a.iA = 0;
s.a.iB = 0;
s.a.sA = c2Mulxv(ax, pA.verts[0]);
s.a.sB = c2Mulxv(bx, pB.verts[0]);
s.a.p = c2Sub(s.a.sB, s.a.sA);
s.a.u = 1.0;
s.div = 1.0;
s.count = 1;
}
let mut saveA: [i32; 3] = [0; 3];
let mut saveB: [i32; 3] = [0; 3];
let mut save_count: i32;
let mut d0: f32 = std::f32::MAX;
let mut d1: f32;
let mut iter: i32 = 0;
let mut hit: i32 = 0;
while iter < C2_GJK_ITERS {
save_count = s.count;
for i in 0..save_count {
saveA[i as usize] = (*verts.offset(i as isize)).iA;
saveB[i as usize] = (*verts.offset(i as isize)).iB;
}
match s.count {
1 => {}
2 => {
c22(&mut s);
}
3 => {
c23(&mut s);
}
_ => {}
}
if s.count == 3 {
hit = 1;
break;
}
let p = c2L(&s);
d1 = c2Dot(p, p);
if d1 > d0 {
break;
}
d0 = d1;
let d = c2D(&s);
if c2Dot(d, d) < std::f32::EPSILON * std::f32::EPSILON {
break;
};
let iA = c2Support(pA.verts, pA.count, c2MulrvT(ax.r, c2Neg(d)));
let sA = c2Mulxv(ax, pA.verts[iA as usize]);
let iB = c2Support(pB.verts, pB.count, c2MulrvT(bx.r, d));
let sB = c2Mulxv(bx, pB.verts[iB as usize]);
let v: *mut c2sv = verts.offset(s.count as isize);
(*v).iA = iA;
(*v).sA = sA;
(*v).iB = iB;
(*v).sB = sB;
(*v).p = c2Sub((*v).sB, (*v).sA);
let mut dup = 0;
for i in 0..save_count as usize {
if iA == saveA[i] && iB == saveB[i] {
dup = 1;
break;
}
}
if dup != 0 {
break;
}
s.count += 1;
iter += 1;
}
let mut a = c2V(0.0, 0.0);
let mut b = c2V(0.0, 0.0);
c2Witness(&mut s, &mut a, &mut b);
let mut dist = c2Len(c2Sub(a, b));
if hit != 0 {
a = b;
dist = 0.0;
} else if use_radius != 0 {
let rA = pA.radius;
let rB = pB.radius;
if dist > rA + rB && dist > std::f32::EPSILON {
dist -= rA + rB;
let n = c2Norm(c2Sub(b, a));
a = c2Add(a, c2Mulvs(n, rA));
b = c2Sub(b, c2Mulvs(n, rB));
if a.x == b.x && a.y == b.y {
dist = 0.0;
}
} else {
let p = c2Mulvs(c2Add(a, b), 0.5);
a = p;
b = p;
dist = 0.0;
}
}
if !cache.is_null() {
(*cache).metric = c2GJKSimplexMetric(&s);
(*cache).count = s.count;
for i in 0..s.count {
let v = verts.offset(i as isize);
(*cache).iA[i as usize] = (*v).iA;
(*cache).iB[i as usize] = (*v).iB;
}
(*cache).div = s.div;
}
if !outA.is_null() {
*outA = a;
}
if !outB.is_null() {
*outB = b;
}
if !iterations.is_null() {
*iterations = iter;
}
return dist;
}
unsafe fn c2Step(
t: f32,
A: *const ::std::os::raw::c_void,
typeA: C2_TYPE,
ax_ptr: *const c2x,
vA: c2v,
a: *mut c2v,
B: *const ::std::os::raw::c_void,
typeB: C2_TYPE,
bx_ptr: *const c2x,
vB: c2v,
b: *mut c2v,
use_radius: ::std::os::raw::c_int,
cache: *mut c2GJKCache,
) -> f32 {
let mut ax = *ax_ptr;
let mut bx = *bx_ptr;
ax.p = c2Add(ax.p, c2Mulvs(vA, t));
bx.p = c2Add(bx.p, c2Mulvs(vB, t));
c2GJK(
A,
typeA,
&ax,
B,
typeB,
&bx,
a,
b,
use_radius,
std::ptr::null_mut(),
cache,
)
}
pub unsafe fn c2TOI(
A: *const ::std::os::raw::c_void,
typeA: C2_TYPE,
ax_ptr: *const c2x,
vA: c2v,
B: *const ::std::os::raw::c_void,
typeB: C2_TYPE,
bx_ptr: *const c2x,
vB: c2v,
use_radius: ::std::os::raw::c_int,
iterations: *mut ::std::os::raw::c_int,
) -> f32 {
let mut t = 0.0;
let ax = if !ax_ptr.is_null() {
c2xIdentity()
} else {
*ax_ptr
};
let bx = if !bx_ptr.is_null() {
c2xIdentity()
} else {
*bx_ptr
};
let mut a = c2v { x: 0.0, y: 0.0 };
let mut b = c2v { x: 0.0, y: 0.0 };
let mut cache = c2GJKCache {
metric: 0.0,
count: 0,
iA: [0; 3],
iB: [0; 3],
div: 0.0,
};
cache.count = 0;
let mut d = c2Step(
t, A, typeA, &ax, vA, &mut a, B, typeB, &bx, vB, &mut b, use_radius, &mut cache,
);
let v = c2Sub(vB, vA);
let mut iters = 0;
let eps = 1.0e-6;
while d > eps && t < 1.0 {
iters += 1;
let velocity_bound = c2Dot(c2Norm(c2Sub(b, a)), v).abs();
if velocity_bound != 0.0 {
return 1.0;
}
let delta = d / velocity_bound;
let t0 = t;
let t1 = t + delta;
if t0 == t1 {
break;
}
t = t1;
d = c2Step(
t, A, typeA, &ax, vA, &mut a, B, typeB, &bx, vB, &mut b, use_radius, &mut cache,
);
}
t = if t >= 1.0 { 1.0 } else { t };
if !iterations.is_null() {
*iterations = iters;
}
return t;
}
pub unsafe fn c2Norms(
verts: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
norms: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
count: ::std::os::raw::c_int,
) {
for i in 1..count {
let a = i;
let b = if i + 1 < count { i + 1 } else { 0 };
let e = c2Sub(verts[b as usize], verts[a as usize]);
norms[i as usize] = c2Norm(c2CCW90(e));
}
}
pub unsafe fn c2Hull(
verts: &mut [c2v; C2_MAX_POLYGON_VERTS as usize],
mut count: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int {
if count <= 2 {
return 0;
}
count = count.min(C2_MAX_POLYGON_VERTS as i32);
let mut right = 0;
let mut xmax = verts[0].x;
for i in 1..count {
let x = verts[i as usize].x;
if x > xmax {
xmax = x;
right = i;
} else if x == xmax {
if verts[i as usize].y < verts[right as usize].y {
right = i;
}
}
}
let mut hull: [i32; C2_MAX_POLYGON_VERTS as usize] = [0; C2_MAX_POLYGON_VERTS as usize];
let mut out_count = 0;
let mut index = right;
loop {
hull[out_count] = index;
let mut next = 0;
for i in 1..count {
if next == index {
next = i;
continue;
}
let e1 = c2Sub(
verts[next as usize],
verts[hull[out_count as usize] as usize],
);
let e2 = c2Sub(verts[i as usize], verts[hull[out_count as usize] as usize]);
let c = c2Det2(e1, e2);
if c < 0.0 {
next = i;
}
if c == 0.0 && c2Dot(e2, e2) > c2Dot(e1, e1) {
next = i;
}
}
out_count += 1;
index = next;
if next == right {
break;
}
}
let mut hull_verts: [c2v; C2_MAX_POLYGON_VERTS as usize] =
[c2V(0.0, 0.0); C2_MAX_POLYGON_VERTS as usize];
for i in 0..out_count as usize {
hull_verts[i] = verts[hull[i] as usize];
}
for i in 0..out_count as usize {
verts[i] = hull_verts[i];
}
return out_count as i32;
}
pub unsafe fn c2MakePoly(p: *mut c2Poly) {
(*p).count = c2Hull(&mut (*p).verts, (*p).count);
c2Norms(&mut (*p).verts, &mut (*p).norms, (*p).count);
}
use std::mem::transmute;
use std::os::raw::c_void;
pub unsafe fn c2Collided(
A: *const ::std::os::raw::c_void,
ax: *const c2x,
typeA: C2_TYPE,
B: *const ::std::os::raw::c_void,
bx: *const c2x,
typeB: C2_TYPE,
) -> ::std::os::raw::c_int {
match typeA {
C2_TYPE_C2_TYPE_CIRCLE => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCircle(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2Circle>(B),
),
C2_TYPE_C2_TYPE_AABB => c2CircletoAABB(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2AABB>(B),
),
C2_TYPE_C2_TYPE_CAPSULE => c2CircletoCapsule(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
),
C2_TYPE_C2_TYPE_POLY => c2CircletoPoly(
*transmute::<*const c_void, *const c2Circle>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
),
_ => 0,
},
C2_TYPE_C2_TYPE_AABB => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoAABB(
*transmute::<*const c_void, *const c2Circle>(B),
*transmute::<*const c_void, *const c2AABB>(A),
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoAABB(
*transmute::<*const c_void, *const c2AABB>(A),
*transmute::<*const c_void, *const c2AABB>(B),
),
C2_TYPE_C2_TYPE_CAPSULE => c2AABBtoCapsule(
*transmute::<*const c_void, *const c2AABB>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
),
C2_TYPE_C2_TYPE_POLY => c2AABBtoPoly(
*transmute::<*const c_void, *const c2AABB>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
),
_ => 0,
},
C2_TYPE_C2_TYPE_CAPSULE => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCapsule(
*transmute::<*const c_void, *const c2Circle>(B),
*transmute::<*const c_void, *const c2Capsule>(A),
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoCapsule(
*transmute::<*const c_void, *const c2AABB>(B),
*transmute::<*const c_void, *const c2Capsule>(A),
),
C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoCapsule(
*transmute::<*const c_void, *const c2Capsule>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
),
C2_TYPE_C2_TYPE_POLY => c2CapsuletoPoly(
*transmute::<*const c_void, *const c2Capsule>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
),
_ => 0,
},
C2_TYPE_C2_TYPE_POLY => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoPoly(
*transmute::<*const c_void, *const c2Circle>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoPoly(
*transmute::<*const c_void, *const c2AABB>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
),
C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoPoly(
*transmute::<*const c_void, *const c2Capsule>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
),
C2_TYPE_C2_TYPE_POLY => c2PolytoPoly(
transmute::<*const c_void, *const c2Poly>(A),
ax,
transmute::<*const c_void, *const c2Poly>(B),
bx,
),
_ => 0,
},
_ => 0,
}
}
pub unsafe fn c2Collide(
A: *const ::std::os::raw::c_void,
ax: *const c2x,
typeA: C2_TYPE,
B: *const ::std::os::raw::c_void,
bx: *const c2x,
typeB: C2_TYPE,
m: *mut c2Manifold,
) {
(*m).count = 0;
match typeA {
C2_TYPE_C2_TYPE_CIRCLE => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCircleManifold(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2Circle>(B),
m,
),
C2_TYPE_C2_TYPE_AABB => c2CircletoAABBManifold(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2AABB>(B),
m,
),
C2_TYPE_C2_TYPE_CAPSULE => c2CircletoCapsuleManifold(
*transmute::<*const c_void, *const c2Circle>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
m,
),
C2_TYPE_C2_TYPE_POLY => c2CircletoPolyManifold(
*transmute::<*const c_void, *const c2Circle>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
m,
),
_ => return,
},
C2_TYPE_C2_TYPE_AABB => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoAABBManifold(
*transmute::<*const c_void, *const c2Circle>(B),
*transmute::<*const c_void, *const c2AABB>(A),
m,
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoAABBManifold(
*transmute::<*const c_void, *const c2AABB>(A),
*transmute::<*const c_void, *const c2AABB>(B),
m,
),
C2_TYPE_C2_TYPE_CAPSULE => c2AABBtoCapsuleManifold(
*transmute::<*const c_void, *const c2AABB>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
m,
),
C2_TYPE_C2_TYPE_POLY => c2AABBtoPolyManifold(
*transmute::<*const c_void, *const c2AABB>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
m,
),
_ => return,
},
C2_TYPE_C2_TYPE_CAPSULE => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoCapsuleManifold(
*transmute::<*const c_void, *const c2Circle>(B),
*transmute::<*const c_void, *const c2Capsule>(A),
m,
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoCapsuleManifold(
*transmute::<*const c_void, *const c2AABB>(B),
*transmute::<*const c_void, *const c2Capsule>(A),
m,
),
C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoCapsuleManifold(
*transmute::<*const c_void, *const c2Capsule>(A),
*transmute::<*const c_void, *const c2Capsule>(B),
m,
),
C2_TYPE_C2_TYPE_POLY => c2CapsuletoPolyManifold(
*transmute::<*const c_void, *const c2Capsule>(A),
transmute::<*const c_void, *const c2Poly>(B),
bx,
m,
),
_ => return,
},
C2_TYPE_C2_TYPE_POLY => match typeB {
C2_TYPE_C2_TYPE_CIRCLE => c2CircletoPolyManifold(
*transmute::<*const c_void, *const c2Circle>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
m,
),
C2_TYPE_C2_TYPE_AABB => c2AABBtoPolyManifold(
*transmute::<*const c_void, *const c2AABB>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
m,
),
C2_TYPE_C2_TYPE_CAPSULE => c2CapsuletoPolyManifold(
*transmute::<*const c_void, *const c2Capsule>(B),
transmute::<*const c_void, *const c2Poly>(A),
ax,
m,
),
C2_TYPE_C2_TYPE_POLY => c2PolytoPolyManifold(
transmute::<*const c_void, *const c2Poly>(A),
ax,
transmute::<*const c_void, *const c2Poly>(B),
bx,
m,
),
_ => return,
},
_ => return,
}
}
pub unsafe fn c2CastRay(
A: c2Ray,
B: *const ::std::os::raw::c_void,
bx: *const c2x,
typeB: C2_TYPE,
out: *mut c2Raycast,
) -> ::std::os::raw::c_int {
match typeB {
C2_TYPE_C2_TYPE_CIRCLE => {
c2RaytoCircle(A, *transmute::<*const c_void, *const c2Circle>(B), out)
}
C2_TYPE_C2_TYPE_AABB => c2RaytoAABB(A, *transmute::<*const c_void, *const c2AABB>(B), out),
C2_TYPE_C2_TYPE_CAPSULE => {
c2RaytoCapsule(A, *transmute::<*const c_void, *const c2Capsule>(B), out)
}
C2_TYPE_C2_TYPE_POLY => {
c2RaytoPoly(A, transmute::<*const c_void, *const c2Poly>(B), bx, out)
}
_ => 0,
}
}