Browse Source

Add solar system

master
C. J. Howard 4 years ago
parent
commit
e16de75386
23 changed files with 471 additions and 748 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +1
    -1
      src/game/astronomy/apparent-size.cpp
  3. +2
    -2
      src/game/astronomy/apparent-size.hpp
  4. +12
    -12
      src/game/astronomy/celestial-coordinates.cpp
  5. +8
    -8
      src/game/astronomy/celestial-coordinates.hpp
  6. +0
    -105
      src/game/astronomy/celestial-mechanics.cpp
  7. +0
    -32
      src/game/astronomy/celestial-mechanics.hpp
  8. +0
    -62
      src/game/astronomy/celestial-time.cpp
  9. +0
    -66
      src/game/astronomy/celestial-time.hpp
  10. +11
    -3
      src/game/bootloader.cpp
  11. +1
    -0
      src/game/cartography/relief-map.cpp
  12. +55
    -0
      src/game/components/celestial-body-component.hpp
  13. +3
    -18
      src/game/components/orbit-component.hpp
  14. +2
    -0
      src/game/game-context.hpp
  15. +55
    -0
      src/game/states/map-state.cpp
  16. +96
    -33
      src/game/states/play-state.cpp
  17. +42
    -26
      src/game/systems/astronomy-system.cpp
  18. +21
    -12
      src/game/systems/astronomy-system.hpp
  19. +68
    -0
      src/game/systems/solar-system.cpp
  20. +64
    -0
      src/game/systems/solar-system.hpp
  21. +5
    -95
      src/game/systems/terrain-system.cpp
  22. +10
    -247
      src/game/systems/weather-system.cpp
  23. +14
    -26
      src/game/systems/weather-system.hpp

+ 1
- 0
CMakeLists.txt View File

