#[cfg(test)]
mod tests;
use crate::{cgmath, prelude::*};
use approx::{AbsDiffEq, UlpsEq};
use cgmath::{EuclideanSpace, MetricSpace, SquareMatrix, Transform};
use std::borrow::Borrow;
#[derive(Debug, Copy, Clone)]
pub struct Aabb2<T> {
min: cgmath::Vector2<T>,
max: cgmath::Vector2<T>,
}
macro_rules! impl_aabb2 {
($vec_type:ty, $scalar_type:ty) => {
impl Default for Aabb2<$scalar_type> {
fn default() -> Self {
Self {
min: <$vec_type>::splat(<$scalar_type>::INFINITY),
max: <$vec_type>::splat(<$scalar_type>::NEG_INFINITY),
}
}
}
impl crate::prelude::Aabb2 for Aabb2<$scalar_type> {
type Vector = $vec_type;
fn from_point(point: Self::Vector) -> Self {
Self {
min: point,
max: point,
}
}
#[inline(always)]
fn from_corners(min: Self::Vector, max: Self::Vector) -> Self {
let mut rv = Self { min: max, max };
rv.add_point(min);
rv
}
#[inline(always)]
fn from_center_and_half_extents(
center: Self::Vector,
half_extents: Self::Vector,
) -> Self {
Self {
min: center - half_extents,
max: center + half_extents,
}
}
#[inline(always)]
fn from_center_and_size(center: Self::Vector, size: Self::Vector) -> Self {
let half_extents = size / 2.0;
Self::from_center_and_half_extents(center, half_extents)
}
fn from_points<I>(points: I) -> Self
where
I: IntoIterator,
I::Item: Borrow<Self::Vector>,
{
let mut aabb = Self::default();
for point in points {
let point = *point.borrow();
aabb.min = aabb.min.min(point);
aabb.max = aabb.max.max(point);
}
aabb
}
#[inline(always)]
fn max(&self) -> Self::Vector {
self.max
}
#[inline(always)]
fn min(&self) -> Self::Vector {
self.min
}
#[inline(always)]
fn add_point(&mut self, pos: Self::Vector) {
self.max = self.max.max(pos);
self.min = self.min.min(pos);
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.max.x < self.min.x
}
#[inline(always)]
fn add_aabb(&mut self, other: &Self) {
self.max = self.max.max(other.max);
self.min = self.min.min(other.min);
}
#[inline(always)]
fn fast_pad(&mut self, delta: Self::Vector) {
self.max += delta;
self.min -= delta;
}
#[inline]
fn pad(&mut self, delta: Self::Vector) {
let center = self.center();
let half_extent = (self.max - self.min) * 0.5;
let new_half_extent = (half_extent + delta).max(Self::Vector::ZERO);
self.max = center + new_half_extent;
self.min = center - new_half_extent;
}
#[inline(always)]
fn contains_point_inclusive(&self, point: Self::Vector) -> bool {
point.x >= self.min.x
&& point.x <= self.max.x
&& point.y >= self.min.y
&& point.y <= self.max.y
}
#[inline(always)]
fn center(&self) -> Self::Vector {
(self.max + self.min) * 0.5
}
#[inline(always)]
fn extents(&self) -> (Self::Vector, Self::Vector, Self::Vector) {
(self.min, self.max, self.max - self.min)
}
#[inline(always)]
fn contains_aabb_inclusive(&self, other: &Self) -> bool {
self.min.x <= other.min.x
&& other.max.x <= self.max.x
&& self.min.y <= other.min.y
&& other.max.y <= self.max.y
}
#[inline(always)]
fn convex_hull(&self) -> Vec<Self::Vector> {
crate::trait_impl::aabb_to_vec::<Aabb2<$scalar_type>>(*self)
}
#[inline(always)]
fn apply<F>(&mut self, f: F)
where
F: Fn(Self::Vector) -> Self::Vector,
{
if !self.is_empty() {
let new_min = f(self.min);
let new_max = f(self.max);
self.min = new_min.min(new_max);
self.max = new_max.max(new_min);
}
}
}
impl From<Aabb2<$scalar_type>> for Vec<$vec_type> {
#[inline(always)]
fn from(other: Aabb2<$scalar_type>) -> Self {
crate::trait_impl::aabb_to_vec(other)
}
}
impl PartialEq for Aabb2<$scalar_type>
where
Aabb2<$scalar_type>: crate::prelude::Aabb2,
{
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
crate::trait_impl::aabb2_partial_eq(self, other)
}
}
};
}
impl_aabb2!(cgmath::Vector2<f64>, f64);
impl_aabb2!(cgmath::Vector2<f32>, f32);
#[derive(Debug, Copy, Clone)]
pub struct Aabb3<T> {
min: cgmath::Vector3<T>,
max: cgmath::Vector3<T>,
}
macro_rules! impl_aabb3 {
($vec_type:ty, $scalar_type:ty) => {
impl Default for Aabb3<$scalar_type> {
fn default() -> Self {
Self {
min: <$vec_type>::splat(<$scalar_type>::INFINITY),
max: <$vec_type>::splat(<$scalar_type>::NEG_INFINITY),
}
}
}
impl crate::prelude::Aabb3 for Aabb3<$scalar_type> {
type Vector = $vec_type;
fn from_point(point: Self::Vector) -> Self {
Self {
min: point,
max: point,
}
}
#[inline(always)]
fn from_corners(min: Self::Vector, max: Self::Vector) -> Self {
let mut rv = Self { min: max, max };
rv.add_point(min);
rv
}
#[inline(always)]
fn from_center_and_half_extents(
center: Self::Vector,
half_extents: Self::Vector,
) -> Self {
Self {
min: center - half_extents,
max: center + half_extents,
}
}
#[inline(always)]
fn from_center_and_size(center: Self::Vector, size: Self::Vector) -> Self {
let half_extents = size / 2.0;
Self::from_center_and_half_extents(center, half_extents)
}
fn from_points<I>(points: I) -> Self
where
I: IntoIterator,
I::Item: Borrow<Self::Vector>,
{
let mut aabb = Self::default();
for point in points {
let point = *point.borrow();
aabb.min = aabb.min.min(point);
aabb.max = aabb.max.max(point);
}
aabb
}
#[inline(always)]
fn max(&self) -> Self::Vector {
self.max
}
#[inline(always)]
fn min(&self) -> Self::Vector {
self.min
}
#[inline(always)]
fn add_point(&mut self, pos: Self::Vector) {
self.max = self.max.max(pos);
self.min = self.min.min(pos);
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.max.x < self.min.x
}
#[inline(always)]
fn add_aabb(&mut self, other: &Self) {
self.max = self.max.max(other.max);
self.min = self.min.min(other.min);
}
#[inline(always)]
fn fast_pad(&mut self, delta: Self::Vector) {
self.max += delta;
self.min -= delta;
}
#[inline]
fn pad(&mut self, delta: Self::Vector) {
let center = self.center();
let half_extent = (self.max - self.min) * 0.5;
let new_half_extent = (half_extent + delta).max(Self::Vector::ZERO);
self.max = center + new_half_extent;
self.min = center - new_half_extent;
}
#[inline(always)]
fn contains_point_inclusive(&self, point: Self::Vector) -> bool {
point.x >= self.min.x
&& point.x <= self.max.x
&& point.y >= self.min.y
&& point.y <= self.max.y
&& point.z >= self.min.z
&& point.z <= self.max.z
}
#[inline(always)]
fn center(&self) -> Self::Vector {
(self.max + self.min) * 0.5
}
#[inline(always)]
fn extents(&self) -> (Self::Vector, Self::Vector, Self::Vector) {
(self.min, self.max, self.max - self.min)
}
#[inline(always)]
fn contains_aabb_inclusive(&self, other: &Self) -> bool {
self.min.x <= other.min.x
&& other.max.x <= self.max.x
&& self.min.y <= other.min.y
&& other.max.y <= self.max.y
&& self.min.z <= other.min.z
&& other.max.z <= self.max.z
}
#[inline(always)]
fn get_plane(&self) -> Option<Plane> {
Plane::get_plane::<Self>(self)
}
#[inline(always)]
fn get_plane_relaxed(&self, epsilon: $scalar_type, max_ulps: u32) -> Option<Plane> {
Plane::get_plane_relaxed::<$vec_type>(self, epsilon, max_ulps)
}
#[inline(always)]
fn apply<F>(&mut self, f: F)
where
F: Fn(Self::Vector) -> Self::Vector,
{
if !self.is_empty() {
let new_min = f(self.min);
let new_max = f(self.max);
self.min = new_min.min(new_max);
self.max = new_max.max(new_min);
}
}
}
impl PartialEq for Aabb3<$scalar_type>
where
Aabb3<$scalar_type>: crate::prelude::Aabb3,
{
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
crate::trait_impl::aabb3_partial_eq(self, other)
}
}
};
}
impl_aabb3!(cgmath::Vector3<f64>, f64);
impl_aabb3!(cgmath::Vector3<f32>, f32);
macro_rules! impl_cgmath_vector2 {
($scalar_type:ty) => {
impl HasXY for crate::cgmath::Vector2<$scalar_type> {
type Scalar =
<crate::cgmath::Vector2<$scalar_type> as crate::cgmath::VectorSpace>::Scalar;
#[inline(always)]
fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
<crate::cgmath::Vector2<$scalar_type>>::new(x, y)
}
#[inline(always)]
fn x(self) -> Self::Scalar {
self.x
}
#[inline(always)]
fn set_x(&mut self, val: Self::Scalar) {
self.x = val
}
#[inline(always)]
fn x_mut(&mut self) -> &mut Self::Scalar {
&mut self.x
}
#[inline(always)]
fn y(self) -> Self::Scalar {
self.y
}
#[inline(always)]
fn set_y(&mut self, val: Self::Scalar) {
self.y = val
}
#[inline(always)]
fn y_mut(&mut self) -> &mut Self::Scalar {
&mut self.y
}
}
impl GenericVector2 for crate::cgmath::Vector2<$scalar_type> {
const ZERO: Self = Self::new(0.0, 0.0);
const ONE: Self = Self::new(1.0, 1.0);
type Vector3 = crate::cgmath::Vector3<$scalar_type>;
type Affine = crate::cgmath::Matrix3<$scalar_type>;
type Aabb = Aabb2<$scalar_type>;
#[inline(always)]
fn new(x: Self::Scalar, y: Self::Scalar) -> Self {
<crate::cgmath::Vector2<$scalar_type>>::new(x, y)
}
#[inline(always)]
fn splat(value: Self::Scalar) -> Self {
Self::new(value, value)
}
#[inline(always)]
fn to_3d(self, z: Self::Scalar) -> Self::Vector3 {
<cgmath::Vector3<$scalar_type>>::new(self.x, self.y, z)
}
#[inline(always)]
fn magnitude(self) -> Self::Scalar {
cgmath::InnerSpace::magnitude(self)
}
#[inline(always)]
fn magnitude_sq(self) -> Self::Scalar {
cgmath::InnerSpace::magnitude2(self)
}
#[inline(always)]
fn dot(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector2<$scalar_type> as cgmath::InnerSpace>::dot(self, rhs)
}
#[inline(always)]
fn normalize(self) -> Self {
<cgmath::Vector2<$scalar_type> as cgmath::InnerSpace>::normalize(self)
}
#[inline(always)]
fn perp_dot(self, other: Self) -> Self::Scalar {
self.x * other.y - self.y * other.x
}
#[inline(always)]
fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self> {
let l_sq = cgmath::InnerSpace::magnitude2(self);
(l_sq > epsilon * epsilon).then(|| self / l_sq.sqrt())
}
#[inline(always)]
fn distance(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector2<$scalar_type> as cgmath::MetricSpace>::distance(self, rhs)
}
#[inline(always)]
fn distance_sq(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector2<$scalar_type>>::distance2(self, rhs)
}
#[inline(always)]
fn min(self, rhs: Self) -> Self {
<cgmath::Vector2<$scalar_type>>::new(self.x.min(rhs.x), self.y.min(rhs.y))
}
#[inline(always)]
fn max(self, rhs: Self) -> Self {
<cgmath::Vector2<$scalar_type>>::new(self.x.max(rhs.x), self.y.max(rhs.y))
}
#[inline(always)]
fn clamp(self, min: Self, max: Self) -> Self {
<cgmath::Vector2<$scalar_type>>::new(
self.x.clamp(min.x, max.x),
self.y.clamp(min.y, max.y),
)
}
#[inline(always)]
fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite()
}
}
impl Approx for cgmath::Vector2<$scalar_type> {
#[inline(always)]
fn is_ulps_eq(
self,
other: Self,
epsilon: <Self::Scalar as AbsDiffEq>::Epsilon,
max_ulps: u32,
) -> bool {
self.x.ulps_eq(&other.x, epsilon, max_ulps)
&& self.y.ulps_eq(&other.y, epsilon, max_ulps)
}
#[inline(always)]
fn is_abs_diff_eq(
self,
other: Self,
epsilon: <Self::Scalar as AbsDiffEq>::Epsilon,
) -> bool {
self.x.abs_diff_eq(&other.x, epsilon) && self.y.abs_diff_eq(&other.y, epsilon)
}
}
};
}
impl_cgmath_vector2!(f32);
impl_cgmath_vector2!(f64);
macro_rules! impl_cgmath_vector3 {
($scalar_type:ty) => {
impl HasXY for cgmath::Vector3<$scalar_type> {
type Scalar = <cgmath::Vector3<$scalar_type> as cgmath::VectorSpace>::Scalar;
#[inline(always)]
fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
<cgmath::Vector3<$scalar_type>>::new(x, y, Self::Scalar::ZERO)
}
#[inline(always)]
fn x(self) -> Self::Scalar {
self.x
}
#[inline(always)]
fn set_x(&mut self, val: Self::Scalar) {
self.x = val
}
#[inline(always)]
fn x_mut(&mut self) -> &mut Self::Scalar {
&mut self.x
}
#[inline(always)]
fn y(self) -> Self::Scalar {
self.y
}
#[inline(always)]
fn set_y(&mut self, val: Self::Scalar) {
self.y = val
}
#[inline(always)]
fn y_mut(&mut self) -> &mut Self::Scalar {
&mut self.y
}
}
impl HasXYZ for cgmath::Vector3<$scalar_type> {
#[inline(always)]
fn new_3d(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self {
<cgmath::Vector3<$scalar_type>>::new(x, y, z)
}
#[inline(always)]
fn z(self) -> Self::Scalar {
self.z
}
#[inline(always)]
fn set_z(&mut self, val: Self::Scalar) {
self.z = val
}
#[inline(always)]
fn z_mut(&mut self) -> &mut Self::Scalar {
&mut self.z
}
}
impl GenericVector3 for cgmath::Vector3<$scalar_type> {
const ZERO: Self = Self::new(0.0, 0.0, 0.0);
const ONE: Self = Self::new(1.0, 1.0, 1.0);
type Vector2 = cgmath::Vector2<$scalar_type>;
type Affine = cgmath::Matrix4<$scalar_type>;
type Aabb = Aabb3<$scalar_type>;
#[inline(always)]
fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self {
<cgmath::Vector3<$scalar_type>>::new(x, y, z)
}
#[inline(always)]
fn splat(value: Self::Scalar) -> Self {
Self::new(value, value, value)
}
#[inline(always)]
fn to_2d(self) -> Self::Vector2 {
Self::Vector2::new(self.x, self.y)
}
#[inline(always)]
fn magnitude(self) -> Self::Scalar {
cgmath::InnerSpace::magnitude(self)
}
#[inline(always)]
fn magnitude_sq(self) -> Self::Scalar {
cgmath::InnerSpace::magnitude2(self)
}
#[inline(always)]
fn normalize(self) -> Self {
cgmath::InnerSpace::normalize(self)
}
#[inline(always)]
fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self> {
let l_sq = cgmath::InnerSpace::magnitude2(self);
(l_sq > epsilon * epsilon).then(|| self / l_sq.sqrt())
}
#[inline(always)]
fn dot(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector3<$scalar_type> as cgmath::InnerSpace>::dot(self, rhs)
}
#[inline(always)]
fn cross(self, rhs: Self) -> Self {
<cgmath::Vector3<$scalar_type>>::cross(self, rhs)
}
#[inline(always)]
fn distance(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector3<$scalar_type> as cgmath::MetricSpace>::distance(self, rhs)
}
#[inline(always)]
fn distance_sq(self, rhs: Self) -> Self::Scalar {
<cgmath::Vector3<$scalar_type>>::distance2(self, rhs)
}
#[inline(always)]
fn min(self, rhs: Self) -> Self {
<cgmath::Vector3<$scalar_type>>::new(
self.x.min(rhs.x),
self.y.min(rhs.y),
self.z.min(rhs.z),
)
}
#[inline(always)]
fn max(self, rhs: Self) -> Self {
<cgmath::Vector3<$scalar_type>>::new(
self.x.max(rhs.x),
self.y.max(rhs.y),
self.z.max(rhs.z),
)
}
#[inline(always)]
fn clamp(self, min: Self, max: Self) -> Self {
<cgmath::Vector3<$scalar_type>>::new(
self.x.clamp(min.x, max.x),
self.y.clamp(min.y, max.y),
self.z.clamp(min.z, max.z),
)
}
#[inline(always)]
fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
}
}
impl Approx for cgmath::Vector3<$scalar_type> {
#[inline(always)]
fn is_ulps_eq(
self,
other: Self,
epsilon: <Self::Scalar as AbsDiffEq>::Epsilon,
max_ulps: u32,
) -> bool {
self.x.ulps_eq(&other.x, epsilon, max_ulps)
&& self.y.ulps_eq(&other.y, epsilon, max_ulps)
&& self.z.ulps_eq(&other.z, epsilon, max_ulps)
}
#[inline(always)]
fn is_abs_diff_eq(
self,
other: Self,
epsilon: <Self::Scalar as AbsDiffEq>::Epsilon,
) -> bool {
self.x.abs_diff_eq(&other.x, epsilon)
&& self.y.abs_diff_eq(&other.y, epsilon)
&& self.z.abs_diff_eq(&other.z, epsilon)
}
}
};
}
impl_cgmath_vector3!(f32);
impl_cgmath_vector3!(f64);
macro_rules! impl_matrix3_cgmath {
($scalar_type:ty) => {
impl Affine2D for cgmath::Matrix3<$scalar_type>
where
cgmath::Vector2<$scalar_type>: GenericVector2<Scalar = $scalar_type> + HasXY,
{
type Vector2 = cgmath::Vector2<$scalar_type>;
#[inline(always)]
fn from_cols_array(array: &[$scalar_type; 9]) -> Self {
cgmath::Matrix3::<$scalar_type>::from_cols(
cgmath::Vector3::<$scalar_type>::new_3d(array[0], array[1], array[2]),
cgmath::Vector3::<$scalar_type>::new_3d(array[3], array[4], array[5]),
cgmath::Vector3::<$scalar_type>::new_3d(array[6], array[7], array[8]),
)
}
#[inline(always)]
fn identity() -> Self {
<cgmath::Matrix3<$scalar_type> as cgmath::SquareMatrix>::identity()
}
#[inline(always)]
fn transform_vector2(
&self,
vec: cgmath::Vector2<$scalar_type>,
) -> cgmath::Vector2<$scalar_type> {
let vec3 = cgmath::Vector3::new(vec.x, vec.y, 0.0);
let transformed = self * vec3;
cgmath::Vector2::<$scalar_type>::new(transformed.x, transformed.y)
}
#[inline(always)]
fn transform_point2(
&self,
point: cgmath::Vector2<$scalar_type>,
) -> cgmath::Vector2<$scalar_type> {
let p: cgmath::Point2<$scalar_type> =
cgmath::Point2::<$scalar_type>::from_vec(point);
self.transform_point(p).to_vec()
}
#[inline(always)]
fn try_inverse(&self) -> Option<Self> {
self.invert()
}
}
};
}
impl_matrix3_cgmath!(f32);
impl_matrix3_cgmath!(f64);
macro_rules! impl_matrix4_cgmath {
($scalar_type:ty) => {
impl Affine3D for cgmath::Matrix4<$scalar_type>
where
cgmath::Vector3<$scalar_type>: GenericVector3<Scalar = $scalar_type> + HasXY,
{
type Vector3 = cgmath::Vector3<$scalar_type>;
#[inline(always)]
fn from_cols_array(array: &[$scalar_type; 16]) -> Self {
cgmath::Matrix4::<$scalar_type>::from_cols(
cgmath::Vector4::<$scalar_type>::new(array[0], array[1], array[2], array[3]),
cgmath::Vector4::<$scalar_type>::new(array[4], array[5], array[6], array[7]),
cgmath::Vector4::<$scalar_type>::new(array[8], array[9], array[10], array[11]),
cgmath::Vector4::<$scalar_type>::new(
array[12], array[13], array[14], array[15],
),
)
}
#[inline(always)]
fn identity() -> Self {
<cgmath::Matrix4<$scalar_type> as cgmath::SquareMatrix>::identity()
}
#[inline(always)]
fn transform_vector3(
&self,
vec: cgmath::Vector3<$scalar_type>,
) -> cgmath::Vector3<$scalar_type> {
let vec4 = cgmath::Vector4::new(vec.x, vec.y, vec.z, 0.0);
let transformed = self * vec4;
cgmath::Vector3::<$scalar_type>::new(transformed.x, transformed.y, transformed.z)
}
#[inline(always)]
fn transform_point3(
&self,
point: cgmath::Vector3<$scalar_type>,
) -> cgmath::Vector3<$scalar_type> {
let p: cgmath::Point3<$scalar_type> =
cgmath::Point3::<$scalar_type>::from_vec(point);
self.transform_point(p).to_vec()
}
#[inline(always)]
fn try_inverse(&self) -> Option<Self> {
self.invert()
}
#[inline(always)]
fn from_plane_to_xy(source_plane: Plane) -> Self {
crate::trait_impl::from_plane_to_xy::<cgmath::Vector3<$scalar_type>>(source_plane)
}
#[inline(always)]
fn from_translation(translation: Self::Vector3) -> Self {
cgmath::Matrix4::<$scalar_type>::from_translation(translation)
}
#[inline(always)]
fn from_scale(scale: Self::Vector3) -> Self {
cgmath::Matrix4::<$scalar_type>::from_nonuniform_scale(scale.x, scale.y, scale.z)
}
}
};
}
impl_matrix4_cgmath!(f32);
impl_matrix4_cgmath!(f64);