pub struct PhysicsWorld<const N: usize, const M: usize = 0> {
pub solver_iterations: u32,
/* private fields */
}Expand description
The physics simulation world.
Manages a fixed-capacity set of rigid bodies and constraints, and steps the simulation forward.
§Type Parameters
N- Maximum number of bodies (compile-time capacity).M- Maximum number of constraints/joints (compile-time capacity).
§Example
use embedded_3dgfx::physics::{PhysicsWorld, RigidBody, Constraint};
use nalgebra::Vector3;
let mut world = PhysicsWorld::<8, 4>::new();
world.set_gravity(Vector3::new(0.0, -9.81, 0.0));
let body = RigidBody::new(2.0)
.with_position(Vector3::new(0.0, 5.0, 0.0));
let id = world.add_body(body).unwrap();
world.step::<8>(1.0 / 60.0);Fields§
§solver_iterations: u32Number of iterations for the constraint solver per substep.
Implementations§
Source§impl<const N: usize, const M: usize> PhysicsWorld<N, M>
impl<const N: usize, const M: usize> PhysicsWorld<N, M>
Sourcepub fn set_gravity(&mut self, gravity: Vector3<f32>)
pub fn set_gravity(&mut self, gravity: Vector3<f32>)
Set the gravity vector (e.g., Vector3::new(0.0, -9.81, 0.0)).
Sourcepub fn add_body(&mut self, body: RigidBody) -> Option<BodyId>
pub fn add_body(&mut self, body: RigidBody) -> Option<BodyId>
Add a body to the world. Returns its BodyId, or None if at capacity.
Sourcepub fn body(&self, id: BodyId) -> Option<&RigidBody>
pub fn body(&self, id: BodyId) -> Option<&RigidBody>
Get an immutable reference to a body by its ID.
Sourcepub fn body_mut(&mut self, id: BodyId) -> Option<&mut RigidBody>
pub fn body_mut(&mut self, id: BodyId) -> Option<&mut RigidBody>
Get a mutable reference to a body by its ID.
Sourcepub fn body_count(&self) -> usize
pub fn body_count(&self) -> usize
Returns the total number of bodies in the world (including inactive).
Sourcepub fn active_body_count(&self) -> usize
pub fn active_body_count(&self) -> usize
Returns the number of active bodies in the world.
Sourcepub fn remove_body(&mut self, id: BodyId) -> bool
pub fn remove_body(&mut self, id: BodyId) -> bool
Deactivate a body, effectively removing it from the simulation.
The body remains in the world (its slot is preserved) but it is skipped
during integration and collision detection. This avoids invalidating
existing BodyIds.
Returns true if the body was found and deactivated, false if the ID
was out of bounds or the body was already inactive.
Sourcepub fn set_active(&mut self, id: BodyId, active: bool) -> bool
pub fn set_active(&mut self, id: BodyId, active: bool) -> bool
Set whether a body is active. Inactive bodies are skipped during integration and collision detection.
Returns true if the body exists, false otherwise.
Sourcepub fn bodies(&self) -> impl Iterator<Item = (BodyId, &RigidBody)>
pub fn bodies(&self) -> impl Iterator<Item = (BodyId, &RigidBody)>
Iterate over all bodies immutably.
Sourcepub fn bodies_mut(&mut self) -> impl Iterator<Item = (BodyId, &mut RigidBody)>
pub fn bodies_mut(&mut self) -> impl Iterator<Item = (BodyId, &mut RigidBody)>
Iterate over all bodies mutably.
Sourcepub fn ray_cast(&self, ray: &Ray, max_distance: f32) -> Option<RayCastHit>
pub fn ray_cast(&self, ray: &Ray, max_distance: f32) -> Option<RayCastHit>
Cast a ray through the world and find the nearest intersection.
Returns information about the hit, or None if no bodies were hit.
§Arguments
ray- The ray to castmax_distance- Maximum distance to check (use f32::MAX for infinite)
§Example
use embedded_3dgfx::physics::{PhysicsWorld, Ray};
use nalgebra::Vector3;
let world = PhysicsWorld::<16>::new();
let ray = Ray::new(
Vector3::new(0.0, 10.0, 0.0),
Vector3::new(0.0, -1.0, 0.0)
);
if let Some(hit) = world.ray_cast(&ray, 100.0) {
println!("Hit body at distance: {}", hit.distance);
}Sourcepub fn add_constraint(&mut self, constraint: Constraint) -> Option<ConstraintId>
pub fn add_constraint(&mut self, constraint: Constraint) -> Option<ConstraintId>
Add a constraint to the world. Returns its ConstraintId, or None
if at capacity.
Sourcepub fn constraint(&self, id: ConstraintId) -> Option<&Constraint>
pub fn constraint(&self, id: ConstraintId) -> Option<&Constraint>
Get an immutable reference to a constraint by its ID.
Sourcepub fn constraint_mut(&mut self, id: ConstraintId) -> Option<&mut Constraint>
pub fn constraint_mut(&mut self, id: ConstraintId) -> Option<&mut Constraint>
Get a mutable reference to a constraint by its ID.
Sourcepub fn remove_constraint(&mut self, id: ConstraintId) -> bool
pub fn remove_constraint(&mut self, id: ConstraintId) -> bool
Remove a constraint by ID (swap-removes; invalidates the last ID).
Returns true if a constraint was removed, false if the ID was
out of bounds.
Sourcepub fn constraint_count(&self) -> usize
pub fn constraint_count(&self) -> usize
Returns the number of constraints in the world.
Sourcepub fn add_distance_constraint(
&mut self,
body_a: BodyId,
anchor_a: Vector3<f32>,
body_b: BodyId,
anchor_b: Vector3<f32>,
compliance: f32,
) -> Option<ConstraintId>
pub fn add_distance_constraint( &mut self, body_a: BodyId, anchor_a: Vector3<f32>, body_b: BodyId, anchor_b: Vector3<f32>, compliance: f32, ) -> Option<ConstraintId>
Helper: create a distance constraint between two bodies.
Anchors are in body-local space. The rest length is computed automatically from the current body positions.
Sourcepub fn add_ball_socket(
&mut self,
body_a: BodyId,
anchor_a: Vector3<f32>,
body_b: BodyId,
anchor_b: Vector3<f32>,
compliance: f32,
) -> Option<ConstraintId>
pub fn add_ball_socket( &mut self, body_a: BodyId, anchor_a: Vector3<f32>, body_b: BodyId, anchor_b: Vector3<f32>, compliance: f32, ) -> Option<ConstraintId>
Helper: create a ball-socket joint between two bodies.
Anchors are in body-local space. The two anchor points will be constrained to coincide (distance = 0).
Sourcepub fn add_fixed_joint(
&mut self,
body_a: BodyId,
anchor_a: Vector3<f32>,
body_b: BodyId,
anchor_b: Vector3<f32>,
compliance: f32,
) -> Option<ConstraintId>
pub fn add_fixed_joint( &mut self, body_a: BodyId, anchor_a: Vector3<f32>, body_b: BodyId, anchor_b: Vector3<f32>, compliance: f32, ) -> Option<ConstraintId>
Helper: create a fixed (weld) joint between two bodies.
Stores the current relative orientation as the target.
Sourcepub fn detect_collisions<const C: usize>(&self) -> Vec<Contact, C>
pub fn detect_collisions<const C: usize>(&self) -> Vec<Contact, C>
Detect all collisions between bodies with colliders.
Uses a sort-and-sweep broad phase on the X axis to prune pairs that
cannot possibly overlap, then runs the narrow-phase collide() test
only on candidate pairs.
Returns contacts in a fixed-capacity buffer. The C const generic sets the
maximum number of contacts per detection pass. For N bodies, worst case is
N*(N-1)/2 pairs, so choose C accordingly.
Pairs where both bodies lack a collider are skipped.
Sourcepub fn resolve_contacts(&mut self, contacts: &[Contact])
pub fn resolve_contacts(&mut self, contacts: &[Contact])
Resolve a set of contacts by applying positional correction, impulse response (linear + angular), and Coulomb friction.
Contact-point velocity includes both linear and angular contributions:
v_contact = v_linear + ω × r, where r is the vector from the body
center to the contact point. Impulses produce both linear velocity changes
and torques via τ = r × J.
Sourcepub fn solve_constraints(&mut self, dt: f32)
pub fn solve_constraints(&mut self, dt: f32)
Solve all constraints using position-based correction.
Uses Extended Position-Based Dynamics (XPBD) style positional correction
with compliance for soft constraints. Each constraint is solved
solver_iterations times per call for convergence.
Sourcepub fn step<const C: usize>(&mut self, dt: f32)
pub fn step<const C: usize>(&mut self, dt: f32)
Advance the simulation by dt seconds.
Integrates all dynamic bodies, detects and resolves collisions, then solves constraints.
The C const generic sets the maximum number of collision contacts per step.
Sourcepub fn step_fixed<const C: usize>(&mut self, dt: f32, substeps: u32)
pub fn step_fixed<const C: usize>(&mut self, dt: f32, substeps: u32)
Advance the simulation using fixed-size substeps for stability.
Divides dt into substeps equal intervals. Each substep runs integration,
collision detection/response, and constraint solving.
Auto Trait Implementations§
impl<const N: usize, const M: usize> Freeze for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> RefUnwindSafe for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> Send for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> Sync for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> Unpin for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> UnsafeUnpin for PhysicsWorld<N, M>
impl<const N: usize, const M: usize> UnwindSafe for PhysicsWorld<N, M>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Source§impl<T> OverflowingAs for T
impl<T> OverflowingAs for T
Source§fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
Source§impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
Source§fn overflowing_cast_from(src: Src) -> (Dst, bool)
fn overflowing_cast_from(src: Src) -> (Dst, bool)
Source§impl<T> SaturatingAs for T
impl<T> SaturatingAs for T
Source§fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
Source§impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
Source§fn saturating_cast_from(src: Src) -> Dst
fn saturating_cast_from(src: Src) -> Dst
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.