Browse Source

Improve world creation functions with added exception handling, add colors to logger on Windows

master
C. J. Howard 1 year ago
parent
commit
a402e70a90
9 changed files with 382 additions and 129 deletions
  1. +37
    -4
      src/debug/logger.cpp
  2. +4
    -0
      src/game/context.hpp
  3. +3
    -1
      src/game/load.cpp
  4. +9
    -18
      src/game/state/nuptial-flight.cpp
  5. +258
    -87
      src/game/world.cpp
  6. +36
    -18
      src/game/world.hpp
  7. +33
    -0
      src/physics/time/constants.hpp
  8. +1
    -1
      src/physics/time/gregorian.hpp
  9. +1
    -0
      src/physics/time/time.hpp

+ 37
- 4
src/debug/logger.cpp View File

@ -21,6 +21,11 @@
#include "utility/timestamp.hpp"
#include <iostream>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
namespace debug {
logger::logger():
@ -84,17 +89,45 @@ void logger::log(const std::string& text)
void logger::warning(const std::string& text)
{
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN);
#endif
log(warning_prefix + text + warning_postfix);
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
}
void logger::error(const std::string& text)
{
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
#endif
log(error_prefix + text + error_postfix);
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
}
void logger::success(const std::string& text)
{
/*
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
#endif
*/
log(success_prefix + text + success_postfix);
/*
#if defined(_WIN32)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
*/
}
void logger::set_auto_newline(bool enabled)
@ -170,21 +203,21 @@ void logger::pop_task(int status, std::string error)
return;
}
std::string message = "} ";
std::string message = "} => ";
tasks.pop();
if (status == EXIT_SUCCESS)
{
message += "=> success";
message += "success";
if (!auto_newline)
message += "\n";
log(message);
success(message);
}
else
{
message += "failed";
message += "failure";
if (!error.empty())
message += " (" + error + ")";
if (!auto_newline)

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

@ -294,6 +294,10 @@ struct context
entity::system::astronomy* astronomy_system;
entity::system::orbit* orbit_system;
entity::system::proteome* proteome_system;
double elevation;
double latitude;
double longitude;
};
} // namespace game

+ 3
- 1
src/game/load.cpp View File

