mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Rename Direction2d/3d
to Dir2/3
(#12189)
# Objective Split up from #12017, rename Bevy's direction types. Currently, Bevy has the `Direction2d`, `Direction3d`, and `Direction3dA` types, which provide a type-level guarantee that their contained vectors remain normalized. They can be very useful for a lot of APIs for safety, explicitness, and in some cases performance, as they can sometimes avoid unnecessary normalizations. However, many consider them to be inconvenient to use, and opt for standard vector types like `Vec3` because of this. One reason is that the direction type names are a bit long and can be annoying to write (of course you can use autocomplete, but just typing `Vec3` is still nicer), and in some intances, the extra characters can make formatting worse. The naming is also inconsistent with Glam's shorter type names, and results in names like `Direction3dA`, which (in my opinion) are difficult to read and even a bit ugly. This PR proposes renaming the types to `Dir2`, `Dir3`, and `Dir3A`. These names are nice and easy to write, consistent with Glam, and work well for variants like the SIMD aligned `Dir3A`. As a bonus, it can also result in nicer formatting in a lot of cases, which can be seen from the diff of this PR. Some examples of what it looks like: (copied from #12017) ```rust // Before let ray_cast = RayCast2d::new(Vec2::ZERO, Direction2d::X, 5.0); // After let ray_cast = RayCast2d::new(Vec2::ZERO, Dir2::X, 5.0); ``` ```rust // Before (an example using Bevy XPBD) let hit = spatial_query.cast_ray( Vec3::ZERO, Direction3d::X, f32::MAX, true, SpatialQueryFilter::default(), ); // After let hit = spatial_query.cast_ray( Vec3::ZERO, Dir3::X, f32::MAX, true, SpatialQueryFilter::default(), ); ``` ```rust // Before self.circle( Vec3::new(0.0, -2.0, 0.0), Direction3d::Y, 5.0, Color::TURQUOISE, ); // After (formatting is collapsed in this case) self.circle(Vec3::new(0.0, -2.0, 0.0), Dir3::Y, 5.0, Color::TURQUOISE); ``` ## Solution Rename `Direction2d`, `Direction3d`, and `Direction3dA` to `Dir2`, `Dir3`, and `Dir3A`. --- ## Migration Guide The `Direction2d` and `Direction3d` types have been renamed to `Dir2` and `Dir3`. ## Additional Context This has been brought up on the Discord a few times, and we had a small [poll](https://discord.com/channels/691052431525675048/1203087353850364004/1212465038711984158) on this. `Dir2`/`Dir3`/`Dir3A` was quite unanimously chosen as the best option, but of course it was a very small poll and inconclusive, so other opinions are certainly welcome too. --------- Co-authored-by: IceSentry <c.giguere42@gmail.com>
This commit is contained in:
parent
043041f3aa
commit
f418de8eb6
23 changed files with 262 additions and 348 deletions
|
@ -5,7 +5,7 @@
|
|||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
use bevy_math::Mat2;
|
||||
use bevy_math::{Direction3d, Quat, Vec2, Vec3};
|
||||
use bevy_math::{Dir3, Quat, Vec2, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
use std::f32::consts::TAU;
|
||||
|
||||
|
@ -106,12 +106,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||
/// # use bevy_render::prelude::*;
|
||||
/// # use bevy_math::prelude::*;
|
||||
/// fn system(mut gizmos: Gizmos) {
|
||||
/// gizmos.circle(Vec3::ZERO, Direction3d::Z, 1., LegacyColor::GREEN);
|
||||
/// gizmos.circle(Vec3::ZERO, Dir3::Z, 1., LegacyColor::GREEN);
|
||||
///
|
||||
/// // Circles have 32 line-segments by default.
|
||||
/// // You may want to increase this for larger circles.
|
||||
/// gizmos
|
||||
/// .circle(Vec3::ZERO, Direction3d::Z, 5., LegacyColor::RED)
|
||||
/// .circle(Vec3::ZERO, Dir3::Z, 5., LegacyColor::RED)
|
||||
/// .segments(64);
|
||||
/// }
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
|
@ -120,7 +120,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
|
|||
pub fn circle(
|
||||
&mut self,
|
||||
position: Vec3,
|
||||
normal: Direction3d,
|
||||
normal: Dir3,
|
||||
radius: f32,
|
||||
color: LegacyColor,
|
||||
) -> EllipseBuilder<'_, 'w, 's, T> {
|
||||
|
|
|
@ -9,7 +9,7 @@ use bevy_ecs::{
|
|||
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
|
||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||
};
|
||||
use bevy_math::{Direction3d, Mat2, Quat, Vec2, Vec3};
|
||||
use bevy_math::{Dir3, Mat2, Quat, Vec2, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
use bevy_transform::TransformPoint;
|
||||
|
||||
|
@ -629,7 +629,7 @@ impl<T: GizmoConfigGroup> Drop for SphereBuilder<'_, '_, '_, T> {
|
|||
self.gizmos
|
||||
.circle(
|
||||
self.position,
|
||||
Direction3d::new_unchecked(self.rotation * axis),
|
||||
Dir3::new_unchecked(self.rotation * axis),
|
||||
self.radius,
|
||||
self.color,
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy_math::primitives::{
|
|||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon,
|
||||
Polyline2d, Primitive2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
};
|
||||
use bevy_math::{Direction2d, Mat2, Vec2};
|
||||
use bevy_math::{Dir2, Mat2, Vec2};
|
||||
use bevy_render::color::LegacyColor;
|
||||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
|
@ -38,12 +38,12 @@ pub trait GizmoPrimitive2d<P: Primitive2d> {
|
|||
|
||||
// direction 2d
|
||||
|
||||
impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d<Direction2d> for Gizmos<'w, 's, T> {
|
||||
impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d<Dir2> for Gizmos<'w, 's, T> {
|
||||
type Output<'a> = () where Self : 'a;
|
||||
|
||||
fn primitive_2d(
|
||||
&mut self,
|
||||
primitive: Direction2d,
|
||||
primitive: Dir2,
|
||||
position: Vec2,
|
||||
angle: f32,
|
||||
color: LegacyColor,
|
||||
|
@ -163,7 +163,7 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d<Capsule2d> for Gizmos<'w, 's,
|
|||
pub struct Line2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
|
||||
gizmos: &'a mut Gizmos<'w, 's, T>,
|
||||
|
||||
direction: Direction2d, // Direction of the line
|
||||
direction: Dir2, // Direction of the line
|
||||
|
||||
position: Vec2, // position of the center of the line
|
||||
rotation: Mat2, // rotation of the line
|
||||
|
@ -262,7 +262,7 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d<Plane2d> for Gizmos<'w, 's, T
|
|||
.draw_arrow(true);
|
||||
|
||||
// draw the plane line
|
||||
let direction = Direction2d::new_unchecked(-normal.perp());
|
||||
let direction = Dir2::new_unchecked(-normal.perp());
|
||||
self.primitive_2d(Line2d { direction }, position, angle, color)
|
||||
.draw_arrow(false);
|
||||
|
||||
|
@ -282,8 +282,8 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d<Plane2d> for Gizmos<'w, 's, T
|
|||
pub struct Segment2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
|
||||
gizmos: &'a mut Gizmos<'w, 's, T>,
|
||||
|
||||
direction: Direction2d, // Direction of the line segment
|
||||
half_length: f32, // Half-length of the line segment
|
||||
direction: Dir2, // Direction of the line segment
|
||||
half_length: f32, // Half-length of the line segment
|
||||
|
||||
position: Vec2, // position of the center of the line segment
|
||||
rotation: Mat2, // rotation of the line segment
|
||||
|
|
|
@ -7,7 +7,7 @@ use bevy_math::primitives::{
|
|||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
|
||||
Polyline3d, Primitive3d, Segment3d, Sphere, Torus,
|
||||
};
|
||||
use bevy_math::{Direction3d, Quat, Vec3};
|
||||
use bevy_math::{Dir3, Quat, Vec3};
|
||||
use bevy_render::color::LegacyColor;
|
||||
|
||||
use crate::prelude::{GizmoConfigGroup, Gizmos};
|
||||
|
@ -35,12 +35,12 @@ pub trait GizmoPrimitive3d<P: Primitive3d> {
|
|||
|
||||
// direction 3d
|
||||
|
||||
impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Direction3d> for Gizmos<'w, 's, T> {
|
||||
impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d<Dir3> for Gizmos<'w, 's, T> {
|
||||
type Output<'a> = () where Self: 'a;
|
||||
|
||||
fn primitive_3d(
|
||||
&mut self,
|
||||
primitive: Direction3d,
|
||||
primitive: Dir3,
|
||||
position: Vec3,
|
||||
rotation: Quat,
|
||||
color: LegacyColor,
|
||||
|
@ -139,7 +139,7 @@ pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
|
|||
gizmos: &'a mut Gizmos<'w, 's, T>,
|
||||
|
||||
// direction of the normal orthogonal to the plane
|
||||
normal: Direction3d,
|
||||
normal: Dir3,
|
||||
|
||||
// Rotation of the sphere around the origin in 3D space
|
||||
rotation: Quat,
|
||||
|
@ -218,7 +218,7 @@ impl<T: GizmoConfigGroup> Drop for Plane3dBuilder<'_, '_, '_, T> {
|
|||
.map(|angle| Quat::from_axis_angle(normal, angle))
|
||||
.for_each(|quat| {
|
||||
let axis_direction = quat * normals_normal;
|
||||
let direction = Direction3d::new_unchecked(axis_direction);
|
||||
let direction = Dir3::new_unchecked(axis_direction);
|
||||
|
||||
// for each axis draw dotted line
|
||||
(0..)
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon,
|
||||
Polyline2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
|
||||
},
|
||||
Direction2d, Mat2, Vec2,
|
||||
Dir2, Mat2, Vec2,
|
||||
};
|
||||
|
||||
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
||||
|
@ -236,7 +236,7 @@ impl Bounded2d for Capsule2d {
|
|||
// Get the line segment between the hemicircles of the rotated capsule
|
||||
let segment = Segment2d {
|
||||
// Multiplying a normalized vector (Vec2::Y) with a rotation returns a normalized vector.
|
||||
direction: Direction2d::new_unchecked(Mat2::from_angle(rotation) * Vec2::Y),
|
||||
direction: Dir2::new_unchecked(Mat2::from_angle(rotation) * Vec2::Y),
|
||||
half_length: self.half_length,
|
||||
};
|
||||
let (a, b) = (segment.point1(), segment.point2());
|
||||
|
@ -266,7 +266,7 @@ mod tests {
|
|||
Capsule2d, Circle, Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle,
|
||||
RegularPolygon, Segment2d, Triangle2d,
|
||||
},
|
||||
Direction2d,
|
||||
Dir2,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -322,31 +322,22 @@ mod tests {
|
|||
fn line() {
|
||||
let translation = Vec2::new(2.0, 1.0);
|
||||
|
||||
let aabb1 = Line2d {
|
||||
direction: Direction2d::Y,
|
||||
}
|
||||
.aabb_2d(translation, 0.0);
|
||||
let aabb1 = Line2d { direction: Dir2::Y }.aabb_2d(translation, 0.0);
|
||||
assert_eq!(aabb1.min, Vec2::new(2.0, -f32::MAX / 2.0));
|
||||
assert_eq!(aabb1.max, Vec2::new(2.0, f32::MAX / 2.0));
|
||||
|
||||
let aabb2 = Line2d {
|
||||
direction: Direction2d::X,
|
||||
}
|
||||
.aabb_2d(translation, 0.0);
|
||||
let aabb2 = Line2d { direction: Dir2::X }.aabb_2d(translation, 0.0);
|
||||
assert_eq!(aabb2.min, Vec2::new(-f32::MAX / 2.0, 1.0));
|
||||
assert_eq!(aabb2.max, Vec2::new(f32::MAX / 2.0, 1.0));
|
||||
|
||||
let aabb3 = Line2d {
|
||||
direction: Direction2d::from_xy(1.0, 1.0).unwrap(),
|
||||
direction: Dir2::from_xy(1.0, 1.0).unwrap(),
|
||||
}
|
||||
.aabb_2d(translation, 0.0);
|
||||
assert_eq!(aabb3.min, Vec2::new(-f32::MAX / 2.0, -f32::MAX / 2.0));
|
||||
assert_eq!(aabb3.max, Vec2::new(f32::MAX / 2.0, f32::MAX / 2.0));
|
||||
|
||||
let bounding_circle = Line2d {
|
||||
direction: Direction2d::Y,
|
||||
}
|
||||
.bounding_circle(translation, 0.0);
|
||||
let bounding_circle = Line2d { direction: Dir2::Y }.bounding_circle(translation, 0.0);
|
||||
assert_eq!(bounding_circle.center, translation);
|
||||
assert_eq!(bounding_circle.radius(), f32::MAX / 2.0);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d,
|
||||
Polyline3d, Segment3d, Sphere, Torus, Triangle2d,
|
||||
},
|
||||
Direction3d, Mat3, Quat, Vec2, Vec3,
|
||||
Dir3, Mat3, Quat, Vec2, Vec3,
|
||||
};
|
||||
|
||||
use super::{Aabb3d, Bounded3d, BoundingSphere};
|
||||
|
@ -150,7 +150,7 @@ impl Bounded3d for Capsule3d {
|
|||
// Get the line segment between the hemispheres of the rotated capsule
|
||||
let segment = Segment3d {
|
||||
// Multiplying a normalized vector (Vec3::Y) with a rotation returns a normalized vector.
|
||||
direction: Direction3d::new_unchecked(rotation * Vec3::Y),
|
||||
direction: Dir3::new_unchecked(rotation * Vec3::Y),
|
||||
half_length: self.half_length,
|
||||
};
|
||||
let (a, b) = (segment.point1(), segment.point2());
|
||||
|
@ -313,7 +313,7 @@ mod tests {
|
|||
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, Line3d, Plane3d, Polyline3d,
|
||||
Segment3d, Sphere, Torus,
|
||||
},
|
||||
Direction3d,
|
||||
Dir3,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -359,38 +359,27 @@ mod tests {
|
|||
fn line() {
|
||||
let translation = Vec3::new(2.0, 1.0, 0.0);
|
||||
|
||||
let aabb1 = Line3d {
|
||||
direction: Direction3d::Y,
|
||||
}
|
||||
.aabb_3d(translation, Quat::IDENTITY);
|
||||
let aabb1 = Line3d { direction: Dir3::Y }.aabb_3d(translation, Quat::IDENTITY);
|
||||
assert_eq!(aabb1.min, Vec3::new(2.0, -f32::MAX / 2.0, 0.0));
|
||||
assert_eq!(aabb1.max, Vec3::new(2.0, f32::MAX / 2.0, 0.0));
|
||||
|
||||
let aabb2 = Line3d {
|
||||
direction: Direction3d::X,
|
||||
}
|
||||
.aabb_3d(translation, Quat::IDENTITY);
|
||||
let aabb2 = Line3d { direction: Dir3::X }.aabb_3d(translation, Quat::IDENTITY);
|
||||
assert_eq!(aabb2.min, Vec3::new(-f32::MAX / 2.0, 1.0, 0.0));
|
||||
assert_eq!(aabb2.max, Vec3::new(f32::MAX / 2.0, 1.0, 0.0));
|
||||
|
||||
let aabb3 = Line3d {
|
||||
direction: Direction3d::Z,
|
||||
}
|
||||
.aabb_3d(translation, Quat::IDENTITY);
|
||||
let aabb3 = Line3d { direction: Dir3::Z }.aabb_3d(translation, Quat::IDENTITY);
|
||||
assert_eq!(aabb3.min, Vec3::new(2.0, 1.0, -f32::MAX / 2.0));
|
||||
assert_eq!(aabb3.max, Vec3::new(2.0, 1.0, f32::MAX / 2.0));
|
||||
|
||||
let aabb4 = Line3d {
|
||||
direction: Direction3d::from_xyz(1.0, 1.0, 1.0).unwrap(),
|
||||
direction: Dir3::from_xyz(1.0, 1.0, 1.0).unwrap(),
|
||||
}
|
||||
.aabb_3d(translation, Quat::IDENTITY);
|
||||
assert_eq!(aabb4.min, Vec3::splat(-f32::MAX / 2.0));
|
||||
assert_eq!(aabb4.max, Vec3::splat(f32::MAX / 2.0));
|
||||
|
||||
let bounding_sphere = Line3d {
|
||||
direction: Direction3d::Y,
|
||||
}
|
||||
.bounding_sphere(translation, Quat::IDENTITY);
|
||||
let bounding_sphere =
|
||||
Line3d { direction: Dir3::Y }.bounding_sphere(translation, Quat::IDENTITY);
|
||||
assert_eq!(bounding_sphere.center, translation);
|
||||
assert_eq!(bounding_sphere.radius(), f32::MAX / 2.0);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Aabb2d, BoundingCircle, IntersectsVolume};
|
||||
use crate::{Direction2d, Ray2d, Vec2};
|
||||
use crate::{Dir2, Ray2d, Vec2};
|
||||
|
||||
/// A raycast intersection test for 2D bounding volumes
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -13,8 +13,8 @@ pub struct RayCast2d {
|
|||
}
|
||||
|
||||
impl RayCast2d {
|
||||
/// Construct a [`RayCast2d`] from an origin, [`Direction2d`], and max distance.
|
||||
pub fn new(origin: Vec2, direction: Direction2d, max: f32) -> Self {
|
||||
/// Construct a [`RayCast2d`] from an origin, [`Dir2`], and max distance.
|
||||
pub fn new(origin: Vec2, direction: Dir2, max: f32) -> Self {
|
||||
Self::from_ray(Ray2d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -108,8 +108,8 @@ pub struct AabbCast2d {
|
|||
}
|
||||
|
||||
impl AabbCast2d {
|
||||
/// Construct an [`AabbCast2d`] from an [`Aabb2d`], origin, [`Direction2d`], and max distance.
|
||||
pub fn new(aabb: Aabb2d, origin: Vec2, direction: Direction2d, max: f32) -> Self {
|
||||
/// Construct an [`AabbCast2d`] from an [`Aabb2d`], origin, [`Dir2`], and max distance.
|
||||
pub fn new(aabb: Aabb2d, origin: Vec2, direction: Dir2, max: f32) -> Self {
|
||||
Self::from_ray(aabb, Ray2d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,8 @@ pub struct BoundingCircleCast {
|
|||
}
|
||||
|
||||
impl BoundingCircleCast {
|
||||
/// Construct a [`BoundingCircleCast`] from a [`BoundingCircle`], origin, [`Direction2d`], and max distance.
|
||||
pub fn new(circle: BoundingCircle, origin: Vec2, direction: Direction2d, max: f32) -> Self {
|
||||
/// Construct a [`BoundingCircleCast`] from a [`BoundingCircle`], origin, [`Dir2`], and max distance.
|
||||
pub fn new(circle: BoundingCircle, origin: Vec2, direction: Dir2, max: f32) -> Self {
|
||||
Self::from_ray(circle, Ray2d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -183,37 +183,37 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of a centered bounding circle
|
||||
RayCast2d::new(Vec2::Y * -5., Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::Y * -5., Dir2::Y, 90.),
|
||||
BoundingCircle::new(Vec2::ZERO, 1.),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of a centered bounding circle, but from the other side
|
||||
RayCast2d::new(Vec2::Y * 5., -Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::Y * 5., -Dir2::Y, 90.),
|
||||
BoundingCircle::new(Vec2::ZERO, 1.),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of an offset circle
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::Y, 90.),
|
||||
BoundingCircle::new(Vec2::Y * 3., 2.),
|
||||
1.,
|
||||
),
|
||||
(
|
||||
// Just barely hit the circle before the max distance
|
||||
RayCast2d::new(Vec2::X, Direction2d::Y, 1.),
|
||||
RayCast2d::new(Vec2::X, Dir2::Y, 1.),
|
||||
BoundingCircle::new(Vec2::ONE, 0.01),
|
||||
0.99,
|
||||
),
|
||||
(
|
||||
// Hit a circle off-center
|
||||
RayCast2d::new(Vec2::X, Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::X, Dir2::Y, 90.),
|
||||
BoundingCircle::new(Vec2::Y * 5., 2.),
|
||||
3.268,
|
||||
),
|
||||
(
|
||||
// Barely hit a circle on the side
|
||||
RayCast2d::new(Vec2::X * 0.99999, Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::X * 0.99999, Dir2::Y, 90.),
|
||||
BoundingCircle::new(Vec2::Y * 5., 1.),
|
||||
4.996,
|
||||
),
|
||||
|
@ -241,17 +241,17 @@ mod tests {
|
|||
for (test, volume) in &[
|
||||
(
|
||||
// The ray doesn't go in the right direction
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::X, 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::X, 90.),
|
||||
BoundingCircle::new(Vec2::Y * 2., 1.),
|
||||
),
|
||||
(
|
||||
// Ray's alignment isn't enough to hit the circle
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::from_xy(1., 1.).unwrap(), 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::from_xy(1., 1.).unwrap(), 90.),
|
||||
BoundingCircle::new(Vec2::Y * 2., 1.),
|
||||
),
|
||||
(
|
||||
// The ray's maximum distance isn't high enough
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::Y, 0.5),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::Y, 0.5),
|
||||
BoundingCircle::new(Vec2::Y * 2., 1.),
|
||||
),
|
||||
] {
|
||||
|
@ -268,12 +268,7 @@ mod tests {
|
|||
fn test_ray_intersection_circle_inside() {
|
||||
let volume = BoundingCircle::new(Vec2::splat(0.5), 1.);
|
||||
for origin in &[Vec2::X, Vec2::Y, Vec2::ONE, Vec2::ZERO] {
|
||||
for direction in &[
|
||||
Direction2d::X,
|
||||
Direction2d::Y,
|
||||
-Direction2d::X,
|
||||
-Direction2d::Y,
|
||||
] {
|
||||
for direction in &[Dir2::X, Dir2::Y, -Dir2::X, -Dir2::Y] {
|
||||
for max in &[0., 1., 900.] {
|
||||
let test = RayCast2d::new(*origin, *direction, *max);
|
||||
|
||||
|
@ -295,37 +290,37 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of a centered aabb
|
||||
RayCast2d::new(Vec2::Y * -5., Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::Y * -5., Dir2::Y, 90.),
|
||||
Aabb2d::new(Vec2::ZERO, Vec2::ONE),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of a centered aabb, but from the other side
|
||||
RayCast2d::new(Vec2::Y * 5., -Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::Y * 5., -Dir2::Y, 90.),
|
||||
Aabb2d::new(Vec2::ZERO, Vec2::ONE),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of an offset aabb
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::Y, 90.),
|
||||
Aabb2d::new(Vec2::Y * 3., Vec2::splat(2.)),
|
||||
1.,
|
||||
),
|
||||
(
|
||||
// Just barely hit the aabb before the max distance
|
||||
RayCast2d::new(Vec2::X, Direction2d::Y, 1.),
|
||||
RayCast2d::new(Vec2::X, Dir2::Y, 1.),
|
||||
Aabb2d::new(Vec2::ONE, Vec2::splat(0.01)),
|
||||
0.99,
|
||||
),
|
||||
(
|
||||
// Hit an aabb off-center
|
||||
RayCast2d::new(Vec2::X, Direction2d::Y, 90.),
|
||||
RayCast2d::new(Vec2::X, Dir2::Y, 90.),
|
||||
Aabb2d::new(Vec2::Y * 5., Vec2::splat(2.)),
|
||||
3.,
|
||||
),
|
||||
(
|
||||
// Barely hit an aabb on corner
|
||||
RayCast2d::new(Vec2::X * -0.001, Direction2d::from_xy(1., 1.).unwrap(), 90.),
|
||||
RayCast2d::new(Vec2::X * -0.001, Dir2::from_xy(1., 1.).unwrap(), 90.),
|
||||
Aabb2d::new(Vec2::Y * 2., Vec2::ONE),
|
||||
1.414,
|
||||
),
|
||||
|
@ -353,17 +348,17 @@ mod tests {
|
|||
for (test, volume) in &[
|
||||
(
|
||||
// The ray doesn't go in the right direction
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::X, 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::X, 90.),
|
||||
Aabb2d::new(Vec2::Y * 2., Vec2::ONE),
|
||||
),
|
||||
(
|
||||
// Ray's alignment isn't enough to hit the aabb
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::from_xy(1., 0.99).unwrap(), 90.),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::from_xy(1., 0.99).unwrap(), 90.),
|
||||
Aabb2d::new(Vec2::Y * 2., Vec2::ONE),
|
||||
),
|
||||
(
|
||||
// The ray's maximum distance isn't high enough
|
||||
RayCast2d::new(Vec2::ZERO, Direction2d::Y, 0.5),
|
||||
RayCast2d::new(Vec2::ZERO, Dir2::Y, 0.5),
|
||||
Aabb2d::new(Vec2::Y * 2., Vec2::ONE),
|
||||
),
|
||||
] {
|
||||
|
@ -380,12 +375,7 @@ mod tests {
|
|||
fn test_ray_intersection_aabb_inside() {
|
||||
let volume = Aabb2d::new(Vec2::splat(0.5), Vec2::ONE);
|
||||
for origin in &[Vec2::X, Vec2::Y, Vec2::ONE, Vec2::ZERO] {
|
||||
for direction in &[
|
||||
Direction2d::X,
|
||||
Direction2d::Y,
|
||||
-Direction2d::X,
|
||||
-Direction2d::Y,
|
||||
] {
|
||||
for direction in &[Dir2::X, Dir2::Y, -Dir2::X, -Dir2::Y] {
|
||||
for max in &[0., 1., 900.] {
|
||||
let test = RayCast2d::new(*origin, *direction, *max);
|
||||
|
||||
|
@ -407,12 +397,7 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of the aabb, that a ray would've also hit
|
||||
AabbCast2d::new(
|
||||
Aabb2d::new(Vec2::ZERO, Vec2::ONE),
|
||||
Vec2::ZERO,
|
||||
Direction2d::Y,
|
||||
90.,
|
||||
),
|
||||
AabbCast2d::new(Aabb2d::new(Vec2::ZERO, Vec2::ONE), Vec2::ZERO, Dir2::Y, 90.),
|
||||
Aabb2d::new(Vec2::Y * 5., Vec2::ONE),
|
||||
3.,
|
||||
),
|
||||
|
@ -421,7 +406,7 @@ mod tests {
|
|||
AabbCast2d::new(
|
||||
Aabb2d::new(Vec2::ZERO, Vec2::ONE),
|
||||
Vec2::Y * 10.,
|
||||
-Direction2d::Y,
|
||||
-Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb2d::new(Vec2::Y * 5., Vec2::ONE),
|
||||
|
@ -432,7 +417,7 @@ mod tests {
|
|||
AabbCast2d::new(
|
||||
Aabb2d::new(Vec2::ZERO, Vec2::ONE),
|
||||
Vec2::X * 1.5,
|
||||
Direction2d::Y,
|
||||
Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb2d::new(Vec2::Y * 5., Vec2::ONE),
|
||||
|
@ -443,7 +428,7 @@ mod tests {
|
|||
AabbCast2d::new(
|
||||
Aabb2d::new(Vec2::X * -2., Vec2::ONE),
|
||||
Vec2::X * 3.,
|
||||
Direction2d::Y,
|
||||
Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb2d::new(Vec2::Y * 5., Vec2::ONE),
|
||||
|
@ -477,7 +462,7 @@ mod tests {
|
|||
BoundingCircleCast::new(
|
||||
BoundingCircle::new(Vec2::ZERO, 1.),
|
||||
Vec2::ZERO,
|
||||
Direction2d::Y,
|
||||
Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingCircle::new(Vec2::Y * 5., 1.),
|
||||
|
@ -488,7 +473,7 @@ mod tests {
|
|||
BoundingCircleCast::new(
|
||||
BoundingCircle::new(Vec2::ZERO, 1.),
|
||||
Vec2::Y * 10.,
|
||||
-Direction2d::Y,
|
||||
-Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingCircle::new(Vec2::Y * 5., 1.),
|
||||
|
@ -499,7 +484,7 @@ mod tests {
|
|||
BoundingCircleCast::new(
|
||||
BoundingCircle::new(Vec2::ZERO, 1.),
|
||||
Vec2::X * 1.5,
|
||||
Direction2d::Y,
|
||||
Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingCircle::new(Vec2::Y * 5., 1.),
|
||||
|
@ -510,7 +495,7 @@ mod tests {
|
|||
BoundingCircleCast::new(
|
||||
BoundingCircle::new(Vec2::X * -1.5, 1.),
|
||||
Vec2::X * 3.,
|
||||
Direction2d::Y,
|
||||
Dir2::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingCircle::new(Vec2::Y * 5., 1.),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Aabb3d, BoundingSphere, IntersectsVolume};
|
||||
use crate::{Direction3d, Ray3d, Vec3};
|
||||
use crate::{Dir3, Ray3d, Vec3};
|
||||
|
||||
/// A raycast intersection test for 3D bounding volumes
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -13,8 +13,8 @@ pub struct RayCast3d {
|
|||
}
|
||||
|
||||
impl RayCast3d {
|
||||
/// Construct a [`RayCast3d`] from an origin, [`Direction3d`], and max distance.
|
||||
pub fn new(origin: Vec3, direction: Direction3d, max: f32) -> Self {
|
||||
/// Construct a [`RayCast3d`] from an origin, [`Dir3`], and max distance.
|
||||
pub fn new(origin: Vec3, direction: Dir3, max: f32) -> Self {
|
||||
Self::from_ray(Ray3d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -115,8 +115,8 @@ pub struct AabbCast3d {
|
|||
}
|
||||
|
||||
impl AabbCast3d {
|
||||
/// Construct an [`AabbCast3d`] from an [`Aabb3d`], origin, [`Direction3d`], and max distance.
|
||||
pub fn new(aabb: Aabb3d, origin: Vec3, direction: Direction3d, max: f32) -> Self {
|
||||
/// Construct an [`AabbCast3d`] from an [`Aabb3d`], origin, [`Dir3`], and max distance.
|
||||
pub fn new(aabb: Aabb3d, origin: Vec3, direction: Dir3, max: f32) -> Self {
|
||||
Self::from_ray(aabb, Ray3d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -152,8 +152,8 @@ pub struct BoundingSphereCast {
|
|||
}
|
||||
|
||||
impl BoundingSphereCast {
|
||||
/// Construct a [`BoundingSphereCast`] from a [`BoundingSphere`], origin, [`Direction3d`], and max distance.
|
||||
pub fn new(sphere: BoundingSphere, origin: Vec3, direction: Direction3d, max: f32) -> Self {
|
||||
/// Construct a [`BoundingSphereCast`] from a [`BoundingSphere`], origin, [`Dir3`], and max distance.
|
||||
pub fn new(sphere: BoundingSphere, origin: Vec3, direction: Dir3, max: f32) -> Self {
|
||||
Self::from_ray(sphere, Ray3d { origin, direction }, max)
|
||||
}
|
||||
|
||||
|
@ -190,37 +190,37 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of a centered bounding sphere
|
||||
RayCast3d::new(Vec3::Y * -5., Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::Y * -5., Dir3::Y, 90.),
|
||||
BoundingSphere::new(Vec3::ZERO, 1.),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of a centered bounding sphere, but from the other side
|
||||
RayCast3d::new(Vec3::Y * 5., -Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::Y * 5., -Dir3::Y, 90.),
|
||||
BoundingSphere::new(Vec3::ZERO, 1.),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of an offset sphere
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::Y, 90.),
|
||||
BoundingSphere::new(Vec3::Y * 3., 2.),
|
||||
1.,
|
||||
),
|
||||
(
|
||||
// Just barely hit the sphere before the max distance
|
||||
RayCast3d::new(Vec3::X, Direction3d::Y, 1.),
|
||||
RayCast3d::new(Vec3::X, Dir3::Y, 1.),
|
||||
BoundingSphere::new(Vec3::new(1., 1., 0.), 0.01),
|
||||
0.99,
|
||||
),
|
||||
(
|
||||
// Hit a sphere off-center
|
||||
RayCast3d::new(Vec3::X, Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::X, Dir3::Y, 90.),
|
||||
BoundingSphere::new(Vec3::Y * 5., 2.),
|
||||
3.268,
|
||||
),
|
||||
(
|
||||
// Barely hit a sphere on the side
|
||||
RayCast3d::new(Vec3::X * 0.99999, Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::X * 0.99999, Dir3::Y, 90.),
|
||||
BoundingSphere::new(Vec3::Y * 5., 1.),
|
||||
4.996,
|
||||
),
|
||||
|
@ -248,17 +248,17 @@ mod tests {
|
|||
for (test, volume) in &[
|
||||
(
|
||||
// The ray doesn't go in the right direction
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::X, 90.),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::X, 90.),
|
||||
BoundingSphere::new(Vec3::Y * 2., 1.),
|
||||
),
|
||||
(
|
||||
// Ray's alignment isn't enough to hit the sphere
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::from_xyz(1., 1., 1.).unwrap(), 90.),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::from_xyz(1., 1., 1.).unwrap(), 90.),
|
||||
BoundingSphere::new(Vec3::Y * 2., 1.),
|
||||
),
|
||||
(
|
||||
// The ray's maximum distance isn't high enough
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::Y, 0.5),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::Y, 0.5),
|
||||
BoundingSphere::new(Vec3::Y * 2., 1.),
|
||||
),
|
||||
] {
|
||||
|
@ -275,14 +275,7 @@ mod tests {
|
|||
fn test_ray_intersection_sphere_inside() {
|
||||
let volume = BoundingSphere::new(Vec3::splat(0.5), 1.);
|
||||
for origin in &[Vec3::X, Vec3::Y, Vec3::ONE, Vec3::ZERO] {
|
||||
for direction in &[
|
||||
Direction3d::X,
|
||||
Direction3d::Y,
|
||||
Direction3d::Z,
|
||||
-Direction3d::X,
|
||||
-Direction3d::Y,
|
||||
-Direction3d::Z,
|
||||
] {
|
||||
for direction in &[Dir3::X, Dir3::Y, Dir3::Z, -Dir3::X, -Dir3::Y, -Dir3::Z] {
|
||||
for max in &[0., 1., 900.] {
|
||||
let test = RayCast3d::new(*origin, *direction, *max);
|
||||
|
||||
|
@ -304,41 +297,37 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of a centered aabb
|
||||
RayCast3d::new(Vec3::Y * -5., Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::Y * -5., Dir3::Y, 90.),
|
||||
Aabb3d::new(Vec3::ZERO, Vec3::ONE),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of a centered aabb, but from the other side
|
||||
RayCast3d::new(Vec3::Y * 5., -Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::Y * 5., -Dir3::Y, 90.),
|
||||
Aabb3d::new(Vec3::ZERO, Vec3::ONE),
|
||||
4.,
|
||||
),
|
||||
(
|
||||
// Hit the center of an offset aabb
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::Y, 90.),
|
||||
Aabb3d::new(Vec3::Y * 3., Vec3::splat(2.)),
|
||||
1.,
|
||||
),
|
||||
(
|
||||
// Just barely hit the aabb before the max distance
|
||||
RayCast3d::new(Vec3::X, Direction3d::Y, 1.),
|
||||
RayCast3d::new(Vec3::X, Dir3::Y, 1.),
|
||||
Aabb3d::new(Vec3::new(1., 1., 0.), Vec3::splat(0.01)),
|
||||
0.99,
|
||||
),
|
||||
(
|
||||
// Hit an aabb off-center
|
||||
RayCast3d::new(Vec3::X, Direction3d::Y, 90.),
|
||||
RayCast3d::new(Vec3::X, Dir3::Y, 90.),
|
||||
Aabb3d::new(Vec3::Y * 5., Vec3::splat(2.)),
|
||||
3.,
|
||||
),
|
||||
(
|
||||
// Barely hit an aabb on corner
|
||||
RayCast3d::new(
|
||||
Vec3::X * -0.001,
|
||||
Direction3d::from_xyz(1., 1., 1.).unwrap(),
|
||||
90.,
|
||||
),
|
||||
RayCast3d::new(Vec3::X * -0.001, Dir3::from_xyz(1., 1., 1.).unwrap(), 90.),
|
||||
Aabb3d::new(Vec3::Y * 2., Vec3::ONE),
|
||||
1.732,
|
||||
),
|
||||
|
@ -366,21 +355,17 @@ mod tests {
|
|||
for (test, volume) in &[
|
||||
(
|
||||
// The ray doesn't go in the right direction
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::X, 90.),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::X, 90.),
|
||||
Aabb3d::new(Vec3::Y * 2., Vec3::ONE),
|
||||
),
|
||||
(
|
||||
// Ray's alignment isn't enough to hit the aabb
|
||||
RayCast3d::new(
|
||||
Vec3::ZERO,
|
||||
Direction3d::from_xyz(1., 0.99, 1.).unwrap(),
|
||||
90.,
|
||||
),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::from_xyz(1., 0.99, 1.).unwrap(), 90.),
|
||||
Aabb3d::new(Vec3::Y * 2., Vec3::ONE),
|
||||
),
|
||||
(
|
||||
// The ray's maximum distance isn't high enough
|
||||
RayCast3d::new(Vec3::ZERO, Direction3d::Y, 0.5),
|
||||
RayCast3d::new(Vec3::ZERO, Dir3::Y, 0.5),
|
||||
Aabb3d::new(Vec3::Y * 2., Vec3::ONE),
|
||||
),
|
||||
] {
|
||||
|
@ -397,14 +382,7 @@ mod tests {
|
|||
fn test_ray_intersection_aabb_inside() {
|
||||
let volume = Aabb3d::new(Vec3::splat(0.5), Vec3::ONE);
|
||||
for origin in &[Vec3::X, Vec3::Y, Vec3::ONE, Vec3::ZERO] {
|
||||
for direction in &[
|
||||
Direction3d::X,
|
||||
Direction3d::Y,
|
||||
Direction3d::Z,
|
||||
-Direction3d::X,
|
||||
-Direction3d::Y,
|
||||
-Direction3d::Z,
|
||||
] {
|
||||
for direction in &[Dir3::X, Dir3::Y, Dir3::Z, -Dir3::X, -Dir3::Y, -Dir3::Z] {
|
||||
for max in &[0., 1., 900.] {
|
||||
let test = RayCast3d::new(*origin, *direction, *max);
|
||||
|
||||
|
@ -426,12 +404,7 @@ mod tests {
|
|||
for (test, volume, expected_distance) in &[
|
||||
(
|
||||
// Hit the center of the aabb, that a ray would've also hit
|
||||
AabbCast3d::new(
|
||||
Aabb3d::new(Vec3::ZERO, Vec3::ONE),
|
||||
Vec3::ZERO,
|
||||
Direction3d::Y,
|
||||
90.,
|
||||
),
|
||||
AabbCast3d::new(Aabb3d::new(Vec3::ZERO, Vec3::ONE), Vec3::ZERO, Dir3::Y, 90.),
|
||||
Aabb3d::new(Vec3::Y * 5., Vec3::ONE),
|
||||
3.,
|
||||
),
|
||||
|
@ -440,7 +413,7 @@ mod tests {
|
|||
AabbCast3d::new(
|
||||
Aabb3d::new(Vec3::ZERO, Vec3::ONE),
|
||||
Vec3::Y * 10.,
|
||||
-Direction3d::Y,
|
||||
-Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb3d::new(Vec3::Y * 5., Vec3::ONE),
|
||||
|
@ -451,7 +424,7 @@ mod tests {
|
|||
AabbCast3d::new(
|
||||
Aabb3d::new(Vec3::ZERO, Vec3::ONE),
|
||||
Vec3::X * 1.5,
|
||||
Direction3d::Y,
|
||||
Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb3d::new(Vec3::Y * 5., Vec3::ONE),
|
||||
|
@ -462,7 +435,7 @@ mod tests {
|
|||
AabbCast3d::new(
|
||||
Aabb3d::new(Vec3::X * -2., Vec3::ONE),
|
||||
Vec3::X * 3.,
|
||||
Direction3d::Y,
|
||||
Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
Aabb3d::new(Vec3::Y * 5., Vec3::ONE),
|
||||
|
@ -496,7 +469,7 @@ mod tests {
|
|||
BoundingSphereCast::new(
|
||||
BoundingSphere::new(Vec3::ZERO, 1.),
|
||||
Vec3::ZERO,
|
||||
Direction3d::Y,
|
||||
Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingSphere::new(Vec3::Y * 5., 1.),
|
||||
|
@ -507,7 +480,7 @@ mod tests {
|
|||
BoundingSphereCast::new(
|
||||
BoundingSphere::new(Vec3::ZERO, 1.),
|
||||
Vec3::Y * 10.,
|
||||
-Direction3d::Y,
|
||||
-Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingSphere::new(Vec3::Y * 5., 1.),
|
||||
|
@ -518,7 +491,7 @@ mod tests {
|
|||
BoundingSphereCast::new(
|
||||
BoundingSphere::new(Vec3::ZERO, 1.),
|
||||
Vec3::X * 1.5,
|
||||
Direction3d::Y,
|
||||
Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingSphere::new(Vec3::Y * 5., 1.),
|
||||
|
@ -529,7 +502,7 @@ mod tests {
|
|||
BoundingSphereCast::new(
|
||||
BoundingSphere::new(Vec3::X * -1.5, 1.),
|
||||
Vec3::X * 3.,
|
||||
Direction3d::Y,
|
||||
Dir3::Y,
|
||||
90.,
|
||||
),
|
||||
BoundingSphere::new(Vec3::Y * 5., 1.),
|
||||
|
|
|
@ -38,13 +38,28 @@ impl std::fmt::Display for InvalidDirectionError {
|
|||
}
|
||||
}
|
||||
|
||||
/// A normalized vector pointing in a direction in 2D space
|
||||
#[deprecated(
|
||||
since = "0.14.0",
|
||||
note = "`Direction2d` has been renamed. Please use `Dir2` instead."
|
||||
)]
|
||||
pub type Direction2d = Dir2;
|
||||
|
||||
/// A normalized vector pointing in a direction in 3D space
|
||||
#[deprecated(
|
||||
since = "0.14.0",
|
||||
note = "`Direction3d` has been renamed. Please use `Dir3` instead."
|
||||
)]
|
||||
pub type Direction3d = Dir3;
|
||||
|
||||
/// A normalized vector pointing in a direction in 2D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction2d(Vec2);
|
||||
impl Primitive2d for Direction2d {}
|
||||
#[doc(alias = "Direction2d")]
|
||||
pub struct Dir2(Vec2);
|
||||
impl Primitive2d for Dir2 {}
|
||||
|
||||
impl Direction2d {
|
||||
impl Dir2 {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec2::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
|
@ -62,7 +77,7 @@ impl Direction2d {
|
|||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction2d`] from a [`Vec2`] that is already normalized.
|
||||
/// Create a [`Dir2`] from a [`Vec2`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
|
@ -95,7 +110,7 @@ impl Direction2d {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec2> for Direction2d {
|
||||
impl TryFrom<Vec2> for Dir2 {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec2) -> Result<Self, Self::Error> {
|
||||
|
@ -103,14 +118,14 @@ impl TryFrom<Vec2> for Direction2d {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction2d {
|
||||
impl std::ops::Deref for Dir2 {
|
||||
type Target = Vec2;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction2d {
|
||||
impl std::ops::Neg for Dir2 {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
|
@ -118,7 +133,7 @@ impl std::ops::Neg for Direction2d {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction2d {
|
||||
impl approx::AbsDiffEq for Dir2 {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
|
@ -129,7 +144,7 @@ impl approx::AbsDiffEq for Direction2d {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction2d {
|
||||
impl approx::RelativeEq for Dir2 {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
|
@ -140,7 +155,7 @@ impl approx::RelativeEq for Direction2d {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction2d {
|
||||
impl approx::UlpsEq for Dir2 {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
|
@ -152,10 +167,11 @@ impl approx::UlpsEq for Direction2d {
|
|||
/// A normalized vector pointing in a direction in 3D space
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction3d(Vec3);
|
||||
impl Primitive3d for Direction3d {}
|
||||
#[doc(alias = "Direction3d")]
|
||||
pub struct Dir3(Vec3);
|
||||
impl Primitive3d for Dir3 {}
|
||||
|
||||
impl Direction3d {
|
||||
impl Dir3 {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec3::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
|
@ -177,7 +193,7 @@ impl Direction3d {
|
|||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction3d`] from a [`Vec3`] that is already normalized.
|
||||
/// Create a [`Dir3`] from a [`Vec3`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
|
@ -210,7 +226,7 @@ impl Direction3d {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec3> for Direction3d {
|
||||
impl TryFrom<Vec3> for Dir3 {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec3) -> Result<Self, Self::Error> {
|
||||
|
@ -218,50 +234,50 @@ impl TryFrom<Vec3> for Direction3d {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Direction3d> for Vec3 {
|
||||
fn from(value: Direction3d) -> Self {
|
||||
impl From<Dir3> for Vec3 {
|
||||
fn from(value: Dir3) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction3d {
|
||||
impl std::ops::Deref for Dir3 {
|
||||
type Target = Vec3;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction3d {
|
||||
impl std::ops::Neg for Dir3 {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Direction3d {
|
||||
impl std::ops::Mul<f32> for Dir3 {
|
||||
type Output = Vec3;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
self.0 * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Direction3d> for Quat {
|
||||
type Output = Direction3d;
|
||||
impl std::ops::Mul<Dir3> for Quat {
|
||||
type Output = Dir3;
|
||||
|
||||
/// Rotates the [`Direction3d`] using a [`Quat`].
|
||||
fn mul(self, direction: Direction3d) -> Self::Output {
|
||||
/// Rotates the [`Dir3`] using a [`Quat`].
|
||||
fn mul(self, direction: Dir3) -> Self::Output {
|
||||
let rotated = self * *direction;
|
||||
|
||||
// Make sure the result is normalized.
|
||||
// This can fail for non-unit quaternions.
|
||||
debug_assert!(rotated.is_normalized());
|
||||
|
||||
Direction3d::new_unchecked(rotated)
|
||||
Dir3::new_unchecked(rotated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction3d {
|
||||
impl approx::AbsDiffEq for Dir3 {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
|
@ -272,7 +288,7 @@ impl approx::AbsDiffEq for Direction3d {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction3d {
|
||||
impl approx::RelativeEq for Dir3 {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
|
@ -283,7 +299,7 @@ impl approx::RelativeEq for Direction3d {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction3d {
|
||||
impl approx::UlpsEq for Dir3 {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
|
@ -295,13 +311,14 @@ impl approx::UlpsEq for Direction3d {
|
|||
/// A normalized SIMD vector pointing in a direction in 3D space.
|
||||
///
|
||||
/// This type stores a 16 byte aligned [`Vec3A`].
|
||||
/// This may or may not be faster than [`Direction3d`]: make sure to benchmark!
|
||||
/// This may or may not be faster than [`Dir3`]: make sure to benchmark!
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Direction3dA(Vec3A);
|
||||
impl Primitive3d for Direction3dA {}
|
||||
#[doc(alias = "Direction3dA")]
|
||||
pub struct Dir3A(Vec3A);
|
||||
impl Primitive3d for Dir3A {}
|
||||
|
||||
impl Direction3dA {
|
||||
impl Dir3A {
|
||||
/// A unit vector pointing along the positive X axis.
|
||||
pub const X: Self = Self(Vec3A::X);
|
||||
/// A unit vector pointing along the positive Y axis.
|
||||
|
@ -323,7 +340,7 @@ impl Direction3dA {
|
|||
Self::new_and_length(value).map(|(dir, _)| dir)
|
||||
}
|
||||
|
||||
/// Create a [`Direction3dA`] from a [`Vec3A`] that is already normalized.
|
||||
/// Create a [`Dir3A`] from a [`Vec3A`] that is already normalized.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
|
@ -356,7 +373,7 @@ impl Direction3dA {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec3A> for Direction3dA {
|
||||
impl TryFrom<Vec3A> for Dir3A {
|
||||
type Error = InvalidDirectionError;
|
||||
|
||||
fn try_from(value: Vec3A) -> Result<Self, Self::Error> {
|
||||
|
@ -364,50 +381,50 @@ impl TryFrom<Vec3A> for Direction3dA {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Direction3dA> for Vec3A {
|
||||
fn from(value: Direction3dA) -> Self {
|
||||
impl From<Dir3A> for Vec3A {
|
||||
fn from(value: Dir3A) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Direction3dA {
|
||||
impl std::ops::Deref for Dir3A {
|
||||
type Target = Vec3A;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Neg for Direction3dA {
|
||||
impl std::ops::Neg for Dir3A {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
Self(-self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<f32> for Direction3dA {
|
||||
impl std::ops::Mul<f32> for Dir3A {
|
||||
type Output = Vec3A;
|
||||
fn mul(self, rhs: f32) -> Self::Output {
|
||||
self.0 * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul<Direction3dA> for Quat {
|
||||
type Output = Direction3dA;
|
||||
impl std::ops::Mul<Dir3A> for Quat {
|
||||
type Output = Dir3A;
|
||||
|
||||
/// Rotates the [`Direction3dA`] using a [`Quat`].
|
||||
fn mul(self, direction: Direction3dA) -> Self::Output {
|
||||
/// Rotates the [`Dir3A`] using a [`Quat`].
|
||||
fn mul(self, direction: Dir3A) -> Self::Output {
|
||||
let rotated = self * *direction;
|
||||
|
||||
// Make sure the result is normalized.
|
||||
// This can fail for non-unit quaternions.
|
||||
debug_assert!(rotated.is_normalized());
|
||||
|
||||
Direction3dA::new_unchecked(rotated)
|
||||
Dir3A::new_unchecked(rotated)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::AbsDiffEq for Direction3dA {
|
||||
impl approx::AbsDiffEq for Dir3A {
|
||||
type Epsilon = f32;
|
||||
fn default_epsilon() -> f32 {
|
||||
f32::EPSILON
|
||||
|
@ -418,7 +435,7 @@ impl approx::AbsDiffEq for Direction3dA {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::RelativeEq for Direction3dA {
|
||||
impl approx::RelativeEq for Dir3A {
|
||||
fn default_max_relative() -> f32 {
|
||||
f32::EPSILON
|
||||
}
|
||||
|
@ -429,7 +446,7 @@ impl approx::RelativeEq for Direction3dA {
|
|||
}
|
||||
|
||||
#[cfg(feature = "approx")]
|
||||
impl approx::UlpsEq for Direction3dA {
|
||||
impl approx::UlpsEq for Dir3A {
|
||||
fn default_max_ulps() -> u32 {
|
||||
4
|
||||
}
|
||||
|
@ -445,87 +462,78 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn dir2_creation() {
|
||||
assert_eq!(Direction2d::new(Vec2::X * 12.5), Ok(Direction2d::X));
|
||||
assert_eq!(Dir2::new(Vec2::X * 12.5), Ok(Dir2::X));
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(0.0, 0.0)),
|
||||
Dir2::new(Vec2::new(0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::INFINITY, 0.0)),
|
||||
Dir2::new(Vec2::new(f32::INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NEG_INFINITY, 0.0)),
|
||||
Dir2::new(Vec2::new(f32::NEG_INFINITY, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new(Vec2::new(f32::NAN, 0.0)),
|
||||
Dir2::new(Vec2::new(f32::NAN, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction2d::new_and_length(Vec2::X * 6.5),
|
||||
Ok((Direction2d::X, 6.5))
|
||||
);
|
||||
assert_eq!(Dir2::new_and_length(Vec2::X * 6.5), Ok((Dir2::X, 6.5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir3_creation() {
|
||||
assert_eq!(Direction3d::new(Vec3::X * 12.5), Ok(Direction3d::X));
|
||||
assert_eq!(Dir3::new(Vec3::X * 12.5), Ok(Dir3::X));
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(0.0, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(0.0, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NAN, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::NAN, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new_and_length(Vec3::X * 6.5),
|
||||
Ok((Direction3d::X, 6.5))
|
||||
);
|
||||
assert_eq!(Dir3::new_and_length(Vec3::X * 6.5), Ok((Dir3::X, 6.5)));
|
||||
|
||||
// Test rotation
|
||||
assert!(
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Direction3d::X)
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Dir3::X)
|
||||
.abs_diff_eq(Vec3::Y, 10e-6)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dir3a_creation() {
|
||||
assert_eq!(Direction3dA::new(Vec3A::X * 12.5), Ok(Direction3dA::X));
|
||||
assert_eq!(Dir3A::new(Vec3A::X * 12.5), Ok(Dir3A::X));
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(0.0, 0.0, 0.0)),
|
||||
Dir3A::new(Vec3A::new(0.0, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Dir3A::new(Vec3A::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Dir3A::new(Vec3A::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new(Vec3A::new(f32::NAN, 0.0, 0.0)),
|
||||
Dir3A::new(Vec3A::new(f32::NAN, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3dA::new_and_length(Vec3A::X * 6.5),
|
||||
Ok((Direction3dA::X, 6.5))
|
||||
);
|
||||
assert_eq!(Dir3A::new_and_length(Vec3A::X * 6.5), Ok((Dir3A::X, 6.5)));
|
||||
|
||||
// Test rotation
|
||||
assert!(
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Direction3dA::X)
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Dir3A::X)
|
||||
.abs_diff_eq(Vec3A::Y, 10e-6)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ pub mod prelude {
|
|||
CubicHermite, CubicNurbs, CubicNurbsError, CubicSegment, RationalCurve,
|
||||
RationalGenerator, RationalSegment,
|
||||
},
|
||||
direction::{Direction2d, Direction3d, Direction3dA},
|
||||
direction::{Dir2, Dir3, Dir3A},
|
||||
primitives::*,
|
||||
BVec2, BVec3, BVec4, EulerRot, FloatExt, IRect, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
|
||||
Quat, Ray2d, Ray3d, Rect, URect, UVec2, UVec3, UVec4, Vec2, Vec2Swizzles, Vec3,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::f32::consts::PI;
|
||||
|
||||
use super::{Primitive2d, WindingOrder};
|
||||
use crate::{Direction2d, Vec2};
|
||||
use crate::{Dir2, Vec2};
|
||||
|
||||
/// A circle primitive
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -131,16 +131,14 @@ impl Ellipse {
|
|||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Plane2d {
|
||||
/// The normal of the plane. The plane will be placed perpendicular to this direction
|
||||
pub normal: Direction2d,
|
||||
pub normal: Dir2,
|
||||
}
|
||||
impl Primitive2d for Plane2d {}
|
||||
|
||||
impl Default for Plane2d {
|
||||
/// Returns the default [`Plane2d`] with a normal pointing in the `+Y` direction.
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
normal: Direction2d::Y,
|
||||
}
|
||||
Self { normal: Dir2::Y }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +151,7 @@ impl Plane2d {
|
|||
#[inline(always)]
|
||||
pub fn new(normal: Vec2) -> Self {
|
||||
Self {
|
||||
normal: Direction2d::new(normal).expect("normal must be nonzero and finite"),
|
||||
normal: Dir2::new(normal).expect("normal must be nonzero and finite"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +164,7 @@ impl Plane2d {
|
|||
pub struct Line2d {
|
||||
/// The direction of the line. The line extends infinitely in both the given direction
|
||||
/// and its opposite direction
|
||||
pub direction: Direction2d,
|
||||
pub direction: Dir2,
|
||||
}
|
||||
impl Primitive2d for Line2d {}
|
||||
|
||||
|
@ -176,7 +174,7 @@ impl Primitive2d for Line2d {}
|
|||
#[doc(alias = "LineSegment2d")]
|
||||
pub struct Segment2d {
|
||||
/// The direction of the line segment
|
||||
pub direction: Direction2d,
|
||||
pub direction: Dir2,
|
||||
/// Half the length of the line segment. The segment extends by this amount in both
|
||||
/// the given direction and its opposite direction
|
||||
pub half_length: f32,
|
||||
|
@ -186,7 +184,7 @@ impl Primitive2d for Segment2d {}
|
|||
impl Segment2d {
|
||||
/// Create a new `Segment2d` from a direction and full length of the segment
|
||||
#[inline(always)]
|
||||
pub fn new(direction: Direction2d, length: f32) -> Self {
|
||||
pub fn new(direction: Dir2, length: f32) -> Self {
|
||||
Self {
|
||||
direction,
|
||||
half_length: length / 2.0,
|
||||
|
@ -205,7 +203,7 @@ impl Segment2d {
|
|||
|
||||
(
|
||||
// We are dividing by the length here, so the vector is normalized.
|
||||
Self::new(Direction2d::new_unchecked(diff / length), length),
|
||||
Self::new(Dir2::new_unchecked(diff / length), length),
|
||||
(point1 + point2) / 2.,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::f32::consts::{FRAC_PI_3, PI};
|
||||
|
||||
use super::{Circle, Primitive3d};
|
||||
use crate::{Direction3d, Vec3};
|
||||
use crate::{Dir3, Vec3};
|
||||
|
||||
/// A sphere primitive
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
@ -70,16 +70,14 @@ impl Sphere {
|
|||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Plane3d {
|
||||
/// The normal of the plane. The plane will be placed perpendicular to this direction
|
||||
pub normal: Direction3d,
|
||||
pub normal: Dir3,
|
||||
}
|
||||
impl Primitive3d for Plane3d {}
|
||||
|
||||
impl Default for Plane3d {
|
||||
/// Returns the default [`Plane3d`] with a normal pointing in the `+Y` direction.
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
normal: Direction3d::Y,
|
||||
}
|
||||
Self { normal: Dir3::Y }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +90,7 @@ impl Plane3d {
|
|||
#[inline(always)]
|
||||
pub fn new(normal: Vec3) -> Self {
|
||||
Self {
|
||||
normal: Direction3d::new(normal).expect("normal must be nonzero and finite"),
|
||||
normal: Dir3::new(normal).expect("normal must be nonzero and finite"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +106,7 @@ impl Plane3d {
|
|||
/// are *collinear* and lie on the same line.
|
||||
#[inline(always)]
|
||||
pub fn from_points(a: Vec3, b: Vec3, c: Vec3) -> (Self, Vec3) {
|
||||
let normal = Direction3d::new((b - a).cross(c - a))
|
||||
let normal = Dir3::new((b - a).cross(c - a))
|
||||
.expect("plane must be defined by three finite points that don't lie on the same line");
|
||||
let translation = (a + b + c) / 3.0;
|
||||
|
||||
|
@ -123,7 +121,7 @@ impl Plane3d {
|
|||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Line3d {
|
||||
/// The direction of the line
|
||||
pub direction: Direction3d,
|
||||
pub direction: Dir3,
|
||||
}
|
||||
impl Primitive3d for Line3d {}
|
||||
|
||||
|
@ -133,7 +131,7 @@ impl Primitive3d for Line3d {}
|
|||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Segment3d {
|
||||
/// The direction of the line
|
||||
pub direction: Direction3d,
|
||||
pub direction: Dir3,
|
||||
/// Half the length of the line segment. The segment extends by this amount in both
|
||||
/// the given direction and its opposite direction
|
||||
pub half_length: f32,
|
||||
|
@ -143,7 +141,7 @@ impl Primitive3d for Segment3d {}
|
|||
impl Segment3d {
|
||||
/// Create a new `Segment3d` from a direction and full length of the segment
|
||||
#[inline(always)]
|
||||
pub fn new(direction: Direction3d, length: f32) -> Self {
|
||||
pub fn new(direction: Dir3, length: f32) -> Self {
|
||||
Self {
|
||||
direction,
|
||||
half_length: length / 2.0,
|
||||
|
@ -162,7 +160,7 @@ impl Segment3d {
|
|||
|
||||
(
|
||||
// We are dividing by the length here, so the vector is normalized.
|
||||
Self::new(Direction3d::new_unchecked(diff / length), length),
|
||||
Self::new(Dir3::new_unchecked(diff / length), length),
|
||||
(point1 + point2) / 2.,
|
||||
)
|
||||
}
|
||||
|
@ -641,31 +639,28 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn direction_creation() {
|
||||
assert_eq!(Direction3d::new(Vec3::X * 12.5), Ok(Direction3d::X));
|
||||
assert_eq!(Dir3::new(Vec3::X * 12.5), Ok(Dir3::X));
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(0.0, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(0.0, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Zero)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::NEG_INFINITY, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::Infinite)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new(Vec3::new(f32::NAN, 0.0, 0.0)),
|
||||
Dir3::new(Vec3::new(f32::NAN, 0.0, 0.0)),
|
||||
Err(InvalidDirectionError::NaN)
|
||||
);
|
||||
assert_eq!(
|
||||
Direction3d::new_and_length(Vec3::X * 6.5),
|
||||
Ok((Direction3d::X, 6.5))
|
||||
);
|
||||
assert_eq!(Dir3::new_and_length(Vec3::X * 6.5), Ok((Dir3::X, 6.5)));
|
||||
|
||||
// Test rotation
|
||||
assert!(
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Direction3d::X)
|
||||
(Quat::from_rotation_z(std::f32::consts::FRAC_PI_2) * Dir3::X)
|
||||
.abs_diff_eq(Vec3::Y, 10e-6)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
primitives::{Plane2d, Plane3d},
|
||||
Direction2d, Direction3d, Vec2, Vec3,
|
||||
Dir2, Dir3, Vec2, Vec3,
|
||||
};
|
||||
|
||||
/// An infinite half-line starting at `origin` and going in `direction` in 2D space.
|
||||
|
@ -10,7 +10,7 @@ pub struct Ray2d {
|
|||
/// The origin of the ray.
|
||||
pub origin: Vec2,
|
||||
/// The direction of the ray.
|
||||
pub direction: Direction2d,
|
||||
pub direction: Dir2,
|
||||
}
|
||||
|
||||
impl Ray2d {
|
||||
|
@ -23,8 +23,7 @@ impl Ray2d {
|
|||
pub fn new(origin: Vec2, direction: Vec2) -> Self {
|
||||
Self {
|
||||
origin,
|
||||
direction: Direction2d::new(direction)
|
||||
.expect("ray direction must be nonzero and finite"),
|
||||
direction: Dir2::new(direction).expect("ray direction must be nonzero and finite"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,7 @@ pub struct Ray3d {
|
|||
/// The origin of the ray.
|
||||
pub origin: Vec3,
|
||||
/// The direction of the ray.
|
||||
pub direction: Direction3d,
|
||||
pub direction: Dir3,
|
||||
}
|
||||
|
||||
impl Ray3d {
|
||||
|
@ -68,8 +67,7 @@ impl Ray3d {
|
|||
pub fn new(origin: Vec3, direction: Vec3) -> Self {
|
||||
Self {
|
||||
origin,
|
||||
direction: Direction3d::new(direction)
|
||||
.expect("ray direction must be nonzero and finite"),
|
||||
direction: Dir3::new(direction).expect("ray direction must be nonzero and finite"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,21 +2,6 @@ use crate as bevy_reflect;
|
|||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_reflect_derive::impl_reflect_value;
|
||||
|
||||
impl_reflect_value!(::bevy_math::Direction2d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
impl_reflect_value!(::bevy_math::Direction3d(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
impl_reflect_value!(::bevy_math::Direction3dA(
|
||||
Debug,
|
||||
PartialEq,
|
||||
Serialize,
|
||||
Deserialize
|
||||
));
|
||||
impl_reflect_value!(::bevy_math::Dir2(Debug, PartialEq, Serialize, Deserialize));
|
||||
impl_reflect_value!(::bevy_math::Dir3(Debug, PartialEq, Serialize, Deserialize));
|
||||
impl_reflect_value!(::bevy_math::Dir3A(Debug, PartialEq, Serialize, Deserialize));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate as bevy_reflect;
|
||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_math::{primitives::*, Direction2d, Vec2};
|
||||
use bevy_math::{primitives::*, Dir2, Vec2};
|
||||
use bevy_reflect_derive::impl_reflect;
|
||||
|
||||
impl_reflect!(
|
||||
|
@ -23,7 +23,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Plane2d {
|
||||
normal: Direction2d,
|
||||
normal: Dir2,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -31,7 +31,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Line2d {
|
||||
direction: Direction2d,
|
||||
direction: Dir2,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -39,7 +39,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Segment2d {
|
||||
direction: Direction2d,
|
||||
direction: Dir2,
|
||||
half_length: f32,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate as bevy_reflect;
|
||||
use crate::{ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_math::{primitives::*, Direction3d, Vec3};
|
||||
use bevy_math::{primitives::*, Dir3, Vec3};
|
||||
use bevy_reflect_derive::impl_reflect;
|
||||
|
||||
impl_reflect!(
|
||||
|
@ -15,7 +15,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Plane3d {
|
||||
normal: Direction3d,
|
||||
normal: Dir3,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -23,7 +23,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Line3d {
|
||||
direction: Direction3d,
|
||||
direction: Dir3,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -31,7 +31,7 @@ impl_reflect!(
|
|||
#[reflect(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[type_path = "bevy_math::primitives"]
|
||||
struct Segment3d {
|
||||
direction: Direction3d,
|
||||
direction: Dir3,
|
||||
half_length: f32,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@ use bevy_ecs::{
|
|||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
};
|
||||
use bevy_log::warn;
|
||||
use bevy_math::{vec2, Direction3d, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3};
|
||||
use bevy_math::{vec2, Dir3, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render_macros::ExtractComponent;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
|
@ -390,7 +390,7 @@ impl Camera {
|
|||
let world_far_plane = ndc_to_world.project_point3(ndc.extend(f32::EPSILON));
|
||||
|
||||
// The fallible direction constructor ensures that world_near_plane and world_far_plane aren't NaN.
|
||||
Direction3d::new(world_far_plane - world_near_plane).map_or(None, |direction| {
|
||||
Dir3::new(world_far_plane - world_near_plane).map_or(None, |direction| {
|
||||
Some(Ray3d {
|
||||
origin: world_near_plane,
|
||||
direction,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy_math::{primitives::Plane3d, Direction3d, Quat, Vec2, Vec3};
|
||||
use bevy_math::{primitives::Plane3d, Dir3, Quat, Vec2, Vec3};
|
||||
use wgpu::PrimitiveTopology;
|
||||
|
||||
use crate::{
|
||||
|
@ -27,7 +27,7 @@ impl Default for PlaneMeshBuilder {
|
|||
impl PlaneMeshBuilder {
|
||||
/// Creates a new [`PlaneMeshBuilder`] from a given normal and size.
|
||||
#[inline]
|
||||
pub fn new(normal: Direction3d, size: Vec2) -> Self {
|
||||
pub fn new(normal: Dir3, size: Vec2) -> Self {
|
||||
Self {
|
||||
plane: Plane3d { normal },
|
||||
half_size: size / 2.0,
|
||||
|
@ -56,7 +56,7 @@ impl PlaneMeshBuilder {
|
|||
/// Sets the normal of the plane, aka the direction the plane is facing.
|
||||
#[inline]
|
||||
#[doc(alias = "facing")]
|
||||
pub fn normal(mut self, normal: Direction3d) -> Self {
|
||||
pub fn normal(mut self, normal: Dir3) -> Self {
|
||||
self.plane = Plane3d { normal };
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::GlobalTransform;
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_math::{Affine3A, Direction3d, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_math::{Affine3A, Dir3, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use std::ops::Mul;
|
||||
|
@ -185,58 +185,58 @@ impl Transform {
|
|||
|
||||
/// Get the unit vector in the local `X` direction.
|
||||
#[inline]
|
||||
pub fn local_x(&self) -> Direction3d {
|
||||
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Direction3d::new(self.rotation * Vec3::X).unwrap()
|
||||
pub fn local_x(&self) -> Dir3 {
|
||||
// Dir3::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Dir3::new(self.rotation * Vec3::X).unwrap()
|
||||
}
|
||||
|
||||
/// Equivalent to [`-local_x()`][Transform::local_x()]
|
||||
#[inline]
|
||||
pub fn left(&self) -> Direction3d {
|
||||
pub fn left(&self) -> Dir3 {
|
||||
-self.local_x()
|
||||
}
|
||||
|
||||
/// Equivalent to [`local_x()`][Transform::local_x()]
|
||||
#[inline]
|
||||
pub fn right(&self) -> Direction3d {
|
||||
pub fn right(&self) -> Dir3 {
|
||||
self.local_x()
|
||||
}
|
||||
|
||||
/// Get the unit vector in the local `Y` direction.
|
||||
#[inline]
|
||||
pub fn local_y(&self) -> Direction3d {
|
||||
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Direction3d::new(self.rotation * Vec3::Y).unwrap()
|
||||
pub fn local_y(&self) -> Dir3 {
|
||||
// Dir3::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Dir3::new(self.rotation * Vec3::Y).unwrap()
|
||||
}
|
||||
|
||||
/// Equivalent to [`local_y()`][Transform::local_y]
|
||||
#[inline]
|
||||
pub fn up(&self) -> Direction3d {
|
||||
pub fn up(&self) -> Dir3 {
|
||||
self.local_y()
|
||||
}
|
||||
|
||||
/// Equivalent to [`-local_y()`][Transform::local_y]
|
||||
#[inline]
|
||||
pub fn down(&self) -> Direction3d {
|
||||
pub fn down(&self) -> Dir3 {
|
||||
-self.local_y()
|
||||
}
|
||||
|
||||
/// Get the unit vector in the local `Z` direction.
|
||||
#[inline]
|
||||
pub fn local_z(&self) -> Direction3d {
|
||||
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Direction3d::new(self.rotation * Vec3::Z).unwrap()
|
||||
pub fn local_z(&self) -> Dir3 {
|
||||
// Dir3::new(x) panics if x is of invalid length, but quat * unit vector is length 1
|
||||
Dir3::new(self.rotation * Vec3::Z).unwrap()
|
||||
}
|
||||
|
||||
/// Equivalent to [`-local_z()`][Transform::local_z]
|
||||
#[inline]
|
||||
pub fn forward(&self) -> Direction3d {
|
||||
pub fn forward(&self) -> Dir3 {
|
||||
-self.local_z()
|
||||
}
|
||||
|
||||
/// Equivalent to [`local_z()`][Transform::local_z]
|
||||
#[inline]
|
||||
pub fn back(&self) -> Direction3d {
|
||||
pub fn back(&self) -> Dir3 {
|
||||
self.local_z()
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ fn setup(mut commands: Commands, loader: Res<AssetServer>) {
|
|||
transform: Transform::from_xyz(-OFFSET_X, -OFFSET_Y, 0.),
|
||||
..default()
|
||||
},
|
||||
Shape::Line(Segment2d::new(Direction2d::from_xy(1., 0.3).unwrap(), 90.)),
|
||||
Shape::Line(Segment2d::new(Dir2::from_xy(1., 0.3).unwrap(), 90.)),
|
||||
Spin,
|
||||
DesiredVolume::Circle,
|
||||
Intersects::default(),
|
||||
|
@ -305,7 +305,7 @@ fn get_and_draw_ray(gizmos: &mut Gizmos, time: &Time) -> RayCast2d {
|
|||
|
||||
let aabb_ray = Ray2d {
|
||||
origin: ray * 250.,
|
||||
direction: Direction2d::new_unchecked(-ray),
|
||||
direction: Dir2::new_unchecked(-ray),
|
||||
};
|
||||
let ray_cast = RayCast2d::from_ray(aabb_ray, dist - 20.);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! This example demonstrates how to use the `Camera::viewport_to_world` method.
|
||||
|
||||
use bevy::math::Direction3d;
|
||||
use bevy::math::Dir3;
|
||||
use bevy::prelude::*;
|
||||
|
||||
fn main() {
|
||||
|
@ -39,7 +39,7 @@ fn draw_cursor(
|
|||
// Draw a circle just above the ground plane at that position.
|
||||
gizmos.circle(
|
||||
point + ground.up() * 0.01,
|
||||
Direction3d::new_unchecked(ground.up()), // Up vector is already normalized.
|
||||
Dir3::new_unchecked(ground.up()), // Up vector is already normalized.
|
||||
0.2,
|
||||
LegacyColor::WHITE,
|
||||
);
|
||||
|
|
|
@ -132,10 +132,10 @@ fn draw_example_collection(
|
|||
.segments(10);
|
||||
|
||||
// Circles have 32 line-segments by default.
|
||||
my_gizmos.circle(Vec3::ZERO, Direction3d::Y, 3., LegacyColor::BLACK);
|
||||
my_gizmos.circle(Vec3::ZERO, Dir3::Y, 3., LegacyColor::BLACK);
|
||||
// You may want to increase this for larger circles or spheres.
|
||||
my_gizmos
|
||||
.circle(Vec3::ZERO, Direction3d::Y, 3.1, LegacyColor::NAVY)
|
||||
.circle(Vec3::ZERO, Dir3::Y, 3.1, LegacyColor::NAVY)
|
||||
.segments(64);
|
||||
my_gizmos
|
||||
.sphere(Vec3::ZERO, Quat::IDENTITY, 3.2, LegacyColor::BLACK)
|
||||
|
|
|
@ -165,26 +165,18 @@ const TRIANGLE: Triangle2d = Triangle2d {
|
|||
],
|
||||
};
|
||||
|
||||
const PLANE_2D: Plane2d = Plane2d {
|
||||
normal: Direction2d::Y,
|
||||
};
|
||||
const PLANE_3D: Plane3d = Plane3d {
|
||||
normal: Direction3d::Y,
|
||||
};
|
||||
const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
|
||||
const PLANE_3D: Plane3d = Plane3d { normal: Dir3::Y };
|
||||
|
||||
const LINE2D: Line2d = Line2d {
|
||||
direction: Direction2d::X,
|
||||
};
|
||||
const LINE3D: Line3d = Line3d {
|
||||
direction: Direction3d::X,
|
||||
};
|
||||
const LINE2D: Line2d = Line2d { direction: Dir2::X };
|
||||
const LINE3D: Line3d = Line3d { direction: Dir3::X };
|
||||
|
||||
const SEGMENT_2D: Segment2d = Segment2d {
|
||||
direction: Direction2d::X,
|
||||
direction: Dir2::X,
|
||||
half_length: BIG_2D,
|
||||
};
|
||||
const SEGMENT_3D: Segment3d = Segment3d {
|
||||
direction: Direction3d::X,
|
||||
direction: Dir3::X,
|
||||
half_length: BIG_3D,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue