mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Rename Rotation2d
to Rot2
(#13694)
# Objective - `Rotation2d` is a very long name for a commonly used type. ## Solution - Rename it to `Rot2` to match `glam`'s naming convention (e.g. `Vec2`) I ran a poll, and `Rot2` was the favorite of the candidate names. This is not actually a breaking change, since `Rotation2d` has not been shipped yet. --------- Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com>
This commit is contained in:
parent
2eb9d5cc38
commit
2165f2218f
7 changed files with 145 additions and 222 deletions
|
@ -8,7 +8,7 @@ use bevy_ecs::{
|
||||||
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
|
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
|
||||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||||
};
|
};
|
||||||
use bevy_math::{Quat, Rotation2d, Vec2, Vec3};
|
use bevy_math::{Quat, Rot2, Vec2, Vec3};
|
||||||
use bevy_transform::TransformPoint;
|
use bevy_transform::TransformPoint;
|
||||||
use bevy_utils::default;
|
use bevy_utils::default;
|
||||||
|
|
||||||
|
@ -707,14 +707,14 @@ where
|
||||||
pub fn rect_2d(
|
pub fn rect_2d(
|
||||||
&mut self,
|
&mut self,
|
||||||
position: Vec2,
|
position: Vec2,
|
||||||
rotation: impl Into<Rotation2d>,
|
rotation: impl Into<Rot2>,
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
color: impl Into<Color>,
|
color: impl Into<Color>,
|
||||||
) {
|
) {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| position + rotation * vec2);
|
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| position + rotation * vec2);
|
||||||
self.linestrip_2d([tl, tr, br, bl, tl], color);
|
self.linestrip_2d([tl, tr, br, bl, tl], color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
mod primitive_impls;
|
mod primitive_impls;
|
||||||
|
|
||||||
use super::{BoundingVolume, IntersectsVolume};
|
use super::{BoundingVolume, IntersectsVolume};
|
||||||
use crate::prelude::{Mat2, Rotation2d, Vec2};
|
use crate::prelude::{Mat2, Rot2, Vec2};
|
||||||
|
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
|
@ -22,11 +22,10 @@ fn point_cloud_2d_center(points: &[Vec2]) -> Vec2 {
|
||||||
pub trait Bounded2d {
|
pub trait Bounded2d {
|
||||||
/// Get an axis-aligned bounding box for the shape with the given translation and rotation.
|
/// Get an axis-aligned bounding box for the shape with the given translation and rotation.
|
||||||
/// The rotation is in radians, counterclockwise, with 0 meaning no rotation.
|
/// The rotation is in radians, counterclockwise, with 0 meaning no rotation.
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d;
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d;
|
||||||
/// Get a bounding circle for the shape
|
/// Get a bounding circle for the shape
|
||||||
/// The rotation is in radians, counterclockwise, with 0 meaning no rotation.
|
/// The rotation is in radians, counterclockwise, with 0 meaning no rotation.
|
||||||
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rotation2d>)
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle;
|
||||||
-> BoundingCircle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A 2D axis-aligned bounding box, or bounding rectangle
|
/// A 2D axis-aligned bounding box, or bounding rectangle
|
||||||
|
@ -60,11 +59,11 @@ impl Aabb2d {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(
|
pub fn from_point_cloud(
|
||||||
translation: Vec2,
|
translation: Vec2,
|
||||||
rotation: impl Into<Rotation2d>,
|
rotation: impl Into<Rot2>,
|
||||||
points: &[Vec2],
|
points: &[Vec2],
|
||||||
) -> Aabb2d {
|
) -> Aabb2d {
|
||||||
// Transform all points by rotation
|
// Transform all points by rotation
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let mut iter = points.iter().map(|point| rotation * *point);
|
let mut iter = points.iter().map(|point| rotation * *point);
|
||||||
|
|
||||||
let first = iter
|
let first = iter
|
||||||
|
@ -101,7 +100,7 @@ impl Aabb2d {
|
||||||
|
|
||||||
impl BoundingVolume for Aabb2d {
|
impl BoundingVolume for Aabb2d {
|
||||||
type Translation = Vec2;
|
type Translation = Vec2;
|
||||||
type Rotation = Rotation2d;
|
type Rotation = Rot2;
|
||||||
type HalfSize = Vec2;
|
type HalfSize = Vec2;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -232,7 +231,7 @@ impl BoundingVolume for Aabb2d {
|
||||||
/// and consider storing the original AABB and rotating that every time instead.
|
/// and consider storing the original AABB and rotating that every time instead.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
|
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let abs_rot_mat = Mat2::from_cols(
|
let abs_rot_mat = Mat2::from_cols(
|
||||||
Vec2::new(rotation.cos, rotation.sin),
|
Vec2::new(rotation.cos, rotation.sin),
|
||||||
Vec2::new(rotation.sin, rotation.cos),
|
Vec2::new(rotation.sin, rotation.cos),
|
||||||
|
@ -479,10 +478,10 @@ impl BoundingCircle {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_point_cloud(
|
pub fn from_point_cloud(
|
||||||
translation: Vec2,
|
translation: Vec2,
|
||||||
rotation: impl Into<Rotation2d>,
|
rotation: impl Into<Rot2>,
|
||||||
points: &[Vec2],
|
points: &[Vec2],
|
||||||
) -> BoundingCircle {
|
) -> BoundingCircle {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let center = point_cloud_2d_center(points);
|
let center = point_cloud_2d_center(points);
|
||||||
let mut radius_squared = 0.0;
|
let mut radius_squared = 0.0;
|
||||||
|
|
||||||
|
@ -524,7 +523,7 @@ impl BoundingCircle {
|
||||||
|
|
||||||
impl BoundingVolume for BoundingCircle {
|
impl BoundingVolume for BoundingCircle {
|
||||||
type Translation = Vec2;
|
type Translation = Vec2;
|
||||||
type Rotation = Rotation2d;
|
type Rotation = Rot2;
|
||||||
type HalfSize = f32;
|
type HalfSize = f32;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -594,7 +593,7 @@ impl BoundingVolume for BoundingCircle {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
|
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
self.center = rotation * self.center;
|
self.center = rotation * self.center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus,
|
Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus,
|
||||||
Segment2d, Triangle2d,
|
Segment2d, Triangle2d,
|
||||||
},
|
},
|
||||||
Dir2, Mat2, Rotation2d, Vec2,
|
Dir2, Mat2, Rot2, Vec2,
|
||||||
};
|
};
|
||||||
use std::f32::consts::{FRAC_PI_2, PI, TAU};
|
use std::f32::consts::{FRAC_PI_2, PI, TAU};
|
||||||
|
|
||||||
|
@ -15,15 +15,11 @@ use smallvec::SmallVec;
|
||||||
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
use super::{Aabb2d, Bounded2d, BoundingCircle};
|
||||||
|
|
||||||
impl Bounded2d for Circle {
|
impl Bounded2d for Circle {
|
||||||
fn aabb_2d(&self, translation: Vec2, _rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
Aabb2d::new(translation, Vec2::splat(self.radius))
|
Aabb2d::new(translation, Vec2::splat(self.radius))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.radius)
|
BoundingCircle::new(translation, self.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +27,7 @@ impl Bounded2d for Circle {
|
||||||
// Compute the axis-aligned bounding points of a rotated arc, used for computing the AABB of arcs and derived shapes.
|
// Compute the axis-aligned bounding points of a rotated arc, used for computing the AABB of arcs and derived shapes.
|
||||||
// The return type has room for 7 points so that the CircularSector code can add an additional point.
|
// The return type has room for 7 points so that the CircularSector code can add an additional point.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn arc_bounding_points(arc: Arc2d, rotation: impl Into<Rotation2d>) -> SmallVec<[Vec2; 7]> {
|
fn arc_bounding_points(arc: Arc2d, rotation: impl Into<Rot2>) -> SmallVec<[Vec2; 7]> {
|
||||||
// Otherwise, the extreme points will always be either the endpoints or the axis-aligned extrema of the arc's circle.
|
// Otherwise, the extreme points will always be either the endpoints or the axis-aligned extrema of the arc's circle.
|
||||||
// We need to compute which axis-aligned extrema are actually contained within the rotated arc.
|
// We need to compute which axis-aligned extrema are actually contained within the rotated arc.
|
||||||
let mut bounds = SmallVec::<[Vec2; 7]>::new();
|
let mut bounds = SmallVec::<[Vec2; 7]>::new();
|
||||||
|
@ -61,7 +57,7 @@ fn arc_bounding_points(arc: Arc2d, rotation: impl Into<Rotation2d>) -> SmallVec<
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Arc2d {
|
impl Bounded2d for Arc2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
// If our arc covers more than a circle, just return the bounding box of the circle.
|
// If our arc covers more than a circle, just return the bounding box of the circle.
|
||||||
if self.half_angle >= PI {
|
if self.half_angle >= PI {
|
||||||
return Circle::new(self.radius).aabb_2d(translation, rotation);
|
return Circle::new(self.radius).aabb_2d(translation, rotation);
|
||||||
|
@ -70,11 +66,7 @@ impl Bounded2d for Arc2d {
|
||||||
Aabb2d::from_point_cloud(translation, 0.0, &arc_bounding_points(*self, rotation))
|
Aabb2d::from_point_cloud(translation, 0.0, &arc_bounding_points(*self, rotation))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
// There are two possibilities for the bounding circle.
|
// There are two possibilities for the bounding circle.
|
||||||
if self.is_major() {
|
if self.is_major() {
|
||||||
// If the arc is major, then the widest distance between two points is a diameter of the arc's circle;
|
// If the arc is major, then the widest distance between two points is a diameter of the arc's circle;
|
||||||
|
@ -90,7 +82,7 @@ impl Bounded2d for Arc2d {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for CircularSector {
|
impl Bounded2d for CircularSector {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
// If our sector covers more than a circle, just return the bounding box of the circle.
|
// If our sector covers more than a circle, just return the bounding box of the circle.
|
||||||
if self.half_angle() >= PI {
|
if self.half_angle() >= PI {
|
||||||
return Circle::new(self.radius()).aabb_2d(translation, rotation);
|
return Circle::new(self.radius()).aabb_2d(translation, rotation);
|
||||||
|
@ -103,11 +95,7 @@ impl Bounded2d for CircularSector {
|
||||||
Aabb2d::from_point_cloud(translation, 0.0, &bounds)
|
Aabb2d::from_point_cloud(translation, 0.0, &bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
if self.arc.is_major() {
|
if self.arc.is_major() {
|
||||||
// If the arc is major, that is, greater than a semicircle,
|
// If the arc is major, that is, greater than a semicircle,
|
||||||
// then bounding circle is just the circle defining the sector.
|
// then bounding circle is just the circle defining the sector.
|
||||||
|
@ -129,22 +117,18 @@ impl Bounded2d for CircularSector {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for CircularSegment {
|
impl Bounded2d for CircularSegment {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
self.arc.aabb_2d(translation, rotation)
|
self.arc.aabb_2d(translation, rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
self.arc.bounding_circle(translation, rotation)
|
self.arc.bounding_circle(translation, rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Ellipse {
|
impl Bounded2d for Ellipse {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
|
|
||||||
// V = (hh * cos(beta), hh * sin(beta))
|
// V = (hh * cos(beta), hh * sin(beta))
|
||||||
// #####*#####
|
// #####*#####
|
||||||
|
@ -174,17 +158,13 @@ impl Bounded2d for Ellipse {
|
||||||
Aabb2d::new(translation, half_size)
|
Aabb2d::new(translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.semi_major())
|
BoundingCircle::new(translation, self.semi_major())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Rhombus {
|
impl Bounded2d for Rhombus {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation_mat = rotation.into();
|
let rotation_mat = rotation.into();
|
||||||
|
|
||||||
let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [
|
let [rotated_x_half_diagonal, rotated_y_half_diagonal] = [
|
||||||
|
@ -201,18 +181,14 @@ impl Bounded2d for Rhombus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.circumradius())
|
BoundingCircle::new(translation, self.circumradius())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Plane2d {
|
impl Bounded2d for Plane2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let normal = rotation * *self.normal;
|
let normal = rotation * *self.normal;
|
||||||
let facing_x = normal == Vec2::X || normal == Vec2::NEG_X;
|
let facing_x = normal == Vec2::X || normal == Vec2::NEG_X;
|
||||||
let facing_y = normal == Vec2::Y || normal == Vec2::NEG_Y;
|
let facing_y = normal == Vec2::Y || normal == Vec2::NEG_Y;
|
||||||
|
@ -226,18 +202,14 @@ impl Bounded2d for Plane2d {
|
||||||
Aabb2d::new(translation, half_size)
|
Aabb2d::new(translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, f32::MAX / 2.0)
|
BoundingCircle::new(translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Line2d {
|
impl Bounded2d for Line2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let direction = rotation * *self.direction;
|
let direction = rotation * *self.direction;
|
||||||
|
|
||||||
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
// Dividing `f32::MAX` by 2.0 is helpful so that we can do operations
|
||||||
|
@ -250,65 +222,49 @@ impl Bounded2d for Line2d {
|
||||||
Aabb2d::new(translation, half_size)
|
Aabb2d::new(translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, f32::MAX / 2.0)
|
BoundingCircle::new(translation, f32::MAX / 2.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Segment2d {
|
impl Bounded2d for Segment2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
// Rotate the segment by `rotation`
|
// Rotate the segment by `rotation`
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let direction = rotation * *self.direction;
|
let direction = rotation * *self.direction;
|
||||||
let half_size = (self.half_length * direction).abs();
|
let half_size = (self.half_length * direction).abs();
|
||||||
|
|
||||||
Aabb2d::new(translation, half_size)
|
Aabb2d::new(translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.half_length)
|
BoundingCircle::new(translation, self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> Bounded2d for Polyline2d<N> {
|
impl<const N: usize> Bounded2d for Polyline2d<N> {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for BoxedPolyline2d {
|
impl Bounded2d for BoxedPolyline2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Triangle2d {
|
impl Bounded2d for Triangle2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
let [a, b, c] = self.vertices.map(|vtx| rotation * vtx);
|
let [a, b, c] = self.vertices.map(|vtx| rotation * vtx);
|
||||||
|
|
||||||
let min = Vec2::new(a.x.min(b.x).min(c.x), a.y.min(b.y).min(c.y));
|
let min = Vec2::new(a.x.min(b.x).min(c.x), a.y.min(b.y).min(c.y));
|
||||||
|
@ -320,12 +276,8 @@ impl Bounded2d for Triangle2d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
let rotation: Rot2 = rotation.into();
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
let rotation: Rotation2d = rotation.into();
|
|
||||||
let [a, b, c] = self.vertices;
|
let [a, b, c] = self.vertices;
|
||||||
|
|
||||||
// The points of the segment opposite to the obtuse or right angle if one exists
|
// The points of the segment opposite to the obtuse or right angle if one exists
|
||||||
|
@ -356,8 +308,8 @@ impl Bounded2d for Triangle2d {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Rectangle {
|
impl Bounded2d for Rectangle {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
|
|
||||||
// Compute the AABB of the rotated rectangle by transforming the half-extents
|
// Compute the AABB of the rotated rectangle by transforming the half-extents
|
||||||
// by an absolute rotation matrix.
|
// by an absolute rotation matrix.
|
||||||
|
@ -368,47 +320,35 @@ impl Bounded2d for Rectangle {
|
||||||
Aabb2d::new(translation, half_size)
|
Aabb2d::new(translation, half_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
let radius = self.half_size.length();
|
let radius = self.half_size.length();
|
||||||
BoundingCircle::new(translation, radius)
|
BoundingCircle::new(translation, radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> Bounded2d for Polygon<N> {
|
impl<const N: usize> Bounded2d for Polygon<N> {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for BoxedPolygon {
|
impl Bounded2d for BoxedPolygon {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
Aabb2d::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
BoundingCircle::from_point_cloud(translation, rotation, &self.vertices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for RegularPolygon {
|
impl Bounded2d for RegularPolygon {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
|
|
||||||
let mut min = Vec2::ZERO;
|
let mut min = Vec2::ZERO;
|
||||||
let mut max = Vec2::ZERO;
|
let mut max = Vec2::ZERO;
|
||||||
|
@ -424,18 +364,14 @@ impl Bounded2d for RegularPolygon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.circumcircle.radius)
|
BoundingCircle::new(translation, self.circumcircle.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bounded2d for Capsule2d {
|
impl Bounded2d for Capsule2d {
|
||||||
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d {
|
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
|
||||||
let rotation: Rotation2d = rotation.into();
|
let rotation: Rot2 = rotation.into();
|
||||||
|
|
||||||
// Get the line segment between the hemicircles of the rotated capsule
|
// Get the line segment between the hemicircles of the rotated capsule
|
||||||
let segment = Segment2d {
|
let segment = Segment2d {
|
||||||
|
@ -455,11 +391,7 @@ impl Bounded2d for Capsule2d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounding_circle(
|
fn bounding_circle(&self, translation: Vec2, _rotation: impl Into<Rot2>) -> BoundingCircle {
|
||||||
&self,
|
|
||||||
translation: Vec2,
|
|
||||||
_rotation: impl Into<Rotation2d>,
|
|
||||||
) -> BoundingCircle {
|
|
||||||
BoundingCircle::new(translation, self.radius + self.half_length)
|
BoundingCircle::new(translation, self.radius + self.half_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
primitives::{Primitive2d, Primitive3d},
|
primitives::{Primitive2d, Primitive3d},
|
||||||
Quat, Rotation2d, Vec2, Vec3, Vec3A,
|
Quat, Rot2, Vec2, Vec3, Vec3A,
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::f32::consts::FRAC_1_SQRT_2;
|
use core::f32::consts::FRAC_1_SQRT_2;
|
||||||
|
@ -200,47 +200,47 @@ impl Dir2 {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slerp(self, rhs: Self, s: f32) -> Self {
|
pub fn slerp(self, rhs: Self, s: f32) -> Self {
|
||||||
let angle = self.angle_between(rhs.0);
|
let angle = self.angle_between(rhs.0);
|
||||||
Rotation2d::radians(angle * s) * self
|
Rot2::radians(angle * s) * self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates this direction to `other`.
|
/// Get the rotation that rotates this direction to `other`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_to(self, other: Self) -> Rotation2d {
|
pub fn rotation_to(self, other: Self) -> Rot2 {
|
||||||
// Rotate `self` to X-axis, then X-axis to `other`:
|
// Rotate `self` to X-axis, then X-axis to `other`:
|
||||||
other.rotation_from_x() * self.rotation_to_x()
|
other.rotation_from_x() * self.rotation_to_x()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates `other` to this direction.
|
/// Get the rotation that rotates `other` to this direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_from(self, other: Self) -> Rotation2d {
|
pub fn rotation_from(self, other: Self) -> Rot2 {
|
||||||
other.rotation_to(self)
|
other.rotation_to(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates the X-axis to this direction.
|
/// Get the rotation that rotates the X-axis to this direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_from_x(self) -> Rotation2d {
|
pub fn rotation_from_x(self) -> Rot2 {
|
||||||
Rotation2d::from_sin_cos(self.0.y, self.0.x)
|
Rot2::from_sin_cos(self.0.y, self.0.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates this direction to the X-axis.
|
/// Get the rotation that rotates this direction to the X-axis.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_to_x(self) -> Rotation2d {
|
pub fn rotation_to_x(self) -> Rot2 {
|
||||||
// (This is cheap, it just negates one component.)
|
// (This is cheap, it just negates one component.)
|
||||||
self.rotation_from_x().inverse()
|
self.rotation_from_x().inverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates this direction to the Y-axis.
|
/// Get the rotation that rotates this direction to the Y-axis.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_from_y(self) -> Rotation2d {
|
pub fn rotation_from_y(self) -> Rot2 {
|
||||||
// `x <- y`, `y <- -x` correspond to rotating clockwise by pi/2;
|
// `x <- y`, `y <- -x` correspond to rotating clockwise by pi/2;
|
||||||
// this transforms the Y-axis into the X-axis, maintaining the relative position
|
// this transforms the Y-axis into the X-axis, maintaining the relative position
|
||||||
// of our direction. Then we just use the same technique as `rotation_from_x`.
|
// of our direction. Then we just use the same technique as `rotation_from_x`.
|
||||||
Rotation2d::from_sin_cos(-self.0.x, self.0.y)
|
Rot2::from_sin_cos(-self.0.x, self.0.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rotation that rotates the Y-axis to this direction.
|
/// Get the rotation that rotates the Y-axis to this direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_to_y(self) -> Rotation2d {
|
pub fn rotation_to_y(self) -> Rot2 {
|
||||||
self.rotation_from_y().inverse()
|
self.rotation_from_y().inverse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,10 +287,10 @@ impl std::ops::Mul<Dir2> for f32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Mul<Dir2> for Rotation2d {
|
impl std::ops::Mul<Dir2> for Rot2 {
|
||||||
type Output = Dir2;
|
type Output = Dir2;
|
||||||
|
|
||||||
/// Rotates the [`Dir2`] using a [`Rotation2d`].
|
/// Rotates the [`Dir2`] using a [`Rot2`].
|
||||||
fn mul(self, direction: Dir2) -> Self::Output {
|
fn mul(self, direction: Dir2) -> Self::Output {
|
||||||
let rotated = self * *direction;
|
let rotated = self * *direction;
|
||||||
|
|
||||||
|
@ -807,21 +807,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dir2_to_rotation2d() {
|
fn dir2_to_rotation2d() {
|
||||||
assert_relative_eq!(
|
assert_relative_eq!(Dir2::EAST.rotation_to(Dir2::NORTH_EAST), Rot2::FRAC_PI_4);
|
||||||
Dir2::EAST.rotation_to(Dir2::NORTH_EAST),
|
assert_relative_eq!(Dir2::NORTH.rotation_from(Dir2::NORTH_EAST), Rot2::FRAC_PI_4);
|
||||||
Rotation2d::FRAC_PI_4
|
assert_relative_eq!(Dir2::SOUTH.rotation_to_x(), Rot2::FRAC_PI_2);
|
||||||
);
|
assert_relative_eq!(Dir2::SOUTH.rotation_to_y(), Rot2::PI);
|
||||||
assert_relative_eq!(
|
assert_relative_eq!(Dir2::NORTH_WEST.rotation_from_x(), Rot2::degrees(135.0));
|
||||||
Dir2::NORTH.rotation_from(Dir2::NORTH_EAST),
|
assert_relative_eq!(Dir2::NORTH_WEST.rotation_from_y(), Rot2::FRAC_PI_4);
|
||||||
Rotation2d::FRAC_PI_4
|
|
||||||
);
|
|
||||||
assert_relative_eq!(Dir2::SOUTH.rotation_to_x(), Rotation2d::FRAC_PI_2);
|
|
||||||
assert_relative_eq!(Dir2::SOUTH.rotation_to_y(), Rotation2d::PI);
|
|
||||||
assert_relative_eq!(
|
|
||||||
Dir2::NORTH_WEST.rotation_from_x(),
|
|
||||||
Rotation2d::degrees(135.0)
|
|
||||||
);
|
|
||||||
assert_relative_eq!(Dir2::NORTH_WEST.rotation_from_y(), Rotation2d::FRAC_PI_4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub use direction::*;
|
||||||
pub use float_ord::*;
|
pub use float_ord::*;
|
||||||
pub use ray::{Ray2d, Ray3d};
|
pub use ray::{Ray2d, Ray3d};
|
||||||
pub use rects::*;
|
pub use rects::*;
|
||||||
pub use rotation2d::Rotation2d;
|
pub use rotation2d::Rot2;
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
pub use sampling::{FromRng, ShapeSample};
|
pub use sampling::{FromRng, ShapeSample};
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ pub mod prelude {
|
||||||
direction::{Dir2, Dir3, Dir3A},
|
direction::{Dir2, Dir3, Dir3A},
|
||||||
primitives::*,
|
primitives::*,
|
||||||
BVec2, BVec3, BVec4, EulerRot, FloatExt, IRect, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
|
BVec2, BVec3, BVec4, EulerRot, FloatExt, IRect, IVec2, IVec3, IVec4, Mat2, Mat3, Mat4,
|
||||||
Quat, Ray2d, Ray3d, Rect, Rotation2d, URect, UVec2, UVec3, UVec4, Vec2, Vec2Swizzles, Vec3,
|
Quat, Ray2d, Ray3d, Rect, Rot2, URect, UVec2, UVec3, UVec4, Vec2, Vec2Swizzles, Vec3,
|
||||||
Vec3Swizzles, Vec4, Vec4Swizzles,
|
Vec3Swizzles, Vec4, Vec4Swizzles,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,19 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use approx::assert_relative_eq;
|
/// # use approx::assert_relative_eq;
|
||||||
/// # use bevy_math::{Rotation2d, Vec2};
|
/// # use bevy_math::{Rot2, Vec2};
|
||||||
/// use std::f32::consts::PI;
|
/// use std::f32::consts::PI;
|
||||||
///
|
///
|
||||||
/// // Create rotations from radians or degrees
|
/// // Create rotations from radians or degrees
|
||||||
/// let rotation1 = Rotation2d::radians(PI / 2.0);
|
/// let rotation1 = Rot2::radians(PI / 2.0);
|
||||||
/// let rotation2 = Rotation2d::degrees(45.0);
|
/// let rotation2 = Rot2::degrees(45.0);
|
||||||
///
|
///
|
||||||
/// // Get the angle back as radians or degrees
|
/// // Get the angle back as radians or degrees
|
||||||
/// assert_eq!(rotation1.as_degrees(), 90.0);
|
/// assert_eq!(rotation1.as_degrees(), 90.0);
|
||||||
/// assert_eq!(rotation2.as_radians(), PI / 4.0);
|
/// assert_eq!(rotation2.as_radians(), PI / 4.0);
|
||||||
///
|
///
|
||||||
/// // "Add" rotations together using `*`
|
/// // "Add" rotations together using `*`
|
||||||
/// assert_relative_eq!(rotation1 * rotation2, Rotation2d::degrees(135.0));
|
/// assert_relative_eq!(rotation1 * rotation2, Rot2::degrees(135.0));
|
||||||
///
|
///
|
||||||
/// // Rotate vectors
|
/// // Rotate vectors
|
||||||
/// assert_relative_eq!(rotation1 * Vec2::X, Vec2::Y);
|
/// assert_relative_eq!(rotation1 * Vec2::X, Vec2::Y);
|
||||||
|
@ -41,7 +41,8 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||||
all(feature = "serialize", feature = "bevy_reflect"),
|
all(feature = "serialize", feature = "bevy_reflect"),
|
||||||
reflect(Serialize, Deserialize)
|
reflect(Serialize, Deserialize)
|
||||||
)]
|
)]
|
||||||
pub struct Rotation2d {
|
#[doc(alias = "rotation", alias = "rotation2d", alias = "rotation_2d")]
|
||||||
|
pub struct Rot2 {
|
||||||
/// The cosine of the rotation angle in radians.
|
/// The cosine of the rotation angle in radians.
|
||||||
///
|
///
|
||||||
/// This is the real part of the unit complex number representing the rotation.
|
/// This is the real part of the unit complex number representing the rotation.
|
||||||
|
@ -52,13 +53,13 @@ pub struct Rotation2d {
|
||||||
pub sin: f32,
|
pub sin: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Rotation2d {
|
impl Default for Rot2 {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::IDENTITY
|
Self::IDENTITY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rotation2d {
|
impl Rot2 {
|
||||||
/// No rotation.
|
/// No rotation.
|
||||||
pub const IDENTITY: Self = Self { cos: 1.0, sin: 0.0 };
|
pub const IDENTITY: Self = Self { cos: 1.0, sin: 0.0 };
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ impl Rotation2d {
|
||||||
sin: 0.382_683_43,
|
sin: 0.382_683_43,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates a [`Rotation2d`] from a counterclockwise angle in radians.
|
/// Creates a [`Rot2`] from a counterclockwise angle in radians.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn radians(radians: f32) -> Self {
|
pub fn radians(radians: f32) -> Self {
|
||||||
#[cfg(feature = "libm")]
|
#[cfg(feature = "libm")]
|
||||||
|
@ -109,13 +110,13 @@ impl Rotation2d {
|
||||||
Self::from_sin_cos(sin, cos)
|
Self::from_sin_cos(sin, cos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`Rotation2d`] from a counterclockwise angle in degrees.
|
/// Creates a [`Rot2`] from a counterclockwise angle in degrees.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn degrees(degrees: f32) -> Self {
|
pub fn degrees(degrees: f32) -> Self {
|
||||||
Self::radians(degrees.to_radians())
|
Self::radians(degrees.to_radians())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`Rotation2d`] from the sine and cosine of an angle in radians.
|
/// Creates a [`Rot2`] from the sine and cosine of an angle in radians.
|
||||||
///
|
///
|
||||||
/// The rotation is only valid if `sin * sin + cos * cos == 1.0`.
|
/// The rotation is only valid if `sin * sin + cos * cos == 1.0`.
|
||||||
///
|
///
|
||||||
|
@ -170,7 +171,7 @@ impl Rotation2d {
|
||||||
|
|
||||||
/// Computes the squared length or norm of the complex number used to represent the rotation.
|
/// Computes the squared length or norm of the complex number used to represent the rotation.
|
||||||
///
|
///
|
||||||
/// This is generally faster than [`Rotation2d::length()`], as it avoids a square
|
/// This is generally faster than [`Rot2::length()`], as it avoids a square
|
||||||
/// root operation.
|
/// root operation.
|
||||||
///
|
///
|
||||||
/// The length is typically expected to be `1.0`. Unexpectedly denormalized rotations
|
/// The length is typically expected to be `1.0`. Unexpectedly denormalized rotations
|
||||||
|
@ -195,7 +196,7 @@ impl Rotation2d {
|
||||||
/// `None` will be returned if the sine and cosine of `self` are both zero (or very close to zero),
|
/// `None` will be returned if the sine and cosine of `self` are both zero (or very close to zero),
|
||||||
/// or if either of them is NaN or infinite.
|
/// or if either of them is NaN or infinite.
|
||||||
///
|
///
|
||||||
/// Note that [`Rotation2d`] should typically already be normalized by design.
|
/// Note that [`Rot2`] should typically already be normalized by design.
|
||||||
/// Manual normalization is only needed when successive operations result in
|
/// Manual normalization is only needed when successive operations result in
|
||||||
/// accumulated floating point error, or if the rotation was constructed
|
/// accumulated floating point error, or if the rotation was constructed
|
||||||
/// with invalid values.
|
/// with invalid values.
|
||||||
|
@ -211,7 +212,7 @@ impl Rotation2d {
|
||||||
|
|
||||||
/// Returns `self` with a length of `1.0`.
|
/// Returns `self` with a length of `1.0`.
|
||||||
///
|
///
|
||||||
/// Note that [`Rotation2d`] should typically already be normalized by design.
|
/// Note that [`Rot2`] should typically already be normalized by design.
|
||||||
/// Manual normalization is only needed when successive operations result in
|
/// Manual normalization is only needed when successive operations result in
|
||||||
/// accumulated floating point error, or if the rotation was constructed
|
/// accumulated floating point error, or if the rotation was constructed
|
||||||
/// with invalid values.
|
/// with invalid values.
|
||||||
|
@ -248,7 +249,7 @@ impl Rotation2d {
|
||||||
(self.length_squared() - 1.0).abs() <= 2e-4
|
(self.length_squared() - 1.0).abs() <= 2e-4
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the rotation is near [`Rotation2d::IDENTITY`].
|
/// Returns `true` if the rotation is near [`Rot2::IDENTITY`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_near_identity(self) -> bool {
|
pub fn is_near_identity(self) -> bool {
|
||||||
// Same as `Quat::is_near_identity`, but using sine and cosine
|
// Same as `Quat::is_near_identity`, but using sine and cosine
|
||||||
|
@ -300,10 +301,10 @@ impl Rotation2d {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_math::Rotation2d;
|
/// # use bevy_math::Rot2;
|
||||||
/// #
|
/// #
|
||||||
/// let rot1 = Rotation2d::IDENTITY;
|
/// let rot1 = Rot2::IDENTITY;
|
||||||
/// let rot2 = Rotation2d::degrees(135.0);
|
/// let rot2 = Rot2::degrees(135.0);
|
||||||
///
|
///
|
||||||
/// let result1 = rot1.nlerp(rot2, 1.0 / 3.0);
|
/// let result1 = rot1.nlerp(rot2, 1.0 / 3.0);
|
||||||
/// assert_eq!(result1.as_degrees(), 28.675055);
|
/// assert_eq!(result1.as_degrees(), 28.675055);
|
||||||
|
@ -338,10 +339,10 @@ impl Rotation2d {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_math::Rotation2d;
|
/// # use bevy_math::Rot2;
|
||||||
/// #
|
/// #
|
||||||
/// let rot1 = Rotation2d::IDENTITY;
|
/// let rot1 = Rot2::IDENTITY;
|
||||||
/// let rot2 = Rotation2d::degrees(135.0);
|
/// let rot2 = Rot2::degrees(135.0);
|
||||||
///
|
///
|
||||||
/// let result1 = rot1.slerp(rot2, 1.0 / 3.0);
|
/// let result1 = rot1.slerp(rot2, 1.0 / 3.0);
|
||||||
/// assert_eq!(result1.as_degrees(), 45.0);
|
/// assert_eq!(result1.as_degrees(), 45.0);
|
||||||
|
@ -355,21 +356,21 @@ impl Rotation2d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f32> for Rotation2d {
|
impl From<f32> for Rot2 {
|
||||||
/// Creates a [`Rotation2d`] from a counterclockwise angle in radians.
|
/// Creates a [`Rot2`] from a counterclockwise angle in radians.
|
||||||
fn from(rotation: f32) -> Self {
|
fn from(rotation: f32) -> Self {
|
||||||
Self::radians(rotation)
|
Self::radians(rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rotation2d> for Mat2 {
|
impl From<Rot2> for Mat2 {
|
||||||
/// Creates a [`Mat2`] rotation matrix from a [`Rotation2d`].
|
/// Creates a [`Mat2`] rotation matrix from a [`Rot2`].
|
||||||
fn from(rot: Rotation2d) -> Self {
|
fn from(rot: Rot2) -> Self {
|
||||||
Mat2::from_cols_array(&[rot.cos, -rot.sin, rot.sin, rot.cos])
|
Mat2::from_cols_array(&[rot.cos, -rot.sin, rot.sin, rot.cos])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Mul for Rotation2d {
|
impl std::ops::Mul for Rot2 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn mul(self, rhs: Self) -> Self::Output {
|
fn mul(self, rhs: Self) -> Self::Output {
|
||||||
|
@ -380,16 +381,16 @@ impl std::ops::Mul for Rotation2d {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::MulAssign for Rotation2d {
|
impl std::ops::MulAssign for Rot2 {
|
||||||
fn mul_assign(&mut self, rhs: Self) {
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
*self = *self * rhs;
|
*self = *self * rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Mul<Vec2> for Rotation2d {
|
impl std::ops::Mul<Vec2> for Rot2 {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
/// Rotates a [`Vec2`] by a [`Rotation2d`].
|
/// Rotates a [`Vec2`] by a [`Rot2`].
|
||||||
fn mul(self, rhs: Vec2) -> Self::Output {
|
fn mul(self, rhs: Vec2) -> Self::Output {
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
rhs.x * self.cos - rhs.y * self.sin,
|
rhs.x * self.cos - rhs.y * self.sin,
|
||||||
|
@ -399,7 +400,7 @@ impl std::ops::Mul<Vec2> for Rotation2d {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "approx", test))]
|
#[cfg(any(feature = "approx", test))]
|
||||||
impl approx::AbsDiffEq for Rotation2d {
|
impl approx::AbsDiffEq for Rot2 {
|
||||||
type Epsilon = f32;
|
type Epsilon = f32;
|
||||||
fn default_epsilon() -> f32 {
|
fn default_epsilon() -> f32 {
|
||||||
f32::EPSILON
|
f32::EPSILON
|
||||||
|
@ -410,7 +411,7 @@ impl approx::AbsDiffEq for Rotation2d {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "approx", test))]
|
#[cfg(any(feature = "approx", test))]
|
||||||
impl approx::RelativeEq for Rotation2d {
|
impl approx::RelativeEq for Rot2 {
|
||||||
fn default_max_relative() -> f32 {
|
fn default_max_relative() -> f32 {
|
||||||
f32::EPSILON
|
f32::EPSILON
|
||||||
}
|
}
|
||||||
|
@ -421,7 +422,7 @@ impl approx::RelativeEq for Rotation2d {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "approx", test))]
|
#[cfg(any(feature = "approx", test))]
|
||||||
impl approx::UlpsEq for Rotation2d {
|
impl approx::UlpsEq for Rot2 {
|
||||||
fn default_max_ulps() -> u32 {
|
fn default_max_ulps() -> u32 {
|
||||||
4
|
4
|
||||||
}
|
}
|
||||||
|
@ -435,13 +436,13 @@ impl approx::UlpsEq for Rotation2d {
|
||||||
mod tests {
|
mod tests {
|
||||||
use approx::assert_relative_eq;
|
use approx::assert_relative_eq;
|
||||||
|
|
||||||
use crate::{Dir2, Rotation2d, Vec2};
|
use crate::{Dir2, Rot2, Vec2};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn creation() {
|
fn creation() {
|
||||||
let rotation1 = Rotation2d::radians(std::f32::consts::FRAC_PI_2);
|
let rotation1 = Rot2::radians(std::f32::consts::FRAC_PI_2);
|
||||||
let rotation2 = Rotation2d::degrees(90.0);
|
let rotation2 = Rot2::degrees(90.0);
|
||||||
let rotation3 = Rotation2d::from_sin_cos(1.0, 0.0);
|
let rotation3 = Rot2::from_sin_cos(1.0, 0.0);
|
||||||
|
|
||||||
// All three rotations should be equal
|
// All three rotations should be equal
|
||||||
assert_relative_eq!(rotation1.sin, rotation2.sin);
|
assert_relative_eq!(rotation1.sin, rotation2.sin);
|
||||||
|
@ -456,7 +457,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rotate() {
|
fn rotate() {
|
||||||
let rotation = Rotation2d::degrees(90.0);
|
let rotation = Rot2::degrees(90.0);
|
||||||
|
|
||||||
assert_relative_eq!(rotation * Vec2::X, Vec2::Y);
|
assert_relative_eq!(rotation * Vec2::X, Vec2::Y);
|
||||||
assert_relative_eq!(rotation * Dir2::Y, Dir2::NEG_X);
|
assert_relative_eq!(rotation * Dir2::Y, Dir2::NEG_X);
|
||||||
|
@ -464,8 +465,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add() {
|
fn add() {
|
||||||
let rotation1 = Rotation2d::degrees(90.0);
|
let rotation1 = Rot2::degrees(90.0);
|
||||||
let rotation2 = Rotation2d::degrees(180.0);
|
let rotation2 = Rot2::degrees(180.0);
|
||||||
|
|
||||||
// 90 deg + 180 deg becomes -90 deg after it wraps around to be within the ]-180, 180] range
|
// 90 deg + 180 deg becomes -90 deg after it wraps around to be within the ]-180, 180] range
|
||||||
assert_eq!((rotation1 * rotation2).as_degrees(), -90.0);
|
assert_eq!((rotation1 * rotation2).as_degrees(), -90.0);
|
||||||
|
@ -473,8 +474,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn subtract() {
|
fn subtract() {
|
||||||
let rotation1 = Rotation2d::degrees(90.0);
|
let rotation1 = Rot2::degrees(90.0);
|
||||||
let rotation2 = Rotation2d::degrees(45.0);
|
let rotation2 = Rot2::degrees(45.0);
|
||||||
|
|
||||||
assert_relative_eq!((rotation1 * rotation2.inverse()).as_degrees(), 45.0);
|
assert_relative_eq!((rotation1 * rotation2.inverse()).as_degrees(), 45.0);
|
||||||
|
|
||||||
|
@ -487,7 +488,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn length() {
|
fn length() {
|
||||||
let rotation = Rotation2d {
|
let rotation = Rot2 {
|
||||||
sin: 10.0,
|
sin: 10.0,
|
||||||
cos: 5.0,
|
cos: 5.0,
|
||||||
};
|
};
|
||||||
|
@ -499,16 +500,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn is_near_identity() {
|
fn is_near_identity() {
|
||||||
assert!(!Rotation2d::radians(0.1).is_near_identity());
|
assert!(!Rot2::radians(0.1).is_near_identity());
|
||||||
assert!(!Rotation2d::radians(-0.1).is_near_identity());
|
assert!(!Rot2::radians(-0.1).is_near_identity());
|
||||||
assert!(Rotation2d::radians(0.00001).is_near_identity());
|
assert!(Rot2::radians(0.00001).is_near_identity());
|
||||||
assert!(Rotation2d::radians(-0.00001).is_near_identity());
|
assert!(Rot2::radians(-0.00001).is_near_identity());
|
||||||
assert!(Rotation2d::radians(0.0).is_near_identity());
|
assert!(Rot2::radians(0.0).is_near_identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn normalize() {
|
fn normalize() {
|
||||||
let rotation = Rotation2d {
|
let rotation = Rot2 {
|
||||||
sin: 10.0,
|
sin: 10.0,
|
||||||
cos: 5.0,
|
cos: 5.0,
|
||||||
};
|
};
|
||||||
|
@ -524,7 +525,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn try_normalize() {
|
fn try_normalize() {
|
||||||
// Valid
|
// Valid
|
||||||
assert!(Rotation2d {
|
assert!(Rot2 {
|
||||||
sin: 10.0,
|
sin: 10.0,
|
||||||
cos: 5.0,
|
cos: 5.0,
|
||||||
}
|
}
|
||||||
|
@ -532,7 +533,7 @@ mod tests {
|
||||||
.is_some());
|
.is_some());
|
||||||
|
|
||||||
// NaN
|
// NaN
|
||||||
assert!(Rotation2d {
|
assert!(Rot2 {
|
||||||
sin: f32::NAN,
|
sin: f32::NAN,
|
||||||
cos: 5.0,
|
cos: 5.0,
|
||||||
}
|
}
|
||||||
|
@ -540,10 +541,10 @@ mod tests {
|
||||||
.is_none());
|
.is_none());
|
||||||
|
|
||||||
// Zero
|
// Zero
|
||||||
assert!(Rotation2d { sin: 0.0, cos: 0.0 }.try_normalize().is_none());
|
assert!(Rot2 { sin: 0.0, cos: 0.0 }.try_normalize().is_none());
|
||||||
|
|
||||||
// Non-finite
|
// Non-finite
|
||||||
assert!(Rotation2d {
|
assert!(Rot2 {
|
||||||
sin: f32::INFINITY,
|
sin: f32::INFINITY,
|
||||||
cos: 5.0,
|
cos: 5.0,
|
||||||
}
|
}
|
||||||
|
@ -553,16 +554,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nlerp() {
|
fn nlerp() {
|
||||||
let rot1 = Rotation2d::IDENTITY;
|
let rot1 = Rot2::IDENTITY;
|
||||||
let rot2 = Rotation2d::degrees(135.0);
|
let rot2 = Rot2::degrees(135.0);
|
||||||
|
|
||||||
assert_eq!(rot1.nlerp(rot2, 1.0 / 3.0).as_degrees(), 28.675055);
|
assert_eq!(rot1.nlerp(rot2, 1.0 / 3.0).as_degrees(), 28.675055);
|
||||||
assert!(rot1.nlerp(rot2, 0.0).is_near_identity());
|
assert!(rot1.nlerp(rot2, 0.0).is_near_identity());
|
||||||
assert_eq!(rot1.nlerp(rot2, 0.5).as_degrees(), 67.5);
|
assert_eq!(rot1.nlerp(rot2, 0.5).as_degrees(), 67.5);
|
||||||
assert_eq!(rot1.nlerp(rot2, 1.0).as_degrees(), 135.0);
|
assert_eq!(rot1.nlerp(rot2, 1.0).as_degrees(), 135.0);
|
||||||
|
|
||||||
let rot1 = Rotation2d::IDENTITY;
|
let rot1 = Rot2::IDENTITY;
|
||||||
let rot2 = Rotation2d::from_sin_cos(0.0, -1.0);
|
let rot2 = Rot2::from_sin_cos(0.0, -1.0);
|
||||||
|
|
||||||
assert!(rot1.nlerp(rot2, 1.0 / 3.0).is_near_identity());
|
assert!(rot1.nlerp(rot2, 1.0 / 3.0).is_near_identity());
|
||||||
assert!(rot1.nlerp(rot2, 0.0).is_near_identity());
|
assert!(rot1.nlerp(rot2, 0.0).is_near_identity());
|
||||||
|
@ -573,16 +574,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn slerp() {
|
fn slerp() {
|
||||||
let rot1 = Rotation2d::IDENTITY;
|
let rot1 = Rot2::IDENTITY;
|
||||||
let rot2 = Rotation2d::degrees(135.0);
|
let rot2 = Rot2::degrees(135.0);
|
||||||
|
|
||||||
assert_eq!(rot1.slerp(rot2, 1.0 / 3.0).as_degrees(), 45.0);
|
assert_eq!(rot1.slerp(rot2, 1.0 / 3.0).as_degrees(), 45.0);
|
||||||
assert!(rot1.slerp(rot2, 0.0).is_near_identity());
|
assert!(rot1.slerp(rot2, 0.0).is_near_identity());
|
||||||
assert_eq!(rot1.slerp(rot2, 0.5).as_degrees(), 67.5);
|
assert_eq!(rot1.slerp(rot2, 0.5).as_degrees(), 67.5);
|
||||||
assert_eq!(rot1.slerp(rot2, 1.0).as_degrees(), 135.0);
|
assert_eq!(rot1.slerp(rot2, 1.0).as_degrees(), 135.0);
|
||||||
|
|
||||||
let rot1 = Rotation2d::IDENTITY;
|
let rot1 = Rot2::IDENTITY;
|
||||||
let rot2 = Rotation2d::from_sin_cos(0.0, -1.0);
|
let rot2 = Rot2::from_sin_cos(0.0, -1.0);
|
||||||
|
|
||||||
assert!((rot1.slerp(rot2, 1.0 / 3.0).as_degrees() - 60.0).abs() < 10e-6);
|
assert!((rot1.slerp(rot2, 1.0 / 3.0).as_degrees() - 60.0).abs() < 10e-6);
|
||||||
assert!(rot1.slerp(rot2, 0.0).is_near_identity());
|
assert!(rot1.slerp(rot2, 0.0).is_near_identity());
|
||||||
|
|
|
@ -25,7 +25,7 @@ use std::f32::consts::TAU;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitives::{Circle, Sphere},
|
primitives::{Circle, Sphere},
|
||||||
Dir2, Dir3, Dir3A, Quat, Rotation2d, ShapeSample, Vec3A,
|
Dir2, Dir3, Dir3A, Quat, Rot2, ShapeSample, Vec3A,
|
||||||
};
|
};
|
||||||
use rand::{
|
use rand::{
|
||||||
distributions::{Distribution, Standard},
|
distributions::{Distribution, Standard},
|
||||||
|
@ -86,14 +86,14 @@ impl Distribution<Dir3A> for Standard {
|
||||||
|
|
||||||
impl FromRng for Dir3A {}
|
impl FromRng for Dir3A {}
|
||||||
|
|
||||||
impl Distribution<Rotation2d> for Standard {
|
impl Distribution<Rot2> for Standard {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Rotation2d {
|
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Rot2 {
|
||||||
let angle = rng.gen_range(0.0..TAU);
|
let angle = rng.gen_range(0.0..TAU);
|
||||||
Rotation2d::radians(angle)
|
Rot2::radians(angle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRng for Rotation2d {}
|
impl FromRng for Rot2 {}
|
||||||
|
|
||||||
impl FromRng for Quat {}
|
impl FromRng for Quat {}
|
||||||
|
|
Loading…
Reference in a new issue