WIP jupiter atmosphere

This commit is contained in:
yuni 2024-11-27 02:33:02 +01:00
parent dbfe4a7790
commit 2d185a810b
4 changed files with 90 additions and 6 deletions

View file

@ -58,12 +58,20 @@ impl Plugin for ActorPlugin {
app.add_systems(
PostUpdate,
(
handle_gforce
.run_if(game_running)
.run_if(alive)
.after(PhysicsSet::Sync)
.after(sync::position_to_transform)
.after(handle_wants_acceleration),
handle_atmosphere
.run_if(game_running)
.run_if(alive)
.after(PhysicsSet::Sync)
.after(sync::position_to_transform)
.before(handle_gforce),
),
);
app.add_systems(
Update,
@ -205,6 +213,13 @@ pub struct WantsMatchVelocityWith(pub String);
pub struct Identifier(pub String);
#[derive(Component)]
pub struct OrbitsJupiter;
#[derive(Component)]
pub struct ExperiencesAtmosphere;
#[derive(Component, Debug)]
pub struct HasAtmosphere {
pub r_inner: f64,
pub r_outer: f64,
}
#[derive(Component)]
pub struct LifeForm {
@ -1109,3 +1124,44 @@ fn handle_gravity(
v.0 += accel;
}
}
fn handle_atmosphere(
time: Res<Time>,
q_atmosphere: Query<(&Position, Option<&LinearVelocity>, &HasAtmosphere)>,
mut q_actor: Query<
(&Position, &mut LinearVelocity),
(With<ExperiencesAtmosphere>, Without<HasAtmosphere>),
>,
) {
let dt = time.delta_seconds() as f64;
for (pos, mut v) 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 dv = if let Some(atmo_v) = atmo_v {
v.0 - atmo_v.0
} else {
v.0
};
let friction = dv * (1.0 - height).powf(4.0) / 4.0;
v.0 -= friction;
if distance < atmo.r_inner {
let outward = (pos.0 - atmo_pos.0).normalize();
let buoyancy = outward * (atmo.r_inner - distance) * dt * 10.0;
v.0 += buoyancy;
}
continue; // max. 1 atmosphere
}
}
}
}

View file

@ -103,6 +103,7 @@ struct ParserState {
is_tidally_locked: bool,
is_mirror: bool,
is_orbitring: bool,
atmosphere: Option<String>,
orbit_distance: Option<f64>,
orbit_object_id: Option<String>,
orbit_phase: Option<f64>,
@ -168,6 +169,7 @@ impl Default for ParserState {
is_tidally_locked: false,
is_mirror: false,
is_orbitring: false,
atmosphere: None,
orbit_distance: None,
orbit_object_id: None,
orbit_phase: None,
@ -647,6 +649,9 @@ pub fn load_defs(mut ew_spawn: EventWriter<SpawnEvent>) {
["collider", "handcrafted"] => {
state.collider_is_one_mesh_of_scene = true;
}
["atmosphere", atmosphere_id] => {
state.atmosphere = Some(atmosphere_id.to_string());
}
["player", "yes"] => {
state.is_player = true;
state.is_alive = true;
@ -1465,6 +1470,8 @@ fn spawn_entities(
});
}
if state.is_player || state.is_vehicle {
actor.insert(actor::ExperiencesAtmosphere);
// used to apply mouse movement to actor rotation
actor.insert(ExternalTorque::ZERO.with_persistence(false));
}
@ -1582,6 +1589,24 @@ fn spawn_entities(
));
});
}
if state.atmosphere.is_some() {
let atmosphere_id = state.atmosphere.clone().unwrap();
let component = match atmosphere_id.as_str() {
"jupiter" => {
Some(actor::HasAtmosphere {
r_inner: scale.x as f64 * 1.01,
r_outer: scale.x as f64 * 1.01 + nature::JUPITER_ATMO_HEIGHT,
})
}
_ => {
error!("Unknown atmosphere id `{atmosphere_id}`");
None
}
};
if let Some(component) = component {
actor.insert(component);
}
}
actor_entity = actor.id();
for ar_asset_name in &state.ar_models {

View file

@ -85,6 +85,7 @@ actor 0 0 0
sphere yes
ring yes
aurora yes
atmosphere jupiter
physics off
rotationy 3.13
rotationz 135

View file

@ -34,6 +34,8 @@ pub const SOL_MASS: f64 = 1.9885e30;
pub const JUPITER_MASS: f64 = 1.8982e27;
pub const EARTH_MASS: f64 = 5.972168e24;
pub const JUPITER_ATMO_HEIGHT: f64 = 1_000_000.0;
// Arbitrary offset to time epoch, to generate more interesting orbital arrangements:
pub const ORBIT_TIME_OFFSET: f64 = 614533234154.0;