Browse Source

Rename solar system -> astronomy system, improve calculations of orbital positions

master
C. J. Howard 4 years ago
parent
commit
f83f659439
13 changed files with 377 additions and 258 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +30
    -0
      src/game/astronomy/astronomical-constants.hpp
  3. +26
    -24
      src/game/astronomy/celestial-mechanics.cpp
  4. +3
    -4
      src/game/astronomy/celestial-mechanics.hpp
  5. +8
    -8
      src/game/bootloader.cpp
  6. +2
    -2
      src/game/game-context.hpp
  7. +65
    -5
      src/game/states/play-state.cpp
  8. +133
    -0
      src/game/systems/astronomy-system.cpp
  9. +103
    -0
      src/game/systems/astronomy-system.hpp
  10. +0
    -132
      src/game/systems/solar-system.cpp
  11. +0
    -81
      src/game/systems/solar-system.hpp
  12. +6
    -1
      src/game/systems/weather-system.cpp
  13. +1
    -0
      src/game/systems/weather-system.hpp

+ 0
- 1
CMakeLists.txt View File

@ -4,7 +4,6 @@ option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)
# Find dependency packages # Find dependency packages
find_package(dr_wav REQUIRED CONFIG) find_package(dr_wav REQUIRED CONFIG)
find_package(stb REQUIRED CONFIG) find_package(stb REQUIRED CONFIG)

+ 30
- 0
src/game/astronomy/astronomical-constants.hpp View File

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

+ 26
- 24
src/game/astronomy/celestial-mechanics.cpp View File

@ -132,50 +132,52 @@ double3x3 approx_moon_ecliptic_rotation(double jd)
double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations) double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations)
{ {
// Approximate eccentric anomaly, E // 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) 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; 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 // 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 // Solve Kepler's equation for eccentric anomaly, E
double ea = solve_kepler(elements.ec, elements.ma, ke_tolerance, ke_iterations); 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 cos_om = std::cos(elements.om);
double sin_om = std::sin(elements.om); double sin_om = std::sin(elements.om);
double cos_i = std::cos(elements.i); 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 } // namespace ast

+ 3
- 4
src/game/astronomy/celestial-mechanics.hpp View File

@ -91,17 +91,16 @@ double3x3 approx_moon_ecliptic_rotation(double jd);
double solve_kepler(double ec, double ma, double tolerance, std::size_t iterations); 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 elements Orbital elements.
* @param ke_tolerance Kepler's equation tolerance. * @param ke_tolerance Kepler's equation tolerance.
* @param ke_iterations Kepler's equation iterations. * @param ke_iterations Kepler's equation iterations.
* @return Orbital state. * @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 } // namespace ast

+ 8
- 8
src/game/bootloader.cpp View File