@ -14,6 +14,7 @@ find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG)
find_package(OpenAL REQUIRED CONFIG) find_package(OpenAL REQUIRED CONFIG)
find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib") find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib")
# Determine dependencies # Determine dependencies
set(STATIC_LIBS set(STATIC_LIBS
dr_wav dr_wav

+ 1
- 1
src/game/astronomy/apparent-size.cpp View File

@ -23,7 +23,7 @@
namespace ast namespace ast
{ {
double angular_radius(double radius, double distance)
double find_angular_radius(double radius, double distance)
{ {
return std::asin(radius / distance); return std::asin(radius / distance);
} }

+ 2
- 2
src/game/astronomy/apparent-size.hpp View File

@ -24,13 +24,13 @@ namespace ast
{ {
/** /**
* Calculates the angular radius of a celestial object.
* Finds the angular radius of a celestial object, given its radius and distance.
* *
* @param radius Radius of the celestial object. * @param radius Radius of the celestial object.
* @param distance Distance to the celestial object. * @param distance Distance to the celestial object.
* @return Angular radius, in radians. * @return Angular radius, in radians.
*/ */
double angular_radius(double radius, double distance);
double find_angular_radius(double radius, double distance);
} // namespace ast } // namespace ast

+ 12
- 12
src/game/astronomy/celestial-coordinates.cpp View File

@ -58,14 +58,14 @@ double3x3 ecliptic_to_equatorial(double ecl)
}; };
} }
double3x3 ecliptic_to_horizontal(double ecl, double lat, double lmst)
double3x3 ecliptic_to_horizontal(double ecl, double lat, double lst)
{ {
const double c_ecl = std::cos(ecl); const double c_ecl = std::cos(ecl);
const double s_ecl = std::sin(ecl); const double s_ecl = std::sin(ecl);
const double c_lat = std::cos(lat); const double c_lat = std::cos(lat);
const double s_lat = std::sin(lat); const double s_lat = std::sin(lat);
const double c_lst = std::cos(lmst);
const double s_lst = std::sin(lmst);
const double c_lst = std::cos(lst);
const double s_lst = std::sin(lst);
return double3x3 return double3x3
{ {
@ -88,12 +88,12 @@ double3x3 equatorial_to_ecliptic(double ecl)
}; };
} }
double3x3 equatorial_to_horizontal(double lat, double lmst)
double3x3 equatorial_to_horizontal(double lat, double lst)
{ {
const double c_lat = std::cos(lat); const double c_lat = std::cos(lat);
const double s_lat = std::sin(lat); const double s_lat = std::sin(lat);
const double c_lst = std::cos(lmst);
const double s_lst = std::sin(lmst);
const double c_lst = std::cos(lst);
const double s_lst = std::sin(lst);
return double3x3 return double3x3
{ {
@ -103,12 +103,12 @@ double3x3 equatorial_to_horizontal(double lat, double lmst)
}; };
} }
double3x3 horizontal_to_equatorial(double lat, double lmst)
double3x3 horizontal_to_equatorial(double lat, double lst)
{ {
const double c_lat = std::cos(lat); const double c_lat = std::cos(lat);
const double s_lat = std::sin(lat); const double s_lat = std::sin(lat);
const double c_lst = std::cos(lmst);
const double s_lst = std::sin(lmst);
const double c_lst = std::cos(lst);
const double s_lst = std::sin(lst);
return double3x3 return double3x3
{ {
@ -118,14 +118,14 @@ double3x3 horizontal_to_equatorial(double lat, double lmst)
}; };
} }
double3x3 horizontal_to_ecliptic(double ecl, double lat, double lmst)
double3x3 horizontal_to_ecliptic(double ecl, double lat, double lst)
{ {
const double c_ecl = std::cos(ecl); const double c_ecl = std::cos(ecl);
const double s_ecl = std::sin(ecl); const double s_ecl = std::sin(ecl);
const double c_lat = std::cos(lat); const double c_lat = std::cos(lat);
const double s_lat = std::sin(lat); const double s_lat = std::sin(lat);
const double c_lst = std::cos(lmst);
const double s_lst = std::sin(lmst);
const double c_lst = std::cos(lst);
const double s_lst = std::sin(lst);
return double3x3 return double3x3
{ {

+ 8
- 8
src/game/astronomy/celestial-coordinates.hpp View File

@ -54,10 +54,10 @@ double3x3 ecliptic_to_equatorial(double ecl);
* *
* @param ecl Obliquity of the ecliptic, in radians. * @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians. * @param lat Observer's latitude, in radians.
* @param lmst Local mean sidereal time.
* @param lst Local sidereal time, in radians.
* @return Transformation matrix. * @return Transformation matrix.
*/ */
double3x3 ecliptic_to_horizontal(double ecl, double lat, double lmst);
double3x3 ecliptic_to_horizontal(double ecl, double lat, double lst);
/** /**
* Produces a matrix which transforms rectangular coordinates from equatorial space to ecliptic space. * Produces a matrix which transforms rectangular coordinates from equatorial space to ecliptic space.
@ -71,29 +71,29 @@ double3x3 equatorial_to_ecliptic(double ecl);
* Produces a matrix which transforms rectangular coordinates from equatorial space to horizontal space. * Produces a matrix which transforms rectangular coordinates from equatorial space to horizontal space.
* *
* @param lat Observer's latitude, in radians. * @param lat Observer's latitude, in radians.
* @param lmst Local mean sidereal time.
* @param lst Local sidereal time, in radians.
* @return Transformation matrix. * @return Transformation matrix.
*/ */
double3x3 equatorial_to_horizontal(double lat, double lmst);
double3x3 equatorial_to_horizontal(double lat, double lst);
/** /**
* Produces a matrix which transforms rectangular coordinates from horizontal space to equatorial space. * Produces a matrix which transforms rectangular coordinates from horizontal space to equatorial space.
* *
* @param lat Observer's latitude, in radians. * @param lat Observer's latitude, in radians.
* @param lmst Local mean sidereal time.
* @param lst Local sidereal time, in radians.
* @return Transformation matrix. * @return Transformation matrix.
*/ */
double3x3 horizontal_to_equatorial(double lat, double lmst);
double3x3 horizontal_to_equatorial(double lat, double lst);
/** /**
* Produces a matrix which transforms rectangular coordinates from horizontal space to ecliptic space. * Produces a matrix which transforms rectangular coordinates from horizontal space to ecliptic space.
* *
* @param ecl Obliquity of the ecliptic, in radians. * @param ecl Obliquity of the ecliptic, in radians.
* @param lat Observer's latitude, in radians. * @param lat Observer's latitude, in radians.
* @param lmst Local mean sidereal time.
* @param lst Local sidereal time, in radians.
* @return Transformation matrix. * @return Transformation matrix.
*/ */
double3x3 horizontal_to_ecliptic(double ecl, double lat, double lmst);
double3x3 horizontal_to_ecliptic(double ecl, double lat, double lst);
/// Matrix which transforms coordinates from horizontal space to a right-handed coordinate system. /// Matrix which transforms coordinates from horizontal space to a right-handed coordinate system.
constexpr double3x3 horizontal_to_right_handed = constexpr double3x3 horizontal_to_right_handed =

+ 0
- 105
src/game/astronomy/celestial-mechanics.cpp View File

@ -24,111 +24,6 @@
namespace ast namespace ast
{ {
double approx_ecliptic_obliquity(double jd)
{
return math::radians<double>(23.4393 - 3.563e-7 * (jd - 2451545.0));
}
double3 approx_sun_ecliptic(double jd)
{
const double t = (jd - 2451545.0) / 36525.0;
const double m = 6.24 + 628.302 * t;
const double longitude = 4.895048 + 628.331951 * t + (0.033417 - 0.000084 * t) * std::sin(m) + 0.000351 * std::sin(m * 2.0);
const double latitude = 0.0;
const double distance = 1.000140 - (0.016708 - 0.000042 * t) * std::cos(m) - 0.000141 * std::cos(m * 2.0);
double3 ecliptic;
ecliptic.x = distance * std::cos(longitude) * std::cos(latitude);
ecliptic.y = distance * std::sin(longitude) * std::cos(latitude);
ecliptic.z = distance * std::sin(latitude);
return ecliptic;
}
double3 approx_moon_ecliptic(double jd)
{
const double t = (jd - 2451545.0) / 36525.0;
const double l1 = 3.8104 + 8399.7091 * t;
const double m1 = 2.3554 + 8328.6911 * t;
const double m = 6.2300 + 628.3019 * t;
const double d = 5.1985 + 7771.3772 * t;
const double d2 = d * 2.0;
const double f = 1.6280 + 8433.4663 * t;
const double longitude = l1
+ 0.1098 * std::sin(m1)
+ 0.0222 * std::sin(d2 - m1)
+ 0.0115 * std::sin(d2)
+ 0.0037 * std::sin(m1 * 2.0)
- 0.0032 * std::sin(m)
- 0.0020 * std::sin(d2)
+ 0.0010 * std::sin(d2 - m1 * 2.0)
+ 0.0010 * std::sin(d2 - m - m1)
+ 0.0009 * std::sin(d2 + m1)
+ 0.0008 * std::sin(d2 - m)
+ 0.0007 * std::sin(m1 - m)
- 0.0006 * std::sin(d)
- 0.0005 * std::sin(m + m1);
const double latitude = 0.0895 * sin(f)
+ 0.0049 * std::sin(m1 + f)
+ 0.0048 * std::sin(m1 - f)
+ 0.0030 * std::sin(d2 - f)
+ 0.0010 * std::sin(d2 + f - m1)
+ 0.0008 * std::sin(d2 - f - m1)
+ 0.0006 * std::sin(d2 + f);
const double r = 1.0 / (0.016593
+ 0.000904 * std::cos(m1)
+ 0.000166 * std::cos(d2 - m1)
+ 0.000137 * std::cos(d2)
+ 0.000049 * std::cos(m1 * 2.0)
+ 0.000015 * std::cos(d2 + m1)
+ 0.000009 * std::cos(d2 - m));
double3 ecliptic;
ecliptic.x = r * std::cos(longitude) * std::cos(latitude);
ecliptic.y = r * std::sin(longitude) * std::cos(latitude);
ecliptic.z = r * std::sin(latitude);
return ecliptic;
}
double3x3 approx_moon_ecliptic_rotation(double jd)
{
const double t = (jd - 2451545.0) / 36525.0;
const double l1 = 3.8104 + 8399.7091 * t;
const double f = 1.6280 + 8433.4663 * t;
const double az0 = f + math::pi<double>;
const double ax = 0.026920;
const double az1 = l1 - f;
double3x3 rz0 =
{
cos(az0), -sin(az0), 0,
sin(az0), cos(az0), 0,
0, 0, 1
};
double3x3 rx =
{
1, 0, 0,
0, cos(ax), -sin(ax),
0, sin(ax), cos(ax)
};
double3x3 rz1 =
{
cos(az1), -sin(az1), 0,
sin(az1), cos(az1), 0,
0, 0, 1
};
return rz0 * rx * rz1;
}
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

+ 0
- 32
src/game/astronomy/celestial-mechanics.hpp View File

@ -47,38 +47,6 @@ struct orbital_state
double3 v; ///< Cartesian velocity, v. double3 v; ///< Cartesian velocity, v.
}; };
/**
* Approximates the obliquity of the ecliptic.
*
* @param jd Julian date.
* @return Obliquity of the ecliptic, in radians.
*/
double approx_ecliptic_obliquity(double jd);
/**
* Approximates the ecliptic coordinates of the Earth's sun.
*
* @param jd Julian date.
* @return Ecliptic rectangular geocentric coordinates of the Earth's sun, with distance in AU.
*/
double3 approx_sun_ecliptic(double jd);
/**
* Approximates the ecliptic coordinates of the Earth's moon.
*
* @param jd Julian date.
* @return Ecliptic rectangular geocentric coordinates of the Earth's moon, with distance in Earth radii.
*/
double3 approx_moon_ecliptic(double jd);
/**
* Approximates the ecliptic rotation of the Earth's moon.
*
* @param jd Julian date.
* @return Rotation matrix representing the moon's rotation in ecliptic space.
*/
double3x3 approx_moon_ecliptic_rotation(double jd);
/** /**
* Iteratively solves Kepler's equation for eccentric anomaly, E. * Iteratively solves Kepler's equation for eccentric anomaly, E.
* *

+ 0
- 62
src/game/astronomy/celestial-time.cpp View File

@ -1,62 +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 "celestial-time.hpp"
#include "math/angles.hpp"
#include <cmath>
namespace ast
{
double ut_to_jd(int year, int month, int day, int hour, int minute, double second)
{
if (month < 3)
{
month += 12;
year -= 1;
}
const signed long Y = year;
const signed long M = month;
const signed long D = day;
const signed long JDN = (1461*(Y+4800+(M-14)/12))/4+(367*(M-2-12*((M-14)/12)))/12-(3*((Y+4900+(M-14)/12)/100))/4+D-32075;
const double h = static_cast<double>(hour - 12) / 24.0;
const double m = static_cast<double>(minute) / 1440.0;
const double s = second / 86400.0;
return static_cast<double>(JDN) + h + m + s;
}
double jd_to_gmst(double jd)
{
return math::wrap_radians<double>(4.894961212 + 6.300388098 * (jd - 2451545.0));
}
double jd_to_lmst(double jd, double longitude)
{
return gmst_to_lmst(jd_to_gmst(jd), longitude);
}
double gmst_to_lmst(double gmst, double longitude)
{
return gmst + longitude;
}
} // namespace ast

+ 0
- 66
src/game/astronomy/celestial-time.hpp View File

@ -1,66 +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_CELESTIAL_TIME_HPP
#define ANTKEEPER_CELESTIAL_TIME_HPP
namespace ast
{
/**
* Calculates the Julian date from a universal time.
*
* @param year Gregorian year, with 1 BC as 0.
* @param month Gregorian month, on [1, 12].
* @param day Gregorian day, on [1, 31].
* @param hour Hour, on [0, 23].
* @param minute Minute, on [0, 59].
* @param second Second on [0, 60).
* @return Julian date with fractional day.
*/
double ut_to_jd(int year, int month, int day, int hour, int minute, double second);
/**
* Calculates the Greenwich mean sidereal time (GMST) from a Julian date.
*
* @param jd Julian date.
* @return GMST, in radians.
*/
double jd_to_gmst(double jd);
/**
* Calculates local mean sidereal time (LMST) from a Julian date.
*
* @param jd Julian date.
* @param longitude Longitude of the observer, in radians.
*/
double jd_to_lmst(double jd, double longitude);
/**
* Calculates local mean sidereal time (LMST) from Greenwich mean sidereal time (GMST).
*
* @param gmst Greenwich mean sidereal time, in radians.
* @param longitude Longitude of the observer, in radians.
* @return Local mean sidereal time, in radians.
*/
double gmst_to_lmst(double gmst, double longitude);
} // namespace ast
#endif // ANTKEEPER_CELESTIAL_TIME_HPP

+ 11
- 3
src/game/bootloader.cpp View File

@ -80,6 +80,7 @@
#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/astronomy-system.hpp" #include "game/systems/astronomy-system.hpp"
#include "game/systems/solar-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"
@ -880,15 +881,16 @@ void setup_systems(game_context* ctx)
// Setup weather system // Setup weather system
ctx->weather_system = new weather_system(*ctx->ecs_registry); ctx->weather_system = new weather_system(*ctx->ecs_registry);
ctx->weather_system->set_ambient_light(ctx->sun_indirect);
ctx->weather_system->set_sun_light(ctx->sun_direct);
ctx->weather_system->set_moon_light(ctx->moon_light);
ctx->weather_system->set_sky_pass(ctx->overworld_sky_pass); ctx->weather_system->set_sky_pass(ctx->overworld_sky_pass);
ctx->weather_system->set_shadow_map_pass(ctx->overworld_shadow_map_pass); ctx->weather_system->set_shadow_map_pass(ctx->overworld_shadow_map_pass);
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);
// Setup astronomy system
ctx->astronomy_system = new astronomy_system(*ctx->ecs_registry); ctx->astronomy_system = new astronomy_system(*ctx->ecs_registry);
ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass);
// Set time scale // Set time scale
float time_scale = 60.0f; float time_scale = 60.0f;
@ -897,6 +899,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); ctx->astronomy_system->set_time_scale(time_scale);
// Setup render system // Setup render system
@ -1196,6 +1199,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->astronomy_system->set_time_scale(time_scale * 50.0f);
} }
); );
@ -1204,6 +1208,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->astronomy_system->set_time_scale(time_scale);
} }
); );
@ -1212,6 +1217,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->astronomy_system->set_time_scale(time_scale * -50.0f);
} }
); );
@ -1220,6 +1226,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->astronomy_system->set_time_scale(time_scale);
} }
); );
@ -1281,6 +1288,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->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();