@ -18,6 +18,7 @@
*/
#include "game/load.hpp"
#include "game/world.hpp"
#include "application.hpp"
#include "debug/logger.hpp"
#include "resources/json.hpp"
@ -61,7 +62,8 @@ void biome(game::context& ctx, const std::filesystem::path& path)
else
ctx.logger->warning("Biome longitude undefined");
ctx.astronomy_system->set_observer_location({elevation, latitude, longitude});
// Set location
game::world::set_location(ctx, elevation, latitude, longitude);
}
else
{

+ 9
- 18
src/game/state/nuptial-flight.cpp View File

@ -44,7 +44,6 @@
#include "game/load.hpp"
#include "game/ant/breed.hpp"
#include "game/ant/morphogenesis.hpp"
#include "physics/time/time.hpp"
#include "math/interpolation.hpp"
#include <iostream>
@ -75,7 +74,7 @@ nuptial_flight::nuptial_flight(game::context& ctx):
breed.sculpturing = ctx.resource_manager->load<ant::trait::sculpturing>("politus-sculpturing.dna");
breed.pigmentation = ctx.resource_manager->load<ant::trait::pigmentation>("rust-pigmentation.dna");
breed.egg = ctx.resource_manager->load<ant::trait::egg>("ellipsoid-egg.dna");
breed.larva = ctx.resource_manager->load<ant::trait::larva>("old-larva.dna");
breed.larva = ctx.resource_manager->load<ant::trait::larva>("long-neck-larva.dna");
breed.cocoon = ctx.resource_manager->load<ant::trait::cocoon>("cocoon-present.dna");
breed.pilosity = ctx.resource_manager->load<ant::trait::pilosity>("hairless-pilosity.dna");
breed.forewings = nullptr;
@ -94,23 +93,9 @@ nuptial_flight::nuptial_flight(game::context& ctx):
// Create world if not yet created
if (ctx.entities.find("planet") == ctx.entities.end())
{
{
// Create cosmos
game::world::load_ephemeris(ctx);
game::world::create_stars(ctx);
game::world::create_sun(ctx);
game::world::create_em_bary(ctx);
game::world::create_earth(ctx);
game::world::create_moon(ctx);
// Set world time
const double utc = 0.0;
const double equinox_2000 = physics::time::gregorian::to_ut1<double>(2000, 1, 1, 12, 0, 0.0, utc);
const double summer_2022 = physics::time::gregorian::to_ut1<double>(2022, 6, 21, 12, 0, 0.0, utc);
game::world::set_time(ctx, summer_2022);
// Set time scale
game::world::set_time_scale(ctx, 60.0);
game::world::cosmogenesis(ctx);
// Create boids
for (int i = 0; i < 50; ++i)
@ -160,6 +145,12 @@ nuptial_flight::nuptial_flight(game::context& ctx):
// Load biome
game::load::biome(ctx, "desert-scrub.bio");
// Set world time
game::world::set_time(ctx, 2022, 6, 21, 12, 0, 0.0);
// Set world time scale
game::world::set_time_scale(ctx, 60.0);
// Setup and enable sky and ground passes
ctx.sky_pass->set_enabled(true);
ctx.ground_pass->set_enabled(true);

+ 258
- 87
src/game/world.cpp View File

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

+ 36
- 18
src/game/world.hpp View File

@ -27,28 +27,46 @@ namespace game {
/// World creation and manipulation functions.
namespace world {
/// Creates an ephemeris.
void load_ephemeris(game::context& ctx);
/// Creates the cosmos.
void cosmogenesis(game::context& ctx);
/// Creates the fixed stars.
void create_stars(game::context& ctx);
/// Creates the sun.
void create_sun(game::context& ctx);
/// Creates the earth-moon barycenter.
void create_em_bary(game::context& ctx);
/// Creates the earth.
void create_earth(game::context& ctx);
/// Creates the moon.
void create_moon(game::context& ctx);
/**
* Sets the location of the observer.
*
* @param ctx Game context.
* @param elevation Elevation, in meters.
* @param latitude Latitude, in radians.
* @param longitude Longitude, in radians.
*/
void set_location(game::context& ctx, double elevation, double latitude, double longitude);
/// Sets the current time.
/**
* Sets the current time.
*
* @param ctx Game context.
* @param t UT1 time, in days.
*/
void set_time(game::context& ctx, double t);
/// Sets rate at which time passes.
/**
* Sets the current time.
*
* @param ctx Game context.
* @param year Astronomical year numbering. 1 BC is `0`, 2 BC is `-1`.
* @param month Month number on `[1, 12]`.
* @param day Day number on `[1, 31]`.
* @param hour Hour number on `[0, 23]`.
* @param minute Minute number on `[0, 59]`.
* @param second Fractional second on `[0.0, 60.0)`.
*/
void set_time(game::context& ctx, int year, int month, int day, int hour, int minute, double second);
/**
* Sets rate at which time passes.
*
* @param ctx Game context.
* @param scale Time scale.
*/
void set_time_scale(game::context& ctx, double scale);
} // namespace menu

+ 33
- 0
src/physics/time/constants.hpp View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2021 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_PHYSICS_TIME_CONSTANTS_HPP
#define ANTKEEPER_PHYSICS_TIME_CONSTANTS_HPP
namespace physics {
namespace time {
/// Number of seconds per day, in seconds.
template <class T>
constexpr T seconds_per_day = T(86400);
} // namespace time
} // namespace physics
#endif // ANTKEEPER_PHYSICS_TIME_CONSTANTS_HPP

+ 1
- 1
src/physics/time/gregorian.hpp View File

@ -47,7 +47,7 @@ template
T to_jd(int year, int month, int day, int hour, int minute, T second, T utc)
{
T jdn = static_cast<T>((1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4 + day - 32075);
return jdn + static_cast<T>(hour - 12) / T(24) + static_cast<T>(minute) / T(1440) + static_cast<T>(second) / T(86400) + utc / T(24);
return jdn + static_cast<T>(hour - 12) / T(24) + static_cast<T>(minute) / T(1440) + static_cast<T>(second) / T(86400) - utc / T(24);
}
/**

+ 1
- 0
src/physics/time/time.hpp View File

@ -27,6 +27,7 @@ namespace time {}
} // namespace physics
#include "constants.hpp"
#include "gregorian.hpp"
#include "jd.hpp"
#include "ut1.hpp"

Loading…
Cancel
Save