From b8f6f4d82b952c3532a153237b98acc53e4a3bca Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Sat, 22 Mar 2025 23:07:08 +0200 Subject: [PATCH 01/13] Make dependencies `no_std` and use `alloc` more --- crates/avian2d/Cargo.toml | 62 +++++++++++++------ crates/avian3d/Cargo.toml | 61 ++++++++++++------ src/collision/collider/backend.rs | 8 +-- .../collider/collider_hierarchy/mod.rs | 2 +- src/collision/collider/parry/mod.rs | 2 +- src/collision/collider/parry/primitives2d.rs | 7 +++ src/collision/collider/parry/primitives3d.rs | 1 + src/collision/diagnostics.rs | 1 + src/collision/mod.rs | 10 ++- src/collision/narrow_phase.rs | 2 +- src/diagnostics/mod.rs | 1 + src/diagnostics/ui.rs | 7 ++- .../rigid_body/mass_properties/mod.rs | 2 +- src/dynamics/solver/contact/mod.rs | 1 + src/dynamics/solver/diagnostics.rs | 1 + src/dynamics/solver/schedule.rs | 2 +- src/lib.rs | 1 + src/prepare.rs | 2 +- src/schedule/mod.rs | 2 +- src/spatial_query/diagnostics.rs | 4 +- 20 files changed, 120 insertions(+), 59 deletions(-) diff --git a/crates/avian2d/Cargo.toml b/crates/avian2d/Cargo.toml index 7abf6f9d..afa07ee5 100644 --- a/crates/avian2d/Cargo.toml +++ b/crates/avian2d/Cargo.toml @@ -27,9 +27,9 @@ f64 = [] debug-plugin = ["bevy/bevy_gizmos", "bevy/bevy_render"] simd = ["parry2d?/simd-stable", "parry2d-f64?/simd-stable"] -parallel = ["parry2d?/parallel", "parry2d-f64?/parallel"] +parallel = ["std", "parry2d?/parallel", "parry2d-f64?/parallel"] enhanced-determinism = [ - "dep:libm", + "libm", "parry2d?/enhanced-determinism", "parry2d-f64?/enhanced-determinism", "bevy_math/libm", @@ -60,6 +60,23 @@ bevy_diagnostic = [] # Enables the `PhysicsDiagnosticsUiPlugin` for visualizing physics diagnostics data with a debug UI. diagnostic_ui = ["bevy_diagnostic", "bevy/bevy_ui"] +# Enable the Rust standard library. +std = [ + "bevy/std", + "bevy_heavy/std", + "bevy_transform_interpolation/std", + "parry2d?/std", + "parry2d-f64?/std", +] + +# Enable `libm` math operations for `no_std` environments and cross-platform determinism. +libm = [ + "dep:libm", + "bevy/libm", + "bevy_heavy/libm", + "bevy_transform_interpolation/libm", +] + [lib] name = "avian2d" path = "../../src/lib.rs" @@ -68,24 +85,32 @@ bench = false [dependencies] avian_derive = { path = "../avian_derive", version = "0.2" } -bevy = { version = "0.16.0-rc.1", default-features = false, features = [ - "std", - "bevy_log", +bevy = { version = "0.16.0-rc.1", default-features = false } +bevy_math = { version = "0.16.0-rc.1", default-features = false } +bevy_heavy = { git = "https://github.com/Jondolf/bevy_heavy", default-features = false, features = [ + "2d", + "3d", ] } -bevy_math = { version = "0.16.0-rc.1" } -bevy_heavy = { git = "https://github.com/Jondolf/bevy_heavy" } -bevy_transform_interpolation = { git = "https://github.com/Jondolf/bevy_transform_interpolation" } +bevy_transform_interpolation = { git = "https://github.com/Jondolf/bevy_transform_interpolation", default-features = false } libm = { version = "0.2", optional = true } -parry2d = { version = "0.17", optional = true } -parry2d-f64 = { version = "0.17", optional = true } -nalgebra = { version = "0.33", features = ["convert-glam029"], optional = true } -serde = { version = "1", features = ["derive"], optional = true } -derive_more = "1" -indexmap = "2.0.0" -arrayvec = "0.7" -fxhash = "0.2.1" -itertools = "0.13" -bitflags = "2.5.0" +parry2d = { version = "0.17", optional = true, default-features = false, features = [ + "required-features", +] } +parry2d-f64 = { version = "0.17", optional = true, default-features = false, features = [ + "required-features", +] } +nalgebra = { version = "0.33", default-features = false, features = [ + "convert-glam029", +], optional = true } +serde = { version = "1", default-features = false, features = [ + "derive", +], optional = true } +derive_more = { version = "1", default-features = false } +log = { version = "0.4", default-features = false } +indexmap = { version = "2.0.0", default-features = false } +arrayvec = { version = "0.7", default-features = false } +itertools = { version = "0.13", default-features = false } +bitflags = { version = "2.5.0", default-features = false } [dev-dependencies] examples_common_2d = { path = "../examples_common_2d" } @@ -94,7 +119,6 @@ bevy_math = { version = "0.16.0-rc.1", features = ["approx"] } bevy_heavy = { git = "https://github.com/Jondolf/bevy_heavy", features = [ "approx", ] } -glam = { version = "0.29", features = ["bytemuck"] } approx = "0.5" bytemuck = "1.19" criterion = { version = "0.5", features = ["html_reports"] } diff --git a/crates/avian3d/Cargo.toml b/crates/avian3d/Cargo.toml index e06d65f5..33cca14a 100644 --- a/crates/avian3d/Cargo.toml +++ b/crates/avian3d/Cargo.toml @@ -28,9 +28,9 @@ f64 = [] debug-plugin = ["bevy/bevy_gizmos", "bevy/bevy_render"] simd = ["parry3d?/simd-stable", "parry3d-f64?/simd-stable"] -parallel = ["parry3d?/parallel", "parry3d-f64?/parallel"] +parallel = ["std", "parry3d?/parallel", "parry3d-f64?/parallel"] enhanced-determinism = [ - "dep:libm", + "libm", "parry3d?/enhanced-determinism", "parry3d-f64?/enhanced-determinism", "bevy_math/libm", @@ -62,6 +62,23 @@ bevy_diagnostic = [] # Enables the `PhysicsDiagnosticsUiPlugin` for visualizing physics diagnostics data with a debug UI. diagnostic_ui = ["bevy_diagnostic", "bevy/bevy_ui"] +# Enable the Rust standard library. +std = [ + "bevy/std", + "bevy_heavy/std", + "bevy_transform_interpolation/std", + "parry3d?/std", + "parry3d-f64?/std", +] + +# Enable `libm` math operations for `no_std` environments and cross-platform determinism. +libm = [ + "dep:libm", + "bevy/libm", + "bevy_heavy/libm", + "bevy_transform_interpolation/libm", +] + [lib] name = "avian3d" path = "../../src/lib.rs" @@ -70,24 +87,32 @@ bench = false [dependencies] avian_derive = { path = "../avian_derive", version = "0.2" } -bevy = { version = "0.16.0-rc.1", default-features = false, features = [ - "std", - "bevy_log", +bevy = { version = "0.16.0-rc.1", default-features = false } +bevy_math = { version = "0.16.0-rc.1", default-features = false } +bevy_heavy = { git = "https://github.com/Jondolf/bevy_heavy", default-features = false, features = [ + "2d", + "3d", ] } -bevy_math = { version = "0.16.0-rc.1" } -bevy_heavy = { git = "https://github.com/Jondolf/bevy_heavy" } -bevy_transform_interpolation = { git = "https://github.com/Jondolf/bevy_transform_interpolation" } +bevy_transform_interpolation = { git = "https://github.com/Jondolf/bevy_transform_interpolation", default-features = false } libm = { version = "0.2", optional = true } -parry3d = { version = "0.17", optional = true } -parry3d-f64 = { version = "0.17", optional = true } -nalgebra = { version = "0.33", features = ["convert-glam029"], optional = true } -serde = { version = "1", features = ["derive"], optional = true } -derive_more = "1" -indexmap = "2.0.0" -arrayvec = "0.7" -fxhash = "0.2.1" -itertools = "0.13" -bitflags = "2.5.0" +parry3d = { version = "0.17", optional = true, default-features = false, features = [ + "required-features", +] } +parry3d-f64 = { version = "0.17", optional = true, default-features = false, features = [ + "required-features", +] } +nalgebra = { version = "0.33", default-features = false, features = [ + "convert-glam029", +], optional = true } +serde = { version = "1", default-features = false, features = [ + "derive", +], optional = true } +derive_more = { version = "1", default-features = false } +log = { version = "0.4", default-features = false } +indexmap = { version = "2.0.0", default-features = false } +arrayvec = { version = "0.7", default-features = false } +itertools = { version = "0.13", default-features = false } +bitflags = { version = "2.5.0", default-features = false } [dev-dependencies] examples_common_3d = { path = "../examples_common_3d" } diff --git a/src/collision/collider/backend.rs b/src/collision/collider/backend.rs index c2f002b9..7aa9411e 100644 --- a/src/collision/collider/backend.rs +++ b/src/collision/collider/backend.rs @@ -309,7 +309,7 @@ fn init_collider_constructors( for (entity, existing_collider, name, constructor) in constructors.iter() { let name = pretty_name(name, entity); if existing_collider.is_some() { - warn!( + log::warn!( "Tried to add a collider to entity {name} via {constructor:#?}, \ but that entity already holds a collider. Skipping.", ); @@ -339,7 +339,7 @@ fn init_collider_constructors( if let Some(collider) = collider { commands.entity(entity).insert(collider); } else { - error!( + log::error!( "Tried to add a collider to entity {name} via {constructor:#?}, \ but the collider could not be generated. Skipping.", ); @@ -400,7 +400,7 @@ fn init_collider_constructor_hierarchies( .cloned() .unwrap_or_else(default_collider) } else if existing_collider.is_some() { - warn!("Tried to add a collider to entity {pretty_name} via {collider_constructor_hierarchy:#?}, \ + log::warn!("Tried to add a collider to entity {pretty_name} via {collider_constructor_hierarchy:#?}, \ but that entity already holds a collider. Skipping. \ If this was intentional, add the name of the collider to overwrite to `ColliderConstructorHierarchy.config`."); continue; @@ -449,7 +449,7 @@ fn init_collider_constructor_hierarchies( .unwrap_or(collider_constructor_hierarchy.default_density), )); } else { - error!( + log::error!( "Tried to add a collider to entity {pretty_name} via {collider_constructor_hierarchy:#?}, \ but the collider could not be generated. Skipping.", ); diff --git a/src/collision/collider/collider_hierarchy/mod.rs b/src/collision/collider/collider_hierarchy/mod.rs index 15caf958..1def147d 100644 --- a/src/collision/collider/collider_hierarchy/mod.rs +++ b/src/collision/collider/collider_hierarchy/mod.rs @@ -121,7 +121,7 @@ impl Relationship for ColliderOf { .insert(RigidBodyColliders(vec![collider])); } } else { - warn!( + log::warn!( "{}Tried to attach collider on entity {collider} to rigid body on entity {rigid_body}, but the rigid body does not exist.", caller.map(|location| format!("{location}: ")).unwrap_or_default(), ); diff --git a/src/collision/collider/parry/mod.rs b/src/collision/collider/parry/mod.rs index 4e73c5ae..40c9fb40 100644 --- a/src/collision/collider/parry/mod.rs +++ b/src/collision/collider/parry/mod.rs @@ -1,9 +1,9 @@ #![allow(clippy::unnecessary_cast)] use crate::{make_isometry, prelude::*}; +use bevy::prelude::*; #[cfg(feature = "collider-from-mesh")] use bevy::render::mesh::{Indices, VertexAttributeValues}; -use bevy::{log, prelude::*}; use collision::contact_query::UnsupportedShape; use itertools::Either; use parry::shape::{RoundShape, SharedShape, TypedShape}; diff --git a/src/collision/collider/parry/primitives2d.rs b/src/collision/collider/parry/primitives2d.rs index 5324dd9b..9a55c424 100644 --- a/src/collision/collider/parry/primitives2d.rs +++ b/src/collision/collider/parry/primitives2d.rs @@ -1,6 +1,7 @@ use crate::{math, AdjustPrecision, Scalar, Vector, FRAC_PI_2, PI, TAU}; use super::{AsF32, Collider, IntoCollider}; +use alloc::boxed::Box; use bevy::prelude::{Deref, DerefMut}; use bevy_math::{bounding::Bounded2d, prelude::*}; use nalgebra::{Point2, UnitVector2, Vector2}; @@ -46,10 +47,12 @@ impl SupportMap for EllipseColliderShape { } impl Shape for EllipseColliderShape { + #[cfg(feature = "std")] fn clone_dyn(&self) -> Box { Box::new(*self) } + #[cfg(feature = "std")] fn scale_dyn( &self, scale: &parry::math::Vector, @@ -99,6 +102,7 @@ impl Shape for EllipseColliderShape { ) } + #[cfg(feature = "std")] fn clone_box(&self) -> Box { Box::new(*self) } @@ -324,10 +328,12 @@ impl PolygonalFeatureMap for RegularPolygonColliderShape { } impl Shape for RegularPolygonColliderShape { + #[cfg(feature = "std")] fn clone_dyn(&self) -> Box { Box::new(*self) } + #[cfg(feature = "std")] fn scale_dyn( &self, scale: &parry::math::Vector, @@ -377,6 +383,7 @@ impl Shape for RegularPolygonColliderShape { ) } + #[cfg(feature = "std")] fn clone_box(&self) -> Box { Box::new(*self) } diff --git a/src/collision/collider/parry/primitives3d.rs b/src/collision/collider/parry/primitives3d.rs index 9917b686..f948808b 100644 --- a/src/collision/collider/parry/primitives3d.rs +++ b/src/collision/collider/parry/primitives3d.rs @@ -1,3 +1,4 @@ +use alloc::vec; use bevy_math::primitives::{ BoxedPolyline3d, Capsule3d, Cone, Cuboid, Cylinder, Line3d, Plane3d, Polyline3d, Segment3d, Sphere, diff --git a/src/collision/diagnostics.rs b/src/collision/diagnostics.rs index 6e0d4a74..97b6390a 100644 --- a/src/collision/diagnostics.rs +++ b/src/collision/diagnostics.rs @@ -1,3 +1,4 @@ +use alloc::{vec, vec::Vec}; use bevy::{ diagnostic::DiagnosticPath, prelude::{ReflectResource, Resource}, diff --git a/src/collision/mod.rs b/src/collision/mod.rs index 8c281a4e..34941a29 100644 --- a/src/collision/mod.rs +++ b/src/collision/mod.rs @@ -38,7 +38,7 @@ mod diagnostics; pub use diagnostics::CollisionDiagnostics; use crate::prelude::*; -use bevy::prelude::*; +use bevy::{platform_support::hash::FixedHasher, prelude::*}; use indexmap::IndexMap; // TODO: Refactor this into a contact graph. @@ -76,18 +76,16 @@ use indexmap::IndexMap; /// However, the public methods only use the current frame's collisions. To access the internal data structure, /// you can use [`get_internal`](Self::get_internal) or [`get_internal_mut`](Self::get_internal_mut). #[derive(Resource, Clone, Debug, Default, PartialEq)] -pub struct Collisions(IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher>); +pub struct Collisions(IndexMap<(Entity, Entity), Contacts, FixedHasher>); impl Collisions { /// Returns a reference to the internal `IndexMap`. - pub fn get_internal(&self) -> &IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher> { + pub fn get_internal(&self) -> &IndexMap<(Entity, Entity), Contacts, FixedHasher> { &self.0 } /// Returns a mutable reference to the internal `IndexMap`. - pub fn get_internal_mut( - &mut self, - ) -> &mut IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher> { + pub fn get_internal_mut(&mut self) -> &mut IndexMap<(Entity, Entity), Contacts, FixedHasher> { &mut self.0 } diff --git a/src/collision/narrow_phase.rs b/src/collision/narrow_phase.rs index 0efa662d..8d17562f 100644 --- a/src/collision/narrow_phase.rs +++ b/src/collision/narrow_phase.rs @@ -861,6 +861,6 @@ pub fn reset_collision_states( /// Runs the [`PostProcessCollisions`] schedule. fn run_post_process_collisions_schedule(world: &mut World) { - trace!("running PostProcessCollisions"); + log::trace!("running PostProcessCollisions"); world.run_schedule(PostProcessCollisions); } diff --git a/src/diagnostics/mod.rs b/src/diagnostics/mod.rs index dbed9ab2..dfa6e13e 100644 --- a/src/diagnostics/mod.rs +++ b/src/diagnostics/mod.rs @@ -76,6 +76,7 @@ pub(crate) use path_macro::impl_diagnostic_paths; pub use total::{PhysicsTotalDiagnostics, PhysicsTotalDiagnosticsPlugin}; use crate::{schedule::PhysicsSchedule, PhysicsStepSet}; +use alloc::vec::Vec; use bevy::{ app::{App, Plugin}, diagnostic::{Diagnostic, DiagnosticPath, Diagnostics, RegisterDiagnostic}, diff --git a/src/diagnostics/ui.rs b/src/diagnostics/ui.rs index caad1c8a..83aade2c 100644 --- a/src/diagnostics/ui.rs +++ b/src/diagnostics/ui.rs @@ -429,9 +429,10 @@ fn update_timers( }; // Linearly interpolating between green and red, with `lower_bound` and `upper_bound`. - let t = (average as f32 - color_config.lower_bound) - / (color_config.upper_bound - color_config.lower_bound); - text_color.0 = Animatable::interpolate(&green, &red, t.min(1.0)).into(); + let t = ((average as f32 - color_config.lower_bound) + / (color_config.upper_bound - color_config.lower_bound)) + .min(1.0); + text_color.0 = (green * (1.0 - t) + red * t).into(); // Make sure the node is visible. node.display = Display::Flex; diff --git a/src/dynamics/rigid_body/mass_properties/mod.rs b/src/dynamics/rigid_body/mass_properties/mod.rs index 4184b83a..e8c14e88 100644 --- a/src/dynamics/rigid_body/mass_properties/mod.rs +++ b/src/dynamics/rigid_body/mass_properties/mod.rs @@ -450,7 +450,7 @@ fn warn_missing_mass( // Warn about dynamic bodies with no mass or inertia if rb.is_dynamic() && !(is_mass_valid && is_inertia_valid) { - warn!( + log::warn!( "Dynamic rigid body {:?} has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.", entity ); diff --git a/src/dynamics/solver/contact/mod.rs b/src/dynamics/solver/contact/mod.rs index 18263b42..dc7c5bf2 100644 --- a/src/dynamics/solver/contact/mod.rs +++ b/src/dynamics/solver/contact/mod.rs @@ -7,6 +7,7 @@ pub use normal_part::ContactNormalPart; pub use tangent_part::ContactTangentPart; use crate::{dynamics::solver::softness_parameters::SoftnessCoefficients, prelude::*}; +use alloc::vec::Vec; use bevy::{ ecs::entity::{Entity, EntityMapper, MapEntities}, reflect::Reflect, diff --git a/src/dynamics/solver/diagnostics.rs b/src/dynamics/solver/diagnostics.rs index b32f7f3e..ddefc458 100644 --- a/src/dynamics/solver/diagnostics.rs +++ b/src/dynamics/solver/diagnostics.rs @@ -1,3 +1,4 @@ +use alloc::{vec, vec::Vec}; use bevy::{ diagnostic::DiagnosticPath, prelude::{ReflectResource, Resource}, diff --git a/src/dynamics/solver/schedule.rs b/src/dynamics/solver/schedule.rs index a63c08fb..7f800ddf 100644 --- a/src/dynamics/solver/schedule.rs +++ b/src/dynamics/solver/schedule.rs @@ -191,7 +191,7 @@ fn run_substep_schedule(world: &mut World) { let _ = world.try_schedule_scope(SubstepSchedule, |world, schedule| { for i in 0..substeps { - trace!("running SubstepSchedule: {i}"); + log::trace!("running SubstepSchedule: {i}"); *world.resource_mut::