+ 1
- 0
src/game/cartography/relief-map.cpp View File

@ -74,6 +74,7 @@ mesh* map_elevation(const std::function& function, float sc
return edge; return edge;
}; };
// Connect vertices with edges and faces
const std::vector<mesh::vertex*>& vertices = mesh->get_vertices(); const std::vector<mesh::vertex*>& vertices = mesh->get_vertices();
for (std::size_t i = 0; i < rows; ++i) for (std::size_t i = 0; i < rows; ++i)
{ {

+ 55
- 0
src/game/components/celestial-body-component.hpp View File

@ -0,0 +1,55 @@
/*
* 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_ECS_CELESTIAL_BODY_COMPONENT_HPP
#define ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP
#include "game/astronomy/celestial-mechanics.hpp"
#include "utility/fundamental-types.hpp"
#include "math/quaternion-type.hpp"
namespace ecs {
struct celestial_body_component
{
ast::orbital_elements orbital_elements;
ast::orbital_elements orbital_rate;
ast::orbital_state orbital_state;
double3 position;
double3 velocity;
double3 acceleration;
double mass;
double radius;
math::quaternion<double> orientation;
};
struct blackbody_radiator
{
double temperature;
};
struct diffuse_reflector
{
double albedo;
};
} // namespace ecs
#endif // ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP

+ 3
- 18
src/game/components/orbit-component.hpp View File

@ -26,26 +26,11 @@ namespace ecs {
struct orbit_component struct orbit_component
{ {
double a; ///< Semi-major axis, a
double d_a;
double ec; ///< Eccentricity, e
double d_ec;
double w; ///< Argument of periapsis, w (radians)
double d_w;
double ma; ///< Mean anomaly, M (radians)
double d_ma;
double i; ///< Inclination, i (radians)
double d_i;
double om; ///< Longitude of the ascending node, OMEGA (radians)
double d_om;
ast::orbital_elements elements;
ast::orbital_elements rate;
ast::orbital_state state;
}; };
} // namespace ecs } // namespace ecs
#endif // ANTKEEPER_ECS_ORBIT_COMPONENT_HPP #endif // ANTKEEPER_ECS_ORBIT_COMPONENT_HPP

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

@ -88,6 +88,7 @@ class tracking_system;
class painting_system; class painting_system;
class weather_system; class weather_system;
class astronomy_system; class astronomy_system;
class solar_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;
@ -246,6 +247,7 @@ struct game_context
painting_system* painting_system; painting_system* painting_system;
weather_system* weather_system; weather_system* weather_system;
astronomy_system* astronomy_system; astronomy_system* astronomy_system;
solar_system* solar_system;
// Game // Game
biome* biome; biome* biome;

+ 55
- 0
src/game/states/map-state.cpp View File

@ -0,0 +1,55 @@
/*
* 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 "animation/ease.hpp"
#include "animation/screen-transition.hpp"
#include "animation/timeline.hpp"
#include "application.hpp"
#include "debug/logger.hpp"
#include "game/game-context.hpp"
#include "input/input-listener.hpp"
#include "event/input-events.hpp"
#include "rasterizer/rasterizer.hpp"
#include "game/states/game-states.hpp"
#include "renderer/passes/sky-pass.hpp"
#include "scene/billboard.hpp"
#include "scene/scene.hpp"
#include <functional>
void map_state_enter(game_context* ctx)
{
logger* logger = ctx->logger;
logger->push_task("Entering map state");
// Disable sky pass
ctx->overworld_sky_pass->set_enabled(false);
// Start fade in
ctx->fade_transition->transition(1.0f, true, ease<float>::in_quad);
logger->pop_task(EXIT_SUCCESS);
}
void map_state_exit(game_context* ctx)
{
logger* logger = ctx->logger;
logger->push_task("Exiting map state");
logger->pop_task(EXIT_SUCCESS);
}

+ 96
- 33
src/game/states/play-state.cpp View File

@ -56,12 +56,18 @@
#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/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 "utility/bit-math.hpp"
#include "game/genetics/genetics.hpp"
#include <iostream> #include <iostream>
#include <bitset>
#include <ctime>
void play_state_enter(game_context* ctx) void play_state_enter(game_context* ctx)
{ {
@ -84,14 +90,9 @@ void play_state_enter(game_context* ctx)
sky_pass->set_sky_model(ctx->resource_manager->load<model>("sky-dome.mdl")); sky_pass->set_sky_model(ctx->resource_manager->load<model>("sky-dome.mdl"));
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_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->weather_system->set_universal_time(0.0);
ctx->solar_system->set_universal_time(0.0);
ctx->astronomy_system->set_observer_location(double3{4.26352e-5, ctx->biome->location[0], ctx->biome->location[1]}); 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_universal_time(0.0);
@ -102,23 +103,26 @@ void play_state_enter(game_context* ctx)
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;
ctx->sun_direct->set_intensity(1.0f);
ctx->sun_direct->set_color({1, 1, 1});
// Create sun // Create sun
{ {
ecs::orbit_component sun_orbit; 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.elements.a = 1.0;
sun_orbit.elements.ec = 0.016709;
sun_orbit.elements.w = math::radians(282.9404);
sun_orbit.elements.ma = math::radians(356.0470);
sun_orbit.elements.i = 0.0;
sun_orbit.elements.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;
sun_orbit.rate.a = 0.0;
sun_orbit.rate.ec = -1.151e-9;
sun_orbit.rate.w = math::radians(4.70935e-5);
sun_orbit.rate.ma = math::radians(0.9856002585);
sun_orbit.rate.i = 0.0;
sun_orbit.rate.om = 0.0;
ecs::transform_component sun_transform; ecs::transform_component sun_transform;
sun_transform.local = math::identity_transform<float>; sun_transform.local = math::identity_transform<float>;
@ -127,6 +131,8 @@ void play_state_enter(game_context* ctx)
auto sun_entity = ecs_registry.create(); auto sun_entity = ecs_registry.create();
ecs_registry.assign<ecs::transform_component>(sun_entity, sun_transform); ecs_registry.assign<ecs::transform_component>(sun_entity, sun_transform);
ecs_registry.assign<ecs::orbit_component>(sun_entity, sun_orbit); ecs_registry.assign<ecs::orbit_component>(sun_entity, sun_orbit);
ctx->astronomy_system->set_sun(sun_entity);
} }
// Create moon // Create moon
@ -134,19 +140,19 @@ void play_state_enter(game_context* ctx)
ecs::orbit_component moon_orbit; 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.elements.a = 0.00256955529;
moon_orbit.elements.ec = 0.0554;
moon_orbit.elements.w = math::radians(318.15);
moon_orbit.elements.ma = math::radians(135.27);
moon_orbit.elements.i = math::radians(5.16);
moon_orbit.elements.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);
moon_orbit.rate.a = 0.0;
moon_orbit.rate.ec = 0.0;
moon_orbit.rate.w = math::radians(0.1643573223); // Argument of periapsis precession period, P_w
moon_orbit.rate.ma = math::radians(13.176358); // Longitude rate, n
moon_orbit.rate.i = 0.0;
moon_orbit.rate.om = math::radians(-18.6 / 365.2422); // Longitude of the ascending node precession period, P_node
ecs::transform_component moon_transform; ecs::transform_component moon_transform;
moon_transform.local = math::identity_transform<float>; moon_transform.local = math::identity_transform<float>;
@ -155,6 +161,8 @@ void play_state_enter(game_context* ctx)
auto moon_entity = ecs_registry.create(); auto moon_entity = ecs_registry.create();
ecs_registry.assign<ecs::transform_component>(moon_entity, moon_transform); ecs_registry.assign<ecs::transform_component>(moon_entity, moon_transform);
ecs_registry.assign<ecs::orbit_component>(moon_entity, moon_orbit); ecs_registry.assign<ecs::orbit_component>(moon_entity, moon_orbit);
ctx->astronomy_system->set_moon(moon_entity);
} }
// Load entity archetypes // Load entity archetypes
@ -395,6 +403,61 @@ void play_state_enter(game_context* ctx)
std::string biome_name = (*ctx->strings)[ctx->biome->name]; std::string biome_name = (*ctx->strings)[ctx->biome->name];
logger->log("Entered biome \"" + biome_name + "\""); logger->log("Entered biome \"" + biome_name + "\"");
std::srand(std::time(nullptr));
//auto rng = [](){ return std::rand(); };
std::random_device rd;
std::mt19937 rng(rd());
std::string sequence_a = "CCTTGCCCTTTGGGTCGCCCCCCTAG";
std::string sequence_b = "ATGTTTCCCGAAGGGTAG";
std::string sequence_c = "AAATGCCCCCCCCCCCCCCCCCCCCCCCCCCCTAGAAAAAAAAA";
std::string orf_a;
std::string protein_a;
std::string protein_b;
std::string protein_c;
std::cout << "sequence a: " << sequence_a << std::endl;
genetics::sequence::transcribe(sequence_a.begin(), sequence_a.end(), sequence_a.begin());
std::cout << "sequence a: " << sequence_a << std::endl;
std::string complement;
genetics::sequence::rna::complement(sequence_a.begin(), sequence_a.end(), std::back_inserter(complement));
std::cout << "complement: " << complement << std::endl;
auto orf = genetics::sequence::find_orf(sequence_a.begin(), sequence_a.end(), genetics::standard_code);
if (orf.start != sequence_a.end())
{
std::copy(orf.start, orf.stop, std::back_inserter(orf_a));
std::cout << "orf a: " << orf_a << std::endl;
genetics::sequence::translate(orf.start, orf.stop, std::back_inserter(protein_a), genetics::standard_code);
std::cout << "protein a: " << protein_a << std::endl;
}
protein_b = "MFFFFP";
protein_c = "MFFFYP";
int score;
std::cout << std::endl;
std::cout << "protein_b: " << protein_b << std::endl;
std::cout << "protein_c: " << protein_c << std::endl;
score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62<int>);
std::cout << "score blosum62: " << score << std::endl;
score = genetics::protein::score(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80<int>);
std::cout << "score blosum80: " << score << std::endl;
std::cout << "identity : " << genetics::protein::identity<float>(protein_b.begin(), protein_b.end(), protein_c.begin()) << std::endl;
std::cout << "similarity62: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62<int>) << std::endl;
std::cout << "similarity80: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80<int>) << std::endl;
} }
void play_state_exit(game_context* ctx) void play_state_exit(game_context* ctx)

+ 42
- 26
src/game/systems/astronomy-system.cpp View File

@ -19,11 +19,10 @@
#include "game/systems/astronomy-system.hpp" #include "game/systems/astronomy-system.hpp"
#include "game/astronomy/celestial-coordinates.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/astronomy/apparent-size.hpp"
#include "game/components/celestial-body-component.hpp"
#include "game/components/transform-component.hpp" #include "game/components/transform-component.hpp"
#include "renderer/passes/sky-pass.hpp"
using namespace ecs; using namespace ecs;
@ -36,49 +35,51 @@ astronomy_system::astronomy_system(entt::registry& registry):
observer_location{0.0, 0.0, 0.0}, observer_location{0.0, 0.0, 0.0},
lst(0.0), lst(0.0),
obliquity(0.0), obliquity(0.0),
ke_tolerance(1e-6),
ke_iterations(10)
sky_pass(nullptr),
sun(entt::null),
moon(entt::null)
{} {}
void astronomy_system::update(double t, double dt) void astronomy_system::update(double t, double dt)
{ {
const double dt_days = dt * days_per_timestep;
// Add scaled timestep to current time // Add scaled timestep to current time
set_universal_time(universal_time + dt_days);
set_universal_time(universal_time + dt * days_per_timestep);
// Update horizontal (topocentric) positions of orbiting bodies
registry.view<orbit_component, transform_component>().each(
[&](auto entity, auto& orbit, auto& transform)
// Update horizontal (topocentric) positions of intrasolar celestial bodies
registry.view<celestial_body_component, transform_component>().each(
[&](auto entity, auto& body, 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 // Transform orbital position from ecliptic space to horizontal space
double3 horizontal = ecliptic_to_horizontal * ecliptic;
double3 horizontal = ecliptic_to_horizontal * body.orbital_state.r;
// Subtract observer's radial distance (planet radius + observer's altitude) // Subtract observer's radial distance (planet radius + observer's altitude)
horizontal.z -= observer_location[0]; horizontal.z -= observer_location[0];
// Calculate azimuth and elevation
// Convert rectangular horizontal coordinates to spherical
double3 spherical = ast::rectangular_to_spherical(horizontal); double3 spherical = ast::rectangular_to_spherical(horizontal);
double2 az_el = {spherical.z - math::pi<double>, spherical.y};
spherical.z -= math::pi<double>;
// Find angular radius
double angular_radius = ast::find_angular_radius(body.radius, spherical.x);
// Transform into local right-handed coordinates // Transform into local right-handed coordinates
double3 translation = ast::horizontal_to_right_handed * horizontal; double3 translation = ast::horizontal_to_right_handed * horizontal;
double3x3 rotation = ast::horizontal_to_right_handed * ecliptic_to_horizontal; double3x3 rotation = ast::horizontal_to_right_handed * ecliptic_to_horizontal;
// Set local transform of transform component
transform.local.translation = math::type_cast<float>(translation); transform.local.translation = math::type_cast<float>(translation);
transform.local.rotation = math::type_cast<float>(math::quaternion_cast(rotation)); transform.local.rotation = math::type_cast<float>(math::quaternion_cast(rotation));
transform.local.scale = math::type_cast<float>(double3{body.radius, body.radius, body.radius});
}); });
if (sky_pass)
{
sky_pass->set_horizon_color({0, 0, 0});
sky_pass->set_zenith_color({1, 1, 1});
sky_pass->set_time_of_day(static_cast<float>(universal_time * 60.0 * 60.0));
//sky_pass->set_observer_location(location[0], location[1], location[2]);
sky_pass->set_julian_day(static_cast<float>(universal_time));
}
} }
void astronomy_system::set_universal_time(double time) void astronomy_system::set_universal_time(double time)
@ -115,6 +116,21 @@ void astronomy_system::set_axial_rotation_at_epoch(double angle)
update_axial_rotation(); update_axial_rotation();
} }
void astronomy_system::set_sky_pass(::sky_pass* pass)
{
this->sky_pass = pass;
}
void astronomy_system::set_sun(entt::entity entity)
{
sun = entity;
}
void astronomy_system::set_moon(entt::entity entity)
{
moon = entity;
}
void astronomy_system::update_axial_rotation() void astronomy_system::update_axial_rotation()
{ {
axial_rotation = math::wrap_radians<double>(axial_rotation_at_epoch + universal_time * axial_rotation_speed); axial_rotation = math::wrap_radians<double>(axial_rotation_at_epoch + universal_time * axial_rotation_speed);

+ 21
- 12
src/game/systems/astronomy-system.hpp View File

@ -23,8 +23,10 @@
#include "entity-system.hpp" #include "entity-system.hpp"
#include "utility/fundamental-types.hpp" #include "utility/fundamental-types.hpp"
class sky_pass;
/** /**
*
* Calculates apparent properties of celestial bodies relative to an observer (magnitude, angular radius, horizontal coordinates) and modifies their model component and/or light component to render them accordingly.
*/ */
class astronomy_system: class astronomy_system:
public entity_system public entity_system
@ -33,7 +35,7 @@ public:
astronomy_system(entt::registry& registry); astronomy_system(entt::registry& registry);
/** /**
* Scales then adds the timestep `dt` to the current Julian date, then recalculates the positions of celestial bodies.
* Scales then adds the timestep `dt` to the current time, then recalculates the positions of celestial bodies.
* *
* @param t Time, in seconds. * @param t Time, in seconds.
* @param dt Delta time, in seconds. * @param dt Delta time, in seconds.
@ -48,7 +50,7 @@ public:
void set_universal_time(double time); 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.
* Sets the factor by which the timestep `dt` will be scaled before being added to the current universal time.
* *
* @param scale Factor by which to scale the timestep. * @param scale Factor by which to scale the timestep.
*/ */
@ -61,6 +63,13 @@ public:
*/ */
void set_observer_location(const double3& location); void set_observer_location(const double3& location);
/**
* 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);
/** /**
* Sets the rotational speed of the observer's planet. * Sets the rotational speed of the observer's planet.
* *
@ -70,12 +79,10 @@ public:
void set_axial_rotation_at_epoch(double angle); 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);
void set_sky_pass(::sky_pass* pass);
void set_sun(entt::entity entity);
void set_moon(entt::entity entity);
private: private:
/// Updates the axial rotation angle /// Updates the axial rotation angle
@ -88,16 +95,18 @@ private:
void update_ecliptic_to_horizontal(); void update_ecliptic_to_horizontal();
double universal_time; double universal_time;
double days_per_timestep;
double lst; double lst;
double axial_rotation_at_epoch; double axial_rotation_at_epoch;
double axial_rotation_speed; double axial_rotation_speed;
double axial_rotation; double axial_rotation;
double days_per_timestep;
double3 observer_location; double3 observer_location;
double obliquity; double obliquity;
double3x3 ecliptic_to_horizontal; double3x3 ecliptic_to_horizontal;
double ke_tolerance;
std::size_t ke_iterations;
sky_pass* sky_pass;
entt::entity sun;
entt::entity moon;
}; };
#endif // ANTKEEPER_ASTRONOMY_SYSTEM_HPP #endif // ANTKEEPER_ASTRONOMY_SYSTEM_HPP

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

@ -0,0 +1,68 @@
/*
* 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/astronomical-constants.hpp"
#include "game/components/celestial-body-component.hpp"
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),
universal_time(0.0),
days_per_timestep(1.0 / seconds_per_day),
ke_tolerance(1e-6),
ke_iterations(10)
{}
void solar_system::update(double t, double dt)
{
// Add scaled timestep to current time
set_universal_time(universal_time + dt * days_per_timestep);
// Update orbital state of intrasolar celestial bodies
registry.view<celestial_body_component>().each(
[&](auto entity, auto& body)
{
ast::orbital_elements elements = body.orbital_elements;
elements.a += body.orbital_rate.a * universal_time;
elements.ec += body.orbital_rate.ec * universal_time;
elements.w += body.orbital_rate.w * universal_time;
elements.ma += body.orbital_rate.ma * universal_time;
elements.i += body.orbital_rate.i * universal_time;
elements.om += body.orbital_rate.om * universal_time;
// Calculate ecliptic orbital position
body.orbital_state.r = ast::orbital_elements_to_ecliptic(elements, ke_tolerance, ke_iterations);
});
}
void solar_system::set_universal_time(double time)
{
universal_time = time;
}
void solar_system::set_time_scale(double scale)
{
days_per_timestep = scale / seconds_per_day;
}

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

@ -0,0 +1,64 @@
/*
* 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"
/**
* Updates positions, velocities, and rotations of intrasolar celestial bodies.
*/
class solar_system:
public entity_system
{
public:
solar_system(entt::registry& registry);
/**
* Scales then adds the timestep `dt` to the current time, 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 universal time.
*
* @param scale Factor by which to scale the timestep.
*/
void set_time_scale(double scale);
private:
double universal_time;
double days_per_timestep;
double ke_tolerance;
std::size_t ke_iterations;
};
#endif // ANTKEEPER_SOLAR_SYSTEM_HPP

+ 5
- 95
src/game/systems/terrain-system.cpp View File

@ -21,6 +21,7 @@
#include "game/components/model-component.hpp" #include "game/components/model-component.hpp"
#include "game/components/collision-component.hpp" #include "game/components/collision-component.hpp"
#include "game/components/transform-component.hpp" #include "game/components/transform-component.hpp"
#include "game/cartography/relief-map.hpp"
#include "renderer/model.hpp" #include "renderer/model.hpp"
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include "geometry/mesh-functions.hpp" #include "geometry/mesh-functions.hpp"
@ -67,102 +68,12 @@ void terrain_system::set_patch_size(float size)
mesh* terrain_system::generate_terrain_mesh(float size, int subdivisions) mesh* terrain_system::generate_terrain_mesh(float size, int subdivisions)
{ {
// Allocate terrain mesh
mesh* terrain_mesh = new mesh();
// Determine vertex count and placement
int columns = static_cast<int>(std::pow(2, subdivisions));
int rows = columns;
int vertex_count = (columns + 1) * (rows + 1);
float vertex_increment = size / static_cast<float>(columns);
float radius = size * 0.5f;
// Generate mesh vertices
float3 position = {0.0f, 0.0f, -radius};
for (int i = 0; i <= rows; ++i)
auto elevation = [](float u, float v) -> float
{ {
position[0] = -radius;
for (int j = 0; j <= columns; ++j)
{
terrain_mesh->add_vertex(position);
position[0] += vertex_increment;
}
position[2] += vertex_increment;
}
// Function to eliminate duplicate edges
std::map<std::array<std::size_t, 2>, mesh::edge*> edge_map;
auto add_or_find_edge = [&](mesh::vertex* start, mesh::vertex* end) -> mesh::edge*
{
mesh::edge* edge;
if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end())
{
edge = it->second;
}
else
{
edge = terrain_mesh->add_edge(start, end);
edge_map[{start->index, end->index}] = edge;
edge_map[{end->index, start->index}] = edge->symmetric;
}
return edge;
return 0.0f;
}; };
const std::vector<mesh::vertex*>& vertices = terrain_mesh->get_vertices();
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < columns; ++j)
{
mesh::vertex* a = vertices[i * (columns + 1) + j];
mesh::vertex* b = vertices[(i + 1) * (columns + 1) + j];
mesh::vertex* c = vertices[i * (columns + 1) + j + 1];
mesh::vertex* d = vertices[(i + 1) * (columns + 1) + j + 1];
// +---+---+
// | \ | / |
// |---+---|
// | / | \ |
// +---+---+
if ((j % 2) == (i % 2))
{
mesh::edge* ab = add_or_find_edge(a, b);
mesh::edge* bd = add_or_find_edge(b, d);
mesh::edge* da = add_or_find_edge(d, a);
mesh::edge* ca = add_or_find_edge(c, a);
mesh::edge* ad = da->symmetric;
mesh::edge* dc = add_or_find_edge(d, c);
// a---c
// | \ |
// b---d
terrain_mesh->add_face({ab, bd, da});
terrain_mesh->add_face({ca, ad, dc});
}
else
{
mesh::edge* ab = add_or_find_edge(a, b);
mesh::edge* bc = add_or_find_edge(b, c);
mesh::edge* ca = add_or_find_edge(c, a);
mesh::edge* cb = bc->symmetric;
mesh::edge* bd = add_or_find_edge(b, d);
mesh::edge* dc = add_or_find_edge(d, c);
// a---c
// | / |
// b---d
terrain_mesh->add_face({ab, bc, ca});
terrain_mesh->add_face({cb, bd, dc});
}
}
}
return terrain_mesh;
return cart::map_elevation(elevation, size, subdivisions);
} }
model* terrain_system::generate_terrain_model(mesh* terrain_mesh) model* terrain_system::generate_terrain_model(mesh* terrain_mesh)
@ -385,4 +296,3 @@ void terrain_system::on_terrain_destroy(entt::registry& registry, entt::entity e
} }
*/ */
} }

