From 35cfbf5ae470ef1b65a425b2f78d698dc9976ec9 Mon Sep 17 00:00:00 2001 From: Willow Sparks Date: Tue, 27 Jan 2026 13:49:33 +0000 Subject: [PATCH] Add StaticCollider struct and Plane collider variant - Add Collider::Plane variant for infinite plane colliders - Add StaticCollider struct with collider, material fields - Export StaticCollider from rust4d_physics Phase 4 (Wave 1): Static Colliders foundation Co-Authored-By: Claude Opus 4.5 --- crates/rust4d_physics/src/body.rs | 46 ++++++++++++++++++++++++++++- crates/rust4d_physics/src/lib.rs | 2 +- crates/rust4d_physics/src/shapes.rs | 11 +++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/crates/rust4d_physics/src/body.rs b/crates/rust4d_physics/src/body.rs index f2f6f80..da0518c 100644 --- a/crates/rust4d_physics/src/body.rs +++ b/crates/rust4d_physics/src/body.rs @@ -1,7 +1,7 @@ //! Rigid body types for 4D physics simulation use crate::material::PhysicsMaterial; -use crate::shapes::Collider; +use crate::shapes::{Collider, Plane4D}; use rust4d_math::Vec4; use slotmap::new_key_type; @@ -127,6 +127,50 @@ impl RigidBody4D { } } +/// A collider that doesn't move (floors, walls, platforms) +/// +/// Static colliders are checked for collision with all dynamic bodies +/// but never move themselves. +#[derive(Clone, Debug)] +pub struct StaticCollider { + /// The collision shape + pub collider: Collider, + /// Physics material (friction and restitution) + pub material: PhysicsMaterial, +} + +impl StaticCollider { + /// Create a new static collider with the given shape and material + pub fn new(collider: Collider, material: PhysicsMaterial) -> Self { + Self { collider, material } + } + + /// Create a plane collider + pub fn plane(normal: Vec4, distance: f32, material: PhysicsMaterial) -> Self { + Self { + collider: Collider::Plane(Plane4D::new(normal, distance)), + material, + } + } + + /// Create a horizontal floor plane at the given Y height + pub fn floor(y: f32, material: PhysicsMaterial) -> Self { + Self { + collider: Collider::Plane(Plane4D::floor(y)), + material, + } + } + + /// Create an AABB static collider + pub fn aabb(center: Vec4, half_extents: Vec4, material: PhysicsMaterial) -> Self { + use crate::shapes::AABB4D; + Self { + collider: Collider::AABB(AABB4D::from_center_half_extents(center, half_extents)), + material, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/rust4d_physics/src/lib.rs b/crates/rust4d_physics/src/lib.rs index f7e865e..5e93c65 100644 --- a/crates/rust4d_physics/src/lib.rs +++ b/crates/rust4d_physics/src/lib.rs @@ -14,7 +14,7 @@ pub mod shapes; pub mod world; // Re-export commonly used types -pub use body::{BodyKey, RigidBody4D}; +pub use body::{BodyKey, RigidBody4D, StaticCollider}; pub use collision::{aabb_vs_aabb, aabb_vs_plane, sphere_vs_aabb, sphere_vs_plane, Contact}; pub use material::PhysicsMaterial; pub use player::{PlayerPhysics, DEFAULT_JUMP_VELOCITY, DEFAULT_PLAYER_RADIUS}; diff --git a/crates/rust4d_physics/src/shapes.rs b/crates/rust4d_physics/src/shapes.rs index a56a4c8..9731c94 100644 --- a/crates/rust4d_physics/src/shapes.rs +++ b/crates/rust4d_physics/src/shapes.rs @@ -168,22 +168,33 @@ impl Plane4D { pub enum Collider { Sphere(Sphere4D), AABB(AABB4D), + Plane(Plane4D), } impl Collider { /// Get the center of the collider + /// + /// For planes, returns a point on the plane at the origin offset. pub fn center(&self) -> Vec4 { match self { Collider::Sphere(s) => s.center, Collider::AABB(b) => b.center(), + Collider::Plane(p) => p.normal * p.distance, } } /// Translate the collider by a delta + /// + /// For planes, this adjusts the distance from origin. pub fn translated(&self, delta: Vec4) -> Self { match self { Collider::Sphere(s) => Collider::Sphere(Sphere4D::new(s.center + delta, s.radius)), Collider::AABB(b) => Collider::AABB(b.translated(delta)), + Collider::Plane(p) => { + // Moving a plane by delta means the distance changes by normal ยท delta + let new_distance = p.distance + p.normal.dot(delta); + Collider::Plane(Plane4D::new(p.normal, new_distance)) + } } } } -- knotmirror 0.0.1