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