pub mod broad_phase;
pub mod epa;
pub mod geometry;
pub mod gjk;
pub use broad_phase::sweep_and_prune;
pub use epa::{epa_penetration, epa_penetration_rot};
pub use geometry::{AABB, Geometry};
pub use gjk::{gjk_distance, gjk_distance_rot};
use crate::math::Vec3;
#[derive(Debug, Clone)]
pub struct Collision {
pub body_i: usize,
pub body_j: usize,
pub contact_point: Vec3,
pub contact_normal: Vec3,
pub penetration_depth: f64,
}
#[cfg(test)]
mod tests {
use super::*;
use geometry::Geometry;
use crate::math::Vec3;
#[test]
fn test_sphere_sphere_separated() {
let s1 = Geometry::Sphere { radius: 1.0 };
let s2 = Geometry::Sphere { radius: 1.0 };
let p1 = Vec3::zeros();
let p2 = Vec3::new(3.0, 0.0, 0.0);
let dist = gjk_distance(&s1, &s2, &p1, &p2);
assert!(
(dist - 1.0).abs() < 1e-6,
"Expected distance ~1.0, got {}",
dist
);
}
#[test]
fn test_sphere_sphere_touching() {
let s1 = Geometry::Sphere { radius: 1.0 };
let s2 = Geometry::Sphere { radius: 1.0 };
let p1 = Vec3::zeros();
let p2 = Vec3::new(2.0, 0.0, 0.0);
let dist = gjk_distance(&s1, &s2, &p1, &p2);
assert!(dist.abs() < 1e-6, "Expected distance ~0.0, got {}", dist);
}
#[test]
fn test_sphere_sphere_penetrating() {
let s1 = Geometry::Sphere { radius: 1.0 };
let s2 = Geometry::Sphere { radius: 1.0 };
let p1 = Vec3::zeros();
let p2 = Vec3::new(1.5, 0.0, 0.0);
let dist = gjk_distance(&s1, &s2, &p1, &p2);
assert!(
dist <= 0.0,
"Expected non-positive distance (penetration), got {}",
dist
);
if let Some(pen) = epa_penetration(&s1, &s2, &p1, &p2) {
assert!(
(pen.0 - 0.5).abs() < 0.1,
"Expected penetration ~0.5, got {}",
pen.0
);
}
}
}