Skip to content

Commit

Permalink
Move raycast module to all-is-cubes-base.
Browse files Browse the repository at this point in the history
This move will help us pre-compute a single set of light propagation
data at build time. It also makes sense abstractly since the raycaster
only has `math` dependencies, rarely changes, and is a fundamental
algorithm for lots of things.
  • Loading branch information
kpreid committed May 12, 2024
1 parent 88fe1c2 commit 4bd005a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 18 deletions.
7 changes: 7 additions & 0 deletions all-is-cubes-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ extern crate alloc;
#[macro_use]
pub mod math;

/// Do not use this module directly; its contents are re-exported from `all-is-cubes`.
pub mod raycast;

/// Do not use this module directly; its contents are re-exported from `all-is-cubes`.
pub mod resolution;

Expand All @@ -30,3 +33,7 @@ pub mod time;

/// Do not use this module directly; its contents are re-exported from `all-is-cubes`.
pub mod util;

// reexport for convenience of our tests
#[doc(hidden)]
pub use euclid;
21 changes: 21 additions & 0 deletions all-is-cubes-base/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,27 @@ macro_rules! notnan {
};
}

#[cfg(not(feature = "std"))]
/// Identical to [`num_traits::Euclid`] except that its signatures are compatible with
/// `std` versions.
///
/// Note: this code is duplicated between `all-is-cubes` and
/// `all-is-cubes-base` so that it doesn't need to be public.
pub(crate) trait Euclid {
#[allow(dead_code)]
fn div_euclid(self, rhs: Self) -> Self;
fn rem_euclid(self, rhs: Self) -> Self;
}
#[cfg(not(feature = "std"))]
impl<T: num_traits::Euclid + Copy> Euclid for T {
fn div_euclid(self, rhs: Self) -> Self {
<T as num_traits::Euclid>::div_euclid(&self, &rhs)
}
fn rem_euclid(self, rhs: Self) -> Self {
<T as num_traits::Euclid>::rem_euclid(&self, &rhs)
}
}

/// Sort exactly two items; swap them if `a > b`.
#[inline]
#[doc(hidden)]
Expand Down
35 changes: 18 additions & 17 deletions all-is-cubes/src/raycast.rs → all-is-cubes-base/src/raycast.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//! Algorithm for raycasting through voxel grids.
//!
//! This deals purely with the question “which cubes does this ray intersect”,
//! and does not concern itself with what might occupy those cubes. If you’re
//! looking for *raytracing*, forming an image from many rays, that’s
//! [`all_is_cubes::raytracer`](crate::raytracer).
use core::f64::consts::TAU;