+ 10
- 247
src/game/systems/weather-system.cpp View File

@ -27,284 +27,47 @@
#include "resources/image.hpp" #include "resources/image.hpp"
#include "game/astronomy/celestial-coordinates.hpp" #include "game/astronomy/celestial-coordinates.hpp"
#include "game/astronomy/celestial-mechanics.hpp" #include "game/astronomy/celestial-mechanics.hpp"
#include "game/astronomy/celestial-time.hpp"
#include <cmath> #include <cmath>
static constexpr double hours_per_day = 24.0;
static constexpr double minutes_per_day = hours_per_day * 60.0;
static constexpr double seconds_per_day = minutes_per_day * 60.0;
static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0;
weather_system::weather_system(entt::registry& registry): weather_system::weather_system(entt::registry& registry):
entity_system(registry), entity_system(registry),
ambient_light(nullptr),
sun_light(nullptr),
moon_light(nullptr),
shadow_light(nullptr),
sky_pass(nullptr), sky_pass(nullptr),
shadow_map_pass(nullptr), shadow_map_pass(nullptr),
material_pass(nullptr), material_pass(nullptr),
time_scale(1.0f),
sun_direction{0.0f, -1.0f, 0.0f},
location{0.0f, 0.0f, 0.0f},
jd(0.0)
universal_time(0.0),
days_per_timestep(1.0 / seconds_per_day)
{} {}
void weather_system::update(double t, double dt) void weather_system::update(double t, double dt)
{ {
jd += (dt * time_scale) / seconds_per_day;
const float latitude = location[0];
const float longitude = location[1];
// Calculate local time
double time_correction = longitude / (math::two_pi<double> / 24.0);
double local_jd = jd + time_correction / 24.0 - 0.5;
double local_time = (local_jd - std::floor(local_jd)) * 24.0;
double lmst = ast::jd_to_lmst(jd, longitude);
double ecl = ast::approx_ecliptic_obliquity(jd);
double3x3 ecliptic_to_horizontal = ast::ecliptic_to_horizontal(ecl, latitude, lmst);
double3 sun_ecliptic = ast::approx_sun_ecliptic(jd);
double3 sun_horizontal = ecliptic_to_horizontal * sun_ecliptic;
sun_horizontal.z -= 4.25875e-5; // Subtract one earth radius (in AU), for positon of observer
double3 sun_spherical = ast::rectangular_to_spherical(sun_horizontal);
double3 sun_positiond = ast::horizontal_to_right_handed * sun_horizontal;
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)});
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
double3 moon_spherical = ast::rectangular_to_spherical(moon_horizontal);
double3 moon_positiond = ast::horizontal_to_right_handed * moon_horizontal;
float2 moon_az_el = {static_cast<float>(moon_spherical.z) - math::pi<float>, static_cast<float>(moon_spherical.y)};
float3 moon_position = math::normalize(math::type_cast<float>(moon_positiond));
double3x3 moon_rotation_matrix = ast::horizontal_to_right_handed * ecliptic_to_horizontal;
math::quaternion<double> moon_rotationd = math::normalize(math::quaternion_cast(moon_rotation_matrix) * math::angle_axis(math::half_pi<double>, double3{0, 1, 0}) * math::angle_axis(-math::half_pi<double>, double3{0, 0, -1}));
math::quaternion<float> moon_rotation =
{
static_cast<float>(moon_rotationd.w),
static_cast<float>(moon_rotationd.x),
static_cast<float>(moon_rotationd.y),
static_cast<float>(moon_rotationd.z)
};
if (sun_light)
{
math::quaternion<float> sun_azimuth_rotation = math::angle_axis(sun_az_el[0], float3{0, 1, 0});
math::quaternion<float> sun_elevation_rotation = math::angle_axis(sun_az_el[1], float3{-1, 0, 0});
math::quaternion<float> sun_az_el_rotation = math::normalize(sun_azimuth_rotation * sun_elevation_rotation);
sun_light->set_rotation(sun_az_el_rotation);
}
if (moon_light)
{
math::quaternion<float> moon_azimuth_rotation = math::angle_axis(moon_az_el[0], float3{0, 1, 0});
math::quaternion<float> moon_elevation_rotation = math::angle_axis(moon_az_el[1], float3{-1, 0, 0});
math::quaternion<float> moon_az_el_rotation = math::normalize(moon_azimuth_rotation * moon_elevation_rotation);
moon_light->set_rotation(moon_az_el_rotation);
}
float sun_gradient_position = static_cast<float>(std::max<double>(0.0, ((sun_az_el[1] + math::half_pi<double>) / math::pi<double>)));
float moon_gradient_position = static_cast<float>(std::max<double>(0.0, ((moon_az_el[1] + math::half_pi<double>) / math::pi<double>)));
float sky_gradient_position = sun_gradient_position;
float ambient_gradient_position = sun_gradient_position;
if (sky_pass)
{
if (sun_light)
{
float3 sun_color = interpolate_gradient(sun_colors, sun_gradient_position);
sun_light->set_color(sun_color);
sun_light->set_intensity(1.0f);
}
if (moon_light)
{
float3 moon_color = interpolate_gradient(moon_colors, moon_gradient_position);
moon_light->set_color(moon_color);
moon_light->set_intensity(1.0f);
}
if (ambient_light)
{
float3 ambient_color = interpolate_gradient(ambient_colors, ambient_gradient_position);
ambient_light->set_color(ambient_color);
ambient_light->set_intensity(0.5f);
}
float3 horizon_color = interpolate_gradient(horizon_colors, sun_gradient_position);
float3 zenith_color = interpolate_gradient(zenith_colors, sun_gradient_position);
sky_pass->set_horizon_color(horizon_color);
sky_pass->set_zenith_color(zenith_color);
sky_pass->set_time_of_day(static_cast<float>(local_time * 60.0 * 60.0));
sky_pass->set_observer_location(location[0], location[1], location[2]);
sky_pass->set_sun_coordinates(sun_position, sun_az_el);
sky_pass->set_moon_coordinates(moon_position, moon_az_el);
sky_pass->set_julian_day(static_cast<float>(jd));
sky_pass->set_moon_rotation(moon_rotation);
}
shadow_light = sun_light;
if (shadow_map_pass)
{
if (sun_az_el[1] < 0.0f)
{
shadow_map_pass->set_light(moon_light);
}
else
{
shadow_map_pass->set_light(sun_light);
}
}
if (material_pass)
{
float shadow_strength = interpolate_gradient(shadow_strengths, sun_gradient_position).x;
material_pass->set_shadow_strength(shadow_strength);
}
}
void weather_system::set_location(float latitude, float longitude, float altitude)
{
location = {latitude, longitude, altitude};
}
void weather_system::set_ambient_light(::ambient_light* light)
{
ambient_light = light;
}
void weather_system::set_sun_light(directional_light* light)
{
sun_light = light;
}
void weather_system::set_moon_light(directional_light* light)
{
moon_light = light;
// Add scaled timestep to current time
set_universal_time(universal_time + dt * days_per_timestep);
} }
void weather_system::set_sky_pass(::sky_pass* pass) void weather_system::set_sky_pass(::sky_pass* pass)
{ {
sky_pass = pass; sky_pass = pass;
if (sky_pass)
{
sky_pass->set_moon_angular_radius(math::radians(1.0f));
sky_pass->set_sun_angular_radius(math::radians(1.1f));
}
} }
void weather_system::set_shadow_map_pass(::shadow_map_pass* pass) void weather_system::set_shadow_map_pass(::shadow_map_pass* pass)
{ {
shadow_map_pass = pass; shadow_map_pass = pass;
if (shadow_map_pass)
{
shadow_map_pass->set_light(shadow_light);
}
} }
void weather_system::set_material_pass(::material_pass* pass) void weather_system::set_material_pass(::material_pass* pass)
{ {
material_pass = pass; material_pass = pass;
material_pass->set_shadow_strength(0.5f);
} }
void weather_system::set_time(int year, int month, int day, int hour, int minute, double second, double tc)
{
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;
}
void weather_system::set_sky_palette(const ::image* image)
{
load_palette(&horizon_colors, image, 0);
load_palette(&zenith_colors, image, 1);
}
void weather_system::set_sun_palette(const ::image* image)
{
load_palette(&sun_colors, image, 0);
}
void weather_system::set_moon_palette(const ::image* image)
{
load_palette(&moon_colors, image, 0);
}
void weather_system::set_ambient_palette(const ::image* image)
{
load_palette(&ambient_colors, image, 0);
}
void weather_system::set_shadow_palette(const ::image* image)
{
load_palette(&shadow_strengths, image, 0);
}
void weather_system::load_palette(std::vector<float3>* palette, const ::image* image, unsigned int row)
void weather_system::set_universal_time(double time)
{ {
unsigned int w = image->get_width();
unsigned int h = image->get_height();
unsigned int c = image->get_channels();
unsigned int y = std::min<unsigned int>(row, h - 1);
palette->clear();
if (image->is_hdr())
{
const float* pixels = static_cast<const float*>(image->get_pixels());
for (unsigned int x = 0; x < w; ++x)
{
unsigned int i = y * w * c + x * c;
float r = pixels[i];
float g = pixels[i + 1];
float b = pixels[i + 2];
palette->push_back(float3{r, g, b});
}
}
else
{
const unsigned char* pixels = static_cast<const unsigned char*>(image->get_pixels());
for (unsigned int x = 0; x < w; ++x)
{
unsigned int i = y * w * c + x * c;
float r = srgb_to_linear(static_cast<float>(pixels[i]) / 255.0f);
float g = srgb_to_linear(static_cast<float>(pixels[i + 1]) / 255.0f);
float b = srgb_to_linear(static_cast<float>(pixels[i + 2]) / 255.0f);
palette->push_back(float3{r, g, b});
}
}
universal_time = time;
} }
float3 weather_system::interpolate_gradient(const std::vector<float3>& gradient, float position)
void weather_system::set_time_scale(double scale)
{ {
if (gradient.empty())
return float3{0.0f, 0.0f, 0.0f};
position *= static_cast<float>(gradient.size() - 1);
int index0 = static_cast<int>(position) % gradient.size();
int index1 = (index0 + 1) % gradient.size();
return math::lerp<float3>(gradient[index0], gradient[index1], position - std::floor(position));
days_per_timestep = scale / seconds_per_day;
} }

