use crate::{Vec2, Vec3};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Aabb2 {
pub min: Vec2,
pub max: Vec2,
}
impl Aabb2 {
#[inline]
pub const fn new(min: Vec2, max: Vec2) -> Self {
Self { min, max }
}
#[inline]
pub fn from_center_size(center: Vec2, size: Vec2) -> Self {
let half = size * 0.5;
Self {
min: center - half,
max: center + half,
}
}
#[inline]
pub fn center(&self) -> Vec2 {
(self.min + self.max) * 0.5
}
#[inline]
pub fn size(&self) -> Vec2 {
self.max - self.min
}
#[inline]
pub fn contains(&self, point: Vec2) -> bool {
point.x >= self.min.x
&& point.x <= self.max.x
&& point.y >= self.min.y
&& point.y <= self.max.y
}
#[inline]
pub fn intersects(&self, other: &Self) -> bool {
self.min.x <= other.max.x
&& self.max.x >= other.min.x
&& self.min.y <= other.max.y
&& self.max.y >= other.min.y
}
#[inline]
pub fn union(&self, other: &Self) -> Self {
Self {
min: Vec2::new(
self.min.x.min(other.min.x),
self.min.y.min(other.min.y),
),
max: Vec2::new(
self.max.x.max(other.max.x),
self.max.y.max(other.max.y),
),
}
}
#[inline]
pub fn expand(&self, margin: Vec2) -> Self {
Self {
min: self.min - margin,
max: self.max + margin,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Aabb3 {
pub min: Vec3,
pub max: Vec3,
}
impl Aabb3 {
#[inline]
pub const fn new(min: Vec3, max: Vec3) -> Self {
Self { min, max }
}
#[inline]
pub fn from_center_size(center: Vec3, size: Vec3) -> Self {
let half = size * 0.5;
Self {
min: center - half,
max: center + half,
}
}
#[inline]
pub fn center(&self) -> Vec3 {
(self.min + self.max) * 0.5
}
#[inline]
pub fn size(&self) -> Vec3 {
self.max - self.min
}
#[inline]
pub fn contains(&self, point: Vec3) -> 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]
pub fn intersects(&self, other: &Self) -> bool {
self.min.x <= other.max.x
&& self.max.x >= other.min.x
&& self.min.y <= other.max.y
&& self.max.y >= other.min.y
&& self.min.z <= other.max.z
&& self.max.z >= other.min.z
}
#[inline]
pub fn union(&self, other: &Self) -> Self {
Self {
min: Vec3::new(
self.min.x.min(other.min.x),
self.min.y.min(other.min.y),
self.min.z.min(other.min.z),
),
max: Vec3::new(
self.max.x.max(other.max.x),
self.max.y.max(other.max.y),
self.max.z.max(other.max.z),
),
}
}
#[inline]
pub fn expand(&self, margin: Vec3) -> Self {
Self {
min: self.min - margin,
max: self.max + margin,
}
}
#[inline]
pub fn corners(&self) -> [Vec3; 8] {
[
Vec3::new(self.min.x, self.min.y, self.min.z),
Vec3::new(self.max.x, self.min.y, self.min.z),
Vec3::new(self.min.x, self.max.y, self.min.z),
Vec3::new(self.max.x, self.max.y, self.min.z),
Vec3::new(self.min.x, self.min.y, self.max.z),
Vec3::new(self.max.x, self.min.y, self.max.z),
Vec3::new(self.min.x, self.max.y, self.max.z),
Vec3::new(self.max.x, self.max.y, self.max.z),
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aabb3_contains() {
let aabb = Aabb3::new(Vec3::ZERO, Vec3::ONE);
assert!(aabb.contains(Vec3::new(0.5, 0.5, 0.5)));
assert!(!aabb.contains(Vec3::new(2.0, 2.0, 2.0)));
}
#[test]
fn test_aabb3_intersects() {
let aabb1 = Aabb3::new(Vec3::ZERO, Vec3::ONE);
let aabb2 = Aabb3::new(Vec3::new(0.5, 0.5, 0.5), Vec3::new(1.5, 1.5, 1.5));
assert!(aabb1.intersects(&aabb2));
}
#[test]
fn test_aabb3_union() {
let aabb1 = Aabb3::new(Vec3::ZERO, Vec3::ONE);
let aabb2 = Aabb3::new(Vec3::ONE, Vec3::new(2.0, 2.0, 2.0));
let union = aabb1.union(&aabb2);
assert_eq!(union.min, Vec3::ZERO);
assert_eq!(union.max, Vec3::new(2.0, 2.0, 2.0));
}
}