#[cfg(test)]
mod tests;
use crate::{nalgebra, prelude::*};
use approx::{AbsDiffEq, UlpsEq};
use std::borrow::Borrow;
#[derive(Debug, Copy, Clone)]
pub struct Aabb2<T> {
min: nalgebra::Vector2<T>,
max: nalgebra::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(always)]
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!(nalgebra::Vector2<f64>, f64);
impl_aabb2!(nalgebra::Vector2<f32>, f32);
#[derive(Debug, Copy, Clone)]
pub struct Aabb3<T> {
min: nalgebra::Vector3<T>,
max: nalgebra::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(always)]
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!(nalgebra::Vector3<f64>, f64);
impl_aabb3!(nalgebra::Vector3<f32>, f32);
macro_rules! impl_nalgebra_point2 {
($vec2_type:ty, $scalar_type:ty) => {
impl HasXY for $vec2_type {
type Scalar = $scalar_type;
#[inline(always)]
fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
<$vec2_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 Approx for $vec2_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)
}
}
};
}
macro_rules! impl_nalgebra_vector2 {
($vec2_type:ty, $vec3_type:ty, $scalar_type:ty, $affine_type:ty) => {
impl GenericVector2 for $vec2_type {
const ZERO: Self = Self::new(0.0, 0.0);
const ONE: Self = Self::new(1.0, 1.0);
type Vector3 = $vec3_type;
type Affine = $affine_type;
type Aabb = Aabb2<$scalar_type>;
#[inline(always)]
fn new(x: Self::Scalar, y: Self::Scalar) -> Self {
<$vec2_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 {
<$vec3_type>::new(self.x, self.y, z)
}
#[inline(always)]
fn magnitude(self) -> Self::Scalar {
self.norm()
}
#[inline(always)]
fn magnitude_sq(self) -> Self::Scalar {
self.norm_squared()
}
#[inline(always)]
fn dot(self, rhs: Self) -> Self::Scalar {
Self::dot(&self, &rhs)
}
#[inline(always)]
fn normalize(self) -> Self {
Self::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> {
<$vec2_type>::try_normalize(&self, epsilon)
}
#[inline(always)]
fn distance(self, rhs: Self) -> Self::Scalar {
(self - rhs).magnitude()
}
#[inline(always)]
fn distance_sq(self, rhs: Self) -> Self::Scalar {
(self - rhs).magnitude_sq()
}
#[inline(always)]
fn min(self, rhs: Self) -> Self {
self.inf(&rhs)
}
#[inline(always)]
fn max(self, rhs: Self) -> Self {
self.sup(&rhs)
}
#[inline(always)]
fn clamp(self, min: Self, max: Self) -> Self {
self.min(max).max(min)
}
#[inline(always)]
fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite()
}
}
};
}
impl_nalgebra_point2!(nalgebra::Point2<f32>, f32);
impl_nalgebra_point2!(nalgebra::Point2<f64>, f64);
impl_nalgebra_point2!(nalgebra::Vector2<f32>, f32);
impl_nalgebra_point2!(nalgebra::Vector2<f64>, f64);
impl_nalgebra_vector2!(
nalgebra::Vector2<f32>,
nalgebra::Vector3<f32>,
f32,
nalgebra::Matrix3<f32>
);
impl_nalgebra_vector2!(
nalgebra::Vector2<f64>,
nalgebra::Vector3<f64>,
f64,
nalgebra::Matrix3<f64>
);
macro_rules! impl_nalgebra_hasxyz {
($vec3_type:ty, $scalar_type:ty) => {
impl HasXY for $vec3_type {
type Scalar = $scalar_type;
#[inline(always)]
fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
<$vec3_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 $vec3_type {
#[inline(always)]
fn new_3d(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self {
<$vec3_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 Approx for $vec3_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)
}
}
};
}
macro_rules! impl_nalgebra_vector3 {
($vec3_type:ty, $vec2_type:ty, $scalar_type:ty) => {
impl GenericVector3 for $vec3_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 = $vec2_type;
type Affine = nalgebra::Matrix4<$scalar_type>;
type Aabb = Aabb3<$scalar_type>;
#[inline(always)]
fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self {
<$vec3_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 {
self.norm()
}
#[inline(always)]
fn magnitude_sq(self) -> Self::Scalar {
self.norm_squared()
}
#[inline(always)]
fn normalize(self) -> Self {
<$vec3_type>::normalize(&self)
}
#[inline(always)]
fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self> {
<$vec3_type>::try_normalize(&self, epsilon)
}
#[inline(always)]
fn dot(self, rhs: Self) -> Self::Scalar {
<$vec3_type>::dot(&self, &rhs)
}
#[inline(always)]
fn cross(self, rhs: Self) -> Self {
<$vec3_type>::cross(&self, &rhs)
}
#[inline(always)]
fn distance(self, rhs: Self) -> Self::Scalar {
(self - rhs).magnitude()
}
#[inline(always)]
fn distance_sq(self, rhs: Self) -> Self::Scalar {
(self - rhs).magnitude_squared()
}
#[inline(always)]
fn min(self, rhs: Self) -> Self {
self.inf(&rhs)
}
#[inline(always)]
fn max(self, rhs: Self) -> Self {
self.sup(&rhs)
}
#[inline(always)]
fn clamp(self, min: Self, max: Self) -> Self {
self.min(max).max(min)
}
#[inline(always)]
fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
}
}
};
}
impl_nalgebra_hasxyz!(nalgebra::Point3<f32>, f32);
impl_nalgebra_hasxyz!(nalgebra::Point3<f64>, f64);
impl_nalgebra_hasxyz!(nalgebra::Vector3<f32>, f32);
impl_nalgebra_hasxyz!(nalgebra::Vector3<f64>, f64);
impl_nalgebra_vector3!(nalgebra::Vector3<f32>, nalgebra::Vector2<f32>, f32);
impl_nalgebra_vector3!(nalgebra::Vector3<f64>, nalgebra::Vector2<f64>, f64);
macro_rules! impl_matrix3 {
($mat_type:ty, $vec_type:ty, $scalar_type:ty) => {
impl Affine2D for $mat_type
where
$vec_type: GenericVector2<Scalar = $scalar_type> + HasXY,
{
type Vector2 = $vec_type;
#[inline(always)]
fn from_cols_array(array: &[$scalar_type; 9]) -> Self {
<$mat_type>::from_column_slice(array)
}
#[inline(always)]
fn identity() -> Self {
<$mat_type>::identity()
}
#[inline(always)]
fn transform_vector2(&self, vec: $vec_type) -> $vec_type {
<$mat_type>::transform_vector(self, &vec)
}
#[inline(always)]
fn transform_point2(&self, point: $vec_type) -> $vec_type {
let point2 = nalgebra::Point2::new(point.x, point.y);
<$mat_type>::transform_point(self, &point2).coords
}
#[inline(always)]
fn try_inverse(&self) -> Option<Self> {
<$mat_type>::try_inverse(*self)
}
}
};
}
impl_matrix3!(nalgebra::Matrix3<f32>, nalgebra::Vector2<f32>, f32);
impl_matrix3!(nalgebra::Matrix3<f64>, nalgebra::Vector2<f64>, f64);
macro_rules! impl_matrix4 {
($mat_type:ty, $vec_type:ty, $scalar_type:ty) => {
impl Affine3D for $mat_type
where
$vec_type: GenericVector3<Scalar = $scalar_type> + HasXY,
{
type Vector3 = $vec_type;
#[inline(always)]
fn from_cols_array(array: &[$scalar_type; 16]) -> Self {
<$mat_type>::from_column_slice(array)
}
#[inline(always)]
fn identity() -> Self {
<$mat_type>::identity()
}
#[inline(always)]
fn transform_vector3(&self, vec: $vec_type) -> $vec_type {
<$mat_type>::transform_vector(self, &vec)
}
#[inline(always)]
fn transform_point3(&self, point: $vec_type) -> $vec_type {
let point3 = nalgebra::Point3::new(point.x, point.y, point.z);
<$mat_type>::transform_point(self, &point3).coords
}
#[inline(always)]
fn try_inverse(&self) -> Option<Self> {
<$mat_type>::try_inverse(*self)
}
#[inline(always)]
fn from_plane_to_xy(source_plane: Plane) -> Self {
crate::trait_impl::from_plane_to_xy::<nalgebra::Vector3<$scalar_type>>(source_plane)
}
#[inline(always)]
fn from_translation(translation: Self::Vector3) -> Self {
crate::trait_impl::from_translation::<nalgebra::Vector3<$scalar_type>>(translation)
}
#[inline(always)]
fn from_scale(scale: Self::Vector3) -> Self {
<$mat_type>::new_nonuniform_scaling(&scale)
}
}
};
}
impl_matrix4!(nalgebra::Matrix4<f32>, nalgebra::Vector3<f32>, f32);
impl_matrix4!(nalgebra::Matrix4<f64>, nalgebra::Vector3<f64>, f64);