+ 14
- 26
src/game/systems/weather-system.hpp View File

@ -45,45 +45,33 @@ public:
*/ */
void set_location(float latitude, float longitude, float altitude); void set_location(float latitude, float longitude, float altitude);
void set_ambient_light(ambient_light* light);
void set_sun_light(directional_light* light);
void set_moon_light(directional_light* light);
void set_sky_pass(::sky_pass* pass); void set_sky_pass(::sky_pass* pass);
void set_shadow_map_pass(::shadow_map_pass* pass); void set_shadow_map_pass(::shadow_map_pass* pass);
void set_material_pass(::material_pass* pass); void set_material_pass(::material_pass* pass);
/// @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);
/**
* Sets the current universal time.
*
* @param time Universal time, in days.
*/
void set_universal_time(double time);
void set_sky_palette(const ::image* image);
void set_sun_palette(const ::image* image);
void set_moon_palette(const ::image* image);
void set_ambient_palette(const ::image* image);
void set_shadow_palette(const ::image* image);
/**
* Sets the factor by which the timestep `dt` will be scaled before being added to the current universal time.
*
* @param scale Factor by which to scale the timestep.
*/
void set_time_scale(double scale);
private: private:
static void load_palette(std::vector<float3>* palette, const ::image* image, unsigned int row); static void load_palette(std::vector<float3>* palette, const ::image* image, unsigned int row);
static float3 interpolate_gradient(const std::vector<float3>& gradient, float position); static float3 interpolate_gradient(const std::vector<float3>& gradient, float position);
double jd;
float3 location;
float time_scale;
float3 sun_direction;
ambient_light* ambient_light;
directional_light* sun_light;
directional_light* moon_light;
directional_light* shadow_light;
double universal_time;
double days_per_timestep;
sky_pass* sky_pass; sky_pass* sky_pass;
shadow_map_pass* shadow_map_pass; shadow_map_pass* shadow_map_pass;
material_pass* material_pass; material_pass* material_pass;
std::vector<float3> sun_colors;
std::vector<float3> moon_colors;
std::vector<float3> ambient_colors;
std::vector<float3> shadow_strengths;
std::vector<float3> horizon_colors;
std::vector<float3> zenith_colors;
}; };
#endif // ANTKEEPER_WEATHER_SYSTEM_HPP #endif // ANTKEEPER_WEATHER_SYSTEM_HPP

Loading…
Cancel
Save