@ -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 |