@ -0,0 +1,30 @@ | |||||
/* | |||||
* Copyright (C) 2020 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* Antkeeper source code is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_ASTRONOMICAL_CONSTANTS_HPP | |||||
#define ANTKEEPER_ASTRONOMICAL_CONSTANTS_HPP | |||||
namespace ast | |||||
{ | |||||
static constexpr double km_per_au = 6.68459e-9; | |||||
} // namespace ast | |||||
#endif // ANTKEEPER_ASTRONOMICAL_CONSTANTS_HPP |
@ -0,0 +1,133 @@ | |||||
/* | |||||
* Copyright (C) 2020 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* Antkeeper source code is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "game/systems/astronomy-system.hpp" | |||||
#include "game/astronomy/celestial-coordinates.hpp" | |||||
#include "game/astronomy/celestial-mechanics.hpp" | |||||
#include "game/astronomy/celestial-time.hpp" | |||||
#include "game/astronomy/astronomical-constants.hpp" | |||||
#include "game/components/orbit-component.hpp" | |||||
#include "game/components/transform-component.hpp" | |||||
using namespace ecs; | |||||
static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0; | |||||
astronomy_system::astronomy_system(entt::registry& registry): | |||||
entity_system(registry), | |||||
universal_time(0.0), | |||||
days_per_timestep(1.0 / seconds_per_day), | |||||
observer_location{0.0, 0.0, 0.0}, | |||||
lst(0.0), | |||||
obliquity(0.0), | |||||
ke_tolerance(1e-6), | |||||
ke_iterations(10) | |||||
{} | |||||
void astronomy_system::update(double t, double dt) | |||||
{ | |||||
const double dt_days = dt * days_per_timestep; | |||||
// Add scaled timestep to current time | |||||
set_universal_time(universal_time + dt_days); | |||||
// Update horizontal (topocentric) positions of orbiting bodies | |||||
registry.view<orbit_component, transform_component>().each( | |||||
[&](auto entity, auto& orbit, auto& transform) | |||||
{ | |||||
ast::orbital_elements orbital_elements; | |||||
orbital_elements.a = orbit.a + orbit.d_a * universal_time; | |||||
orbital_elements.ec = orbit.ec + orbit.d_ec * universal_time; | |||||
orbital_elements.w = orbit.w + orbit.d_w * universal_time; | |||||
orbital_elements.ma = math::wrap_radians(orbit.ma + orbit.d_ma * universal_time); | |||||
orbital_elements.i = orbit.i + orbit.d_i * universal_time; | |||||
orbital_elements.om = math::wrap_radians(orbit.om + orbit.d_om * universal_time); | |||||
// Calculate ecliptic orbital position | |||||
double3 ecliptic = ast::orbital_elements_to_ecliptic(orbital_elements, ke_tolerance, ke_iterations); | |||||
// Transform orbital position from ecliptic space to horizontal space | |||||
double3 horizontal = ecliptic_to_horizontal * ecliptic; | |||||
// Subtract observer's radial distance (planet radius + observer's altitude) | |||||
horizontal.z -= observer_location[0]; | |||||
// Calculate azimuth and elevation | |||||
double3 spherical = ast::rectangular_to_spherical(horizontal); | |||||
double2 az_el = {spherical.z - math::pi<double>, spherical.y}; | |||||
// Transform into local right-handed coordinates | |||||
double3 translation = ast::horizontal_to_right_handed * horizontal; | |||||
double3x3 rotation = ast::horizontal_to_right_handed * ecliptic_to_horizontal; | |||||
transform.local.translation = math::type_cast<float>(translation); | |||||
transform.local.rotation = math::type_cast<float>(math::quaternion_cast(rotation)); | |||||
}); | |||||
} | |||||
void astronomy_system::set_universal_time(double time) | |||||
{ | |||||
universal_time = time; | |||||
update_axial_rotation(); | |||||
} | |||||
void astronomy_system::set_time_scale(double scale) | |||||
{ | |||||
days_per_timestep = scale / seconds_per_day; | |||||
} | |||||
void astronomy_system::set_observer_location(const double3& location) | |||||
{ | |||||
observer_location = location; | |||||
update_sidereal_time(); | |||||
} | |||||
void astronomy_system::set_obliquity(double angle) | |||||
{ | |||||
obliquity = angle; | |||||
update_ecliptic_to_horizontal(); | |||||
} | |||||
void astronomy_system::set_axial_rotation_speed(double speed) | |||||
{ | |||||
axial_rotation_speed = speed; | |||||
} | |||||
void astronomy_system::set_axial_rotation_at_epoch(double angle) | |||||
{ | |||||
axial_rotation_at_epoch = angle; | |||||
update_axial_rotation(); | |||||
} | |||||
void astronomy_system::update_axial_rotation() | |||||
{ | |||||
axial_rotation = math::wrap_radians<double>(axial_rotation_at_epoch + universal_time * axial_rotation_speed); | |||||
update_sidereal_time(); | |||||
} | |||||
void astronomy_system::update_sidereal_time() | |||||
{ | |||||
lst = math::wrap_radians<double>(axial_rotation + observer_location[2]); | |||||
update_ecliptic_to_horizontal(); | |||||
} | |||||
void astronomy_system::update_ecliptic_to_horizontal() | |||||
{ | |||||
ecliptic_to_horizontal = ast::ecliptic_to_horizontal(obliquity, observer_location[1], lst); | |||||
} |
@ -0,0 +1,103 @@ | |||||
/* | |||||
* Copyright (C) 2020 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* Antkeeper source code is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_ASTRONOMY_SYSTEM_HPP | |||||
#define ANTKEEPER_ASTRONOMY_SYSTEM_HPP | |||||
#include "entity-system.hpp" | |||||
#include "utility/fundamental-types.hpp" | |||||
/** | |||||
* | |||||
*/ | |||||
class astronomy_system: | |||||
public entity_system | |||||
{ | |||||
public: | |||||
astronomy_system(entt::registry& registry); | |||||
/** | |||||
* Scales then adds the timestep `dt` to the current Julian date, then recalculates the positions of celestial bodies. | |||||
* | |||||
* @param t Time, in seconds. | |||||
* @param dt Delta time, in seconds. | |||||
*/ | |||||
virtual void update(double t, double dt); | |||||
/** | |||||
* Sets the current universal time. | |||||
* | |||||
* @param time Universal time, in days. | |||||
*/ | |||||
void set_universal_time(double time); | |||||
/** | |||||
* Sets the factor by which the timestep `dt` will be scaled before being added to the current Julian date. | |||||
* | |||||
* @param scale Factor by which to scale the timestep. | |||||
*/ | |||||
void set_time_scale(double scale); | |||||
/** | |||||
* Sets the location of the observer. | |||||
* | |||||
* @param location Spherical coordinates of the observer, in the ISO order of radial distance, polar angle (radians), and azimuthal angle (radians). | |||||
*/ | |||||
void set_observer_location(const double3& location); | |||||
/** | |||||
* Sets the rotational speed of the observer's planet. | |||||
* | |||||
* @param speed Rotational speed, in radians per day. | |||||
*/ | |||||
void set_axial_rotation_speed(double speed); | |||||
void set_axial_rotation_at_epoch(double angle); | |||||
/** | |||||
* Sets the obliquity of the ecliptic, a.k.a. axial tilt. | |||||
* | |||||
* @param angle Angle between the planet's rotational axis and its orbital axis, in radians. | |||||
*/ | |||||
void set_obliquity(double angle); | |||||
private: | |||||
/// Updates the axial rotation angle | |||||
void update_axial_rotation(); | |||||
/// Updates the local sidereal time (LST) and dependent variables | |||||
void update_sidereal_time(); | |||||
/// Updates the ecliptic-to-horizontal transformation matrix | |||||
void update_ecliptic_to_horizontal(); | |||||
double universal_time; | |||||
double lst; | |||||
double axial_rotation_at_epoch; | |||||
double axial_rotation_speed; | |||||
double axial_rotation; | |||||
double days_per_timestep; | |||||
double3 observer_location; | |||||
double obliquity; | |||||
double3x3 ecliptic_to_horizontal; | |||||
double ke_tolerance; | |||||
std::size_t ke_iterations; | |||||
}; | |||||
#endif // ANTKEEPER_ASTRONOMY_SYSTEM_HPP |
@ -1,132 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2020 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* Antkeeper source code is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "game/systems/solar-system.hpp" | |||||
#include "game/astronomy/celestial-coordinates.hpp" | |||||
#include "game/astronomy/celestial-mechanics.hpp" | |||||
#include "game/astronomy/celestial-time.hpp" | |||||
#include "game/components/orbit-component.hpp" | |||||
#include "game/components/transform-component.hpp" | |||||
#include <iostream> | |||||
using namespace ecs; | |||||
static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0; | |||||
solar_system::solar_system(entt::registry& registry): | |||||
entity_system(registry), | |||||
julian_date(0.0), | |||||
time_scale(1.0), | |||||
latitude(0.0), | |||||
longitude(0.0), | |||||
altitude(0.0) | |||||
{} | |||||
void solar_system::update(double t, double dt) | |||||
{ | |||||
// Add scaled timestep to Julian date | |||||
set_julian_date(julian_date + (dt * time_scale) / seconds_per_day); | |||||
const double ke_tolerance = 1e-6; | |||||
const std::size_t ke_iterations = 10; | |||||
ast::orbital_elements sun_elements; | |||||
sun_elements.a = 1.0; | |||||
sun_elements.ec = 0.016709; | |||||
sun_elements.w = math::radians(282.9404); | |||||
sun_elements.ma = math::radians(356.0470); | |||||
sun_elements.i = math::radians(0.0); | |||||
sun_elements.om = math::radians(0.0); | |||||
const double j2k_day = julian_date - 2451545.0; | |||||
const double j2k_century = (julian_date - 2451545.0) / 36525.0; | |||||
sun_elements.ec += math::radians(-1.151e-9) * j2k_day; | |||||
sun_elements.w += math::radians(4.70935e-5) * j2k_day; | |||||
sun_elements.ma += math::radians(0.9856002585) * j2k_day; | |||||
ast::orbital_state sun_ecliptic = ast::orbital_elements_to_state(sun_elements, ke_tolerance, ke_iterations); | |||||
double3 sun_horizontal = ecliptic_to_horizontal * sun_ecliptic.r; | |||||
sun_horizontal.z -= 4.25875e-5; | |||||
double3 sun_spherical = ast::rectangular_to_spherical(sun_horizontal); | |||||
double2 sun_az_el = {sun_spherical.z - math::pi<double>, sun_spherical.y}; | |||||
//std::cout << "new azel: " << math::degrees(sun_az_el.x) << ", " << math::degrees(sun_az_el.y) << std::endl; | |||||
// Update horizontal (topocentric) positions of orbiting bodies | |||||
registry.view<orbit_component, transform_component>().each( | |||||
[&](auto entity, auto& orbit, auto& transform) | |||||
{ | |||||
/* | |||||
double a = orbit.a; | |||||
double ec = orbit.ec; | |||||
double w = orbit.w; | |||||
double ma = orbit.ma; | |||||
double i = orbit.i; | |||||
double om = orbit.om; | |||||
double3 ecliptic = ast::solve_kepler(a, ec, w, ma, i, om); | |||||
double3 horizontal = ecliptic_to_horizontal * ecliptic; | |||||
// Subtract Earth's radius (in AU), for positon of observer | |||||
horizontal.z -= 4.25875e-5; | |||||
// Transform into local right-handed coordinates | |||||
double3 translation = ast::horizontal_to_right_handed * horizontal; | |||||
double3x3 rotation = ast::horizontal_to_right_handed * ecliptic_to_horizontal; | |||||
transform.local.translation = math::type_cast<float>(translation); | |||||
transform.local.rotation = math::type_cast<float>(math::quaternion_cast(rotation)); | |||||
*/ | |||||
}); | |||||
} | |||||
void solar_system::set_julian_date(double jd) | |||||
{ | |||||
julian_date = jd; | |||||
// Recalculate obliquity of the ecliptic | |||||
ecl = ast::approx_ecliptic_obliquity(julian_date); | |||||
// Recalculate LMST | |||||
lmst = ast::jd_to_lmst(julian_date, longitude); | |||||
// Recalculate ecliptic to horizontal transformation matrix | |||||
ecliptic_to_horizontal = ast::ecliptic_to_horizontal(ecl, latitude, lmst); | |||||
} | |||||
void solar_system::set_time_scale(double scale) | |||||
{ | |||||
time_scale = scale; | |||||
} | |||||
void solar_system::set_observer_location(double latitude, double longitude, double altitude) | |||||
{ | |||||
this->latitude = latitude; | |||||
this->longitude = longitude; | |||||
this->altitude = altitude; | |||||
// Recalculate LMST | |||||
lmst = ast::jd_to_lmst(julian_date, longitude); | |||||
// Recalculate ecliptic to horizontal transformation matrix | |||||
ecliptic_to_horizontal = ast::ecliptic_to_horizontal(ecl, latitude, lmst); | |||||
} |
@ -1,81 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2020 Christopher J. Howard | |||||
* | |||||
* This file is part of Antkeeper source code. | |||||
* | |||||
* Antkeeper source code is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 3 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* Antkeeper source code is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef ANTKEEPER_SOLAR_SYSTEM_HPP | |||||
#define ANTKEEPER_SOLAR_SYSTEM_HPP | |||||
#include "entity-system.hpp" | |||||
#include "utility/fundamental-types.hpp" | |||||
/** | |||||
* | |||||
*/ | |||||
class solar_system: | |||||
public entity_system | |||||
{ | |||||
public: | |||||
solar_system(entt::registry& registry); | |||||
/** | |||||
* Scales then adds the timestep `dt` to the current Julian date, then recalculates the positions of celestial bodies. | |||||
*/ | |||||
virtual void update(double t, double dt); | |||||
/** | |||||
* Sets the current Julian date. | |||||
* | |||||
* @param jd Julian date. | |||||
*/ | |||||
void set_julian_date(double jd); | |||||
/** | |||||
* Sets the factor by which the timestep `dt` will be scaled before being added to the current Julian date. | |||||
* | |||||
* @param scale Factor by which to scale the timestep. | |||||
*/ | |||||
void set_time_scale(double scale); | |||||
/** | |||||
* Sets the latitude, longitude, and altitude of the observer. | |||||
* | |||||
* @param latitude Observer latitude, in radians. | |||||
* @param longitude Observer longitude, in radians. | |||||
* @param altitude Observer altitude, in meters. | |||||
*/ | |||||
void set_observer_location(double latitude, double longitude, double altitude); | |||||
private: | |||||
double julian_date; | |||||
double time_scale; | |||||
double latitude; | |||||
double longitude; | |||||
double altitude; | |||||
double lmst; | |||||
double ecl; | |||||
double3x3 ecliptic_to_horizontal; | |||||
double3 sun_position; | |||||
double3 sunlight_direction; | |||||
double3 moon_position; | |||||
double3 moonlight_direction; | |||||
}; | |||||
#endif // ANTKEEPER_SOLAR_SYSTEM_HPP |