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>,
q_atmosphere: Query<(&Position, Option<&LinearVelocity>, &HasAtmosphere)>,
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>),
>,
) {
let dt = time.delta_seconds() as f64;
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 {
let distance = atmo_pos.distance(pos.0);
if distance < atmo.r_outer {
// height is between 0.0 (collides with planet) and 1.0 (outside of atmosphere)
let height = if distance < atmo.r_inner {
0.0
} else {
(distance - atmo.r_inner) / (atmo.r_outer - atmo.r_inner)
};
let density = nature::jupiter_altitude_to_density(distance);
let pressure = nature::jupiter_altitude_to_pressure(distance);
let drag_coef = nature::DRAG_COEFFICIENT_SPHERE;
let radius = trans.scale.x as f64;
let area = PI * radius * radius;
let dv = if let Some(atmo_v) = atmo_v {
v.0 - atmo_v.0
} else {
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 pressure > 1000.0 {
hp.damage += f32::INFINITY; // better luck next time
@ -1166,9 +1179,9 @@ fn handle_atmosphere(
}
if player.is_some() {
let density = nature::jupiter_altitude_to_density(distance);
settings.atmo_pressure = Some(pressure);
settings.atmo_altitude = Some(distance - nature::JUPITER_RADIUS);
settings.atmo_drag = Some(drag_accel.length());
settings.atmo_density = Some(density);
reset_player_gauges = false;
}
@ -1190,5 +1203,6 @@ fn handle_atmosphere(
settings.atmo_pressure = None;
settings.atmo_altitude = 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 {
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 {
atmo += format!("dens: {}g/m³\n", nature::readable_si(val*1000.0)).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_drag {
atmo += format!("drag: {}m/s²\n", nature::readable_si(val)).as_str();
}
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 DRAG_COEFFICIENT_SPHERE: f64 = 0.47; // at Reynolds number 10e4
// Arbitrary offset to time epoch, to generate more interesting orbital arrangements:
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());
}
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_density: Option<f64>,
pub atmo_altitude: Option<f64>,
pub atmo_drag: Option<f64>,
pub font_size_hud: f32,
pub font_size_fps: f32,
pub font_size_conversations: f32,
@ -206,6 +207,7 @@ impl Default for Settings {
atmo_pressure: None,
atmo_density: None,
atmo_altitude: None,
atmo_drag: None,
font_size_hud: 24.0,
font_size_fps: 14.0,
font_size_conversations: 32.0,