use super::{check_cast_hit, ensure_small, ray_capsule, v};
use crate::geometry::{ray_cast_capsule, Capsule, RayCastInput};
use crate::math_functions::{distance, mul_add, point_to_segment_distance};
#[test]
fn ray_cast_capsule_side_test() {
let ray_cap = ray_capsule();
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(0.0, -6.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(0.0, 1.0, 0.0),
v(0.0, 1.0, 0.0),
1.0 / 3.0,
1e-5,
);
}
{
let input = RayCastInput {
origin: v(0.0, 0.0, 3.0),
translation: v(0.0, 0.0, -6.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(0.0, 0.0, 1.0),
v(0.0, 0.0, 1.0),
1.0 / 3.0,
1e-5,
);
}
{
let input = RayCastInput {
origin: v(-1.0, 3.0, 0.0),
translation: v(0.0, -6.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(-1.0, 1.0, 0.0),
v(0.0, 1.0, 0.0),
1.0 / 3.0,
1e-5,
);
}
}
#[test]
fn ray_cast_capsule_oblique_test() {
let ray_cap = ray_capsule();
let input = RayCastInput {
origin: v(-3.0, 3.0, 0.0),
translation: v(4.0, -4.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(-1.0, 1.0, 0.0),
v(0.0, 1.0, 0.0),
0.5,
1e-4,
);
}
#[test]
fn ray_cast_capsule_cap_test() {
let ray_cap = ray_capsule();
let k = 0.70710678;
{
let input = RayCastInput {
origin: v(5.0, 0.0, 0.0),
translation: v(-8.0, 0.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(3.0, 0.0, 0.0),
v(1.0, 0.0, 0.0),
1.0 / 4.0,
1e-5,
);
}
{
let input = RayCastInput {
origin: v(4.0, 2.0, 0.0),
translation: v(-4.0, -4.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(2.0 + k, k, 0.0),
v(k, k, 0.0),
0.323223,
1e-4,
);
}
{
let input = RayCastInput {
origin: v(-4.0, 2.0, 0.0),
translation: v(4.0, -4.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(-2.0 - k, k, 0.0),
v(-k, k, 0.0),
0.323223,
1e-4,
);
}
}
#[test]
fn ray_cast_capsule_miss_test() {
let ray_cap = ray_capsule();
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(0.0, 4.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
{
let input = RayCastInput {
origin: v(0.0, 4.0, 2.0),
translation: v(0.0, -8.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
{
let input = RayCastInput {
origin: v(0.0, 5.0, 0.0),
translation: v(0.0, -1.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(8.0, 0.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
{
let input = RayCastInput {
origin: v(4.0, 3.0, 0.0),
translation: v(0.0, -6.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
}
#[test]
fn ray_cast_capsule_interior_test() {
let ray_cap = ray_capsule();
{
let input = RayCastInput {
origin: v(0.0, 0.0, 0.0),
translation: v(0.0, -5.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
assert!(out.hit);
assert_eq!(out.fraction, 0.0);
ensure_small(distance(out.point, input.origin), f32::EPSILON);
}
{
let input = RayCastInput {
origin: v(2.5, 0.0, 0.0),
translation: v(0.0, 0.0, 5.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
assert!(out.hit);
assert_eq!(out.fraction, 0.0);
ensure_small(distance(out.point, input.origin), f32::EPSILON);
}
{
let input = RayCastInput {
origin: v(0.0, 0.0, 0.0),
translation: v(0.0, 0.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
assert!(out.hit);
ensure_small(distance(out.point, input.origin), f32::EPSILON);
}
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(0.0, 0.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
}
#[test]
fn ray_cast_capsule_degenerate_test() {
let c = Capsule {
center1: v(0.0, 0.0, 0.0),
center2: v(0.0, 0.0, 0.0),
radius: 1.0,
};
let input = RayCastInput {
origin: v(-4.0, 0.0, 0.0),
translation: v(8.0, 0.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&c, &input);
check_cast_hit(
out,
input.origin,
input.translation,
v(-1.0, 0.0, 0.0),
v(-1.0, 0.0, 0.0),
3.0 / 8.0,
1e-5,
);
}
#[test]
fn ray_cast_capsule_clip_test() {
let ray_cap = ray_capsule();
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(0.0, -6.0, 0.0),
max_fraction: 0.3,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(0.0, -6.0, 0.0),
max_fraction: 0.5,
};
let out = ray_cast_capsule(&ray_cap, &input);
assert!(out.hit);
ensure_small(out.fraction - 1.0 / 3.0, 1e-5);
}
}
#[test]
fn ray_cast_capsule_parallel_test() {
let ray_cap = ray_capsule();
let axis_y = Capsule {
center1: v(0.0, 0.0, 0.0),
center2: v(0.0, 10.0, 0.0),
radius: 1.0,
};
{
let input = RayCastInput {
origin: v(1.0001, 100.0, 0.0),
translation: v(-0.001, -200.0, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&axis_y, &input);
assert!(out.hit);
let on_seg = point_to_segment_distance(axis_y.center1, axis_y.center2, out.point);
ensure_small(distance(out.point, on_seg) - axis_y.radius, 1e-3);
let on_ray = mul_add(input.origin, out.fraction, input.translation);
ensure_small(distance(out.point, on_ray), 1e-3);
}
{
let input = RayCastInput {
origin: v(-1000.0, 1.0001, 0.0),
translation: v(2000.0, -0.001, 0.0),
max_fraction: 1.0,
};
let out = ray_cast_capsule(&ray_cap, &input);
assert!(out.hit);
let on_seg = point_to_segment_distance(ray_cap.center1, ray_cap.center2, out.point);
ensure_small(distance(out.point, on_seg) - ray_cap.radius, 1e-3);
}
{
let input = RayCastInput {
origin: v(0.0, 3.0, 0.0),
translation: v(8.0, 0.0, 0.0),
max_fraction: 1.0,
};
assert!(!ray_cast_capsule(&ray_cap, &input).hit);
}
}