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 std::f32::consts::PI;
use std::f64::consts::PI as PI64;
use std::time::SystemTime;
pub struct CommandsPlugin;
impl Plugin for CommandsPlugin {
@ -68,6 +69,9 @@ struct ParserState {
is_sun: bool,
is_moon: bool,
is_point_of_interest: bool,
orbit_distance: Option<f64>,
orbit_object_id: Option<String>,
orbit_phase: Option<f64>,
has_physics: bool,
has_ring: bool,
wants_maxrotation: Option<f64>,
@ -119,6 +123,9 @@ impl Default for ParserState {
is_sun: false,
is_moon: false,
is_point_of_interest: false,
orbit_distance: None,
orbit_object_id: None,
orbit_phase: None,
has_physics: true,
has_ring: false,
wants_maxrotation: None,
@ -227,14 +234,20 @@ pub fn load_defs(
["relativeto", id] => {
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] => {
if let (Ok(r), Ok(phase)) = (radius_str.parse::<f64>(), phase_str.parse::<f64>()) {
let phase_deg = phase * PI64 * 2.0;
state.pos = DVec3::new(
state.pos.x + r * phase_deg.cos(),
state.pos.y,
state.pos.z + r * phase_deg.sin(),
);
state.orbit_distance = Some(r);
state.orbit_phase = Some(phase * PI64 * 2.0);
}
else {
error!("Can't parse float: {line}");
@ -492,7 +505,7 @@ fn spawn_entities(
let state = &state_wrapper.0;
if state.class == DefClass::Actor {
// 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()) {
Some(pos) => {
state.pos + *pos
@ -505,6 +518,30 @@ fn spawn_entities(
} else {
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 {
5.0
} else if state.is_moon && settings.large_moons {
@ -526,7 +563,7 @@ fn spawn_entities(
actor.insert(SleepingDisabled);
actor.insert(world::DespawnOnPlayerDeath);
actor.insert(actor::HitPoints::default());
actor.insert(Position::from(relative_pos));
actor.insert(Position::from(absolute_pos));
actor.insert(Rotation::from(state.rotation));
if state.is_sphere {
let sphere_texture_handle = if let Some(model) = &state.model {
@ -653,7 +690,7 @@ fn spawn_entities(
}
if !state.id.is_empty() {
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() {
actor.insert(chat::Talker {
@ -730,10 +767,10 @@ fn spawn_entities(
ring_radius: nature::JUPITER_RING_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()
},
Position::new(relative_pos),
Position::new(absolute_pos),
Rotation::from(Quat::IDENTITY),
//Rotation::from(Quat::from_rotation_x(-0.3f32.to_radians())),
NotShadowCaster,

View file

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

View file

@ -10,6 +10,9 @@
//
// 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 OXY_S: f32 = OXYGEN_USE_KG_PER_S;
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 EARTH_GRAVITY: f32 = 9.81;
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 JUPITER_RADIUS: f64 = 71_492_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)
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 {
(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(),
);
}