@ -79,7 +79,7 @@
#include "game/systems/tracking-system.hpp" #include "game/systems/tracking-system.hpp"
#include "game/systems/painting-system.hpp" #include "game/systems/painting-system.hpp"
#include "game/systems/weather-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/components/marker-component.hpp"
#include "game/entity-commands.hpp" #include "game/entity-commands.hpp"
#include "utility/paths.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); ctx->weather_system->set_material_pass(ctx->overworld_material_pass);
// Setup solar system // Setup solar system
ctx->solar_system = new solar_system(*ctx->ecs_registry);
ctx->astronomy_system = new astronomy_system(*ctx->ecs_registry);
// Set time scale // Set time scale
float time_scale = 60.0f; float time_scale = 60.0f;
@ -897,7 +897,7 @@ void setup_systems(game_context* ctx)
time_scale = ctx->config->get<float>("time_scale"); time_scale = ctx->config->get<float>("time_scale");
} }
ctx->weather_system->set_time_scale(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 // Setup render system
ctx->render_system = new ::render_system(*ctx->ecs_registry); ctx->render_system = new ::render_system(*ctx->ecs_registry);
@ -1196,7 +1196,7 @@ void setup_controls(game_context* ctx)
[ctx, time_scale]() [ctx, time_scale]()
{ {
ctx->weather_system->set_time_scale(time_scale * 50.0f); 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 ctx->control_system->get_fast_forward_control()->set_deactivated_callback
@ -1204,7 +1204,7 @@ void setup_controls(game_context* ctx)
[ctx, time_scale]() [ctx, time_scale]()
{ {
ctx->weather_system->set_time_scale(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 ctx->control_system->get_rewind_control()->set_activated_callback
@ -1212,7 +1212,7 @@ void setup_controls(game_context* ctx)
[ctx, time_scale]() [ctx, time_scale]()
{ {
ctx->weather_system->set_time_scale(time_scale * -50.0f); 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 ctx->control_system->get_rewind_control()->set_deactivated_callback
@ -1220,7 +1220,7 @@ void setup_controls(game_context* ctx)
[ctx, time_scale]() [ctx, time_scale]()
{ {
ctx->weather_system->set_time_scale(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->tracking_system->update(t, dt);
ctx->painting_system->update(t, dt); ctx->painting_system->update(t, dt);
ctx->weather_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(); //(*ctx->focal_point_tween)[1] = ctx->orbit_cam->get_focal_point();

+ 2
- 2
src/game/game-context.hpp View File

@ -87,7 +87,7 @@ class outline_pass;
class tracking_system; class tracking_system;
class painting_system; class painting_system;
class weather_system; class weather_system;
class solar_system;
class astronomy_system;
struct biome; struct biome;
template <typename T> class animation; template <typename T> class animation;
template <typename T> class material_property; template <typename T> class material_property;
@ -245,7 +245,7 @@ struct game_context
tracking_system* tracking_system; tracking_system* tracking_system;
painting_system* painting_system; painting_system* painting_system;
weather_system* weather_system; weather_system* weather_system;
solar_system* solar_system;
astronomy_system* astronomy_system;
// Game // Game
biome* biome; biome* biome;

+ 65
- 5
src/game/states/play-state.cpp View File

@ -32,6 +32,7 @@
#include "game/components/tool-component.hpp" #include "game/components/tool-component.hpp"
#include "game/components/transform-component.hpp" #include "game/components/transform-component.hpp"
#include "game/components/camera-follow-component.hpp" #include "game/components/camera-follow-component.hpp"
#include "game/components/orbit-component.hpp"
#include "game/entity-commands.hpp" #include "game/entity-commands.hpp"
#include "game/game-context.hpp" #include "game/game-context.hpp"
#include "game/states/game-states.hpp" #include "game/states/game-states.hpp"
@ -55,11 +56,12 @@
#include "game/systems/render-system.hpp" #include "game/systems/render-system.hpp"
#include "game/systems/tool-system.hpp" #include "game/systems/tool-system.hpp"
#include "game/systems/weather-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 "game/biome.hpp"
#include "utility/fundamental-types.hpp" #include "utility/fundamental-types.hpp"
#include "utility/gamma.hpp" #include "utility/gamma.hpp"
#include "game/astronomy/celestial-time.hpp" #include "game/astronomy/celestial-time.hpp"
#include <iostream>
void play_state_enter(game_context* ctx) 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<model>("moon.mdl")); sky_pass->set_moon_model(ctx->resource_manager->load<model>("moon.mdl"));
ctx->weather_system->set_location(ctx->biome->location[0], ctx->biome->location[1], ctx->biome->location[2]); 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_sky_palette(ctx->biome->sky_palette);
ctx->weather_system->set_sun_palette(ctx->biome->sun_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_ambient_palette(ctx->biome->ambient_palette);
ctx->weather_system->set_moon_palette(ctx->biome->moon_palette); ctx->weather_system->set_moon_palette(ctx->biome->moon_palette);
ctx->weather_system->set_shadow_palette(ctx->biome->shadow_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; resource_manager* resource_manager = ctx->resource_manager;
entt::registry& ecs_registry = *ctx->ecs_registry; 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<float>;
sun_transform.warp = true;
auto sun_entity = ecs_registry.create();
ecs_registry.assign<ecs::transform_component>(sun_entity, sun_transform);
ecs_registry.assign<ecs::orbit_component>(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<float>;
moon_transform.warp = true;
auto moon_entity = ecs_registry.create();
ecs_registry.assign<ecs::transform_component>(moon_entity, moon_transform);
ecs_registry.assign<ecs::orbit_component>(moon_entity, moon_orbit);
}
// Load entity archetypes // Load entity archetypes
ecs::archetype* ant_hill_archetype = resource_manager->load<ecs::archetype>("ant-hill.ent"); ecs::archetype* ant_hill_archetype = resource_manager->load<ecs::archetype>("ant-hill.ent");

+ 133
- 0
src/game/systems/astronomy-system.cpp View File

@ -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);
}

+ 103
- 0
src/game/systems/astronomy-system.hpp View File

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

+ 0
- 132
src/game/systems/solar-system.cpp View File

@ -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);
}

+ 0
- 81
src/game/systems/solar-system.hpp View File

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

+ 6
- 1
src/game/systems/weather-system.cpp View File

@ -29,7 +29,6 @@
#include "game/astronomy/celestial-mechanics.hpp" #include "game/astronomy/celestial-mechanics.hpp"
#include "game/astronomy/celestial-time.hpp" #include "game/astronomy/celestial-time.hpp"
#include <cmath> #include <cmath>
#include <iostream>
static constexpr double hours_per_day = 24.0; static constexpr double hours_per_day = 24.0;
static constexpr double minutes_per_day = hours_per_day * 60.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<float>(sun_spherical.z) - math::pi<float>, static_cast<float>(sun_spherical.y)}; float2 sun_az_el = {static_cast<float>(sun_spherical.z) - math::pi<float>, static_cast<float>(sun_spherical.y)};
float3 sun_position = math::normalize(float3{static_cast<float>(sun_positiond.x), static_cast<float>(sun_positiond.y), static_cast<float>(sun_positiond.z)}); float3 sun_position = math::normalize(float3{static_cast<float>(sun_positiond.x), static_cast<float>(sun_positiond.y), static_cast<float>(sun_positiond.z)});
double3 moon_ecliptic = ast::approx_moon_ecliptic(jd); double3 moon_ecliptic = ast::approx_moon_ecliptic(jd);
double3 moon_horizontal = ecliptic_to_horizontal * moon_ecliptic; double3 moon_horizontal = ecliptic_to_horizontal * moon_ecliptic;
moon_horizontal.z -= 1.0; // Subtract one earth radius, for position of observer 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; 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) void weather_system::set_time_scale(float scale)
{ {
time_scale = scale; time_scale = scale;

+ 1
- 0
src/game/systems/weather-system.hpp View File

@ -54,6 +54,7 @@ public:
/// @param tc Timezone correction, in hours /// @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(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_time_scale(float scale);
void set_sky_palette(const ::image* image); void set_sky_palette(const ::image* image);

Loading…
Cancel
Save