Skip to content
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

Add no_std Support to bevy_math #15810

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
41 changes: 31 additions & 10 deletions crates/bevy_math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ keywords = ["bevy"]
rust-version = "1.68.2"

[dependencies]
glam = { version = "0.29", features = ["bytemuck"] }
glam = { version = "0.29", default-features = false, features = ["bytemuck"] }
derive_more = { version = "1", default-features = false, features = [
"error",
"from",
"display",
"into",
] }
itertools = "0.13.0"
serde = { version = "1", features = ["derive"], optional = true }
itertools = { version = "0.13.0", default-features = false }
serde = { version = "1", default-features = false, features = [
"derive",
], optional = true }
libm = { version = "0.2", optional = true }
approx = { version = "0.5", optional = true }
rand = { version = "0.8", features = [
"alloc",
], default-features = false, optional = true }
approx = { version = "0.5", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true }
rand_distr = { version = "0.4.3", optional = true }
smallvec = { version = "1.11" }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
Expand All @@ -36,11 +36,30 @@ approx = "0.5"
rand = "0.8"
rand_chacha = "0.3"
# Enable the approx feature when testing.
bevy_math = { path = ".", version = "0.15.0-dev", features = ["approx"] }
bevy_math = { path = ".", version = "0.15.0-dev", default-features = false, features = [
"approx",
] }
glam = { version = "0.29", features = ["approx"] }

[features]
default = ["rand", "bevy_reflect", "curve"]
default = ["std", "rand", "bevy_reflect", "curve"]
std = [
"alloc",
"glam/std",
"derive_more/std",
"itertools/use_std",
"serde?/std",
"approx?/std",
"rand?/std",
"rand_distr?/std",
]
alloc = [
"itertools/use_alloc",
"serde?/alloc",
"rand?/alloc",
"rand_distr?/alloc",
]

serialize = ["dep:serde", "glam/serde"]
bushrat011899 marked this conversation as resolved.
Show resolved Hide resolved
# Enable approx for glam types to approximate floating point equality comparisons and assertions
approx = ["dep:approx", "glam/approx"]
Expand All @@ -56,7 +75,9 @@ debug_glam_assert = ["glam/debug-glam-assert"]
# Enable the rand dependency for shape_sampling
rand = ["dep:rand", "dep:rand_distr", "glam/rand"]
# Include code related to the Curve trait
curve = []
curve = ["alloc"]
# Enable bevy_reflect (requires std)
bevy_reflect = ["dep:bevy_reflect", "std"]

[lints]
workspace = true
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_math/src/bounding/bounded2d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod primitive_impls;

use super::{BoundingVolume, IntersectsVolume};
use crate::{
ops::{copysign, sqrt},
prelude::{Mat2, Rot2, Vec2},
FloatPow, Isometry2d,
};
Expand Down Expand Up @@ -488,7 +489,7 @@ impl BoundingCircle {
}
}

BoundingCircle::new(isometry * center, radius_squared.sqrt())
BoundingCircle::new(isometry * center, sqrt(radius_squared))
}

