set moon orbit phases according to real time clock

This commit is contained in:
yuni 2024-04-30 00:29:37 +02:00
parent 2eb2915f62
commit 7f5894f9f7
3 changed files with 73 additions and 19 deletions

View file

@ -19,6 +19,7 @@ use crate::{actor, camera, chat, hud, nature, shading, skeleton, var, world};
use regex::Regex; use regex::Regex;
use std::f32::consts::PI; use std::f32::consts::PI;
use std::f64::consts::PI as PI64; use std::f64::consts::PI as PI64;
use std::time::SystemTime;
pub struct CommandsPlugin; pub struct CommandsPlugin;
impl Plugin for CommandsPlugin { impl Plugin for CommandsPlugin {
@ -68,6 +69,9 @@ struct ParserState {
is_sun: bool, is_sun: bool,
is_moon: bool, is_moon: bool,
is_point_of_interest: bool, is_point_of_interest: bool,
orbit_distance: Option<f64>,
orbit_object_id: Option<String>,
orbit_phase: Option<f64>,
has_physics: bool, has_physics: bool,
has_ring: bool, has_ring: bool,
wants_maxrotation: Option<f64>, wants_maxrotation: Option<f64>,
@ -119,6 +123,9 @@ impl Default for ParserState {
is_sun: false, is_sun: false,
is_moon: false, is_moon: false,
is_point_of_interest: false, is_point_of_interest: false,
orbit_distance: None,
orbit_object_id: None,
orbit_phase: None,
has_physics: true, has_physics: true,
has_ring: false, has_ring: false,
wants_maxrotation: None, wants_maxrotation: None,
@ -227,14 +234,20 @@ pub fn load_defs(
["relativeto", id] => { ["relativeto", id] => {
state.relative_to = Some(id.to_string()); state.relative_to = Some(id.to_string());
} }
["orbitaround", object_id, radius_str] => {
if let Ok(r) = radius_str.parse::<f64>() {
state.orbit_distance = Some(r);
state.orbit_object_id = Some(object_id.to_string());
}
else {
error!("Can't parse float: {line}");
continue;
}
}
["orbit", radius_str, phase_str] => { ["orbit", radius_str, phase_str] => {
if let (Ok(r), Ok(phase)) = (radius_str.parse::<f64>(), phase_str.parse::<f64>()) { if let (Ok(r), Ok(phase)) = (radius_str.parse::<f64>(), phase_str.parse::<f64>()) {
let phase_deg = phase * PI64 * 2.0; state.orbit_distance = Some(r);
state.pos = DVec3::new( state.orbit_phase = Some(phase * PI64 * 2.0);
state.pos.x + r * phase_deg.cos(),
state.pos.y,
state.pos.z + r * phase_deg.sin(),
);
} }
else { else {
error!("Can't parse float: {line}"); error!("Can't parse float: {line}");
@ -492,7 +505,7 @@ fn spawn_entities(
let state = &state_wrapper.0; let state = &state_wrapper.0;
if state.class == DefClass::Actor { if state.class == DefClass::Actor {
// Preprocessing // Preprocessing
let relative_pos = if let Some(id) = &state.relative_to { let mut absolute_pos = if let Some(id) = &state.relative_to {
match id2pos.0.get(&id.to_string()) { match id2pos.0.get(&id.to_string()) {
Some(pos) => { Some(pos) => {
state.pos + *pos state.pos + *pos
@ -505,6 +518,30 @@ fn spawn_entities(
} else { } else {
state.pos state.pos
}; };
if let Some(r) = state.orbit_distance {
let phase_radians: f64 = if let Some(phase_radians) = state.orbit_phase {
phase_radians
} else if let Some(id) = &state.orbit_object_id {
let mass = match id.as_str() {
"jupiter" => nature::JUPITER_MASS,
_ => {
error!("Found no mass for object `{id}`");
continue;
}
};
let orbital_period = nature::simple_orbital_period(mass, r);
if let Ok(epoch) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
PI64 * 2.0 * (epoch.as_secs_f64() % orbital_period) / orbital_period
} else {
error!("Can't determine current time `{id}`");
0.0
}
} else {
error!("if state.orbit_distance is set, then either state.orbit_object_id or state.orbit_phase must be set as well.");
continue;
};
absolute_pos += nature::phase_dist_to_coords(phase_radians, r);
}
let scale = Vec3::splat(if state.is_sun { let scale = Vec3::splat(if state.is_sun {
5.0 5.0
} else if state.is_moon && settings.large_moons { } else if state.is_moon && settings.large_moons {
@ -526,7 +563,7 @@ fn spawn_entities(
actor.insert(SleepingDisabled); actor.insert(SleepingDisabled);
actor.insert(world::DespawnOnPlayerDeath); actor.insert(world::DespawnOnPlayerDeath);
actor.insert(actor::HitPoints::default()); actor.insert(actor::HitPoints::default());
actor.insert(Position::from(relative_pos)); actor.insert(Position::from(absolute_pos));
actor.insert(Rotation::from(state.rotation)); actor.insert(Rotation::from(state.rotation));
if state.is_sphere { if state.is_sphere {
let sphere_texture_handle = if let Some(model) = &state.model { let sphere_texture_handle = if let Some(model) = &state.model {
@ -653,7 +690,7 @@ fn spawn_entities(
} }
if !state.id.is_empty() { if !state.id.is_empty() {
actor.insert(actor::Identifier(state.id.clone())); actor.insert(actor::Identifier(state.id.clone()));
id2pos.0.insert(state.id.clone(), relative_pos); id2pos.0.insert(state.id.clone(), absolute_pos);
} }
if !state.chat.is_empty() { if !state.chat.is_empty() {
actor.insert(chat::Talker { actor.insert(chat::Talker {
@ -730,10 +767,10 @@ fn spawn_entities(
ring_radius: nature::JUPITER_RING_RADIUS as f32, ring_radius: nature::JUPITER_RING_RADIUS as f32,
jupiter_radius: nature::JUPITER_RADIUS as f32, jupiter_radius: nature::JUPITER_RADIUS as f32,
}), }),
transform: Transform::from_translation(relative_pos.as_vec3()), transform: Transform::from_translation(absolute_pos.as_vec3()),
..default() ..default()
}, },
Position::new(relative_pos), Position::new(absolute_pos),
Rotation::from(Quat::IDENTITY), Rotation::from(Quat::IDENTITY),
//Rotation::from(Quat::from_rotation_x(-0.3f32.to_radians())), //Rotation::from(Quat::from_rotation_x(-0.3f32.to_radians())),
NotShadowCaster, NotShadowCaster,

View file

@ -152,7 +152,7 @@ actor 0 0 0 io
name Io name Io
id io id io
relativeto jupiter relativeto jupiter
orbit 421700e3 0.65 orbitaround jupiter 421700e3
scale 1822e3 scale 1822e3
rotationy -0.40 rotationy -0.40
rotationx -0.50 rotationx -0.50
@ -165,7 +165,7 @@ actor 0 0 0 europa
name Europa name Europa
id europa id europa
relativeto jupiter relativeto jupiter
orbit 670900e3 0.35 orbitaround jupiter 670900e3
scale 1561e3 scale 1561e3
rotationy 0.20 rotationy 0.20
rotationx -0.50 rotationx -0.50
@ -178,7 +178,7 @@ actor 0 0 0 ganymede
name Ganymede name Ganymede
id ganymede id ganymede
relativeto jupiter relativeto jupiter
orbit 1070400e3 0.93 orbitaround jupiter 1070400e3
scale 2634e3 scale 2634e3
rotationy -0.40 rotationy -0.40
rotationx -0.50 rotationx -0.50
@ -191,7 +191,7 @@ actor 0 0 0 callisto
name Callisto name Callisto
id callisto id callisto
relativeto jupiter relativeto jupiter
orbit 1882700e3 0.45 orbitaround jupiter 1882700e3
scale 2410e3 scale 2410e3
rotationy -0.40 rotationy -0.40
rotationx -0.50 rotationx -0.50
@ -204,7 +204,7 @@ actor 0 0 0 moonlet
name Thebe name Thebe
relativeto jupiter relativeto jupiter
id thebe id thebe
orbit 221900e3 0.66 orbitaround jupiter 221900e3
scale 50e3 scale 50e3
angularmomentum 0 0.025 0 angularmomentum 0 0.025 0
actor -55e3 44e3 0 suitv2 actor -55e3 44e3 0 suitv2
@ -226,7 +226,7 @@ actor 0 0 0 moonlet
name Metis name Metis
relativeto jupiter relativeto jupiter
id metis id metis
orbit 128000e3 0.8 orbitaround jupiter 128000e3
scale 21.5e3 scale 21.5e3
angularmomentum 0 0.025 0 angularmomentum 0 0.025 0
@ -234,7 +234,7 @@ actor 0 0 0 moonlet
name Adrastea name Adrastea
relativeto jupiter relativeto jupiter
id adrastea id adrastea
orbit 129000e3 0.5 orbitaround jupiter 129000e3
scale 8.2e3 scale 8.2e3
angularmomentum 0 0.025 0 angularmomentum 0 0.025 0
@ -242,7 +242,7 @@ actor 0 0 0 moonlet
name Amalthea name Amalthea
relativeto jupiter relativeto jupiter
id amalthea id amalthea
orbit 181365.84e3 0.2 orbitaround jupiter 181365.84e3
scale 83.5e3 scale 83.5e3
angularmomentum 0 0.025 0 angularmomentum 0 0.025 0

View file

@ -10,6 +10,9 @@
// //
// This module manages the messy, impure parts of our universe. // This module manages the messy, impure parts of our universe.
use bevy::math::DVec3;
use std::f64::consts::PI as PI64;
pub const OXYGEN_USE_KG_PER_S: f32 = 1e-5; pub const OXYGEN_USE_KG_PER_S: f32 = 1e-5;
pub const OXY_S: f32 = OXYGEN_USE_KG_PER_S; pub const OXY_S: f32 = OXYGEN_USE_KG_PER_S;
pub const OXY_M: f32 = OXYGEN_USE_KG_PER_S * 60.0; pub const OXY_M: f32 = OXYGEN_USE_KG_PER_S * 60.0;
@ -20,10 +23,12 @@ pub const PARSEC2METER: f64 = 3.0857e16;
pub const DIST_JUPTER_SUN: f64 = 778479.0e6; pub const DIST_JUPTER_SUN: f64 = 778479.0e6;
pub const EARTH_GRAVITY: f32 = 9.81; pub const EARTH_GRAVITY: f32 = 9.81;
pub const C: f64 = 299792458.0; // m/s pub const C: f64 = 299792458.0; // m/s
pub const G: f64 = 6.6743015e-11; // Gravitational constant in Nm²/kg²
pub const SOL_RADIUS: f64 = 696_300_000.0; pub const SOL_RADIUS: f64 = 696_300_000.0;
pub const JUPITER_RADIUS: f64 = 71_492_000.0; pub const JUPITER_RADIUS: f64 = 71_492_000.0;
pub const JUPITER_RING_RADIUS: f64 = 229_000_000.0; pub const JUPITER_RING_RADIUS: f64 = 229_000_000.0;
pub const JUPITER_MASS: f64 = 1.8982e27;
// Each star's values: (x, y, z, magnitude, color index, distance, name) // Each star's values: (x, y, z, magnitude, color index, distance, name)
pub const STARS: &[(f32, f32, f32, f32, f32, f32, &str)] = &include!("data/stars.in"); pub const STARS: &[(f32, f32, f32, f32, f32, f32, &str)] = &include!("data/stars.in");
@ -139,3 +144,15 @@ pub fn lorenz_factor(speed: f64) -> f64 {
pub fn lorenz_factor_custom_c(speed: f64, c: f64) -> f64 { pub fn lorenz_factor_custom_c(speed: f64, c: f64) -> f64 {
(1.0 - (speed.powf(2.0) / c.powf(2.0))).sqrt() (1.0 - (speed.powf(2.0) / c.powf(2.0))).sqrt()
} }
pub fn simple_orbital_period(mass: f64, distance: f64) -> f64 {
return 2.0 * PI64 * (distance.powf(3.0) / (G * mass)).sqrt();
}
pub fn phase_dist_to_coords(phase_radians: f64, distance: f64) -> DVec3 {
return DVec3::new(
distance * phase_radians.cos(),
0.0,
distance * phase_radians.sin(),
);
}