Skip to main content

gizmo_physics_rigid/components/
vehicle.rs

1use gizmo_math::Vec3;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub struct Wheel {
6    /// Local attachment point of the wheel suspension to the chassis
7    pub local_position: Vec3,
8    /// Direction the suspension ray is cast (usually -Y, relative to chassis)
9    pub direction: Vec3,
10    /// Radius of the tire
11    pub radius: f32,
12    /// Suspension rest length (maximum droop)
13    pub suspension_rest_length: f32,
14    /// Suspension stiffness (spring constant k)
15    pub suspension_stiffness: f32,
16    /// Suspension damping (shock absorber c)
17    pub suspension_damping: f32,
18    
19    /// Does this wheel steer?
20    pub is_steering: bool,
21    /// Does this wheel receive engine power?
22    pub is_drive: bool,
23    
24    /// Base grip factor (how much lateral force before slipping)
25    pub base_grip: f32,
26    pub drift_grip: f32,
27    pub slip_threshold: f32,
28    
29    /// Coefficient of rolling resistance (Crr)
30    pub rolling_resistance_coefficient: f32,
31    
32    // Internal state
33    #[serde(skip)]
34    pub is_grounded: bool,
35    #[serde(skip)]
36    pub suspension_compression: f32,
37    #[serde(skip)]
38    pub contact_point: Vec3,
39    #[serde(skip)]
40    pub contact_normal: Vec3,
41    #[serde(skip)]
42    pub slip_angle: f32,
43}
44
45impl Default for Wheel {
46    fn default() -> Self {
47        Self {
48            local_position: Vec3::ZERO,
49            direction: Vec3::new(0.0, -1.0, 0.0),
50            radius: 0.4,
51            suspension_rest_length: 0.5,
52            suspension_stiffness: 40000.0,
53            suspension_damping: 3000.0,
54            is_steering: false,
55            is_drive: false,
56            base_grip: 15.0,
57            drift_grip: 5.0,
58            slip_threshold: 4.0,
59            rolling_resistance_coefficient: 0.015,
60            is_grounded: false,
61            suspension_compression: 0.0,
62            contact_point: Vec3::ZERO,
63            contact_normal: Vec3::Y,
64            slip_angle: 0.0,
65        }
66    }
67}
68
69#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
70pub struct Gearbox {
71    /// Gear ratios (e.g., [3.0, 2.0, 1.5, 1.0, 0.8])
72    pub gears: Vec<f32>,
73    /// Reverse gear ratio
74    pub reverse_ratio: f32,
75    /// Final drive multiplier
76    pub final_drive: f32,
77    /// Current gear index (0-based)
78    pub current_gear: usize,
79    /// Whether shifting happens automatically based on speed
80    pub is_automatic: bool,
81    /// Speeds at which to shift up (m/s)
82    pub shift_up_speeds: Vec<f32>,
83    /// Speeds at which to shift down (m/s)
84    pub shift_down_speeds: Vec<f32>,
85    /// True if the car is in reverse
86    pub is_reversing: bool,
87}
88
89impl Default for Gearbox {
90    fn default() -> Self {
91        Self {
92            gears: vec![3.0, 2.0, 1.5, 1.1, 0.85, 0.65],
93            reverse_ratio: 3.0,
94            final_drive: 3.5,
95            current_gear: 0,
96            is_automatic: true,
97            shift_up_speeds: vec![15.0, 30.0, 45.0, 60.0, 75.0],
98            shift_down_speeds: vec![10.0, 20.0, 35.0, 50.0, 65.0],
99            is_reversing: false,
100        }
101    }
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
105pub struct Vehicle {
106    pub wheels: Vec<Wheel>,
107    
108    /// Engine power (throttle multiplier)
109    pub engine_power: f32,
110    /// Brake force multiplier
111    pub brake_force: f32,
112    /// Maximum steering angle (radians)
113    pub max_steer_angle: f32,
114    
115    /// Vehicle Gearbox
116    pub gearbox: Gearbox,
117    
118    /// Aerodynamic Drag coefficient (Cd)
119    pub aerodynamic_drag: f32,
120    /// Frontal Area (m^2)
121    pub frontal_area: f32,
122    /// Downforce coefficient (Cl)
123    pub downforce_coefficient: f32,
124    
125    /// Current normalized throttle input [-1.0, 1.0]
126    #[serde(skip)]
127    pub current_throttle: f32,
128    /// Current steering angle (radians)
129    #[serde(skip)]
130    pub current_steer: f32,
131    /// Current brake input [0.0, 1.0]
132    #[serde(skip)]
133    pub current_brake: f32,
134}
135
136impl Default for Vehicle {
137    fn default() -> Self {
138        Self {
139            wheels: Vec::new(),
140            engine_power: 10000.0,
141            brake_force: 5000.0,
142            max_steer_angle: 0.5,
143            gearbox: Gearbox::default(),
144            aerodynamic_drag: 0.3,
145            frontal_area: 2.2,
146            downforce_coefficient: 0.5,
147            current_throttle: 0.0,
148            current_steer: 0.0,
149            current_brake: 0.0,
150        }
151    }
152}
153
154gizmo_core::impl_component!(Vehicle);