#![cfg(feature = "std")]
use std::f32::consts;
use approx::assert_abs_diff_eq;
use glam::Vec2;
use rstest::*;
use impacted::{CollisionShape, Transform};
#[rstest]
#[case(CollisionShape::new_circle(1.0), CollisionShape::new_circle(1.0))]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::ZERO)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_angle_translation(2.0, Vec2::ZERO)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_scale_angle_translation(Vec2::splat(2.0), 2.0, Vec2::ZERO)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::new(2.0, 0.0))),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.0)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.5).with_transform(Transform::from_translation(Vec2::Y * 2.1)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_translation(Vec2::X * 1.9)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.3)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_segment(Vec2::ZERO, Vec2::X)
)]
fn collides(#[case] shape1: CollisionShape, #[case] shape2: CollisionShape) {
assert!(shape1.is_collided_with(&shape2));
let contact = shape1.contact_with(&shape2);
assert!(contact.is_some(), "{contact:?}");
}
#[rstest]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 2.1)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 2.1)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_translation(Vec2::X * 2.1)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.5)),
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_segment(Vec2::X * 2.0, Vec2::X * 3.0),
)]
fn does_not_collide(#[case] shape1: CollisionShape, #[case] shape2: CollisionShape) {
assert!(!shape1.is_collided_with(&shape2));
let contact = shape1.contact_with(&shape2);
assert!(contact.is_none(), "{contact:?}");
}
#[rstest]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.95)),
Vec2::new(-1.0, 0.0)
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 1.95)),
Vec2::new(0.0, -1.0)
)]
#[case(
CollisionShape::new_rectangle(1.0, 1.0),
CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.95)),
Vec2::new(1.0, 0.0)
)]
#[case(
CollisionShape::new_rectangle(2.0, 2.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4 + 0.1, Vec2::X * 2.3)),
Vec2::new(-1.0, 0.0)
)]
#[case(
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4 + 0.1, Vec2::X * 2.3)),
CollisionShape::new_rectangle(2.0, 2.0),
Vec2::new(1.0, 0.0)
)]
fn contact_normal(
#[case] shape1: CollisionShape,
#[case] shape2: CollisionShape,
#[case] expected_normal: Vec2,
) {
let contact = shape1.contact_with(&shape2).unwrap();
assert_abs_diff_eq!(Vec2::from(contact.normal), expected_normal, epsilon = 0.001);
}
#[rstest]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::X * 1.95)),
0.05
)]
#[case(
CollisionShape::new_circle(1.0),
CollisionShape::new_circle(1.0).with_transform(Transform::from_translation(Vec2::Y * 1.0)),
1.0
)]
#[case(
CollisionShape::new_rectangle(1.0, 1.0),
CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.95)),
0.05
)]
#[case(
CollisionShape::new_rectangle(1.0, 1.0),
CollisionShape::new_rectangle(1.0, 1.0).with_transform(Transform::from_translation(Vec2::X * -0.5)),
0.5
)]
#[case(
CollisionShape::new_rectangle(2.0, 2.0),
CollisionShape::new_rectangle(2.0, 2.0).with_transform(Transform::from_angle_translation(consts::FRAC_PI_4, Vec2::X * 2.3)),
0.1142
)]
fn contact_penetration(
#[case] shape1: CollisionShape,
#[case] shape2: CollisionShape,
#[case] expected_penetration: f32,
) {
let contact = shape1.contact_with(&shape2).unwrap();
assert_abs_diff_eq!(contact.penetration, expected_penetration, epsilon = 0.0001);
}