use glam_det::nums::Signed;
use glam_det::{Cross, Dot, UnitQuat, UnitVec3, Vec3};
use super::capsule::capsule_infinite_plane_overlap_test;
use super::convex_hull::convex_hull_infinite_plane_overlap_test;
use super::cuboid::cuboid_infinite_plane_overlap_test;
use super::sphere::sphere_infinite_plane_overlap_test;
use super::traits::OverlapTest;
use crate::{Capsule, ConvexHullId, Cuboid, Cylinder, InfinitePlane, ShapeContainer, Sphere};
impl OverlapTest<Sphere> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &Sphere,
offset_target: Vec3,
orientation: UnitQuat,
_: UnitQuat,
_: Option<&ShapeContainer>,
) -> bool {
sphere_infinite_plane_overlap_test(*target, *self, offset_target, orientation)
}
}
impl OverlapTest<Cuboid> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &Cuboid,
offset_target: Vec3,
orientation: UnitQuat,
orientation_target: UnitQuat,
_: Option<&ShapeContainer>,
) -> bool {
cuboid_infinite_plane_overlap_test(
*target,
*self,
offset_target,
orientation_target,
orientation,
)
}
}
impl OverlapTest<Capsule> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &Capsule,
offset_target: Vec3,
orientation: UnitQuat,
orientation_target: UnitQuat,
_: Option<&ShapeContainer>,
) -> bool {
capsule_infinite_plane_overlap_test(
*target,
*self,
offset_target,
orientation_target,
orientation,
)
}
}
#[inline]
pub(super) fn cylinder_infinite_plane_overlap_test(
cylinder: Cylinder,
_: InfinitePlane,
offset_infinite_plane_to_cylinder: Vec3,
orientation_cylinder: UnitQuat,
orientation_infinite_plane: UnitQuat,
) -> bool {
let cylinder_in_infinite_plane =
orientation_infinite_plane.inverse() * offset_infinite_plane_to_cylinder;
let cylinder_axis_in_infinite_plane =
orientation_infinite_plane.inverse() * orientation_cylinder * UnitVec3::Y;
let top_center_in_infinite_plane =
cylinder_in_infinite_plane + cylinder_axis_in_infinite_plane * cylinder.half_height();
let bottom_center_in_infinite_plane =
cylinder_in_infinite_plane + cylinder_axis_in_infinite_plane * (-cylinder.half_height());
let contact_dir = ((UnitVec3::Y.cross(cylinder_axis_in_infinite_plane))
.cross(cylinder_axis_in_infinite_plane))
.normalize_or_zero();
let top0 = top_center_in_infinite_plane + contact_dir * cylinder.radius();
let top1 = top_center_in_infinite_plane - contact_dir * cylinder.radius();
let bottom0 = bottom_center_in_infinite_plane + contact_dir * cylinder.radius();
let bottom1 = bottom_center_in_infinite_plane - contact_dir * cylinder.radius();
(top0.y <= 0.0f32) || (top1.y <= 0.0f32) || (bottom0.y <= 0.0f32) || (bottom1.y <= 0.0f32)
}
impl OverlapTest<Cylinder> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &Cylinder,
offset_target: Vec3,
orientation: UnitQuat,
orientation_target: UnitQuat,
_: Option<&ShapeContainer>,
) -> bool {
cylinder_infinite_plane_overlap_test(
*target,
*self,
offset_target,
orientation_target,
orientation,
)
}
}
#[inline]
fn infinite_plane_infinite_plane_overlap_test(
_a: InfinitePlane,
_b: InfinitePlane,
offset_target: Vec3,
orientation_plane_a: UnitQuat,
orientation_plane_b: UnitQuat,
) -> bool {
let plane_a_axis_in_plane_b = orientation_plane_b.inverse() * orientation_plane_a * UnitVec3::Y;
let plane_b_axis = orientation_plane_b * UnitVec3::Y;
offset_target.y == 0.0f32
|| (plane_a_axis_in_plane_b.dot(plane_b_axis.as_vec3()) + 1.0f32).absf() >= f32::EPSILON
}
impl OverlapTest<InfinitePlane> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &InfinitePlane,
offset_target: Vec3,
orientation: UnitQuat,
orientation_target: UnitQuat,
_: Option<&ShapeContainer>,
) -> bool {
infinite_plane_infinite_plane_overlap_test(
*target,
*self,
offset_target,
orientation_target,
orientation,
)
}
}
impl OverlapTest<ConvexHullId> for InfinitePlane {
#[inline]
fn overlap_test(
&self,
target: &ConvexHullId,
offset_target: Vec3,
orientation: UnitQuat,
orientation_target: UnitQuat,
container: Option<&ShapeContainer>,
) -> bool {
convex_hull_infinite_plane_overlap_test(
*target,
*self,
0.0001_f32,
-offset_target,
orientation_target,
orientation,
container,
)
}
}
#[cfg(test)]
mod tests {
use glam_det::{UnitQuat, Vec3};
use wasm_bindgen_test::*;
use super::*;
use crate::overlap::test_overlap_test::test_overlap_test;
#[test]
#[wasm_bindgen_test]
fn test_cylinder_infinite_plane() {
let _ = env_logger::builder().is_test(true).try_init();
let infinite_plane = InfinitePlane::default();
let cylinder = Cylinder::new(2.0, 2.0);
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.1, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, -2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(45.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 3.3, 0.0),
UnitQuat::from_rotation_y(30.0),
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(45.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.83, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(45.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(135.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.83, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(135.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_z(45.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_z(60.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.74, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_z(60.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.74, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_z(60.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.5_f32, -0.5_f32, 0.5_f32, 0.85_f32),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.35_f32, -0.15_f32, 0.35_f32, 0.5_f32),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cylinder,
Vec3::new(0.0, 2.83, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.35_f32, -0.15_f32, 0.35_f32, 0.5_f32),
None
));
}
#[test]
#[wasm_bindgen_test]
fn test_infinite_plane_sphere() {
let _ = env_logger::builder().is_test(true).try_init();
let sphere = Sphere::new(1.0f32);
let infinite_plane = InfinitePlane::default();
assert!(test_overlap_test(
&infinite_plane,
&sphere,
Vec3::new(0.0, -0.5, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&sphere,
Vec3::new(0.0, -1.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&sphere,
Vec3::new(0.0, 1.1, 0.0),
UnitQuat::from_rotation_x(45.0),
UnitQuat::IDENTITY,
None
));
assert!(!test_overlap_test(
&infinite_plane,
&sphere,
Vec3::new(0.0, 1.1, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(45.0),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&sphere,
Vec3::new(0.0, 10.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
}
#[test]
#[wasm_bindgen_test]
fn test_infinite_plane_cuboid() {
let _ = env_logger::builder().is_test(true).try_init();
let cube = Cuboid::new(Vec3::new(1.0, 1.0, 1.0));
let infinite_plane = InfinitePlane::default();
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 0.5, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 0.4, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.0, 0.0, 0.3826834, 0.9238795),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, std::f32::consts::FRAC_1_SQRT_2, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.0, 0.0, 0.3826834, 0.9238795),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 0.8, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.3535534, -0.1464466, 0.3535534, 0.8535534),
None
));
assert!(test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 0.25, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.3535534, -0.1464466, 0.3535534, 0.8535534),
None
));
assert!(!test_overlap_test(
&infinite_plane,
&cube,
Vec3::new(0.0, 5.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
}
#[test]
#[wasm_bindgen_test]
fn test_infinite_plane_capsule() {
let _ = env_logger::builder().is_test(true).try_init();
let capsule = Capsule::new(1.0, 1.0);
let infinite_plane = InfinitePlane::default();
assert!(test_overlap_test(
&infinite_plane,
&capsule,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&capsule,
Vec3::new(0.0, 1.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(test_overlap_test(
&infinite_plane,
&capsule,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.0, 0.0, 1.0, 0.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&capsule,
Vec3::new(0.0, 1.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(0.0, 0.0, 1.0, 0.0),
None
));
assert!(test_overlap_test(
&infinite_plane,
&capsule,
Vec3::new(0.0, 1.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_xyzw_unchecked(
0.0,
0.0,
std::f32::consts::FRAC_1_SQRT_2,
std::f32::consts::FRAC_1_SQRT_2
),
None
));
}
#[test]
fn test_infinite_plane_infinite_plane() {
let _ = env_logger::builder().is_test(true).try_init();
let infinite_plane_a = InfinitePlane::default();
let infinite_plane_b = InfinitePlane::default();
assert!(infinite_plane_a.overlap_test(
&infinite_plane_b,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(infinite_plane_a.overlap_test(
&infinite_plane_b,
Vec3::new(0.0, 1.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::IDENTITY,
None
));
assert!(infinite_plane_a.overlap_test(
&infinite_plane_b,
Vec3::new(0.0, 10.0, 0.0),
UnitQuat::IDENTITY,
UnitQuat::from_rotation_x(45.0),
None
));
assert!(infinite_plane_a.overlap_test(
&infinite_plane_b,
Vec3::new(0.0, 0.0, 0.0),
UnitQuat::from_rotation_z(45.0),
UnitQuat::from_rotation_x(45.0),
None
));
assert!(!infinite_plane_a.overlap_test(
&infinite_plane_b,
Vec3::new(0.0, 2.0, 0.0),
UnitQuat::from_xyzw_unchecked(0.0_f32, 0.0_f32, 0.0_f32, 1.0_f32),
UnitQuat::from_xyzw_unchecked(1.0_f32, 0.0_f32, 0.0_f32, 0.0_f32),
None
));
}
}