Skip to content

Add Rotation2d #11658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f39c6ea
Add `Rotation2d`
Jondolf Feb 1, 2024
fef12d6
Use `Rotation2d`
Jondolf Feb 1, 2024
f51a8c9
Reflect `Rotation2d`
Jondolf Feb 1, 2024
82892c9
Add `libm`
Jondolf Feb 1, 2024
174a09e
Merge branch 'main' into rotation2d
Jondolf Feb 1, 2024
98f1db4
Add some docs to impls
Jondolf Feb 1, 2024
a986cdc
Add tests
Jondolf Feb 1, 2024
2c3d020
Rotate directions
Jondolf Feb 1, 2024
47b0742
Add constants to `Rotation2d`
Jondolf Feb 1, 2024
0c30306
Mention angle range in docs
Jondolf Feb 1, 2024
6eb039a
Fix libm input
Jondolf Feb 1, 2024
deddf7b
Add missing doc comment
Jondolf Feb 1, 2024
d62e5fa
Fix condition
Jondolf Feb 2, 2024
c16b146
Note conditions for valid rotation using `from_sin_cos`
Jondolf Feb 2, 2024
52ea83d
Use parenthesis interval notation
Jondolf Feb 2, 2024
fc6f582
Remove `Rotation2d::new`
Jondolf Feb 2, 2024
260ec57
Impl `approx` traits and improve docs
Jondolf Feb 2, 2024
f518c96
Rename `from_radians` to `radians` and `from_degrees` to `degrees`
Jondolf Feb 2, 2024
d700581
Use `angle_between` to simplify logic
Jondolf Feb 3, 2024
dc63b0a
Merge branch 'main' into rotation2d
Jondolf Feb 3, 2024
b80c875
Fix doc comment and add `debug_assert!`
Jondolf Feb 28, 2024
702c1f6
Add length and normalization helpers and fix `lerp`
Jondolf Feb 29, 2024
e612c8d
Use sin and cos directly for `is_near_identity`
Jondolf Feb 29, 2024
5804977
Improve lerp and slerp docs and tests
Jondolf Feb 29, 2024
586fb49
Merge branch 'main' into rotation2d
Jondolf Feb 29, 2024
4de7b2a
Fix direction type
Jondolf Feb 29, 2024
6de3be0
Improve `lerp` docs
Jondolf Mar 4, 2024
8d5a2eb
Merge branch 'main' into rotation2d
Jondolf Mar 4, 2024
f8a393a
Rename `lerp` to `nlerp`
Jondolf Mar 4, 2024
c34b9dc
Revert accidental argument type change
Jondolf Mar 4, 2024
57d333b
Use consistent assertions for unit-length after rotating `Dir2`
Jondolf Mar 4, 2024
617a5b4
Fix typo
Jondolf Mar 4, 2024
c1904f5
Address review comments regarding normalization
Jondolf Mar 7, 2024
16b078d
Merge branch 'main' into rotation2d
Jondolf Mar 7, 2024
7e61be6
Use `Rotation2d` for 2D bounding volumes
Jondolf Mar 7, 2024
7b53dfe
Fix test
Jondolf Mar 7, 2024
3e0fa74
Explain `is_normalized` threshold value
Jondolf Mar 8, 2024
58cf454
Merge branch 'main' into rotation2d
Jondolf Mar 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions crates/bevy_gizmos/src/gizmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use bevy_ecs::{
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
world::{unsafe_world_cell::UnsafeWorldCell, World},
};
use bevy_math::{Dir3, Mat2, Quat, Vec2, Vec3};
use bevy_math::{Dir3, Quat, Rotation2d, Vec2, Vec3};
use bevy_transform::TransformPoint;

