|
|
@ -39,6 +39,8 @@ |
|
|
|
#include "physics/light/photometry.hpp"
|
|
|
|
#include "physics/orbit/orbit.hpp"
|
|
|
|
#include "physics/orbit/ephemeris.hpp"
|
|
|
|
#include "physics/time/gregorian.hpp"
|
|
|
|
#include "physics/time/constants.hpp"
|
|
|
|
#include "render/material.hpp"
|
|
|
|
#include "render/model.hpp"
|
|
|
|
#include "render/passes/shadow-map-pass.hpp"
|
|
|
@ -55,16 +57,145 @@ |
|
|
|
namespace game { |
|
|
|
namespace world { |
|
|
|
|
|
|
|
/// Loads an ephemeris.
|
|
|
|
static void load_ephemeris(game::context& ctx); |
|
|
|
|
|
|
|
/// Creates the fixed stars.
|
|
|
|
static void create_stars(game::context& ctx); |
|
|
|
|
|
|
|
/// Creates the Sun.
|
|
|
|
static void create_sun(game::context& ctx); |
|
|
|
|
|
|
|
/// Creates the Earth-Moon system.
|
|
|
|
static void create_earth_moon_system(game::context& ctx); |
|
|
|
|
|
|
|
/// Creates the Earth.
|
|
|
|
static void create_earth(game::context& ctx); |
|
|
|
|
|
|
|
/// Creates the Moon.
|
|
|
|
static void create_moon(game::context& ctx); |
|
|
|
|
|
|
|
void cosmogenesis(game::context& ctx) |
|
|
|
{ |
|
|
|
ctx.logger->push_task("Generating cosmos"); |
|
|
|
|
|
|
|
load_ephemeris(ctx); |
|
|
|
create_stars(ctx); |
|
|
|
create_sun(ctx); |
|
|
|
create_earth_moon_system(ctx); |
|
|
|
|
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void set_location(game::context& ctx, double elevation, double latitude, double longitude) |
|
|
|
{ |
|
|
|
// Update context location
|
|
|
|
ctx.elevation = elevation; |
|
|
|
ctx.latitude = latitude; |
|
|
|
ctx.longitude = longitude; |
|
|
|
|
|
|
|
// Pass location to astronomy system
|
|
|
|
ctx.astronomy_system->set_observer_location({elevation, latitude, longitude}); |
|
|
|
} |
|
|
|
|
|
|
|
void set_time(game::context& ctx, double t) |
|
|
|
{ |
|
|
|
ctx.logger->push_task("Setting time to UT1 " + std::to_string(t)); |
|
|
|
try |
|
|
|
{ |
|
|
|
ctx.astronomy_system->set_time(t); |
|
|
|
ctx.orbit_system->set_time(t); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void set_time(game::context& ctx, int year, int month, int day, int hour, int minute, double second) |
|
|
|
{ |
|
|
|
const double utc_offset = ctx.longitude / (math::two_pi<double> / 24.0); |
|
|
|
const double t = physics::time::gregorian::to_ut1<double>(year, month, day, hour, minute, second, utc_offset); |
|
|
|
set_time(ctx, t); |
|
|
|
} |
|
|
|
|
|
|
|
void set_time_scale(game::context& ctx, double scale) |
|
|
|
{ |
|
|
|
ctx.logger->push_task("Setting time scale to " + std::to_string(scale)); |
|
|
|
try |
|
|
|
{ |
|
|
|
// Convert time scale from seconds to days
|
|
|
|
const double astronomical_scale = scale / physics::time::seconds_per_day<double>; |
|
|
|
|
|
|
|
ctx.orbit_system->set_time_scale(astronomical_scale); |
|
|
|
ctx.astronomy_system->set_time_scale(astronomical_scale); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void load_ephemeris(game::context& ctx) |
|
|
|
{ |
|
|
|
// Load ephemeris
|
|
|
|
ctx.orbit_system->set_ephemeris(ctx.resource_manager->load<physics::orbit::ephemeris<double>>("de421.eph")); |
|
|
|
ctx.logger->push_task("Loading ephemeris"); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
std::string ephemeris_filename; |
|
|
|
if (ctx.config->contains("ephemeris")) |
|
|
|
{ |
|
|
|
ephemeris_filename = (*ctx.config)["ephemeris"].get<std::string>(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ctx.logger->warning("No ephemeris set in config"); |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ctx.orbit_system->set_ephemeris(ctx.resource_manager->load<physics::orbit::ephemeris<double>>(ephemeris_filename)); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void create_stars(game::context& ctx) |
|
|
|
{ |
|
|
|
ctx.logger->push_task("Generating fixed stars"); |
|
|
|
|
|
|
|
// Load star catalog
|
|
|
|
string_table* star_catalog = ctx.resource_manager->load<string_table>("stars.csv"); |
|
|
|
string_table* star_catalog = nullptr; |
|
|
|
try |
|
|
|
{ |
|
|
|
std::string star_catalog_filename; |
|
|
|
if (ctx.config->contains("star_catalog")) |
|
|
|
{ |
|
|
|
star_catalog_filename = (*ctx.config)["star_catalog"].get<std::string>(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ctx.logger->warning("No star catalog set in config"); |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
star_catalog = ctx.resource_manager->load<string_table>(star_catalog_filename); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Allocate star catalog vertex data
|
|
|
|
std::size_t star_count = 0; |
|
|
@ -83,22 +214,21 @@ void create_stars(game::context& ctx) |
|
|
|
{ |
|
|
|
const string_table_row& catalog_row = (*star_catalog)[i]; |
|
|
|
|
|
|
|
// Parse star catalog item
|
|
|
|
double ra = 0.0; |
|
|
|
double dec = 0.0; |
|
|
|
double vmag = 0.0; |
|
|
|
double bv_color = 0.0; |
|
|
|
|
|
|
|
// Parse star catalog entry
|
|
|
|
double bv = 0.0; |
|
|
|
try |
|
|
|
{ |
|
|
|
ra = std::stod(catalog_row[1]); |
|
|
|
dec = std::stod(catalog_row[2]); |
|
|
|
vmag = std::stod(catalog_row[3]); |
|
|
|
bv_color = std::stod(catalog_row[4]); |
|
|
|
bv = std::stod(catalog_row[4]); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
ctx.logger->warning("Invalid star catalog item on row " + std::to_string(i)); |
|
|
|
} |
|
|
|
|
|
|
|
// Convert right ascension and declination from degrees to radians
|
|
|
@ -112,7 +242,7 @@ void create_stars(game::context& ctx) |
|
|
|
double brightness = physics::light::vmag::to_brightness(vmag); |
|
|
|
|
|
|
|
// Convert color index to color temperature
|
|
|
|
double cct = color::index::bv_to_cct(bv_color); |
|
|
|
double cct = color::index::bv_to_cct(bv); |
|
|
|
|
|
|
|
// Calculate XYZ color from color temperature
|
|
|
|
double3 color_xyz = color::cct::to_xyz(cct); |
|
|
@ -191,106 +321,147 @@ void create_stars(game::context& ctx) |
|
|
|
|
|
|
|
// Pass starlight illuminance to astronomy system
|
|
|
|
ctx.astronomy_system->set_starlight_illuminance(starlight_illuminance); |
|
|
|
|
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void create_sun(game::context& ctx) |
|
|
|
{ |
|
|
|
// Create sun entity
|
|
|
|
entity::archetype* sun_archetype = ctx.resource_manager->load<entity::archetype>("sun.ent"); |
|
|
|
entity::id sun_eid = sun_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["sun"] = sun_eid; |
|
|
|
|
|
|
|
// Create sun directional light scene object
|
|
|
|
scene::directional_light* sun_light = new scene::directional_light(); |
|
|
|
sun_light->set_color({0, 0, 0}); |
|
|
|
sun_light->update_tweens(); |
|
|
|
|
|
|
|
// Create sky ambient light scene object
|
|
|
|
scene::ambient_light* sky_light = new scene::ambient_light(); |
|
|
|
sky_light->set_color({0, 0, 0}); |
|
|
|
sky_light->update_tweens(); |
|
|
|
ctx.logger->push_task("Generating Sun"); |
|
|
|
|
|
|
|
// Add sun light scene objects to surface scene
|
|
|
|
ctx.surface_scene->add_object(sun_light); |
|
|
|
ctx.surface_scene->add_object(sky_light); |
|
|
|
try |
|
|
|
{ |
|
|
|
// Create sun entity
|
|
|
|
entity::archetype* sun_archetype = ctx.resource_manager->load<entity::archetype>("sun.ent"); |
|
|
|
entity::id sun_eid = sun_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["sun"] = sun_eid; |
|
|
|
|
|
|
|
// Create sun directional light scene object
|
|
|
|
scene::directional_light* sun_light = new scene::directional_light(); |
|
|
|
sun_light->set_color({0, 0, 0}); |
|
|
|
sun_light->update_tweens(); |
|
|
|
|
|
|
|
// Create sky ambient light scene object
|
|
|
|
scene::ambient_light* sky_light = new scene::ambient_light(); |
|
|
|
sky_light->set_color({0, 0, 0}); |
|
|
|
sky_light->update_tweens(); |
|
|
|
|
|
|
|
// Add sun light scene objects to surface scene
|
|
|
|
ctx.surface_scene->add_object(sun_light); |
|
|
|
ctx.surface_scene->add_object(sky_light); |
|
|
|
|
|
|
|
// Pass direct sun light scene object to shadow map pass and astronomy system
|
|
|
|
ctx.surface_shadow_map_pass->set_light(sun_light); |
|
|
|
ctx.astronomy_system->set_sun_light(sun_light); |
|
|
|
ctx.astronomy_system->set_sky_light(sky_light); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Pass direct sun light scene object to shadow map pass and astronomy system
|
|
|
|
ctx.surface_shadow_map_pass->set_light(sun_light); |
|
|
|
ctx.astronomy_system->set_sun_light(sun_light); |
|
|
|
ctx.astronomy_system->set_sky_light(sky_light); |
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void create_em_bary(game::context& ctx) |
|
|
|
void create_earth_moon_system(game::context& ctx) |
|
|
|
{ |
|
|
|
// Create earth-moon barycenter entity
|
|
|
|
entity::archetype* em_bary_archetype = ctx.resource_manager->load<entity::archetype>("em-bary.ent"); |
|
|
|
entity::id em_bary_eid = em_bary_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["em_bary"] = em_bary_eid; |
|
|
|
ctx.logger->push_task("Generating Earth-Moon system"); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
// Create Earth-Moon barycenter entity
|
|
|
|
entity::archetype* em_bary_archetype = ctx.resource_manager->load<entity::archetype>("em-bary.ent"); |
|
|
|
entity::id em_bary_eid = em_bary_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["em_bary"] = em_bary_eid; |
|
|
|
|
|
|
|
// Create Earth
|
|
|
|
create_earth(ctx); |
|
|
|
|
|
|
|
// Create Moon
|
|
|
|
create_moon(ctx); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void create_earth(game::context& ctx) |
|
|
|
{ |
|
|
|
// Create earth entity
|
|
|
|
entity::archetype* earth_archetype = ctx.resource_manager->load<entity::archetype>("earth.ent"); |
|
|
|
entity::id earth_eid = earth_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["earth"] = earth_eid; |
|
|
|
ctx.logger->push_task("Generating Earth"); |
|
|
|
|
|
|
|
// Assign orbital parent
|
|
|
|
ctx.entity_registry->get<entity::component::orbit>(earth_eid).parent = ctx.entities["em_bary"]; |
|
|
|
|
|
|
|
// Assign earth terrain component
|
|
|
|
entity::component::terrain terrain; |
|
|
|
terrain.elevation = [](double, double) -> double |
|
|
|
try |
|
|
|
{ |
|
|
|
// Create earth entity
|
|
|
|
entity::archetype* earth_archetype = ctx.resource_manager->load<entity::archetype>("earth.ent"); |
|
|
|
entity::id earth_eid = earth_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["earth"] = earth_eid; |
|
|
|
|
|
|
|
// Assign orbital parent
|
|
|
|
ctx.entity_registry->get<entity::component::orbit>(earth_eid).parent = ctx.entities["em_bary"]; |
|
|
|
|
|
|
|
// Assign earth terrain component
|
|
|
|
entity::component::terrain terrain; |
|
|
|
terrain.elevation = [](double, double) -> double |
|
|
|
{ |
|
|
|
//return math::random<double>(0.0, 1.0);
|
|
|
|
return 0.0; |
|
|
|
}; |
|
|
|
terrain.max_lod = 0; |
|
|
|
terrain.patch_material = nullptr; |
|
|
|
//ctx.entity_registry->assign<entity::component::terrain>(earth_eid, terrain);
|
|
|
|
|
|
|
|
// Pass earth to astronomy system as reference body
|
|
|
|
ctx.astronomy_system->set_reference_body(earth_eid); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
//return math::random<double>(0.0, 1.0);
|
|
|
|
return 0.0; |
|
|
|
}; |
|
|
|
terrain.max_lod = 0; |
|
|
|
terrain.patch_material = nullptr; |
|
|
|
//ctx.entity_registry->assign<entity::component::terrain>(earth_eid, terrain);
|
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Pass earth to astronomy system as reference body
|
|
|
|
ctx.astronomy_system->set_reference_body(earth_eid); |
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
void create_moon(game::context& ctx) |
|
|
|
{ |
|
|
|
// Create lunar entity
|
|
|
|
entity::archetype* moon_archetype = ctx.resource_manager->load<entity::archetype>("moon.ent"); |
|
|
|
entity::id moon_eid = moon_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["moon"] = moon_eid; |
|
|
|
|
|
|
|
// Assign orbital parent
|
|
|
|
ctx.entity_registry->get<entity::component::orbit>(moon_eid).parent = ctx.entities["em_bary"]; |
|
|
|
|
|
|
|
// Pass moon model to sky pass
|
|
|
|
ctx.sky_pass->set_moon_model(ctx.resource_manager->load<render::model>("moon.mdl")); |
|
|
|
ctx.logger->push_task("Generating Moon"); |
|
|
|
|
|
|
|
// Create moon directional light scene object
|
|
|
|
scene::directional_light* moon_light = new scene::directional_light(); |
|
|
|
moon_light->set_color({0, 0, 0}); |
|
|
|
moon_light->update_tweens(); |
|
|
|
|
|
|
|
// Add moon light scene objects to surface scene
|
|
|
|
ctx.surface_scene->add_object(moon_light); |
|
|
|
|
|
|
|
// Pass moon light scene object to astronomy system
|
|
|
|
ctx.astronomy_system->set_moon_light(moon_light); |
|
|
|
} |
|
|
|
|
|
|
|
void set_time(game::context& ctx, double t) |
|
|
|
{ |
|
|
|
ctx.astronomy_system->set_time(t); |
|
|
|
ctx.orbit_system->set_time(t); |
|
|
|
} |
|
|
|
|
|
|
|
void set_time_scale(game::context& ctx, double scale) |
|
|
|
{ |
|
|
|
static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0; |
|
|
|
scale /= seconds_per_day; |
|
|
|
try |
|
|
|
{ |
|
|
|
// Create lunar entity
|
|
|
|
entity::archetype* moon_archetype = ctx.resource_manager->load<entity::archetype>("moon.ent"); |
|
|
|
entity::id moon_eid = moon_archetype->create(*ctx.entity_registry); |
|
|
|
ctx.entities["moon"] = moon_eid; |
|
|
|
|
|
|
|
// Assign orbital parent
|
|
|
|
ctx.entity_registry->get<entity::component::orbit>(moon_eid).parent = ctx.entities["em_bary"]; |
|
|
|
|
|
|
|
// Pass moon model to sky pass
|
|
|
|
ctx.sky_pass->set_moon_model(ctx.resource_manager->load<render::model>("moon.mdl")); |
|
|
|
|
|
|
|
// Create moon directional light scene object
|
|
|
|
scene::directional_light* moon_light = new scene::directional_light(); |
|
|
|
moon_light->set_color({0, 0, 0}); |
|
|
|
moon_light->update_tweens(); |
|
|
|
|
|
|
|
// Add moon light scene objects to surface scene
|
|
|
|
ctx.surface_scene->add_object(moon_light); |
|
|
|
|
|
|
|
// Pass moon light scene object to astronomy system
|
|
|
|
ctx.astronomy_system->set_moon_light(moon_light); |
|
|
|
} |
|
|
|
catch (const std::exception&) |
|
|
|
{ |
|
|
|
ctx.logger->pop_task(EXIT_FAILURE); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ctx.orbit_system->set_time_scale(scale); |
|
|
|
ctx.astronomy_system->set_time_scale(scale); |
|
|
|
ctx.logger->pop_task(EXIT_SUCCESS); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace world
|
|
|
|