simplecar2-rs is a pure Rust vehicle dynamics crate designed for arcade-sim driving games and real-time simulations. It models 4-wheel raycast spring-damper suspension, lateral anti-roll bars, Ackermann steering geometry, and combustion or electric torque curves at over a million steps per second.
$ cargo add simplecar2-rs
Experience the exact mathematical models implemented in simplecar2-rs executing directly in your browser.
Every subsystem in simplecar2-rs operates as a decoupled, deterministic state machine ready for Bevy ECS and network rollback.
Simulates spring compression, bump & rebound damping, and anti-roll sway bar force transfer without expensive rigid body joint constraints.
Dual powertrain modes: accurate combustion engine RPM torque curves with rev limiters, or instant flat-torque electric motor profiles with regenerative braking.
Multi-speed planetary or dual-clutch transmission with automatic upshift/downshift logic, rev-limiter safety overspeed shift, and shift torque cut.
Configurable final drive split: 50/50 open differential, 100% spooled locked differential with normal load bias, or clutch-pack limited slip with speed delta lockup.
Calculates exact distinct inner and outer wheel turn angles to trace concentric circles, with velocity-sensitive high speed steering lock reduction.
Built strictly on glam and serde. Easily drops into Bevy, Rapier, PhysX, or bespoke custom simulation pipelines with zero friction.
The analytical physics models underlying the simplecar2-rs implementation.
When cornering, centrifugal force produces chassis roll angle $\phi$, compressing the outer wheel ($x_{\text{outer}}$) and extending the inner wheel ($x_{\text{inner}}$). The sway bar creates equal and opposite corrective normal forces:
Torque transfer between engine flywheel ($\omega_{\text{engine}}$) and transmission input shaft ($\omega_{\text{trans}}$) uses hyperbolic tangent friction smoothing:
Drop simplecar2 into your Cargo.toml and initialize your vehicle state machine in seconds.
# Add to your dependencies
[dependencies]
simplecar2 = "0.1"
glam = "0.29"
use glam::{Quat, Vec3};
use simplecar2::prelude::*;
fn main() {
// 1. Configure vehicle chassis, suspension & powertrain
let mut vehicle = Vehicle::new(VehicleConfig::default());
// 2. Supply driver inputs
let inputs = VehicleInputs {
steer: 0.25, // Steer angle [-1.0, 1.0]
throttle: 0.85, // 85% throttle
brake: 0.0,
handbrake: false,
clutch_pedal: 0.0, // Clutch engaged
};
// 3. Provide raycast contact results from physics world (Rapier, XPBD, etc.)
let hits = [
Some(WheelRaycastHit { distance: 0.40, point: Vec3::new(-0.81, 0.0, 1.35), normal: Vec3::Y }),
Some(WheelRaycastHit { distance: 0.40, point: Vec3::new(0.81, 0.0, 1.35), normal: Vec3::Y }),
Some(WheelRaycastHit { distance: 0.40, point: Vec3::new(-0.81, 0.0, -1.30), normal: Vec3::Y }),
Some(WheelRaycastHit { distance: 0.40, point: Vec3::new(0.81, 0.0, -1.30), normal: Vec3::Y }),
];
// 4. Advance physics step
let forces = vehicle.step(
&inputs, hits,
Vec3::new(0.0, 0.45, 0.0),
Quat::IDENTITY,
Vec3::new(0.0, 0.0, 14.0),
Vec3::ZERO,
1.0 / 60.0,
).unwrap();
println!("Total force: {:?}", forces.total_force);
println!("Engine RPM: {:.0}", vehicle.engine_state.rpm);
}
Comparative physics performance measuring full 4-wheel raycast suspension, drivetrain, and limited-slip differential. View Full BENCHMARKS.md →
100% pass rate across the full vehicle physics specification.