Skip to content

Commit

Permalink
Create aabb directory and ball module.
Browse files Browse the repository at this point in the history
  • Loading branch information
finnbear committed Jan 7, 2025
1 parent e3b92cc commit 950ca20
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 72 deletions.
72 changes: 0 additions & 72 deletions src/aabb.rs → src/aabb/aabb_impl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//! Axis Aligned Bounding Boxes.
use nalgebra::{Point, SVector};
use std::fmt;
use std::ops::Index;
Expand All @@ -23,76 +21,6 @@ impl<T: BHValue + std::fmt::Display, const D: usize> fmt::Display for Aabb<T, D>
}
}

/// A trait implemented by things that may or may not intersect an AABB and, by extension,
/// things that can be used to traverse a BVH.
pub trait AabbIntersection<T: BHValue, const D: usize> {
/// Returns whether this object intersects an [`Aabb`].
///
/// # Examples
/// ```
/// use bvh::aabb::{Aabb, AabbIntersection};
/// use nalgebra::Point3;
///
/// struct XyPlane;
///
/// impl AabbIntersection<f32,3> for XyPlane {
/// fn intersects_aabb(&self, aabb: &Aabb<f32,3>) -> bool {
/// aabb.min[2] <= 0.0 && aabb.max[2] >= 0.0
/// }
/// }
///
/// let xy_plane = XyPlane;
/// let aabb = Aabb::with_bounds(Point3::new(-1.0,-1.0,-1.0), Point3::new(1.0,1.0,1.0));
/// assert!(xy_plane.intersects_aabb(&aabb));
/// ```
///
/// [`Aabb`]: struct.Aabb.html
///
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool;
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Aabb<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
for i in 0..D {
if self.max[i] < aabb.min[i] || aabb.max[i] < self.min[i] {
return false;
}
}
true
}
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Point<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
aabb.contains(self)
}
}

/// In 2D, a circle. In 3D, a sphere. This can be used for traversing BVH's.
pub struct Ball<T: BHValue, const D: usize> {
/// The center of the ball.
pub center: Point<T, D>,
/// The radius of the ball.
pub radius: T,
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Ball<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
// https://gamemath.com/book/geomtests.html A.14
// Finding the point in/on the AABB that is closest to the ball's center or,
// more specifically, find the squared distance betwen that point and the
// ball's center.
let mut distance_squared = T::zero();
for i in 0..D {
let closest_on_aabb = self.center[i].clamp(aabb.min[i], aabb.max[i]);
distance_squared += closest_on_aabb.powi(2);
}

// Then test if that point is in/on the ball.
distance_squared <= self.radius
}
}

/// A trait implemented by things which can be bounded by an [`Aabb`].
///
/// [`Aabb`]: struct.Aabb.html
Expand Down
48 changes: 48 additions & 0 deletions src/aabb/intersection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use nalgebra::Point;

use crate::{aabb::Aabb, bounding_hierarchy::BHValue};

/// A trait implemented by things that may or may not intersect an AABB and, by extension,
/// things that can be used to traverse a BVH.
pub trait AabbIntersection<T: BHValue, const D: usize> {
/// Returns whether this object intersects an [`Aabb`].
///
/// # Examples
/// ```
/// use bvh::aabb::{Aabb, AabbIntersection};
/// use nalgebra::Point3;
///
/// struct XyPlane;
///
/// impl AabbIntersection<f32,3> for XyPlane {
/// fn intersects_aabb(&self, aabb: &Aabb<f32,3>) -> bool {
/// aabb.min[2] <= 0.0 && aabb.max[2] >= 0.0
/// }
/// }
///
/// let xy_plane = XyPlane;
/// let aabb = Aabb::with_bounds(Point3::new(-1.0,-1.0,-1.0), Point3::new(1.0,1.0,1.0));
/// assert!(xy_plane.intersects_aabb(&aabb));
/// ```
///
/// [`Aabb`]: struct.Aabb.html
///
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool;
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Aabb<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
for i in 0..D {
if self.max[i] < aabb.min[i] || aabb.max[i] < self.min[i] {
return false;
}
}
true
}
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Point<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
aabb.contains(self)
}
}
7 changes: 7 additions & 0 deletions src/aabb/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Axis Aligned Bounding Boxes.
mod aabb_impl;
mod intersection;

pub use aabb_impl::*;
pub use intersection::*;
32 changes: 32 additions & 0 deletions src/ball.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Balls, including circles and spheres.
use crate::{
aabb::{Aabb, AabbIntersection},
bounding_hierarchy::BHValue,
};
use nalgebra::Point;

/// In 2D, a circle. In 3D, a sphere. This can be used for traversing BVH's.
pub struct Ball<T: BHValue, const D: usize> {
/// The center of the ball.
pub center: Point<T, D>,
/// The radius of the ball.
pub radius: T,
}

impl<T: BHValue, const D: usize> AabbIntersection<T, D> for Ball<T, D> {
fn intersects_aabb(&self, aabb: &Aabb<T, D>) -> bool {
// https://gamemath.com/book/geomtests.html A.14
// Finding the point in/on the AABB that is closest to the ball's center or,
// more specifically, find the squared distance betwen that point and the
// ball's center.
let mut distance_squared = T::zero();
for i in 0..D {
let closest_on_aabb = self.center[i].clamp(aabb.min[i], aabb.max[i]);
distance_squared += closest_on_aabb.powi(2);
}

// Then test if that point is in/on the ball.
distance_squared <= self.radius
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
extern crate test;

pub mod aabb;
pub mod ball;
pub mod bounding_hierarchy;
pub mod bvh;
pub mod flat_bvh;
Expand Down

0 comments on commit 950ca20

Please sign in to comment.