diff --git a/src/cmd.rs b/src/cmd.rs index 6d19ceb..057fff0 100644 --- a/src/cmd.rs +++ b/src/cmd.rs @@ -91,6 +91,7 @@ struct ParserState { is_moon: bool, is_planet: bool, is_point_of_interest: bool, + is_tidally_locked: bool, orbit_distance: Option, orbit_object_id: Option, orbit_phase: Option, @@ -149,6 +150,7 @@ impl Default for ParserState { is_moon: false, is_planet: false, is_point_of_interest: false, + is_tidally_locked: false, orbit_distance: None, orbit_object_id: None, orbit_phase: None, @@ -456,6 +458,9 @@ pub fn load_defs(mut ew_spawn: EventWriter) { ["ring", "yes"] => { state.has_ring = true; } + ["tidally", "locked"] => { + state.is_tidally_locked = true; + } ["pointofinterest", "yes"] => { state.is_point_of_interest = true; } @@ -848,6 +853,17 @@ fn spawn_entities( None }; absolute_pos += nature::pos_offset_for_orbiting_body(r, mass, state.orbit_phase); + + if state.is_tidally_locked { + if let Some(mass) = mass { + rotation = + Quat::from_rotation_y(nature::rotation_for_orbiting_body(r, mass) as f32); + } else { + error!("Attempted to use 'tidally locked' without specifying mass via 'orbitaround'"); + } + } + } else if state.is_tidally_locked { + error!("Attempted to use 'tidally locked' without specifying orbital distance via 'orbitaround'"); } let scale = Vec3::splat( if state.is_sun { diff --git a/src/data/defs.txt b/src/data/defs.txt index 49684f9..2769dba 100644 --- a/src/data/defs.txt +++ b/src/data/defs.txt @@ -127,10 +127,11 @@ actor 0 0 0 relativeto jupiter id thebe orbitaround jupiter 221900e3 + tidally locked scale 50e3 moon yes collider handcrafted - angularmomentum 0 0.0 0 + angularmomentum 0 0 0 actor 0 0 0 orbitring relativeto jupiter scale 221900e3 diff --git a/src/nature.rs b/src/nature.rs index 68e5601..b9811f2 100644 --- a/src/nature.rs +++ b/src/nature.rs @@ -230,3 +230,18 @@ pub fn pos_offset_for_orbiting_body( } return phase_dist_to_coords(-phase_radians, r); } + +/// Assumes the "front" (as seen in blender) is pointing at the orbited mass +pub fn rotation_for_orbiting_body( + orbit_distance: f64, + mass: f64, +) -> f64 { + if let Ok(epoch) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { + let orbital_period = nature::simple_orbital_period(mass, orbit_distance); + let now = epoch.as_secs_f64() + ORBIT_TIME_OFFSET; + PI * 2.0 * (now % orbital_period) / orbital_period - PI * 0.5 + } else { + eprintln!("WARNING: Can't determine current time in calculate_position_offset_for_orbiting_body()."); + 0.0 + } +}