1use c2_sys as ffi;
54use std::os::raw::c_void;
55
56const MAX_POLYGON_VERTS: usize = ffi::C2_MAX_POLYGON_VERTS as usize;
57
58#[derive(Debug, Copy, Clone)]
60pub struct Vec2(ffi::c2v);
61
62impl Vec2 {
63 pub fn new(x: f32, y: f32) -> Vec2 {
65 Vec2(ffi::c2v { x, y })
66 }
67
68 pub fn x(self) -> f32 {
70 self.0.x
71 }
72
73 pub fn set_x(&mut self, x: f32) {
75 self.0.x = x;
76 }
77
78 pub fn y(self) -> f32 {
80 self.0.y
81 }
82
83 pub fn set_y(&mut self, y: f32) {
85 self.0.y = y;
86 }
87}
88
89impl From<[f32; 2]> for Vec2 {
90 fn from(v: [f32; 2]) -> Vec2 {
91 Vec2::new(v[0], v[1])
92 }
93}
94
95#[derive(Debug, Copy, Clone)]
97pub struct Rotation(ffi::c2r);
98
99impl Rotation {
100 pub fn zero() -> Self {
102 Rotation::radians(0.0)
103 }
104
105 pub fn radians(radians: f32) -> Rotation {
107 Rotation(ffi::c2r {
108 c: radians.cos(),
109 s: radians.sin(),
110 })
111 }
112
113 pub fn degrees(degrees: f32) -> Rotation {
115 Rotation::radians(degrees.to_radians())
116 }
117
118 pub fn cos(self) -> f32 {
120 self.0.c
121 }
122
123 pub fn sin(self) -> f32 {
125 self.0.s
126 }
127}
128
129#[derive(Debug, Copy, Clone)]
131pub struct Circle(ffi::c2Circle);
132
133impl Circle {
134 pub fn new<V: Into<Vec2>>(position: V, radius: f32) -> Circle {
136 Circle(ffi::c2Circle {
137 p: position.into().0,
138 r: radius,
139 })
140 }
141}
142
143#[derive(Debug, Copy, Clone)]
145pub struct AABB(ffi::c2AABB);
146
147impl AABB {
148 pub fn new<V: Into<Vec2>>(min: V, max: V) -> AABB {
150 AABB(ffi::c2AABB {
151 min: min.into().0,
152 max: max.into().0,
153 })
154 }
155
156 pub fn min(self) -> Vec2 {
158 Vec2(self.0.min)
159 }
160
161 pub fn max(self) -> Vec2 {
163 Vec2(self.0.max)
164 }
165}
166
167#[derive(Debug, Copy, Clone)]
169pub struct Capsule(ffi::c2Capsule);
170
171impl Capsule {
172 pub fn new<V: Into<Vec2>>(start: V, end: V, radius: f32) -> Capsule {
174 Capsule(ffi::c2Capsule {
175 a: start.into().0,
176 b: end.into().0,
177 r: radius,
178 })
179 }
180}
181
182#[derive(Debug, Copy, Clone)]
184pub struct Poly(ffi::c2Poly);
185
186impl Poly {
187 pub fn from_slice<V: Copy + Into<Vec2>>(verts: &[V]) -> Poly {
189 let mut poly = ffi::c2Poly {
190 count: verts.len() as i32,
191 verts: [ffi::c2v { x: 0.0, y: 0.0 }; MAX_POLYGON_VERTS],
192 norms: [ffi::c2v { x: 0.0, y: 0.0 }; MAX_POLYGON_VERTS],
193 };
194 for i in 0..verts.len().min(MAX_POLYGON_VERTS) {
195 poly.verts[i] = verts[i].into().0;
196 }
197 unsafe {
198 ffi::c2MakePoly(&mut poly);
199 }
200 Poly(poly)
201 }
202
203 pub fn from_array<V: Copy + Into<Vec2>>(count: usize, verts: [V; MAX_POLYGON_VERTS]) -> Poly {
205 Poly::from_slice(&verts[..count])
206 }
207
208 pub fn count(self) -> usize {
210 self.0.count as usize
211 }
212
213 pub fn get_vert(self, index: usize) -> Vec2 {
215 Vec2(self.0.verts[index])
216 }
217}
218
219#[derive(Debug, Copy, Clone)]
221pub struct Transformation(ffi::c2x);
222
223impl Transformation {
224 pub fn new<V: Into<Vec2>>(position: V, rotation: Rotation) -> Transformation {
226 Transformation(ffi::c2x {
227 p: position.into().0,
228 r: rotation.0,
229 })
230 }
231
232 pub fn position(self) -> Vec2 {
234 Vec2(self.0.p)
235 }
236
237 pub fn set_position(&mut self, position: Vec2) {
238 self.0.p = position.0;
239 }
240
241 pub fn rotation(self) -> Rotation {
243 Rotation(self.0.r)
244 }
245
246 pub fn set_rotation(&mut self, rotation: Rotation) {
247 self.0.r = rotation.0;
248 }
249}
250
251pub struct Ray(ffi::c2Ray);
253
254impl Ray {
255 pub fn new<V: Into<Vec2>>(position: V, ray: V) -> Ray {
257 let ray = ray.into().0;
258 let distance = (ray.x * ray.x + ray.y * ray.y).sqrt();
259 let direction = Vec2::new(ray.x / distance, ray.y / distance);
260 Ray(ffi::c2Ray {
261 p: position.into().0,
262 d: direction.0,
263 t: distance,
264 })
265 }
266}
267
268#[derive(Debug, Copy, Clone)]
270pub struct RayCast(ffi::c2Raycast);
271
272impl RayCast {
273 pub fn time_of_impact(self) -> f32 {
274 self.0.t
275 }
276
277 pub fn position_of_impact(self, ray: Ray) -> Vec2 {
278 Vec2::new(
279 ray.0.p.x + ray.0.d.x * self.0.t,
280 ray.0.p.y + ray.0.d.y * self.0.t,
281 )
282 }
283
284 pub fn normal(self) -> Vec2 {
286 Vec2(self.0.n)
287 }
288}
289
290pub type GjkCache = ffi::c2GJKCache;
291
292#[derive(Debug, Copy, Clone)]
294pub struct Manifold(ffi::c2Manifold);
295
296impl Manifold {
297 pub fn count(self) -> i32 {
298 self.0.count
299 }
300
301 pub fn depths(self) -> [f32; 2] {
302 self.0.depths
303 }
304
305 pub fn contact_points(self) -> [Vec2; 2] {
306 [
307 Vec2(self.0.contact_points[0]),
308 Vec2(self.0.contact_points[1]),
309 ]
310 }
311
312 pub fn normal(self) -> Vec2 {
314 Vec2(self.0.n)
315 }
316}
317
318#[repr(u32)]
320#[derive(Debug, Copy, Clone)]
321pub enum Type {
322 None = ffi::C2_TYPE_C2_TYPE_NONE,
323 Circle = ffi::C2_TYPE_C2_TYPE_CIRCLE,
324 AABB = ffi::C2_TYPE_C2_TYPE_AABB,
325 Capsule = ffi::C2_TYPE_C2_TYPE_CAPSULE,
326 Poly = ffi::C2_TYPE_C2_TYPE_POLY,
327}
328
329#[derive(Debug, Copy, Clone)]
331pub struct GjkResponse {
332 distance: f32,
333 closest_points: (Vec2, Vec2),
334}
335
336impl GjkResponse {
337 pub fn distance(self) -> f32 {
338 self.distance
339 }
340
341 pub fn closest_points(self) -> (Vec2, Vec2) {
342 self.closest_points
343 }
344}
345
346pub struct GjkRunner<'a, ShapeA, ShapeB> {
348 a: &'a ShapeA,
349 b: &'a ShapeB,
350 use_radius: bool,
351 cache: Option<&'a mut GjkCache>,
352 iterations: Option<&'a mut i32>,
353}
354
355pub struct ToiRunner<'a, ShapeA, ShapeB> {
357 a: &'a ShapeA,
358 b: &'a ShapeB,
359 a_velocity: Vec2,
360 b_velocity: Vec2,
361 use_radius: bool,
362 iterations: Option<&'a mut i32>,
363}
364
365pub mod prelude {
366 use super::*;
367
368 impl Ray {
369 pub fn cast<T: Shape + AdvancedShape>(self, shape: T) -> Option<RayCast> {
370 unsafe {
371 let mut raycast = RayCast(ffi::c2Raycast {
372 t: 0.0,
373 n: Vec2::new(0.0, 0.0).0,
374 });
375 let hit = ffi::c2CastRay(
376 self.0,
377 shape.shape(),
378 shape.transformation(),
379 T::shape_type() as u32,
380 &mut raycast.0,
381 );
382 if hit != 0 {
383 Some(raycast)
384 } else {
385 None
386 }
387 }
388 }
389 }
390
391 pub trait Shape {
392 fn shape_type() -> Type;
393
394 fn shape(&self) -> *const c_void {
395 self as *const _ as *const c_void
396 }
397
398 fn transformation(&self) -> *const ffi::c2x {
399 std::ptr::null()
400 }
401 }
402
403 pub trait BasicShape: Shape {
404 fn collides_with<T: Shape>(&self, other: &T) -> bool {
406 unsafe {
407 ffi::c2Collided(
408 self.shape(),
409 self.transformation(),
410 Self::shape_type() as u32,
411 other.shape(),
412 other.transformation(),
413 T::shape_type() as u32,
414 ) != 0
415 }
416 }
417
418 fn manifold<T: Shape>(&self, other: &T) -> Manifold {
420 let mut manifold = Manifold(ffi::c2Manifold {
421 count: 0,
422 depths: [0.0, 0.0],
423 contact_points: [ffi::c2v { x: 0.0, y: 0.0 }, ffi::c2v { x: 0.0, y: 0.0 }],
424 n: ffi::c2v { x: 0.0, y: 0.0 },
425 });
426 unsafe {
427 ffi::c2Collide(
428 self.shape(),
429 self.transformation(),
430 Self::shape_type() as u32,
431 other.shape(),
432 other.transformation(),
433 T::shape_type() as u32,
434 &mut manifold.0,
435 );
436 }
437 manifold
438 }
439 }
440
441 impl<'a, ShapeA, ShapeB> GjkRunner<'a, ShapeA, ShapeB>
442 where
443 ShapeA: Shape,
444 ShapeB: Shape,
445 {
446 pub fn new(a: &'a ShapeA, b: &'a ShapeB) -> GjkRunner<'a, ShapeA, ShapeB> {
447 GjkRunner {
448 a,
449 b,
450 use_radius: true,
451 cache: None,
452 iterations: None,
453 }
454 }
455
456 pub fn use_radius(mut self, use_radius: bool) -> GjkRunner<'a, ShapeA, ShapeB> {
457 self.use_radius = use_radius;
458 self
459 }
460
461 pub fn set_cache(mut self, cache: &'a mut GjkCache) -> GjkRunner<'a, ShapeA, ShapeB> {
462 self.cache = Some(cache);
463 self
464 }
465
466 pub fn set_iterations(mut self, iterations: &'a mut i32) -> GjkRunner<'a, ShapeA, ShapeB> {
467 self.iterations = Some(iterations);
468 self
469 }
470
471 pub fn run(self) -> GjkResponse {
473 let mut response = GjkResponse {
474 distance: 0.0,
475 closest_points: (Vec2::new(0.0, 0.0), Vec2::new(0.0, 0.0)),
476 };
477 let cache_ptr = match self.cache {
478 Some(cache) => cache as *mut GjkCache,
479 None => std::ptr::null_mut(),
480 };
481 let iterations_ptr = match self.iterations {
482 Some(iterations) => iterations as *mut i32,
483 None => std::ptr::null_mut(),
484 };
485 unsafe {
486 let distance = ffi::c2GJK(
487 self.a.shape(),
488 ShapeA::shape_type() as u32,
489 self.a.transformation(),
490 self.b.shape(),
491 ShapeB::shape_type() as u32,
492 self.b.transformation(),
493 &mut (response.closest_points.0).0,
494 &mut (response.closest_points.1).0,
495 self.use_radius as i32,
496 iterations_ptr,
497 cache_ptr,
498 );
499 response.distance = distance;
500 }
501 response
502 }
503 }
504
505 impl<'a, ShapeA, ShapeB> ToiRunner<'a, ShapeA, ShapeB>
506 where
507 ShapeA: Shape,
508 ShapeB: Shape,
509 {
510 pub fn new(a: &'a ShapeA, b: &'a ShapeB) -> ToiRunner<'a, ShapeA, ShapeB> {
511 ToiRunner {
512 a,
513 b,
514 a_velocity: Vec2::new(0.0, 0.0),
515 b_velocity: Vec2::new(0.0, 0.0),
516 use_radius: true,
517 iterations: None,
518 }
519 }
520
521 pub fn set_velocities(
522 mut self,
523 a_velocity: Vec2,
524 b_velocity: Vec2,
525 ) -> ToiRunner<'a, ShapeA, ShapeB> {
526 self.a_velocity = a_velocity;
527 self.b_velocity = b_velocity;
528 self
529 }
530
531 pub fn use_radius(mut self, use_radius: bool) -> ToiRunner<'a, ShapeA, ShapeB> {
532 self.use_radius = use_radius;
533 self
534 }
535
536 pub fn set_iterations(mut self, iterations: &'a mut i32) -> ToiRunner<'a, ShapeA, ShapeB> {
537 self.iterations = Some(iterations);
538 self
539 }
540
541 pub fn run(self) -> f32 {
542 let iterations_ptr = match self.iterations {
543 Some(iterations) => iterations as *mut i32,
544 None => std::ptr::null_mut(),
545 };
546 let result = unsafe {
547 ffi::c2TOI(
548 self.a.shape(),
549 ShapeA::shape_type() as u32,
550 self.a.transformation(),
551 self.a_velocity.0,
552 self.b.shape(),
553 ShapeB::shape_type() as u32,
554 self.b.transformation(),
555 self.b_velocity.0,
556 self.use_radius as i32,
557 iterations_ptr,
558 )
559 };
560 result
561 }
562 }
563
564 pub trait AdvancedShape: Shape {
565 fn gjk<'a, T: Shape>(&'a self, other: &'a T) -> GjkRunner<'a, Self, T>
566 where
567 Self: Sized,
568 T: Sized,
569 {
570 GjkRunner::new(self, other)
571 }
572
573 fn time_of_impact<'a, T: Shape>(&'a self, other: &'a T) -> ToiRunner<'a, Self, T>
574 where
575 Self: Sized,
576 T: Sized,
577 {
578 ToiRunner::new(self, other)
579 }
580 }
581
582 impl Shape for Circle {
583 fn shape_type() -> Type {
584 Type::Circle
585 }
586 }
587
588 impl BasicShape for Circle {}
589 impl AdvancedShape for Circle {}
590
591 impl Shape for AABB {
592 fn shape_type() -> Type {
593 Type::AABB
594 }
595 }
596
597 impl BasicShape for AABB {}
598 impl AdvancedShape for AABB {}
599
600 impl Shape for Capsule {
601 fn shape_type() -> Type {
602 Type::Capsule
603 }
604 }
605
606 impl BasicShape for Capsule {}
607 impl AdvancedShape for Capsule {}
608
609 impl Shape for Poly {
610 fn shape_type() -> Type {
611 Type::Poly
612 }
613 }
614
615 impl BasicShape for Poly {}
616 impl AdvancedShape for Poly {}
617
618 impl Shape for (Circle, Transformation) {
619 fn shape_type() -> Type {
620 Type::Circle
621 }
622
623 fn shape(&self) -> *const c_void {
624 &self.0 as *const _ as *const c_void
625 }
626
627 fn transformation(&self) -> *const ffi::c2x {
628 &self.1 as *const _ as *const ffi::c2x
629 }
630 }
631
632 impl AdvancedShape for (Circle, Transformation) {}
633
634 impl Shape for (AABB, Transformation) {
635 fn shape_type() -> Type {
636 Type::AABB
637 }
638
639 fn shape(&self) -> *const c_void {
640 &self.0 as *const _ as *const c_void
641 }
642
643 fn transformation(&self) -> *const ffi::c2x {
644 &self.1 as *const _ as *const ffi::c2x
645 }
646 }
647
648 impl AdvancedShape for (AABB, Transformation) {}
649
650 impl Shape for (Capsule, Transformation) {
651 fn shape_type() -> Type {
652 Type::Capsule
653 }
654
655 fn shape(&self) -> *const c_void {
656 &self.0 as *const _ as *const c_void
657 }
658
659 fn transformation(&self) -> *const ffi::c2x {
660 &self.1 as *const _ as *const ffi::c2x
661 }
662 }
663
664 impl AdvancedShape for (Capsule, Transformation) {}
665
666 impl Shape for (Poly, Transformation) {
667 fn shape_type() -> Type {
668 Type::Poly
669 }
670
671 fn shape(&self) -> *const c_void {
672 &self.0 as *const _ as *const c_void
673 }
674
675 fn transformation(&self) -> *const ffi::c2x {
676 &self.1 as *const _ as *const ffi::c2x
677 }
678 }
679
680 impl BasicShape for (Poly, Transformation) {}
681 impl AdvancedShape for (Poly, Transformation) {}
682}