atmosphere: implement drag

This commit is contained in:
yuni 2024-11-28 04:39:00 +01:00
parent bbbf9c839b
commit ac522eb130
4 changed files with 39 additions and 14 deletions

View file

@ -1131,33 +1131,46 @@ fn handle_atmosphere(
mut settings: ResMut<Settings>, mut settings: ResMut<Settings>,
q_atmosphere: Query<(&Position, Option<&LinearVelocity>, &HasAtmosphere)>, q_atmosphere: Query<(&Position, Option<&LinearVelocity>, &HasAtmosphere)>,
mut q_actor: Query< mut q_actor: Query<
(&Position, &mut LinearVelocity, Option<&mut HitPoints>, Option<&PlayerCamera>), (
&Position,
&mut LinearVelocity,
&Transform,
&Mass,
Option<&mut HitPoints>,
Option<&PlayerCamera>,
),
(With<ExperiencesAtmosphere>, Without<HasAtmosphere>), (With<ExperiencesAtmosphere>, Without<HasAtmosphere>),
>, >,
) { ) {
let dt = time.delta_seconds() as f64; let dt = time.delta_seconds() as f64;
let mut reset_player_gauges = true; let mut reset_player_gauges = true;
for (pos, mut v, mut hp, player) in &mut q_actor { for (pos, mut v, trans, mass, mut hp, player) in &mut q_actor {
for (atmo_pos, atmo_v, atmo) in &q_atmosphere { for (atmo_pos, atmo_v, atmo) in &q_atmosphere {
let distance = atmo_pos.distance(pos.0); let distance = atmo_pos.distance(pos.0);
if distance < atmo.r_outer { if distance < atmo.r_outer {
// height is between 0.0 (collides with planet) and 1.0 (outside of atmosphere) let density = nature::jupiter_altitude_to_density(distance);
let height = if distance < atmo.r_inner { let pressure = nature::jupiter_altitude_to_pressure(distance);
0.0 let drag_coef = nature::DRAG_COEFFICIENT_SPHERE;
} else { let radius = trans.scale.x as f64;
(distance - atmo.r_inner) / (atmo.r_outer - atmo.r_inner) let area = PI * radius * radius;
};
let dv = if let Some(atmo_v) = atmo_v { let dv = if let Some(atmo_v) = atmo_v {
v.0 - atmo_v.0 v.0 - atmo_v.0
} else { } else {
v.0 v.0
}; };
let friction = dv * (1.0 - height).powf(16.0) * dt * 10.0;
v.0 -= friction;
let pressure = nature::jupiter_altitude_to_pressure(distance); let drag_accel;
if dv == DVec3::ZERO {
drag_accel = DVec3::ZERO;
} else {
let speed = dv.length();
let drag_force = nature::drag_force(density, speed, area, drag_coef);
drag_accel = -dv.normalize() * (drag_force / mass.0 * dt).clamp(0.0, speed);
v.0 += drag_accel;
}
if let Some(ref mut hp) = hp { if let Some(ref mut hp) = hp {
if pressure > 1000.0 { if pressure > 1000.0 {
hp.damage += f32::INFINITY; // better luck next time hp.damage += f32::INFINITY; // better luck next time
@ -1166,9 +1179,9 @@ fn handle_atmosphere(
} }
if player.is_some() { if player.is_some() {
let density = nature::jupiter_altitude_to_density(distance);
settings.atmo_pressure = Some(pressure); settings.atmo_pressure = Some(pressure);
settings.atmo_altitude = Some(distance - nature::JUPITER_RADIUS); settings.atmo_altitude = Some(distance - nature::JUPITER_RADIUS);
settings.atmo_drag = Some(drag_accel.length());
settings.atmo_density = Some(density); settings.atmo_density = Some(density);
reset_player_gauges = false; reset_player_gauges = false;
} }
@ -1190,5 +1203,6 @@ fn handle_atmosphere(
settings.atmo_pressure = None; settings.atmo_pressure = None;
settings.atmo_altitude = None; settings.atmo_altitude = None;
settings.atmo_density = None; settings.atmo_density = None;
settings.atmo_drag = None;
} }
} }

View file

@ -880,11 +880,14 @@ fn update_speedometer(
if let Some(val) = settings.atmo_altitude { if let Some(val) = settings.atmo_altitude {
atmo += format!("alt: {}m\n", nature::readable_si(val)).as_str(); atmo += format!("alt: {}m\n", nature::readable_si(val)).as_str();
} }
if let Some(val) = settings.atmo_pressure {
atmo += format!("p: {}bar\n", nature::readable_si(val as f64)).as_str();
}
if let Some(val) = settings.atmo_density { if let Some(val) = settings.atmo_density {
atmo += format!("dens: {}g/m³\n", nature::readable_si(val*1000.0)).as_str(); atmo += format!("dens: {}g/m³\n", nature::readable_si(val*1000.0)).as_str();
} }
if let Some(val) = settings.atmo_pressure { if let Some(val) = settings.atmo_drag {
atmo += format!("p: {}bar\n", nature::readable_si(val as f64)).as_str(); atmo += format!("drag: {}m/s²\n", nature::readable_si(val)).as_str();
} }
speed_text.sections[0].value = atmo; speed_text.sections[0].value = atmo;

View file

@ -36,6 +36,8 @@ pub const EARTH_MASS: f64 = 5.972168e24;
pub const JUPITER_ATMO_HEIGHT: f64 = 1_000_000.0; pub const JUPITER_ATMO_HEIGHT: f64 = 1_000_000.0;
pub const DRAG_COEFFICIENT_SPHERE: f64 = 0.47; // at Reynolds number 10e4
// Arbitrary offset to time epoch, to generate more interesting orbital arrangements: // Arbitrary offset to time epoch, to generate more interesting orbital arrangements:
pub const ORBIT_TIME_OFFSET: f64 = 614533234154.0; pub const ORBIT_TIME_OFFSET: f64 = 614533234154.0;
@ -329,3 +331,7 @@ pub fn jupiter_altitude_to_density(altitude: f64) -> f64 {
} }
return 25000.0 / (1.0 + (0.00000580528 * x + 361.44394).exp()); return 25000.0 / (1.0 + (0.00000580528 * x + 361.44394).exp());
} }
pub fn drag_force(density: f64, speed: f64, area: f64, drag_coefficient: f64) -> f64 {
return 0.5 * density * speed * speed * area * drag_coefficient;
}

View file

@ -55,6 +55,7 @@ pub struct Settings {
pub atmo_pressure: Option<f64>, pub atmo_pressure: Option<f64>,
pub atmo_density: Option<f64>, pub atmo_density: Option<f64>,
pub atmo_altitude: Option<f64>, pub atmo_altitude: Option<f64>,
pub atmo_drag: Option<f64>,
pub font_size_hud: f32, pub font_size_hud: f32,
pub font_size_fps: f32, pub font_size_fps: f32,
pub font_size_conversations: f32, pub font_size_conversations: f32,
@ -206,6 +207,7 @@ impl Default for Settings {
atmo_pressure: None, atmo_pressure: None,
atmo_density: None, atmo_density: None,
atmo_altitude: None, atmo_altitude: None,
atmo_drag: None,
font_size_hud: 24.0, font_size_hud: 24.0,
font_size_fps: 14.0, font_size_fps: 14.0,
font_size_conversations: 32.0, font_size_conversations: 32.0,