diff --git a/CMakeLists.txt b/CMakeLists.txt index c7a360c..d4aa351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,6 @@ option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) - # Find dependency packages find_package(dr_wav REQUIRED CONFIG) find_package(stb REQUIRED CONFIG) diff --git a/src/game/astronomy/astronomical-constants.hpp b/src/game/astronomy/astronomical-constants.hpp new file mode 100644 index 0000000..d4e0a25 --- /dev/null +++ b/src/game/astronomy/astronomical-constants.hpp @@ -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 . + */ + +#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 diff --git a/src/game/astronomy/celestial-mechanics.cpp b/src/game/astronomy/celestial-mechanics.cpp index f6232b7..9e4565a 100644 --- a/src/game/astronomy/celestial-mechanics.cpp +++ b/src/game/astronomy/celestial-mechanics.cpp @@ -132,50 +132,52 @@ double3x3 approx_moon_ecliptic_rotation(double jd) double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations) { // Approximate eccentric anomaly, E - double ea0 = ma + ec * std::sin(ma) * (1.0 + ec * std::cos(ma)); + double e0 = ma + ec * std::sin(ma) * (1.0 + ec * std::cos(ma)); - // Iteratively converge ea0 and ea1 + // Iteratively converge E0 and E1 for (std::size_t i = 0; i < iterations; ++i) { - double ea1 = ea0; - ea0 = ea1 - (ea1 - ec * std::sin(ea1) - ma) / (1.0 - ec * std::cos(ea1)); - if (std::abs(ea1 - ea0) < tolerance) + double e1 = e0 - (e0 - ec * std::sin(e0) - ma) / (1.0 - ec * std::cos(e0)); + double error = std::abs(e1 - e0); + e0 = e1; + + if (error < tolerance) break; } - return ea0; + return e0; } -orbital_state orbital_elements_to_state(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations) +double3 orbital_elements_to_ecliptic(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations) { - orbital_state state; - // Calculate semi-minor axis, b - double b = std::sqrt(1.0 - elements.ec * elements.ec); + double b = elements.a * std::sqrt(1.0 - elements.ec * elements.ec); // Solve Kepler's equation for eccentric anomaly, E double ea = solve_kepler(elements.ec, elements.ma, ke_tolerance, ke_iterations); - // Calculate radial distance (r) and true anomaly (v) - double x = elements.a * (std::cos(ea) - elements.ec); - double y = b * std::sin(ea); - double r = std::sqrt(x * x + y * y); - double v = std::atan2(y, x); + // Calculate radial distance, r; and true anomaly, v + double xv = elements.a * (std::cos(ea) - elements.ec); + double yv = b * std::sin(ea); + double r = std::sqrt(xv * xv + yv * yv); + double v = std::atan2(yv, xv); - // Convert (r, v) to ecliptic rectangular coordinates + // Calculate true longitude, l + double l = elements.w + v; + + // Transform vector (r, 0, 0) from local coordinates to ecliptic coordinates + // = Rz(-omega) * Rx(-i) * Rz(-l) * r double cos_om = std::cos(elements.om); double sin_om = std::sin(elements.om); double cos_i = std::cos(elements.i); - double cos_wv = std::cos(elements.w + v); - double sin_wv = std::sin(elements.w + v); - state.r = + double cos_l = std::cos(l); + double sin_l = std::sin(l); + return double3 { - r * (cos_om * cos_wv - sin_om * sin_wv * cos_i), - r * (sin_om * cos_wv + cos_om * sin_wv * cos_i), - r * sin_wv * std::sin(elements.i) + r * (cos_om * cos_l - sin_om * sin_l * cos_i), + r * (sin_om * cos_l + cos_om * sin_l * cos_i), + r * sin_l * std::sin(elements.i) }; - - return state; } } // namespace ast diff --git a/src/game/astronomy/celestial-mechanics.hpp b/src/game/astronomy/celestial-mechanics.hpp index fb7f656..efa0ed8 100644 --- a/src/game/astronomy/celestial-mechanics.hpp +++ b/src/game/astronomy/celestial-mechanics.hpp @@ -91,17 +91,16 @@ double3x3 approx_moon_ecliptic_rotation(double jd); double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations); /** - * Calculates orbital state vectors from Keplerian orbital elements. + * Calculates the ecliptic rectangular orbital position from Keplerian orbital elements. * - * @note Only works for elliptic orbits. - * @todo Calculate orbital state velocity. + * @note Only works for elliptical orbits. * * @param elements Orbital elements. * @param ke_tolerance Kepler's equation tolerance. * @param ke_iterations Kepler's equation iterations. * @return Orbital state. */ -orbital_state orbital_elements_to_state(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations); +double3 orbital_elements_to_ecliptic(const orbital_elements& elements, double ke_tolerance, std::size_t ke_iterations); } // namespace ast diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 02abb3e..725b5e6 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -79,7 +79,7 @@ #include "game/systems/tracking-system.hpp" #include "game/systems/painting-system.hpp" #include "game/systems/weather-system.hpp" -#include "game/systems/solar-system.hpp" +#include "game/systems/astronomy-system.hpp" #include "game/components/marker-component.hpp" #include "game/entity-commands.hpp" #include "utility/paths.hpp" @@ -888,7 +888,7 @@ void setup_systems(game_context* ctx) ctx->weather_system->set_material_pass(ctx->overworld_material_pass); // Setup solar system - ctx->solar_system = new solar_system(*ctx->ecs_registry); + ctx->astronomy_system = new astronomy_system(*ctx->ecs_registry); // Set time scale float time_scale = 60.0f; @@ -897,7 +897,7 @@ void setup_systems(game_context* ctx) time_scale = ctx->config->get("time_scale"); } ctx->weather_system->set_time_scale(time_scale); - ctx->solar_system->set_time_scale(time_scale); + ctx->astronomy_system->set_time_scale(time_scale); // Setup render system ctx->render_system = new ::render_system(*ctx->ecs_registry); @@ -1196,7 +1196,7 @@ void setup_controls(game_context* ctx) [ctx, time_scale]() { ctx->weather_system->set_time_scale(time_scale * 50.0f); - ctx->solar_system->set_time_scale(time_scale * 50.0f); + ctx->astronomy_system->set_time_scale(time_scale * 50.0f); } ); ctx->control_system->get_fast_forward_control()->set_deactivated_callback @@ -1204,7 +1204,7 @@ void setup_controls(game_context* ctx) [ctx, time_scale]() { ctx->weather_system->set_time_scale(time_scale); - ctx->solar_system->set_time_scale(time_scale); + ctx->astronomy_system->set_time_scale(time_scale); } ); ctx->control_system->get_rewind_control()->set_activated_callback @@ -1212,7 +1212,7 @@ void setup_controls(game_context* ctx) [ctx, time_scale]() { ctx->weather_system->set_time_scale(time_scale * -50.0f); - ctx->solar_system->set_time_scale(time_scale * -50.0f); + ctx->astronomy_system->set_time_scale(time_scale * -50.0f); } ); ctx->control_system->get_rewind_control()->set_deactivated_callback @@ -1220,7 +1220,7 @@ void setup_controls(game_context* ctx) [ctx, time_scale]() { ctx->weather_system->set_time_scale(time_scale); - ctx->solar_system->set_time_scale(time_scale); + ctx->astronomy_system->set_time_scale(time_scale); } ); @@ -1281,7 +1281,7 @@ void setup_callbacks(game_context* ctx) ctx->tracking_system->update(t, dt); ctx->painting_system->update(t, dt); ctx->weather_system->update(t, dt); - ctx->solar_system->update(t, dt); + ctx->astronomy_system->update(t, dt); //(*ctx->focal_point_tween)[1] = ctx->orbit_cam->get_focal_point(); diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp index 71162dd..9b8c997 100644 --- a/src/game/game-context.hpp +++ b/src/game/game-context.hpp @@ -87,7 +87,7 @@ class outline_pass; class tracking_system; class painting_system; class weather_system; -class solar_system; +class astronomy_system; struct biome; template class animation; template class material_property; @@ -245,7 +245,7 @@ struct game_context tracking_system* tracking_system; painting_system* painting_system; weather_system* weather_system; - solar_system* solar_system; + astronomy_system* astronomy_system; // Game biome* biome; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index b1b7370..f70302a 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -32,6 +32,7 @@ #include "game/components/tool-component.hpp" #include "game/components/transform-component.hpp" #include "game/components/camera-follow-component.hpp" +#include "game/components/orbit-component.hpp" #include "game/entity-commands.hpp" #include "game/game-context.hpp" #include "game/states/game-states.hpp" @@ -55,11 +56,12 @@ #include "game/systems/render-system.hpp" #include "game/systems/tool-system.hpp" #include "game/systems/weather-system.hpp" -#include "game/systems/solar-system.hpp" +#include "game/systems/astronomy-system.hpp" #include "game/biome.hpp" #include "utility/fundamental-types.hpp" #include "utility/gamma.hpp" #include "game/astronomy/celestial-time.hpp" +#include void play_state_enter(game_context* ctx) { @@ -83,19 +85,77 @@ void play_state_enter(game_context* ctx) sky_pass->set_moon_model(ctx->resource_manager->load("moon.mdl")); ctx->weather_system->set_location(ctx->biome->location[0], ctx->biome->location[1], ctx->biome->location[2]); - ctx->weather_system->set_time(2017, 6, 1, 5, 0, 0.0, -5.0); + ctx->weather_system->set_time(2000, 1, 1, 12, 0, 0.0, 0.0); + ctx->weather_system->set_time(0.0); ctx->weather_system->set_sky_palette(ctx->biome->sky_palette); ctx->weather_system->set_sun_palette(ctx->biome->sun_palette); ctx->weather_system->set_ambient_palette(ctx->biome->ambient_palette); ctx->weather_system->set_moon_palette(ctx->biome->moon_palette); ctx->weather_system->set_shadow_palette(ctx->biome->shadow_palette); - ctx->solar_system->set_observer_location(ctx->biome->location[0], ctx->biome->location[1], ctx->biome->location[2]); - double jd = ast::ut_to_jd(2017, 6, 1, 5, 0, 0.0) - -5.0 / 24.0; - ctx->solar_system->set_julian_date(jd); + ctx->astronomy_system->set_observer_location(double3{4.26352e-5, ctx->biome->location[0], ctx->biome->location[1]}); + ctx->astronomy_system->set_universal_time(0.0); + ctx->astronomy_system->set_obliquity(math::radians(23.4393)); + ctx->astronomy_system->set_axial_rotation_at_epoch(math::radians(280.4606)); + ctx->astronomy_system->set_axial_rotation_speed(math::radians(360.9856)); resource_manager* resource_manager = ctx->resource_manager; entt::registry& ecs_registry = *ctx->ecs_registry; + + + // Create sun + { + ecs::orbit_component sun_orbit; + sun_orbit.a = 1.0; + sun_orbit.ec = 0.016709; + sun_orbit.w = math::radians(282.9404); + sun_orbit.ma = math::radians(356.0470); + sun_orbit.i = 0.0; + sun_orbit.om = 0.0; + + sun_orbit.d_a = 0.0; + sun_orbit.d_ec = -1.151e-9; + sun_orbit.d_w = math::radians(4.70935e-5); + sun_orbit.d_ma = math::radians(0.9856002585); + sun_orbit.d_i = 0.0; + sun_orbit.d_om = 0.0; + + ecs::transform_component sun_transform; + sun_transform.local = math::identity_transform; + sun_transform.warp = true; + + auto sun_entity = ecs_registry.create(); + ecs_registry.assign(sun_entity, sun_transform); + ecs_registry.assign(sun_entity, sun_orbit); + } + + // Create moon + { + + ecs::orbit_component moon_orbit; + + moon_orbit.a = 0.00256955529; + moon_orbit.ec = 0.0554; + moon_orbit.w = math::radians(318.15); + moon_orbit.ma = math::radians(135.27); + moon_orbit.i = math::radians(5.16); + moon_orbit.om = math::radians(125.08); + + moon_orbit.d_a = 0.0; + moon_orbit.d_ec = 0.0; + moon_orbit.d_w = math::radians(0.1643573223); + moon_orbit.d_ma = math::radians(13.176358); + moon_orbit.d_i = 0.0; + moon_orbit.d_om = math::radians(-0.0529538083); + + ecs::transform_component moon_transform; + moon_transform.local = math::identity_transform; + moon_transform.warp = true; + + auto moon_entity = ecs_registry.create(); + ecs_registry.assign(moon_entity, moon_transform); + ecs_registry.assign(moon_entity, moon_orbit); + } // Load entity archetypes ecs::archetype* ant_hill_archetype = resource_manager->load("ant-hill.ent"); diff --git a/src/game/systems/astronomy-system.cpp b/src/game/systems/astronomy-system.cpp new file mode 100644 index 0000000..5d75c2b --- /dev/null +++ b/src/game/systems/astronomy-system.cpp @@ -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 . + */ + +#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().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, 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(translation); + transform.local.rotation = math::type_cast(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(axial_rotation_at_epoch + universal_time * axial_rotation_speed); + update_sidereal_time(); +} + +void astronomy_system::update_sidereal_time() +{ + lst = math::wrap_radians(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); +} diff --git a/src/game/systems/astronomy-system.hpp b/src/game/systems/astronomy-system.hpp new file mode 100644 index 0000000..88b3bf2 --- /dev/null +++ b/src/game/systems/astronomy-system.hpp @@ -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 . + */ + +#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 diff --git a/src/game/systems/solar-system.cpp b/src/game/systems/solar-system.cpp deleted file mode 100644 index b9463ae..0000000 --- a/src/game/systems/solar-system.cpp +++ /dev/null @@ -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 . - */ - -#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 - -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, 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().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(translation); - transform.local.rotation = math::type_cast(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); -} diff --git a/src/game/systems/solar-system.hpp b/src/game/systems/solar-system.hpp deleted file mode 100644 index e599664..0000000 --- a/src/game/systems/solar-system.hpp +++ /dev/null @@ -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 . - */ - -#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 diff --git a/src/game/systems/weather-system.cpp b/src/game/systems/weather-system.cpp index 07a6104..69838fd 100644 --- a/src/game/systems/weather-system.cpp +++ b/src/game/systems/weather-system.cpp @@ -29,7 +29,6 @@ #include "game/astronomy/celestial-mechanics.hpp" #include "game/astronomy/celestial-time.hpp" #include -#include static constexpr double hours_per_day = 24.0; static constexpr double minutes_per_day = hours_per_day * 60.0; @@ -75,6 +74,7 @@ void weather_system::update(double t, double dt) float2 sun_az_el = {static_cast(sun_spherical.z) - math::pi, static_cast(sun_spherical.y)}; float3 sun_position = math::normalize(float3{static_cast(sun_positiond.x), static_cast(sun_positiond.y), static_cast(sun_positiond.z)}); + double3 moon_ecliptic = ast::approx_moon_ecliptic(jd); double3 moon_horizontal = ecliptic_to_horizontal * moon_ecliptic; moon_horizontal.z -= 1.0; // Subtract one earth radius, for position of observer @@ -221,6 +221,11 @@ void weather_system::set_time(int year, int month, int day, int hour, int minute jd = ast::ut_to_jd(year, month, day, hour, minute, second) - tc / 24.0; } +void weather_system::set_time(double time) +{ + jd = time + 2451545.0; +} + void weather_system::set_time_scale(float scale) { time_scale = scale; diff --git a/src/game/systems/weather-system.hpp b/src/game/systems/weather-system.hpp index d352389..c9bffaf 100644 --- a/src/game/systems/weather-system.hpp +++ b/src/game/systems/weather-system.hpp @@ -54,6 +54,7 @@ public: /// @param tc Timezone correction, in hours void set_time(int year, int month, int day, int hour, int minute, double second, double tc); + void set_time(double time); void set_time_scale(float scale); void set_sky_palette(const ::image* image);