1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::mem;
use std::marker::PhantomData;
use common::math::{Vec2, Transform};
use collision::shapes::Shape;

#[repr(C)]
#[doc(hidden)]
pub struct RawProxy {
    buffer: [Vec2; 2],
    vertices: *const Vec2,
    count: i32,
    radius: f32,
}

impl RawProxy {
    unsafe fn new(shape: *const ffi::Shape, index: i32) -> RawProxy {
        let mut proxy = mem::zeroed();
        ffi::DistanceProxy_set(&mut proxy, shape, index);
        proxy
    }
}

pub struct Proxy<'a> {
    #[doc(hidden)]
    pub raw: RawProxy,
    #[doc(hidden)]
    pub phantom: PhantomData<&'a ()>,
}

impl<'a> Proxy<'a> {
    pub fn new<S: Shape>(shape: &'a S, index: i32) -> Proxy<'a> {
        Proxy {
            raw: unsafe { RawProxy::new(shape.base_ptr(), index) },
            phantom: PhantomData,
        }
    }
}

#[repr(C)]
pub struct SimplexCache {
    pub metric: f32,
    pub count: u16,
    pub index_a: [u8; 3],
    pub index_b: [u8; 3],
}

#[repr(C)]
#[doc(hidden)]
pub struct RawInput {
    proxy_a: RawProxy,
    proxy_b: RawProxy,
    transform_a: Transform,
    transform_b: Transform,
    use_radii: bool,
}

pub struct Input<'a> {
    raw: RawInput,
    phantom: PhantomData<&'a ()>,
}

impl<'a> Input<'a> {
    pub fn new(proxy_a: Proxy<'a>,
               proxy_b: Proxy<'a>,
               transform_a: Transform,
               transform_b: Transform,
               use_radii: bool)
               -> Input<'a> {
        Input {
            raw: RawInput {
                proxy_a: proxy_a.raw,
                proxy_b: proxy_b.raw,
                transform_a: transform_a,
                transform_b: transform_b,
                use_radii: use_radii,
            },
            phantom: PhantomData,
        }
    }

    pub fn query(&self, cache: &mut SimplexCache) -> Output {
        unsafe {
            let mut out = mem::zeroed();
            ffi::distance(&mut out, cache, &self.raw);
            out
        }
    }
}

#[repr(C)]
pub struct Output {
    pub point_a: Vec2,
    pub point_b: Vec2,
    pub distance: f32,
    pub iterations: i32,
}

#[doc(hidden)]
pub mod ffi {
    pub use collision::shapes::ffi::Shape;
    use super::{RawProxy, RawInput, SimplexCache, Output};

    extern "C" {
        pub fn DistanceProxy_set(slf: *mut RawProxy, shape: *const Shape, index: i32);
        pub fn distance(output: *mut Output, cache: *mut SimplexCache, input: *const RawInput);
    }
}