/// Get the radius of the bounding circle
Expand Down Expand Up @@ -539,7 +540,7 @@ impl BoundingVolume for BoundingCircle {
#[inline(always)]
fn contains(&self, other: &Self) -> bool {
let diff = self.radius() - other.radius();
self.center.distance_squared(other.center) <= diff.squared().copysign(diff)
self.center.distance_squared(other.center) <= copysign(diff.squared(), diff)
}

#[inline(always)]
Expand Down
20 changes: 12 additions & 8 deletions crates/bevy_math/src/bounding/bounded2d/primitive_impls.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
//! Contains [`Bounded2d`] implementations for [geometric primitives](crate::primitives).

use crate::{
ops,
ops::{self, abs, rem_euclid},
primitives::{
Annulus, Arc2d, BoxedPolygon, BoxedPolyline2d, Capsule2d, Circle, CircularSector,
CircularSegment, Ellipse, Line2d, Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon,
Rhombus, Segment2d, Triangle2d,
Annulus, Arc2d, Capsule2d, Circle, CircularSector, CircularSegment, Ellipse, Line2d,
Plane2d, Polygon, Polyline2d, Rectangle, RegularPolygon, Rhombus, Segment2d, Triangle2d,
},
Dir2, Isometry2d, Mat2, Rot2, Vec2,
};
use core::f32::consts::{FRAC_PI_2, PI, TAU};

#[cfg(feature = "alloc")]
use crate::primitives::{BoxedPolygon, BoxedPolyline2d};

use smallvec::SmallVec;

use super::{Aabb2d, Bounded2d, BoundingCircle};
Expand Down Expand Up @@ -41,11 +43,11 @@ fn arc_bounding_points(arc: Arc2d, rotation: impl Into<Rot2>) -> SmallVec<[Vec2;
// The half-angles are measured from a starting point of π/2, being the angle of Vec2::Y.
// Compute the normalized angles of the endpoints with the rotation taken into account, and then
// check if we are looking for an angle that is between or outside them.
let left_angle = (FRAC_PI_2 + arc.half_angle + rotation.as_radians()).rem_euclid(TAU);
let right_angle = (FRAC_PI_2 - arc.half_angle + rotation.as_radians()).rem_euclid(TAU);
let left_angle = rem_euclid(FRAC_PI_2 + arc.half_angle + rotation.as_radians(), TAU);
let right_angle = rem_euclid(FRAC_PI_2 - arc.half_angle + rotation.as_radians(), TAU);
let inverted = left_angle < right_angle;
for extremum in [Vec2::X, Vec2::Y, Vec2::NEG_X, Vec2::NEG_Y] {
let angle = extremum.to_angle().rem_euclid(TAU);
let angle = rem_euclid(extremum.to_angle(), TAU);
// If inverted = true, then right_angle > left_angle, so we are looking for an angle that is not between them.
// There's a chance that this condition fails due to rounding error, if the endpoint angle is juuuust shy of the axis.
// But in that case, the endpoint itself is within rounding error of the axis and will define the bounds just fine.
Expand Down Expand Up @@ -286,6 +288,7 @@ impl<const N: usize> Bounded2d for Polyline2d<N> {
}
}

#[cfg(feature = "alloc")]
impl Bounded2d for BoxedPolyline2d {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
Expand Down Expand Up @@ -348,7 +351,7 @@ impl Bounded2d for Rectangle {
// Compute the AABB of the rotated rectangle by transforming the half-extents
// by an absolute rotation matrix.
let (sin, cos) = isometry.rotation.sin_cos();
let abs_rot_mat = Mat2::from_cols_array(&[cos.abs(), sin.abs(), sin.abs(), cos.abs()]);
let abs_rot_mat = Mat2::from_cols_array(&[abs(cos), abs(sin), abs(sin), abs(cos)]);
let half_size = abs_rot_mat * self.half_size;

Aabb2d::new(isometry.translation, half_size)
Expand All @@ -371,6 +374,7 @@ impl<const N: usize> Bounded2d for Polygon<N> {
}
}

#[cfg(feature = "alloc")]
impl Bounded2d for BoxedPolygon {
fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
Aabb2d::from_point_cloud(isometry, &self.vertices)
Expand Down
17 changes: 11 additions & 6 deletions crates/bevy_math/src/bounding/bounded3d/extrusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use glam::{Vec2, Vec3A, Vec3Swizzles};

use crate::{
bounding::{BoundingCircle, BoundingVolume},
ops,
ops::{self, sqrt},
primitives::{
BoxedPolygon, BoxedPolyline2d, Capsule2d, Cuboid, Cylinder, Ellipse, Extrusion, Line2d,
Polygon, Polyline2d, Primitive2d, Rectangle, RegularPolygon, Segment2d, Triangle2d,
Capsule2d, Cuboid, Cylinder, Ellipse, Extrusion, Line2d, Polygon, Polyline2d, Primitive2d,
Rectangle, RegularPolygon, Segment2d, Triangle2d,
},
Isometry2d, Isometry3d, Quat, Rot2,
};

#[cfg(feature = "alloc")]
use crate::primitives::{BoxedPolygon, BoxedPolyline2d};

use crate::{bounding::Bounded2d, primitives::Circle};

use super::{Aabb3d, Bounded3d, BoundingSphere};
Expand All @@ -26,7 +29,7 @@ impl BoundedExtrusion for Circle {
let top = (segment_dir * half_depth).abs();

let e = (Vec3A::ONE - segment_dir * segment_dir).max(Vec3A::ZERO);
let half_size = self.radius * Vec3A::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let half_size = self.radius * Vec3A::new(sqrt(e.x), sqrt(e.y), sqrt(e.z));

Aabb3d {
min: isometry.translation - half_size - top,
Expand Down Expand Up @@ -56,8 +59,8 @@ impl BoundedExtrusion for Ellipse {
let m = -axis.x / axis.y;
let signum = axis.signum();

let y = signum.y * b * b / (b * b + m * m * a * a).sqrt();
let x = signum.x * a * (1. - y * y / b / b).sqrt();
let y = signum.y * b * b / sqrt(b * b + m * m * a * a);
let x = signum.x * a * sqrt(1. - y * y / b / b);
isometry.rotation * Vec3A::new(x, y, 0.)
});

Expand Down Expand Up @@ -104,6 +107,7 @@ impl<const N: usize> BoundedExtrusion for Polyline2d<N> {
}
}

#[cfg(feature = "alloc")]
impl BoundedExtrusion for BoxedPolyline2d {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
Expand Down Expand Up @@ -144,6 +148,7 @@ impl<const N: usize> BoundedExtrusion for Polygon<N> {
}
}

#[cfg(feature = "alloc")]
impl BoundedExtrusion for BoxedPolygon {
fn extrusion_aabb_3d(&self, half_depth: f32, isometry: impl Into<Isometry3d>) -> Aabb3d {
let isometry = isometry.into();
Expand Down
11 changes: 7 additions & 4 deletions crates/bevy_math/src/bounding/bounded3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ mod primitive_impls;
use glam::Mat3;

use super::{BoundingVolume, IntersectsVolume};
use crate::{ops::FloatPow, Isometry3d, Quat, Vec3A};
use crate::{
ops::{copysign, sqrt, FloatPow},
Isometry3d, Quat, Vec3A,
};

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
Expand Down Expand Up @@ -494,7 +497,7 @@ impl BoundingSphere {
}
}

BoundingSphere::new(isometry * center, radius_squared.sqrt())
BoundingSphere::new(isometry * center, sqrt(radius_squared))
}

/// Get the radius of the bounding sphere
Expand Down Expand Up @@ -528,7 +531,7 @@ impl BoundingSphere {
} else {
// The point is outside the sphere.
// Find the closest point on the surface of the sphere.
let dir_to_point = point / distance_squared.sqrt();
let dir_to_point = point / sqrt(distance_squared);
self.center + radius * dir_to_point
}
}
Expand Down Expand Up @@ -557,7 +560,7 @@ impl BoundingVolume for BoundingSphere {
#[inline(always)]
fn contains(&self, other: &Self) -> bool {
let diff = self.radius() - other.radius();
self.center.distance_squared(other.center) <= diff.squared().copysign(diff)
self.center.distance_squared(other.center) <= copysign(diff.squared(), diff)
}

#[inline(always)]
Expand Down
18 changes: 11 additions & 7 deletions crates/bevy_math/src/bounding/bounded3d/primitive_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ use glam::Vec3A;

use crate::{
bounding::{Bounded2d, BoundingCircle},
ops,
ops::{self, sqrt},
primitives::{
BoxedPolyline3d, Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, InfinitePlane3d,
Line3d, Polyline3d, Segment3d, Sphere, Torus, Triangle2d, Triangle3d,
Capsule3d, Cone, ConicalFrustum, Cuboid, Cylinder, InfinitePlane3d, Line3d, Polyline3d,
Segment3d, Sphere, Torus, Triangle2d, Triangle3d,
},
Isometry2d, Isometry3d, Mat3, Vec2, Vec3,
};

#[cfg(feature = "alloc")]
use crate::primitives::BoxedPolyline3d;

use super::{Aabb3d, Bounded3d, BoundingSphere};

impl Bounded3d for Sphere {
Expand Down Expand Up @@ -100,6 +103,7 @@ impl<const N: usize> Bounded3d for Polyline3d<N> {
}
}

#[cfg(feature = "alloc")]
impl Bounded3d for BoxedPolyline3d {
fn aabb_3d(&self, isometry: impl Into<Isometry3d>) -> Aabb3d {
Aabb3d::from_point_cloud(isometry, self.vertices.iter().copied())
Expand Down Expand Up @@ -144,7 +148,7 @@ impl Bounded3d for Cylinder {
let bottom = -top;

let e = (Vec3A::ONE - segment_dir * segment_dir).max(Vec3A::ZERO);
let half_size = self.radius * Vec3A::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let half_size = self.radius * Vec3A::new(sqrt(e.x), sqrt(e.y), sqrt(e.z));

Aabb3d {
min: isometry.translation + (top - half_size).min(bottom - half_size),
Expand Down Expand Up @@ -195,7 +199,7 @@ impl Bounded3d for Cone {
let bottom = -top;

let e = (Vec3A::ONE - segment_dir * segment_dir).max(Vec3A::ZERO);
let half_extents = Vec3A::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let half_extents = Vec3A::new(sqrt(e.x), sqrt(e.y), sqrt(e.z));

Aabb3d {
min: isometry.translation + top.min(bottom - self.radius * half_extents),
Expand Down Expand Up @@ -236,7 +240,7 @@ impl Bounded3d for ConicalFrustum {
let bottom = -top;

let e = (Vec3A::ONE - segment_dir * segment_dir).max(Vec3A::ZERO);
let half_extents = Vec3A::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let half_extents = Vec3A::new(sqrt(e.x), sqrt(e.y), sqrt(e.z));

Aabb3d {
min: isometry.translation
Expand Down Expand Up @@ -319,7 +323,7 @@ impl Bounded3d for Torus {
// Reference: http://iquilezles.org/articles/diskbbox/
let normal = isometry.rotation * Vec3A::Y;
let e = (Vec3A::ONE - normal * normal).max(Vec3A::ZERO);
let disc_half_size = self.major_radius * Vec3A::new(e.x.sqrt(), e.y.sqrt(), e.z.sqrt());
let disc_half_size = self.major_radius * Vec3A::new(sqrt(e.x), sqrt(e.y), sqrt(e.z));

// Expand the disc by the minor radius to get the torus half-size
let half_size = disc_half_size + Vec3A::splat(self.minor_radius);
Expand Down
9 changes: 6 additions & 3 deletions crates/bevy_math/src/bounding/raycast2d.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{Aabb2d, BoundingCircle, IntersectsVolume};
use crate::{ops::FloatPow, Dir2, Ray2d, Vec2};
use crate::{
ops::{copysign, sqrt, FloatPow},
Dir2, Ray2d, Vec2,
};

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
Expand Down Expand Up @@ -77,10 +80,10 @@ impl RayCast2d {
let projected = offset.dot(*self.ray.direction);
let closest_point = offset - projected * *self.ray.direction;
let distance_squared = circle.radius().squared() - closest_point.length_squared();
if distance_squared < 0. || projected.squared().copysign(-projected) < -distance_squared {
if distance_squared < 0. || copysign(projected.squared(), -projected) < -distance_squared {
None
} else {
let toi = -projected - distance_squared.sqrt();
let toi = -projected - sqrt(distance_squared);
if toi > self.max {
None
} else {
Expand Down
9 changes: 6 additions & 3 deletions crates/bevy_math/src/bounding/raycast3d.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{Aabb3d, BoundingSphere, IntersectsVolume};
use crate::{ops::FloatPow, Dir3A, Ray3d, Vec3A};
use crate::{
ops::{copysign, sqrt, FloatPow},
Dir3A, Ray3d, Vec3A,
};

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
Expand Down Expand Up @@ -74,10 +77,10 @@ impl RayCast3d {
let projected = offset.dot(*self.direction);
let closest_point = offset - projected * *self.direction;
let distance_squared = sphere.radius().squared() - closest_point.length_squared();
if distance_squared < 0. || projected.squared().copysign(-projected) < -distance_squared {
if distance_squared < 0. || copysign(projected.squared(), -projected) < -distance_squared {
None
} else {
let toi = -projected - distance_squared.sqrt();
let toi = -projected - sqrt(distance_squared);
if toi > self.max {
None
} else {
Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_math/src/common_traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! This module contains abstract mathematical traits shared by types used in `bevy_math`.

use crate::{ops, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};
use crate::{
ops::{self, abs},
Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4,
};
use core::{
fmt::Debug,
ops::{Add, Div, Mul, Neg, Sub},
Expand Down Expand Up @@ -157,7 +160,7 @@ impl NormedVectorSpace for Vec2 {
impl NormedVectorSpace for f32 {
#[inline]
fn norm(self) -> f32 {
self.abs()
abs(self)
}

#[inline]
Expand Down
Loading