use euclid::Vector3D;
Expand Down Expand Up @@ -46,6 +39,7 @@ impl Ray {
/// Other than the use of [`Into`], this is equivalent to a struct literal.
///
/// ```
/// # use all_is_cubes_base as all_is_cubes;
/// use all_is_cubes::euclid::{point3, vec3};
/// use all_is_cubes::raycast::Ray;
///
Expand All @@ -65,21 +59,23 @@ impl Ray {
}

/// Prepares a [`Raycaster`] that will iterate over cubes intersected by this ray.
#[must_use]
pub fn cast(&self) -> Raycaster {
Raycaster::new(self.origin, self.direction)
}

/// Scale the ray's coordinates by the given factor.
#[allow(dead_code)] // TODO: this is expected to be used by voxel collision
pub(crate) fn scale_all(self, scale: FreeCoordinate) -> Self {
#[must_use]
pub fn scale_all(self, scale: FreeCoordinate) -> Self {
Self {
origin: self.origin * scale,
direction: self.direction * scale,
}
}

/// Scale the ray's direction vector by the given factor.
pub(crate) fn scale_direction(self, scale: FreeCoordinate) -> Self {
#[must_use]
pub fn scale_direction(self, scale: FreeCoordinate) -> Self {
Self {
origin: self.origin,
direction: self.direction * scale,
Expand All @@ -89,8 +85,9 @@ impl Ray {
/// Return `self.origin + self.direction`, the “far end” of the ray.
///
/// This only makes sense in contexts which are specifically using the length of the
/// direction vector as a distance.
pub(crate) fn unit_endpoint(self) -> FreePoint {
/// direction vector as a distance, or for visualization as a line segment.
#[must_use]
pub fn unit_endpoint(self) -> FreePoint {
self.origin + self.direction
}

Expand Down Expand Up @@ -165,9 +162,7 @@ impl Geometry for Ray {
/// Iterator over grid positions that intersect a given ray.
///
/// The grid is of unit cubes which are identified by the integer coordinates of
/// their most negative corners, the same definition used by [`Space`] and [`GridAab`].
///
/// [`Space`]: crate::space::Space
/// their most negative corners, the same definition used by [`Cube`].
//
//---
//
Expand Down Expand Up @@ -238,6 +233,7 @@ impl Raycaster {
/// to restrict it.
///
/// ```
/// # use all_is_cubes_base as all_is_cubes;
/// use all_is_cubes::math::Cube;
/// use all_is_cubes::raycast::Raycaster;
///
Expand Down Expand Up @@ -326,7 +322,8 @@ impl Raycaster {
/// Like [`Self::within`] but not moving self.
///
/// TODO: This function was added for the needs of the raytracer. Think about API design more.
pub(crate) fn set_bounds(&mut self, bounds: GridAab) {
#[doc(hidden)]
pub fn set_bounds(&mut self, bounds: GridAab) {
if self.bounds.is_none() {
self.bounds = Some(Vector3D::new(
bounds.x_range(),
Expand All @@ -346,7 +343,8 @@ impl Raycaster {
/// intervening `next()` is not currently guaranteed.
///
/// TODO: This function was added for the needs of the raytracer. Think about API design more.
pub(crate) fn remove_bound(&mut self) {
#[doc(hidden)]
pub fn remove_bound(&mut self) {
self.bounds = None;
}

Expand Down Expand Up @@ -608,6 +606,7 @@ impl RaycastStep {
/// [`Face7::Within`].
///
/// ```
/// # use all_is_cubes_base as all_is_cubes;
/// use all_is_cubes::math::Face7;
/// use all_is_cubes::raycast::Raycaster;
///
Expand All @@ -629,6 +628,7 @@ impl RaycastStep {
/// `self.cube_ahead() == self.cube_behind()`.
///
/// ```
/// # use all_is_cubes_base as all_is_cubes;
/// use all_is_cubes::math::Cube;
/// use all_is_cubes::raycast::Raycaster;
///
Expand Down Expand Up @@ -665,6 +665,7 @@ impl RaycastStep {
/// no more than +1.0 different.
///
/// ```
/// # use all_is_cubes_base as all_is_cubes;
/// use all_is_cubes::euclid::point3;
/// use all_is_cubes::raycast::Ray;
///
Expand Down
11 changes: 10 additions & 1 deletion all-is-cubes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ pub mod listen;
pub mod math;
pub mod op;
pub mod physics;
pub mod raycast;
pub mod raytracer;
#[cfg(feature = "rerun")]
#[doc(hidden)]
Expand All @@ -183,6 +182,16 @@ pub mod transaction;
pub mod universe;
pub mod util;

/// Algorithm for raycasting through voxel grids.
///
/// This deals purely with the question “which cubes does this ray intersect”,
/// and does not concern itself with what might occupy those cubes. If you’re
/// looking for *raytracing*, forming an image from many rays, that’s
/// [`all_is_cubes::raytracer`](crate::raytracer).
pub mod raycast {
pub use all_is_cubes_base::raycast::*;
}

/// Re-export the version of the `arcstr` string type library we're using.
pub use arcstr;
/// Re-export the version of the `euclid` vector math library we're using.
Expand Down
3 changes: 3 additions & 0 deletions all-is-cubes/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub use all_is_cubes_base::math::GridAab;
#[cfg(not(feature = "std"))]
/// Identical to [`num_traits::Euclid`] except that its signatures are compatible with
/// `std` versions.
///
/// Note: this code is duplicated between `all-is-cubes` and
/// `all-is-cubes-base` so that it doesn't need to be public.
pub(crate) trait Euclid {
fn div_euclid(self, rhs: Self) -> Self;
fn rem_euclid(self, rhs: Self) -> Self;
Expand Down

0 comments on commit 4bd005a

Please sign in to comment.