use crate::{
Expand Down Expand Up @@ -590,11 +590,17 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
/// # bevy_ecs::system::assert_is_system(system);
/// ```
#[inline]
pub fn rect_2d(&mut self, position: Vec2, rotation: f32, size: Vec2, color: impl Into<Color>) {
pub fn rect_2d(
&mut self,
position: Vec2,
rotation: impl Into<Rotation2d>,
size: Vec2,
color: impl Into<Color>,
) {
if !self.enabled {
return;
}
let rotation = Mat2::from_angle(rotation);
let rotation: Rotation2d = rotation.into();
let [tl, tr, br, bl] = rect_inner(size).map(|vec2| position + rotation * vec2);
self.linestrip_2d([tl, tr, br, bl, tl], color);
}
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ keywords = ["bevy"]
glam = { version = "0.25", features = ["bytemuck"] }
thiserror = "1.0"
serde = { version = "1", features = ["derive"], optional = true }
libm = { version = "0.2", optional = true }
approx = { version = "0.5", optional = true }

[dev-dependencies]
Expand All @@ -25,7 +26,7 @@ approx = ["dep:approx", "glam/approx"]
mint = ["glam/mint"]
# Enable libm mathematical functions for glam types to ensure consistent outputs
# across platforms at the cost of losing hardware-level optimization using intrinsics
libm = ["glam/libm"]
libm = ["dep:libm", "glam/libm"]
# Enable assertions to check the validity of parameters passed to glam
glam_assert = ["glam/glam-assert"]
# Enable assertions in debug builds to check the validity of parameters passed to glam
Expand Down
67 changes: 42 additions & 25 deletions crates/bevy_math/src/bounding/bounded2d/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
mod primitive_impls;

use glam::Mat2;

use super::{BoundingVolume, IntersectsVolume};
use crate::prelude::Vec2;
use crate::prelude::{Mat2, Rotation2d, Vec2};

/// Computes the geometric center of the given set of points.
#[inline(always)]
Expand All @@ -21,10 +19,11 @@ fn point_cloud_2d_center(points: &[Vec2]) -> Vec2 {
pub trait Bounded2d {
/// 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.
fn aabb_2d(&self, translation: Vec2, rotation: f32) -> Aabb2d;
fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rotation2d>) -> Aabb2d;
/// Get a bounding circle for the shape
/// The rotation is in radians, counterclockwise, with 0 meaning no rotation.
fn bounding_circle(&self, translation: Vec2, rotation: f32) -> BoundingCircle;
fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rotation2d>)
-> BoundingCircle;
}

/// A 2D axis-aligned bounding box, or bounding rectangle
Expand Down Expand Up @@ -55,10 +54,14 @@ impl Aabb2d {
///
/// Panics if the given set of points is empty.
#[inline(always)]
pub fn from_point_cloud(translation: Vec2, rotation: f32, points: &[Vec2]) -> Aabb2d {
pub fn from_point_cloud(
translation: Vec2,
rotation: impl Into<Rotation2d>,
points: &[Vec2],
) -> Aabb2d {
// Transform all points by rotation
let rotation_mat = Mat2::from_angle(rotation);
let mut iter = points.iter().map(|point| rotation_mat * *point);
let rotation: Rotation2d = rotation.into();
let mut iter = points.iter().map(|point| rotation * *point);

let first = iter
.next()
Expand Down Expand Up @@ -94,7 +97,7 @@ impl Aabb2d {

impl BoundingVolume for Aabb2d {
type Translation = Vec2;
type Rotation = f32;
type Rotation = Rotation2d;
type HalfSize = Vec2;

#[inline(always)]
Expand Down Expand Up @@ -157,7 +160,11 @@ impl BoundingVolume for Aabb2d {
/// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
/// and consider storing the original AABB and rotating that every time instead.
#[inline(always)]
fn transformed_by(mut self, translation: Self::Translation, rotation: Self::Rotation) -> Self {
fn transformed_by(
mut self,
translation: Self::Translation,
rotation: impl Into<Self::Rotation>,
) -> Self {
self.transform_by(translation, rotation);
self
}
Expand All @@ -170,7 +177,11 @@ impl BoundingVolume for Aabb2d {
/// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
/// and consider storing the original AABB and rotating that every time instead.
#[inline(always)]
fn transform_by(&mut self, translation: Self::Translation, rotation: Self::Rotation) {
fn transform_by(
&mut self,
translation: Self::Translation,
rotation: impl Into<Self::Rotation>,
) {
self.rotate_by(rotation);
self.translate_by(translation);
}
Expand All @@ -189,7 +200,7 @@ impl BoundingVolume for Aabb2d {
/// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
/// and consider storing the original AABB and rotating that every time instead.
#[inline(always)]
fn rotated_by(mut self, rotation: Self::Rotation) -> Self {
fn rotated_by(mut self, rotation: impl Into<Self::Rotation>) -> Self {
self.rotate_by(rotation);
self
}
Expand All @@ -202,11 +213,14 @@ impl BoundingVolume for Aabb2d {
/// can cause the AABB to grow indefinitely. Avoid applying multiple rotations to the same AABB,
/// and consider storing the original AABB and rotating that every time instead.
#[inline(always)]
fn rotate_by(&mut self, rotation: Self::Rotation) {
let rot_mat = Mat2::from_angle(rotation);
let abs_rot_mat = Mat2::from_cols(rot_mat.x_axis.abs(), rot_mat.y_axis.abs());
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
let rotation: Rotation2d = rotation.into();
let abs_rot_mat = Mat2::from_cols(
Vec2::new(rotation.cos, rotation.sin),
Vec2::new(rotation.sin, rotation.cos),
);
let half_size = abs_rot_mat * self.half_size();
*self = Self::new(rot_mat * self.center(), half_size);
*self = Self::new(rotation * self.center(), half_size);
}
}

Expand Down Expand Up @@ -431,7 +445,12 @@ impl BoundingCircle {
///
/// The bounding circle is not guaranteed to be the smallest possible.
#[inline(always)]
pub fn from_point_cloud(translation: Vec2, rotation: f32, points: &[Vec2]) -> BoundingCircle {
pub fn from_point_cloud(
translation: Vec2,
rotation: impl Into<Rotation2d>,
points: &[Vec2],
) -> BoundingCircle {
let rotation: Rotation2d = rotation.into();
let center = point_cloud_2d_center(points);
let mut radius_squared = 0.0;

Expand All @@ -443,10 +462,7 @@ impl BoundingCircle {
}
}

BoundingCircle::new(
Mat2::from_angle(rotation) * center + translation,
radius_squared.sqrt(),
)
BoundingCircle::new(rotation * center + translation, radius_squared.sqrt())
}

/// Get the radius of the bounding circle
Expand Down Expand Up @@ -476,7 +492,7 @@ impl BoundingCircle {

impl BoundingVolume for BoundingCircle {
type Translation = Vec2;
type Rotation = f32;
type Rotation = Rotation2d;
type HalfSize = f32;

#[inline(always)]
Expand Down Expand Up @@ -531,13 +547,14 @@ impl BoundingVolume for BoundingCircle {
}

#[inline(always)]
fn translate_by(&mut self, translation: Vec2) {
fn translate_by(&mut self, translation: Self::Translation) {
self.center += translation;
}

#[inline(always)]
fn rotate_by(&mut self, rotation: f32) {
self.center = Mat2::from_angle(rotation) * self.center;
fn rotate_by(&mut self, rotation: impl Into<Self::Rotation>) {
let rotation: Rotation2d = rotation.into();
self.center = rotation * self.center;
}
}

Expand Down
Loading