From 4e7da2cf4e7105f6b18e3081a1fa114bfb0e83b4 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sat, 2 Dec 2023 15:53:35 +0200 Subject: [PATCH] Add `Ray2d` and `Ray3d` primitives --- crates/bevy_math/src/primitives/dim2.rs | 35 +++++++++++++++++++++- crates/bevy_math/src/primitives/dim3.rs | 40 ++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/crates/bevy_math/src/primitives/dim2.rs b/crates/bevy_math/src/primitives/dim2.rs index 35e5363dc6acd..631ff7421c3e5 100644 --- a/crates/bevy_math/src/primitives/dim2.rs +++ b/crates/bevy_math/src/primitives/dim2.rs @@ -2,7 +2,7 @@ use super::{Primitive2d, WindingOrder}; use crate::Vec2; /// A normalized vector pointing in a direction in 2D space -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct Direction2d(Vec2); impl From for Direction2d { @@ -63,6 +63,32 @@ pub struct Plane2d { } impl Primitive2d for Plane2d {} +/// An infinite half-line starting at `origin` and going in `direction` in 2D space. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Ray2d { + /// The origin of the ray. + pub origin: Vec2, + /// The direction of the ray. + pub direction: Direction2d, +} + +impl Ray2d { + /// Create a new `Ray2d` from a given origin and direction + #[inline] + pub fn new(origin: Vec2, direction: Vec2) -> Self { + Self { + origin, + direction: direction.into(), + } + } + + /// Get a point at a given distance along the ray + #[inline] + pub fn get_point(&self, distance: f32) -> Vec2 { + self.origin + *self.direction * distance + } +} + /// An infinite line along a direction in 2D space. /// /// For a finite line: [`Segment2d`] @@ -323,6 +349,13 @@ impl RegularPolygon { mod tests { use super::*; + #[test] + fn ray_math() { + let ray = Ray2d::new(Vec2::ZERO, Vec2::Y * 10.0); + assert_eq!(*ray.direction, Vec2::Y, "ray direction is not normalized"); + assert_eq!(ray.get_point(2.0), Vec2::Y * 2.0); + } + #[test] fn triangle_winding_order() { let mut cw_triangle = Triangle2d::new( diff --git a/crates/bevy_math/src/primitives/dim3.rs b/crates/bevy_math/src/primitives/dim3.rs index 891f51558fd3b..1529044af5e9a 100644 --- a/crates/bevy_math/src/primitives/dim3.rs +++ b/crates/bevy_math/src/primitives/dim3.rs @@ -2,7 +2,7 @@ use super::Primitive3d; use crate::Vec3; /// A normalized vector pointing in a direction in 3D space -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct Direction3d(Vec3); impl From for Direction3d { @@ -43,6 +43,32 @@ pub struct Plane3d { } impl Primitive3d for Plane3d {} +/// An infinite half-line starting at `origin` and going in `direction` in 3D space. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Ray3d { + /// The origin of the ray. + pub origin: Vec3, + /// The direction of the ray. + pub direction: Direction3d, +} + +impl Ray3d { + /// Create a new `Ray3d` from a given origin and direction + #[inline] + pub fn new(origin: Vec3, direction: Vec3) -> Self { + Self { + origin, + direction: direction.into(), + } + } + + /// Get a point at a given distance along the ray + #[inline] + pub fn get_point(&self, distance: f32) -> Vec3 { + self.origin + *self.direction * distance + } +} + /// An infinite line along a direction in 3D space. /// /// For a finite line: [`Segment3d`] @@ -331,3 +357,15 @@ impl Torus { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ray_math() { + let ray = Ray3d::new(Vec3::ZERO, Vec3::Z * 10.0); + assert_eq!(*ray.direction, Vec3::Z, "ray direction is not normalized"); + assert_eq!(ray.get_point(2.0), Vec3::Z * 2.0); + } +}