rocketsim 0.2.4

Simulate Rocket League games at maximum efficiency
Documentation
use std::ops::{Add, AddAssign, Sub};

use glam::{Affine3A, Vec3A};

/// Axis-aligned bounding box in uu (or BT where noted by the caller).
///
/// Used for broadphase bounds, boost-pad queries, and goal volumes.
#[derive(Clone, Copy, Debug, Default)]
pub struct Aabb {
    pub min: Vec3A,
    pub max: Vec3A,
}

impl Aabb {
    pub const ZERO: Self = Self {
        min: Vec3A::ZERO,
        max: Vec3A::ZERO,
    };

    #[inline]
    #[must_use]
    pub const fn new(min: Vec3A, max: Vec3A) -> Self {
        Self { min, max }
    }

    /// Center point (`(min + max) / 2`).
    #[inline]
    #[must_use]
    pub fn center(&self) -> Vec3A {
        (self.min + self.max) * 0.5
    }

    /// Surface area (broadphase cost heuristic).
    #[must_use]
    pub fn area(&self) -> f32 {
        let extents = self.max - self.min;
        2.0 * (extents.x * extents.y + extents.x * extents.z + extents.y * extents.z)
    }

    /// True when the boxes overlap (touching counts).
    #[inline]
    #[must_use]
    pub fn intersects(&self, rhs: &Self) -> bool {
        self.min.cmple(rhs.max).all() && self.max.cmpge(rhs.min).all()
    }

    /// Smallest box containing both inputs.
    #[must_use]
    pub fn combine(&self, rhs: &Self) -> Self {
        Self::new(self.min.min(rhs.min), self.max.max(rhs.max))
    }

    /// Finds the point inside the AABB nearest to the given point
    #[inline]
    #[must_use]
    pub fn clamp(&self, point: Vec3A) -> Vec3A {
        point.clamp(self.min, self.max)
    }

    pub(crate) fn from_half_extents_transform(
        half_extents: Vec3A,
        margin: f32,
        t: &Affine3A,
    ) -> Self {
        let half_extents_with_margin = half_extents + margin;
        let abs_b = t.matrix3.abs();
        let center = t.translation;
        let extent = abs_b * half_extents_with_margin;

        Self {
            min: center - extent,
            max: center + extent,
        }
    }

    pub(crate) fn transform(&self, trans: &Affine3A, margin: f32) -> Self {
        let local_half_extents = 0.5 * (self.max - self.min) + margin;

        let local_center = self.center();
        let abs_b = trans.matrix3.abs();
        let center = trans.transform_point3a(local_center);
        let extent = abs_b * local_half_extents;

        Self {
            min: center - extent,
            max: center + extent,
        }
    }
}

impl Add for Aabb {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Self {
            min: self.min.min(rhs.min),
            max: self.max.max(rhs.max),
        }
    }
}

impl AddAssign for Aabb {
    fn add_assign(&mut self, rhs: Self) {
        self.min = self.min.min(rhs.min);
        self.max = self.max.max(rhs.max);
    }
}

impl Sub<Vec3A> for Aabb {
    type Output = Self;

    fn sub(self, rhs: Vec3A) -> Self::Output {
        Self {
            min: self.min - rhs,
            max: self.max - rhs,
        }
    }
}