Browse Source

Improve photometric and astronomic calculations

master
C. J. Howard 2 years ago
parent
commit
86308e2b90
23 changed files with 554 additions and 102 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +7
    -1
      src/astro/apparent-size.hpp
  3. +2
    -2
      src/entity/components/blackbody.hpp
  4. +20
    -0
      src/entity/components/celestial-body.hpp
  5. +145
    -15
      src/entity/systems/astronomy.cpp
  6. +5
    -0
      src/entity/systems/astronomy.hpp
  7. +13
    -16
      src/entity/systems/blackbody.cpp
  8. +1
    -1
      src/entity/systems/blackbody.hpp
  9. +1
    -0
      src/game/state/boot.cpp
  10. +14
    -7
      src/game/state/nuptial-flight.cpp
  11. +41
    -11
      src/game/world.cpp
  12. +5
    -2
      src/game/world.hpp
  13. +47
    -0
      src/geom/solid-angle.hpp
  14. +8
    -6
      src/physics/light/blackbody.hpp
  15. +5
    -4
      src/physics/orbit/frame.hpp
  16. +77
    -0
      src/physics/time/gregorian.hpp
  17. +22
    -7
      src/physics/time/jd.hpp
  18. +2
    -0
      src/physics/time/time.hpp
  19. +13
    -4
      src/physics/time/ut1.hpp
  20. +5
    -1
      src/render/passes/ground-pass.cpp
  21. +79
    -20
      src/render/passes/sky-pass.cpp
  22. +23
    -4
      src/render/passes/sky-pass.hpp
  23. +19
    -0
      src/resources/entity-archetype-loader.cpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
option(VERSION_STRING "Project version string" "0.0.0") option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)

+ 7
- 1
src/astro/apparent-size.hpp View File

@ -20,6 +20,8 @@
#ifndef ANTKEEPER_ASTRO_APPARENT_SIZE_HPP #ifndef ANTKEEPER_ASTRO_APPARENT_SIZE_HPP
#define ANTKEEPER_ASTRO_APPARENT_SIZE_HPP #define ANTKEEPER_ASTRO_APPARENT_SIZE_HPP
#include <cmath>
namespace astro namespace astro
{ {
@ -30,7 +32,11 @@ namespace astro
* @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 find_angular_radius(double radius, double distance);
template <class T>
T angular_radius(T radius, T distance)
{
return std::asin(radius / distance);
}
} // namespace astro } // namespace astro

+ 2
- 2
src/entity/components/blackbody.hpp View File

@ -29,8 +29,8 @@ struct blackbody
/// Effective temperature, in Kelvin. /// Effective temperature, in Kelvin.
double temperature; double temperature;
/// (Dependent) RGB luminous intensity, in candela.
double3 luminous_intensity;
/// (Dependent) RGB luminance, in lumens.
double3 luminance;
}; };
} // namespace component } // namespace component

+ 20
- 0
src/entity/components/celestial-body.hpp View File

@ -41,8 +41,28 @@ struct celestial_body
/// Location of the prime meridian at epoch, as a rotation about the north pole, in radians. /// Location of the prime meridian at epoch, as a rotation about the north pole, in radians.
double prime_meridian; double prime_meridian;
/*
/// Quadratic e coefficients for the right ascension of the body's north pole, in radians. Right ascension is calculated as `x + y * T + z * T^2`, where `T` is the Julian centuries (36525 days) from epoch.
double3 pole_ra;
/// Quadratic coefficients for the declination of the body's north pole, in radians. Declination is calculated as `x + y * T + z * T^2`, where `T` is the Julian centuries (36525 days) from epoch.
double3 pole_ra;
/// Quadratic coefficients for the rotation state of the body's prime meridian, in radians. Prime meridian rotation is calculated as `x + y * d + z * d^2`, where `d` is the days from epoch.
double3 prime_meridian;
/// Linear coefficients of the nutation and precession angles, in radians. Angles are calculated as `x + y * d`, where `d` is the days from epoch.
std::vector<double2> nutation_precession_angles;
std::vector<double> nutation_precession_ra;
std::vector<double> nutation_precession_dec;
std::vector<double> nutation_precession_pm;
*/
/// Sidereal rotation period, in rotations per day. /// Sidereal rotation period, in rotations per day.
double rotation_period; double rotation_period;
/// Geometric albedo
double albedo;
}; };
} // namespace component } // namespace component

+ 145
- 15
src/entity/systems/astronomy.cpp View File

@ -21,6 +21,7 @@
#include "astro/apparent-size.hpp" #include "astro/apparent-size.hpp"
#include "entity/components/blackbody.hpp" #include "entity/components/blackbody.hpp"
#include "entity/components/transform.hpp" #include "entity/components/transform.hpp"
#include "entity/components/diffuse-reflector.hpp"
#include "geom/intersection.hpp" #include "geom/intersection.hpp"
#include "geom/cartesian.hpp" #include "geom/cartesian.hpp"
#include "color/color.hpp" #include "color/color.hpp"
@ -31,6 +32,9 @@
#include "physics/light/refraction.hpp" #include "physics/light/refraction.hpp"
#include "physics/atmosphere.hpp" #include "physics/atmosphere.hpp"
#include "geom/cartesian.hpp" #include "geom/cartesian.hpp"
#include "astro/apparent-size.hpp"
#include "astro/illuminance.hpp"
#include "geom/solid-angle.hpp"
#include <iostream> #include <iostream>
namespace entity { namespace entity {
@ -59,6 +63,8 @@ astronomy::astronomy(entity::registry& registry):
observer_location{0, 0, 0}, observer_location{0, 0, 0},
sun_light(nullptr), sun_light(nullptr),
sky_light(nullptr), sky_light(nullptr),
moon_light(nullptr),
camera(nullptr),
sky_pass(nullptr) sky_pass(nullptr)
{ {
// Construct transformation which transforms coordinates from ENU to EUS // Construct transformation which transforms coordinates from ENU to EUS
@ -74,6 +80,8 @@ astronomy::astronomy(entity::registry& registry):
void astronomy::update(double t, double dt) void astronomy::update(double t, double dt)
{ {
double total_illuminance = 0.0;
// Add scaled timestep to current time // Add scaled timestep to current time
set_universal_time(universal_time + dt * time_scale); set_universal_time(universal_time + dt * time_scale);
@ -126,13 +134,13 @@ void astronomy::update(double t, double dt)
// Update local transform // Update local transform
if (orbit.parent != entt::null) if (orbit.parent != entt::null)
{ {
transform.local.translation = math::normalize(math::type_cast<float>(r_eus)) * 1000.0f;
transform.local.translation = math::normalize(math::type_cast<float>(r_eus));
transform.local.rotation = math::type_cast<float>(rotation_eus); transform.local.rotation = math::type_cast<float>(rotation_eus);
transform.local.scale = {50.0f, 50.0f, 50.0f};
transform.local.scale = {1.0f, 1.0f, 1.0f};
} }
/*
if (orbit.parent == entt::null)
if (orbit.parent != entt::null)
{ {
// RA-DEC // RA-DEC
const double3 r_bci = icrf_to_bci * orbit.icrf_position; const double3 r_bci = icrf_to_bci * orbit.icrf_position;
@ -150,10 +158,10 @@ void astronomy::update(double t, double dt)
const double el = math::degrees(r_enu_spherical.y); const double el = math::degrees(r_enu_spherical.y);
const double az = math::degrees(r_enu_spherical.z); const double az = math::degrees(r_enu_spherical.z);
std::cout << "t: " << this->universal_time << "; ra: " << ra << "; dec: " << dec << std::endl;
std::cout << "t: " << this->universal_time << "; az: " << az << "; el: " << el << std::endl;
//std::cout << "t: " << this->universal_time << "; ra: " << ra << "; dec: " << dec << std::endl;
//std::cout << "t: " << this->universal_time << "; az: " << az << "; el: " << el << std::endl;
} }
*/
}); });
// Update blackbody lighting // Update blackbody lighting
@ -173,9 +181,6 @@ void astronomy::update(double t, double dt)
// Calculate distance from observer to blackbody // Calculate distance from observer to blackbody
double blackbody_distance = math::length(blackbody_position_eus) - body.radius; double blackbody_distance = math::length(blackbody_position_eus) - body.radius;
// Calculate blackbody distance attenuation
double distance_attenuation = 1.0 / (blackbody_distance * blackbody_distance);
// Init atmospheric transmittance // Init atmospheric transmittance
double3 atmospheric_transmittance = {1.0, 1.0, 1.0}; double3 atmospheric_transmittance = {1.0, 1.0, 1.0};
@ -221,23 +226,31 @@ void astronomy::update(double t, double dt)
) )
); );
// Calculate blackbody solid angle
const double angular_radius = astro::angular_radius(body.radius, blackbody_distance);
const double solid_angle = geom::solid_angle::cone(angular_radius);
const double3 blackbody_illuminance = blackbody.luminance * solid_angle;
// Sun illuminance at the outer atmosphere // Sun illuminance at the outer atmosphere
float3 sun_illuminance_outer = math::type_cast<float>(blackbody.luminous_intensity * distance_attenuation);
float3 sun_illuminance_outer = math::type_cast<float>(blackbody_illuminance);
// Sun illuminance at sea level // Sun illuminance at sea level
float3 sun_illuminance_inner = math::type_cast<float>(blackbody.luminous_intensity * distance_attenuation * atmospheric_transmittance);
float3 sun_illuminance_inner = math::type_cast<float>(blackbody_illuminance * atmospheric_transmittance);
// Update blackbody light color and intensity // Update blackbody light color and intensity
sun_light->set_color(sun_illuminance_inner); sun_light->set_color(sun_illuminance_inner);
sun_light->set_intensity(1.0f); sun_light->set_intensity(1.0f);
total_illuminance += (sun_illuminance_inner.x + sun_illuminance_inner.y + sun_illuminance_inner.z) / 3.0;
// Upload blackbody params to sky pass // Upload blackbody params to sky pass
if (this->sky_pass) if (this->sky_pass)
{ {
this->sky_pass->set_sun_position(math::type_cast<float>(blackbody_position_eus)); this->sky_pass->set_sun_position(math::type_cast<float>(blackbody_position_eus));
this->sky_pass->set_sun_illuminance(sun_illuminance_outer, sun_illuminance_inner); this->sky_pass->set_sun_illuminance(sun_illuminance_outer, sun_illuminance_inner);
double blackbody_angular_radius = std::asin((body.radius * 2.0) / (blackbody_distance * 2.0));
double blackbody_angular_radius = astro::angular_radius(body.radius, blackbody_distance);
this->sky_pass->set_sun_angular_radius(static_cast<float>(blackbody_angular_radius)); this->sky_pass->set_sun_angular_radius(static_cast<float>(blackbody_angular_radius));
} }
} }
@ -246,11 +259,109 @@ void astronomy::update(double t, double dt)
{ {
double3 blackbody_position_enu_spherical = physics::orbit::frame::enu::spherical(icrf_to_enu * orbit.icrf_position); double3 blackbody_position_enu_spherical = physics::orbit::frame::enu::spherical(icrf_to_enu * orbit.icrf_position);
double illuminance = 25000.0 * std::max<double>(0.0, std::sin(blackbody_position_enu_spherical.y));
const double starlight_illuminance = 0.0011;
const double sky_illuminance = 25000.0 * std::max<double>(0.0, std::sin(blackbody_position_enu_spherical.y));
const double sky_light_illuminance = sky_illuminance + starlight_illuminance;
total_illuminance += sky_light_illuminance;
sky_light->set_color({1.0f, 1.0f, 1.0f}); sky_light->set_color({1.0f, 1.0f, 1.0f});
sky_light->set_intensity(static_cast<float>(illuminance));
sky_light->set_intensity(static_cast<float>(sky_illuminance));
} }
const double3& blackbody_icrf_position = orbit.icrf_position;
// Update diffuse reflectors
this->registry.view<component::celestial_body, component::orbit, component::diffuse_reflector, component::transform>().each(
[&](entity::id entity_id, const auto& reflector_body, const auto& reflector_orbit, const auto& reflector, const auto& transform)
{
// Calculate distance to blackbody and direction of incoming light
double3 blackbody_light_direction_icrf = reflector_orbit.icrf_position - blackbody_icrf_position;
double blackbody_distance = math::length(blackbody_light_direction_icrf);
blackbody_light_direction_icrf = blackbody_light_direction_icrf / blackbody_distance;
// Transform blackbody light direction from the ICRF frame to the EUS frame
double3 blackbody_light_direction_eus = icrf_to_eus.r * blackbody_light_direction_icrf;
// Calculate blackbody solid angle
const double blackbody_angular_radius = astro::angular_radius(body.radius, blackbody_distance);
const double blackbody_solid_angle = geom::solid_angle::cone(blackbody_angular_radius);
// Calculate blackbody illuminance
double3 view_direction_icrf = reflector_orbit.icrf_position - reference_orbit.icrf_position;
const double reflector_distance = math::length(view_direction_icrf);
view_direction_icrf = view_direction_icrf / reflector_distance;
const double3 sunlight_illuminance = blackbody.luminance * blackbody_solid_angle;
const double reflector_angular_radius = astro::angular_radius(reflector_body.radius, reflector_distance);
const double reflector_solid_angle = geom::solid_angle::cone(reflector_angular_radius);
const double reflector_phase_factor = dot(view_direction_icrf, blackbody_light_direction_icrf) * 0.5 + 0.5;
const double3 planet_luminance = (sunlight_illuminance * reference_body.albedo) / math::pi<double>;
const double planet_angular_radius = astro::angular_radius(reference_body.radius, reflector_distance);
const double planet_solid_angle = geom::solid_angle::cone(planet_angular_radius);
const double planet_phase_factor = math::dot(-view_direction_icrf, math::normalize(reference_orbit.icrf_position - blackbody_icrf_position)) * 0.5 + 0.5;
const double3 planetlight_illuminance = planet_luminance * planet_solid_angle * planet_phase_factor;
double3 planetlight_direction_eus = math::normalize(icrf_to_eus.r * view_direction_icrf);
const double3 reflected_sunlight_luminance = (sunlight_illuminance * reflector.albedo) / math::pi<double>;
const double3 reflected_sunlight_illuminance = reflected_sunlight_luminance * reflector_solid_angle * reflector_phase_factor;
const double3 reflected_planetlight_luminance = (planetlight_illuminance * reflector.albedo) / math::pi<double>;
const double3 reflected_planetlight_illuminance = reflected_planetlight_luminance * reflector_solid_angle;
std::cout << "sunlight illuminance: " << sunlight_illuminance << std::endl;
std::cout << "reflected sunlight illuminance: " << reflected_sunlight_illuminance << std::endl;
std::cout << "planetlight illuminance: " << planetlight_illuminance << std::endl;
std::cout << "reflected planetlight illuminance: " << reflected_planetlight_illuminance << std::endl;
std::cout << "reflector phase: " << reflector_phase_factor << std::endl;
std::cout << "planet phase: " << planet_phase_factor << std::endl;
if (this->sky_pass)
{
this->sky_pass->set_moon_position(transform.local.translation);
this->sky_pass->set_moon_rotation(transform.local.rotation);
this->sky_pass->set_moon_angular_radius(static_cast<float>(reflector_angular_radius));
this->sky_pass->set_moon_sunlight_direction(math::type_cast<float>(blackbody_light_direction_eus));
this->sky_pass->set_moon_sunlight_illuminance(math::type_cast<float>(sunlight_illuminance));
this->sky_pass->set_moon_planetlight_direction(math::type_cast<float>(planetlight_direction_eus));
this->sky_pass->set_moon_planetlight_illuminance(math::type_cast<float>(planetlight_illuminance));
}
if (this->moon_light)
{
float3 reflector_up_eus = math::type_cast<float>(icrf_to_eus.r * double3{0, 0, 1});
double3 reflected_illuminance = reflected_sunlight_illuminance + reflected_planetlight_illuminance;
reflected_illuminance *= std::max<double>(0.0, std::sin(transform.local.translation.y));
total_illuminance += (reflected_illuminance.x + reflected_illuminance.y + reflected_illuminance.z) / 3.0;
this->moon_light->set_color(math::type_cast<float>(reflected_illuminance));
this->moon_light->set_rotation
(
math::look_rotation
(
math::normalize(-transform.local.translation),
reflector_up_eus
)
);
}
/*
std::cout << "moon: sun solid angle: " << blackbody_solid_angle << std::endl;
std::cout << "moon: sun illuminance: " << blackbody_illuminance << std::endl;
std::cout << "moon: moon luminance: " << reflector_luminance << std::endl;
std::cout << "sun brightness: " << sun_brightness << std::endl;
std::cout << "vega brightness: " << vega_brightness << std::endl;
std::cout << "earth: moon distance: " << reflector_distance << std::endl;
std::cout << "earth: moon solid angle: " << reflector_solid_angle << std::endl;
std::cout << "earth: moon phase: " << reflector_phase << std::endl;
std::cout << "earth: moon phase angle: " << math::degrees(reflector_phase_angle) << std::endl;
std::cout << "earth: moon illum %: " << reflector_illumination_factor * 100.0 << std::endl;
std::cout << "earth: moon illuminance: " << reflector_illuminance << std::endl;
std::cout << "earth: moon phase-modulated illuminance: " << reflector_illuminance * reflector_illumination_factor << std::endl;
*/
});
}); });
// Update sky pass topocentric frame // Update sky pass topocentric frame
@ -280,6 +391,15 @@ void astronomy::update(double t, double dt)
sky_pass->set_atmosphere_radii(reference_body.radius, reference_body.radius + reference_atmosphere.exosphere_altitude); sky_pass->set_atmosphere_radii(reference_body.radius, reference_body.radius + reference_atmosphere.exosphere_altitude);
} }
} }
// Auto-exposure
if (camera)
{
const double calibration = 250.0;
const double ev100 = std::log2((total_illuminance * 100.0) / calibration);
// std::cout << "EV100: " << ev100 << std::endl;
camera->set_exposure(static_cast<float>(ev100));
}
} }
void astronomy::set_universal_time(double time) void astronomy::set_universal_time(double time)
@ -314,6 +434,16 @@ void astronomy::set_sky_light(scene::ambient_light* light)
sky_light = light; sky_light = light;
} }
void astronomy::set_moon_light(scene::directional_light* light)
{
moon_light = light;
}
void astronomy::set_camera(scene::camera* camera)
{
this->camera = camera;
}
void astronomy::set_sky_pass(::render::sky_pass* pass) void astronomy::set_sky_pass(::render::sky_pass* pass)
{ {
this->sky_pass = pass; this->sky_pass = pass;

+ 5
- 0
src/entity/systems/astronomy.hpp View File

@ -24,6 +24,7 @@
#include "entity/id.hpp" #include "entity/id.hpp"
#include "scene/directional-light.hpp" #include "scene/directional-light.hpp"
#include "scene/ambient-light.hpp" #include "scene/ambient-light.hpp"
#include "scene/camera.hpp"
#include "utility/fundamental-types.hpp" #include "utility/fundamental-types.hpp"
#include "math/se3.hpp" #include "math/se3.hpp"
#include "render/passes/sky-pass.hpp" #include "render/passes/sky-pass.hpp"
@ -81,6 +82,8 @@ public:
void set_sun_light(scene::directional_light* light); void set_sun_light(scene::directional_light* light);
void set_sky_light(scene::ambient_light* light); void set_sky_light(scene::ambient_light* light);
void set_moon_light(scene::directional_light* light);
void set_camera(scene::camera* camera);
void set_sky_pass(::render::sky_pass* pass); void set_sky_pass(::render::sky_pass* pass);
@ -105,6 +108,8 @@ private:
scene::directional_light* sun_light; scene::directional_light* sun_light;
scene::ambient_light* sky_light; scene::ambient_light* sky_light;
scene::directional_light* moon_light;
scene::camera* camera;
::render::sky_pass* sky_pass; ::render::sky_pass* sky_pass;
}; };

+ 13
- 16
src/entity/systems/blackbody.cpp View File

@ -51,7 +51,7 @@ void blackbody::set_rgb_wavelengths(const double3& wavelengths)
rgb_wavelengths_m = wavelengths * 1e-9; rgb_wavelengths_m = wavelengths * 1e-9;
} }
void blackbody::update_luminous_intensity(entity::id entity_id)
void blackbody::update_luminance(entity::id entity_id)
{ {
// Abort if entity has no blackbody component // Abort if entity has no blackbody component
if (!registry.has<component::blackbody>(entity_id)) if (!registry.has<component::blackbody>(entity_id))
@ -60,8 +60,8 @@ void blackbody::update_luminous_intensity(entity::id entity_id)
// Get blackbody component of the entity // Get blackbody component of the entity
component::blackbody& blackbody = registry.get<component::blackbody>(entity_id); component::blackbody& blackbody = registry.get<component::blackbody>(entity_id);
// Clear luminous intensity
blackbody.luminous_intensity = {0, 0, 0};
// Clear luminance
blackbody.luminance = {0, 0, 0};
// Abort if entity has no celestial body component // Abort if entity has no celestial body component
if (!registry.has<component::celestial_body>(entity_id)) if (!registry.has<component::celestial_body>(entity_id))
@ -70,47 +70,44 @@ void blackbody::update_luminous_intensity(entity::id entity_id)
// Get celestial body component of the entity // Get celestial body component of the entity
const component::celestial_body& celestial_body = registry.get<component::celestial_body>(entity_id); const component::celestial_body& celestial_body = registry.get<component::celestial_body>(entity_id);
// Calculate (spherical) surface area of the celestial body
const double surface_area = 4.0 * math::pi<double> * celestial_body.radius * celestial_body.radius;
// Construct a lambda function which calculates the blackbody's RGB luminous intensity of a given wavelength
auto rgb_luminous_intensity = [blackbody, surface_area](double wavelength_nm) -> double3
// Construct a lambda function which calculates the blackbody's RGB luminance of a given wavelength
auto rgb_luminance = [blackbody](double wavelength_nm) -> double3
{ {
// Convert wavelength from nanometers to meters // Convert wavelength from nanometers to meters
const double wavelength_m = wavelength_nm * 1e-9; const double wavelength_m = wavelength_nm * 1e-9;
// Calculate the spectral intensity of the wavelength // Calculate the spectral intensity of the wavelength
const double spectral_intensity = physics::light::blackbody::spectral_intensity<double>(blackbody.temperature, surface_area, wavelength_m);
const double spectral_radiance = physics::light::blackbody::spectral_radiance<double>(blackbody.temperature, wavelength_m);
// Calculate the ACEScg color of the wavelength using CIE color matching functions // Calculate the ACEScg color of the wavelength using CIE color matching functions
double3 spectral_color = color::xyz::to_acescg(color::xyz::match(wavelength_nm)); double3 spectral_color = color::xyz::to_acescg(color::xyz::match(wavelength_nm));
// Scale the spectral color by spectral intensity // Scale the spectral color by spectral intensity
return spectral_color * spectral_intensity * 1e-9 * physics::light::max_luminous_efficacy<double>;
return spectral_color * spectral_radiance * 1e-9 * physics::light::max_luminous_efficacy<double>;
}; };
// Integrate the blackbody RGB luminous intensity over wavelengths in the visible spectrum
blackbody.luminous_intensity = math::quadrature::simpson(rgb_luminous_intensity, visible_wavelengths_nm.begin(), visible_wavelengths_nm.end());
// Integrate the blackbody RGB luminance over wavelengths in the visible spectrum
blackbody.luminance = math::quadrature::simpson(rgb_luminance, visible_wavelengths_nm.begin(), visible_wavelengths_nm.end());
} }
void blackbody::on_blackbody_construct(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody) void blackbody::on_blackbody_construct(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody)
{ {
update_luminous_intensity(entity_id);
update_luminance(entity_id);
} }
void blackbody::on_blackbody_replace(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody) void blackbody::on_blackbody_replace(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody)
{ {
update_luminous_intensity(entity_id);
update_luminance(entity_id);
} }
void blackbody::on_celestial_body_construct(entity::registry& registry, entity::id entity_id, entity::component::celestial_body& celestial_body) void blackbody::on_celestial_body_construct(entity::registry& registry, entity::id entity_id, entity::component::celestial_body& celestial_body)
{ {
update_luminous_intensity(entity_id);
update_luminance(entity_id);
} }
void blackbody::on_celestial_body_replace(entity::registry& registry, entity::id entity_id, entity::component::celestial_body& celestial_body) void blackbody::on_celestial_body_replace(entity::registry& registry, entity::id entity_id, entity::component::celestial_body& celestial_body)
{ {
update_luminous_intensity(entity_id);
update_luminance(entity_id);
} }
} // namespace system } // namespace system

+ 1
- 1
src/entity/systems/blackbody.hpp View File

@ -49,7 +49,7 @@ public:
void set_rgb_wavelengths(const double3& wavelengths); void set_rgb_wavelengths(const double3& wavelengths);
private: private:
void update_luminous_intensity(entity::id entity_id);
void update_luminance(entity::id entity_id);
void on_blackbody_construct(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody); void on_blackbody_construct(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody);
void on_blackbody_replace(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody); void on_blackbody_replace(entity::registry& registry, entity::id entity_id, entity::component::blackbody& blackbody);

+ 1
- 0
src/game/state/boot.cpp View File

@ -492,6 +492,7 @@ void boot::setup_rendering()
ctx.sky_pass = new render::sky_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); ctx.sky_pass = new render::sky_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager);
ctx.sky_pass->set_enabled(false); ctx.sky_pass->set_enabled(false);
ctx.sky_pass->set_magnification(4.0f);
ctx.app->get_event_dispatcher()->subscribe<mouse_moved_event>(ctx.sky_pass); ctx.app->get_event_dispatcher()->subscribe<mouse_moved_event>(ctx.sky_pass);
ctx.ground_pass = new render::ground_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager); ctx.ground_pass = new render::ground_pass(ctx.rasterizer, ctx.hdr_framebuffer, ctx.resource_manager);

+ 14
- 7
src/game/state/nuptial-flight.cpp View File

@ -43,6 +43,8 @@
#include "game/load.hpp" #include "game/load.hpp"
#include "game/ant/breed.hpp" #include "game/ant/breed.hpp"
#include "game/ant/morphogenesis.hpp" #include "game/ant/morphogenesis.hpp"
#include "physics/time/time.hpp"
#include <iostream>
using namespace game::ant; using namespace game::ant;
@ -93,11 +95,15 @@ nuptial_flight::nuptial_flight(game::context& ctx):
{ {
game::world::create_stars(ctx); game::world::create_stars(ctx);
game::world::create_sun(ctx); game::world::create_sun(ctx);
game::world::create_planet(ctx);
game::world::create_em_bary(ctx);
game::world::create_earth(ctx);
game::world::create_moon(ctx); game::world::create_moon(ctx);
// Set time to solar noon
game::world::set_time(ctx, 50.0);//107.3);
// 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 spring_2000 = physics::time::gregorian::to_ut1<double>(2000, 6, 19, 12, 0, 0.0, utc);
game::world::set_time(ctx, 55.0);
// Freeze time // Freeze time
game::world::set_time_scale(ctx, 0.0); game::world::set_time_scale(ctx, 0.0);
@ -277,9 +283,10 @@ void nuptial_flight::setup_camera()
constraint_stack.head = spring_constraint_eid; constraint_stack.head = spring_constraint_eid;
ctx.entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack); ctx.entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
} }
ctx.surface_camera->set_exposure(15.0f);
float ev100 = 15.0f;
ctx.surface_camera->set_exposure(ev100);
ctx.astronomy_system->set_camera(ctx.surface_camera);
} }
void nuptial_flight::enable_keeper_controls() void nuptial_flight::enable_keeper_controls()
@ -306,7 +313,7 @@ void nuptial_flight::enable_keeper_controls()
bool gamepad_invert_pan = false; bool gamepad_invert_pan = false;
bool mouse_look_toggle = false; bool mouse_look_toggle = false;
ctx.mouse_look = false; ctx.mouse_look = false;
const double time_scale = 5000.0;
const double time_scale = 10000.0;
if (ctx.config->contains("mouse_tilt_sensitivity")) if (ctx.config->contains("mouse_tilt_sensitivity"))
mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>()); mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());
@ -665,7 +672,7 @@ void nuptial_flight::enable_ant_controls()
float gamepad_pan_sensitivity = 1.0f; float gamepad_pan_sensitivity = 1.0f;
bool gamepad_invert_tilt = false; bool gamepad_invert_tilt = false;
bool gamepad_invert_pan = false; bool gamepad_invert_pan = false;
const double time_scale = 5000.0;
const double time_scale = 10000.0;
if (ctx.config->contains("mouse_tilt_sensitivity")) if (ctx.config->contains("mouse_tilt_sensitivity"))
mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>()); mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());

+ 41
- 11
src/game/world.cpp View File

@ -50,6 +50,7 @@
#include "gl/texture-filter.hpp" #include "gl/texture-filter.hpp"
#include "render/material-flags.hpp" #include "render/material-flags.hpp"
#include "config.hpp" #include "config.hpp"
#include <iostream>
namespace game { namespace game {
namespace world { namespace world {
@ -68,6 +69,8 @@ void create_stars(game::context& ctx)
float* star_vertex_data = new float[star_count * star_vertex_size]; float* star_vertex_data = new float[star_count * star_vertex_size];
float* star_vertex = star_vertex_data; float* star_vertex = star_vertex_data;
double starlight_illuminance = 0.0;
// Build star catalog vertex data // Build star catalog vertex data
for (std::size_t i = 1; i < star_catalog->size(); ++i) for (std::size_t i = 1; i < star_catalog->size(); ++i)
{ {
@ -91,6 +94,8 @@ void create_stars(game::context& ctx)
continue; continue;
} }
starlight_illuminance += astro::vmag_to_lux(vmag);
// Convert right ascension and declination from degrees to radians // Convert right ascension and declination from degrees to radians
ra = math::wrap_radians(math::radians(ra)); ra = math::wrap_radians(math::radians(ra));
dec = math::wrap_radians(math::radians(dec)); dec = math::wrap_radians(math::radians(dec));
@ -123,6 +128,8 @@ void create_stars(game::context& ctx)
*(star_vertex++) = static_cast<float>(brightness); *(star_vertex++) = static_cast<float>(brightness);
} }
std::cout << "TOTAL STARLIGHT: " << starlight_illuminance << std::endl;
// Unload star catalog // Unload star catalog
ctx.resource_manager->unload("stars.csv"); ctx.resource_manager->unload("stars.csv");
@ -203,17 +210,28 @@ void create_sun(game::context& ctx)
ctx.astronomy_system->set_sky_light(sky_light); ctx.astronomy_system->set_sky_light(sky_light);
} }
void create_planet(game::context& ctx)
void create_em_bary(game::context& ctx)
{ {
// Create planet entity
entity::archetype* planet_archetype = ctx.resource_manager->load<entity::archetype>("planet.ent");
entity::id planet_eid = planet_archetype->create(*ctx.entity_registry);
ctx.entities["planet"] = planet_eid;
// 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;
// Assign orbital parent // Assign orbital parent
ctx.entity_registry->get<entity::component::orbit>(planet_eid).parent = ctx.entities["sun"];
ctx.entity_registry->get<entity::component::orbit>(em_bary_eid).parent = ctx.entities["sun"];
}
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;
// Assign planetary terrain component
// 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; entity::component::terrain terrain;
terrain.elevation = [](double, double) -> double terrain.elevation = [](double, double) -> double
{ {
@ -222,10 +240,10 @@ void create_planet(game::context& ctx)
}; };
terrain.max_lod = 0; terrain.max_lod = 0;
terrain.patch_material = nullptr; terrain.patch_material = nullptr;
//ctx.entity_registry->assign<entity::component::terrain>(planet_eid, terrain);
//ctx.entity_registry->assign<entity::component::terrain>(earth_eid, terrain);
// Pass planet to astronomy system as reference body
ctx.astronomy_system->set_reference_body(planet_eid);
// Pass earth to astronomy system as reference body
ctx.astronomy_system->set_reference_body(earth_eid);
} }
void create_moon(game::context& ctx) void create_moon(game::context& ctx)
@ -236,10 +254,22 @@ void create_moon(game::context& ctx)
ctx.entities["moon"] = moon_eid; ctx.entities["moon"] = moon_eid;
// Assign orbital parent // Assign orbital parent
ctx.entity_registry->get<entity::component::orbit>(moon_eid).parent = ctx.entities["planet"];
ctx.entity_registry->get<entity::component::orbit>(moon_eid).parent = ctx.entities["em_bary"];
// Pass moon model to sky pass // Pass moon model to sky pass
ctx.sky_pass->set_moon_model(ctx.resource_manager->load<render::model>("moon.mdl")); 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({1, 1, 1});
moon_light->set_intensity(1.0f);
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) void set_time(game::context& ctx, double t)

+ 5
- 2
src/game/world.hpp View File

@ -33,8 +33,11 @@ void create_stars(game::context& ctx);
/// Creates the sun. /// Creates the sun.
void create_sun(game::context& ctx); void create_sun(game::context& ctx);
/// Creates the planet.
void create_planet(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. /// Creates the moon.
void create_moon(game::context& ctx); void create_moon(game::context& ctx);

+ 47
- 0
src/geom/solid-angle.hpp View File

@ -0,0 +1,47 @@
/*
* 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_GEOM_SOLID_ANGLE_HPP
#define ANTKEEPER_GEOM_SOLID_ANGLE_HPP
#include "math/constants.hpp"
#include <cmath>
namespace geom {
/// Solid angle functions.
namespace solid_angle {
/**
* Calculates the solid angle of a cone.
*
* @param theta Apex angle of the cone, in radians.
*
* @return Solid angle of the cone, in steradians.
*/
template <class T>
T cone(T theta)
{
return math::two_pi<T> * (T(1) - std::cos(theta));
}
} // namespace solid_angle
} // namespace geom
#endif // ANTKEEPER_GEOM_SOLID_ANGLE_HPP

+ 8
- 6
src/physics/light/blackbody.hpp View File

@ -57,10 +57,11 @@ T radiant_flux(T t, T a);
* *
* @param t Temperature of the blackbody, in kelvin. * @param t Temperature of the blackbody, in kelvin.
* @param a Surface area of the blackbody, in square meters. * @param a Surface area of the blackbody, in square meters.
* @param omega Solid angle, in steradians.
* @return Radiant intensity of the blackbody, in watt per steradian. * @return Radiant intensity of the blackbody, in watt per steradian.
*/ */
template <class T> template <class T>
T radiant_intensity(T t, T a);
T radiant_intensity(T t, T a, T omega);
/** /**
* Calculates the spectral exitance of a blackbody for the given wavelength. * Calculates the spectral exitance of a blackbody for the given wavelength.
@ -91,11 +92,12 @@ T spectral_flux(T t, T a, T lambda, T c = constants::speed_of_light);
* @param t Temperature of the blackbody, in kelvin. * @param t Temperature of the blackbody, in kelvin.
* @param a Surface area of the blackbody, in square meters. * @param a Surface area of the blackbody, in square meters.
* @param lambda Wavelength of light, in meters. * @param lambda Wavelength of light, in meters.
* @param omega Solid angle, in steradians.
* @param c Speed of light in medium. * @param c Speed of light in medium.
* @return Spectral intensity of the blackbody for the given wavelength, in watt per steradian per meter. * @return Spectral intensity of the blackbody for the given wavelength, in watt per steradian per meter.
*/ */
template <class T> template <class T>
T spectral_intensity(T t, T a, T lambda, T c = constants::speed_of_light<T>);
T spectral_intensity(T t, T a, T lambda, T omega, T c = constants::speed_of_light<T>);
/** /**
* Calculates the spectral radiance of a blackbody for the given wavelength. * Calculates the spectral radiance of a blackbody for the given wavelength.
@ -122,9 +124,9 @@ T radiant_flux(T t, T a)
} }
template <class T> template <class T>
T radiant_intensity(T t, T a)
T radiant_intensity(T t, T a, T omega)
{ {
return radiant_flux(t, a) / (T(4) * math::pi<T>);
return radiant_flux(t, a) / omega;
} }
template <class T> template <class T>
@ -149,9 +151,9 @@ T spectral_flux(T t, T a, T lambda, T c)
} }
template <class T> template <class T>
T spectral_intensity(T t, T a, T lambda, T c)
T spectral_intensity(T t, T a, T lambda, T omega, T c)
{ {
return spectral_flux(t, a, lambda, c) / (T(4) * math::pi<T>);
return spectral_flux(t, a, lambda, c) / omega;
} }
template <class T> template <class T>

+ 5
- 4
src/physics/orbit/frame.hpp View File

@ -211,9 +211,9 @@ namespace bci {
{ {
const math::quaternion<T> r = math::normalize const math::quaternion<T> r = math::normalize
( (
math::quaternion<T>::rotate_z(-w) *
math::quaternion<T>::rotate_z(-math::half_pi<T> - ra) *
math::quaternion<T>::rotate_x(-math::half_pi<T> + dec) * math::quaternion<T>::rotate_x(-math::half_pi<T> + dec) *
math::quaternion<T>::rotate_z(-math::half_pi<T> - ra)
math::quaternion<T>::rotate_z(-w)
); );
return math::transformation::se3<T>{{T(0), T(0), T(0)}, r}; return math::transformation::se3<T>{{T(0), T(0), T(0)}, r};
@ -296,9 +296,10 @@ namespace bcbf {
{ {
const math::quaternion<T> r = math::normalize const math::quaternion<T> r = math::normalize
( (
math::quaternion<T>::rotate_z(math::half_pi<T> + ra) *
math::quaternion<T>::rotate_z(w) *
math::quaternion<T>::rotate_x(math::half_pi<T> - dec) * math::quaternion<T>::rotate_x(math::half_pi<T> - dec) *
math::quaternion<T>::rotate_z(w)
math::quaternion<T>::rotate_z(math::half_pi<T> + ra)
); );
return math::transformation::se3<T>{{T(0), T(0), T(0)}, r}; return math::transformation::se3<T>{{T(0), T(0), T(0)}, r};

+ 77
- 0
src/physics/time/gregorian.hpp View File

@ -0,0 +1,77 @@
/*
* 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_GREGORIAN_HPP
#define ANTKEEPER_PHYSICS_TIME_GREGORIAN_HPP
#include "physics/time/jd.hpp"
namespace physics {
namespace time {
// Gregorian calender time.
namespace gregorian {
/**
* Calculates the JD time from a Gregorian date and time. Valid for all dates after November 23, 4713.
*
* @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)`.
* @param utc UTC offset.
*
* @return JD time.
*
* @see L. E. Doggett, Ch. 12, "Calendars", p. 606, in Seidelmann 1992
*/
template <class T>
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);
}
/**
* Calculates the UT1 time from a Gregorian date and time. Valid for all dates after November 23, 4713.
*
* @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)`.
* @param utc UTC offset.
*
* @return UT1 time.
*/
template <class T>
T to_ut1(int year, int month, int day, int hour, int minute, T second, T utc)
{
return physics::time::jd::to_ut1<T>(to_jd<T>(year, month, day, hour, minute, second, utc));
}
} // namespace gregorian
} // namespace time
} // namespace physics
#endif // ANTKEEPER_PHYSICS_TIME_GREGORIAN_HPP

src/astro/apparent-size.cpp → src/physics/time/jd.hpp View File

@ -17,15 +17,30 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "apparent-size.hpp"
#include <cmath>
#ifndef ANTKEEPER_PHYSICS_TIME_JD_HPP
#define ANTKEEPER_PHYSICS_TIME_JD_HPP
namespace astro
{
namespace physics {
namespace time {
// Julian day (JD)
namespace jd {
double find_angular_radius(double radius, double distance)
/**
* Converts JD to UT1
*
* @param t JD time.
* @return UT1 time.
*/
template <class T>
T to_ut1(T t)
{ {
return std::asin(radius / distance);
return t - T(2451545);
} }
} // namespace astro
} // namespace jd
} // namespace time
} // namespace physics
#endif // ANTKEEPER_PHYSICS_TIME_JD_HPP

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

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

+ 13
- 4
src/physics/time/ut1.hpp View File

@ -25,18 +25,27 @@
namespace physics { namespace physics {
namespace time { namespace time {
/// Functions which operate on UT1 universal time.
/// UT1 universal time.
namespace ut1 { namespace ut1 {
/**
* Converts UT1 to JD
*
* @param t UT1 time.
* @return JD time.
*/
template <class T>
T to_jd(T t)
{
return t + T(2451545);
}
/** /**
* Calculates the Earth Rotation Angle (ERA) at a given UT1 date. * Calculates the Earth Rotation Angle (ERA) at a given UT1 date.
* *
* @param t J2000 UT1 date. * @param t J2000 UT1 date.
* @return ERA at the given date, in radians. * @return ERA at the given date, in radians.
*/ */
template <class T>
T era(T t);
template <class T> template <class T>
T era(T t) T era(T t)
{ {

+ 5
- 1
src/render/passes/ground-pass.cpp View File

@ -123,7 +123,11 @@ void ground_pass::render(const render::context& ctx, render::queue& queue) const
const scene::directional_light* directional_light = static_cast<const scene::directional_light*>(light); const scene::directional_light* directional_light = static_cast<const scene::directional_light*>(light);
// Pre-expose light // Pre-expose light
directional_light_color = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure;
float3 light_color = light->get_scaled_color_tween().interpolate(ctx.alpha) * ctx.exposure;
if (light_color.x < directional_light_color.x)
break;
directional_light_color = light_color;
directional_light_direction = static_cast<const scene::directional_light*>(light)->get_direction_tween().interpolate(ctx.alpha); directional_light_direction = static_cast<const scene::directional_light*>(light)->get_direction_tween().interpolate(ctx.alpha);
break; break;

+ 79
- 20
src/render/passes/sky-pass.cpp View File

@ -74,7 +74,15 @@ sky_pass::sky_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffe
sun_illuminance_outer_tween(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>), sun_illuminance_outer_tween(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>),
sun_illuminance_inner_tween(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>), sun_illuminance_inner_tween(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>),
icrf_to_eus_translation({0, 0, 0}, math::lerp<float3, float>), icrf_to_eus_translation({0, 0, 0}, math::lerp<float3, float>),
icrf_to_eus_rotation(math::quaternion<float>::identity(), math::nlerp<float>)
icrf_to_eus_rotation(math::quaternion<float>::identity(), math::nlerp<float>),
moon_position_tween(float3{0, 0, 0}, math::lerp<float3, float>),
moon_rotation_tween(math::quaternion<float>::identity(), math::nlerp<float>),
moon_angular_radius_tween(0.0f, math::lerp<float, float>),
moon_sunlight_direction_tween(float3{0, 0, 0}, math::lerp<float3, float>),
moon_sunlight_illuminance_tween(float3{0, 0, 0}, math::lerp<float3, float>),
moon_planetlight_direction_tween(float3{0, 0, 0}, math::lerp<float3, float>),
moon_planetlight_illuminance_tween(float3{0, 0, 0}, math::lerp<float3, float>),
magnification(1.0f)
{} {}
sky_pass::~sky_pass() sky_pass::~sky_pass()
@ -146,8 +154,8 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const
if (sun_direction_input) if (sun_direction_input)
sun_direction_input->upload(sun_direction); sun_direction_input->upload(sun_direction);
if (sun_angular_radius_input) if (sun_angular_radius_input)
sun_angular_radius_input->upload(sun_angular_radius);
sun_angular_radius_input->upload(sun_angular_radius * magnification);
// Pre-exposure sun color // Pre-exposure sun color
if (sun_illuminance_input) if (sun_illuminance_input)
sun_illuminance_input->upload(sun_illuminance_outer * ctx.exposure); sun_illuminance_input->upload(sun_illuminance_outer * ctx.exposure);
@ -218,38 +226,43 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const
rasterizer->draw_arrays(*stars_model_vao, stars_model_drawing_mode, stars_model_start_index, stars_model_index_count); rasterizer->draw_arrays(*stars_model_vao, stars_model_drawing_mode, stars_model_start_index, stars_model_index_count);
} }
/*
// Draw moon model // Draw moon model
float3 moon_position = moon_position_tween.interpolate(ctx.alpha); float3 moon_position = moon_position_tween.interpolate(ctx.alpha);
float moon_angular_radius = math::radians(2.0f);
if (moon_position.y >= -moon_angular_radius)
float moon_angular_radius = moon_angular_radius_tween.interpolate(ctx.alpha) * magnification;
//if (moon_position.y >= -moon_angular_radius)
{ {
float moon_distance = (clip_near + clip_far) * 0.5f; float moon_distance = (clip_near + clip_far) * 0.5f;
float moon_radius = moon_angular_radius * moon_distance; float moon_radius = moon_angular_radius * moon_distance;
math::transform<float> moon_transform; math::transform<float> moon_transform;
moon_transform.translation = moon_position * -moon_distance;
moon_transform.rotation = math::quaternion<float>::identity();
moon_transform.translation = math::normalize(moon_position) * moon_distance;
moon_transform.rotation = moon_rotation_tween.interpolate(ctx.alpha);
moon_transform.scale = {moon_radius, moon_radius, moon_radius}; moon_transform.scale = {moon_radius, moon_radius, moon_radius};
model = math::matrix_cast(moon_transform); model = math::matrix_cast(moon_transform);
model_view = view * model;
model_view_projection = projection * model_view;
float3x3 normal_model = math::transpose(math::inverse(math::resize<3, 3>(model))); float3x3 normal_model = math::transpose(math::inverse(math::resize<3, 3>(model)));
rasterizer->use_program(*moon_shader_program); rasterizer->use_program(*moon_shader_program);
if (moon_model_view_projection_input)
moon_model_view_projection_input->upload(model_view_projection);
if (moon_model_input)
moon_model_input->upload(model);
if (moon_view_projection_input)
moon_view_projection_input->upload(view_projection);
if (moon_normal_model_input) if (moon_normal_model_input)
moon_normal_model_input->upload(normal_model); moon_normal_model_input->upload(normal_model);
if (moon_moon_position_input)
moon_moon_position_input->upload(moon_position);
if (moon_sun_position_input)
moon_sun_position_input->upload(sun_position);
if (moon_camera_position_input)
moon_camera_position_input->upload(ctx.camera_transform.translation);
if (moon_sunlight_direction_input)
moon_sunlight_direction_input->upload(math::normalize(moon_sunlight_direction_tween.interpolate(ctx.alpha)));
if (moon_planetlight_direction_input)
moon_planetlight_direction_input->upload(math::normalize(moon_planetlight_direction_tween.interpolate(ctx.alpha)));
if (moon_sunlight_illuminance_input)
moon_sunlight_illuminance_input->upload(moon_sunlight_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure);
if (moon_planetlight_illuminance_input)
moon_planetlight_illuminance_input->upload(moon_planetlight_illuminance_tween.interpolate(ctx.alpha) * ctx.exposure);
moon_material->upload(ctx.alpha); moon_material->upload(ctx.alpha);
rasterizer->draw_arrays(*moon_model_vao, moon_model_drawing_mode, moon_model_start_index, moon_model_index_count); rasterizer->draw_arrays(*moon_model_vao, moon_model_drawing_mode, moon_model_start_index, moon_model_index_count);
} }
*/
} }
void sky_pass::set_sky_model(const model* model) void sky_pass::set_sky_model(const model* model)
@ -322,10 +335,14 @@ void sky_pass::set_moon_model(const model* model)
if (moon_shader_program) if (moon_shader_program)
{ {
moon_model_view_projection_input = moon_shader_program->get_input("model_view_projection");
moon_model_input = moon_shader_program->get_input("model");
moon_view_projection_input = moon_shader_program->get_input("view_projection");
moon_normal_model_input = moon_shader_program->get_input("normal_model"); moon_normal_model_input = moon_shader_program->get_input("normal_model");
moon_moon_position_input = moon_shader_program->get_input("moon_position");
moon_sun_position_input = moon_shader_program->get_input("sun_position");
moon_camera_position_input = moon_shader_program->get_input("camera_position");
moon_sunlight_direction_input = moon_shader_program->get_input("sunlight_direction");
moon_sunlight_illuminance_input = moon_shader_program->get_input("sunlight_illuminance");
moon_planetlight_direction_input = moon_shader_program->get_input("planetlight_direction");
moon_planetlight_illuminance_input = moon_shader_program->get_input("planetlight_illuminance");
} }
} }
} }
@ -416,7 +433,19 @@ void sky_pass::update_tweens()
sun_illuminance_inner_tween.update(); sun_illuminance_inner_tween.update();
icrf_to_eus_translation.update(); icrf_to_eus_translation.update();
icrf_to_eus_rotation.update(); icrf_to_eus_rotation.update();
moon_position_tween.update(); moon_position_tween.update();
moon_rotation_tween.update();
moon_angular_radius_tween.update();
moon_sunlight_direction_tween.update();
moon_sunlight_illuminance_tween.update();
moon_planetlight_direction_tween.update();
moon_planetlight_illuminance_tween.update();
}
void sky_pass::set_magnification(float magnification)
{
this->magnification = magnification;
} }
void sky_pass::set_icrf_to_eus(const math::transformation::se3<float>& transformation) void sky_pass::set_icrf_to_eus(const math::transformation::se3<float>& transformation)
@ -474,6 +503,36 @@ void sky_pass::set_moon_position(const float3& position)
moon_position_tween[1] = position; moon_position_tween[1] = position;
} }
void sky_pass::set_moon_rotation(const math::quaternion<float>& rotation)
{
moon_rotation_tween[1] = rotation;
}
void sky_pass::set_moon_angular_radius(float angular_radius)
{
moon_angular_radius_tween[1] = angular_radius;
}
void sky_pass::set_moon_sunlight_direction(const float3& direction)
{
moon_sunlight_direction_tween[1] = direction;
}
void sky_pass::set_moon_sunlight_illuminance(const float3& illuminance)
{
moon_sunlight_illuminance_tween[1] = illuminance;
}
void sky_pass::set_moon_planetlight_direction(const float3& direction)
{
moon_planetlight_direction_tween[1] = direction;
}
void sky_pass::set_moon_planetlight_illuminance(const float3& illuminance)
{
moon_planetlight_illuminance_tween[1] = illuminance;
}
void sky_pass::handle_event(const mouse_moved_event& event) void sky_pass::handle_event(const mouse_moved_event& event)
{ {
mouse_position = {static_cast<float>(event.x), static_cast<float>(event.y)}; mouse_position = {static_cast<float>(event.x), static_cast<float>(event.y)};

+ 23
- 4
src/render/passes/sky-pass.hpp View File

@ -55,6 +55,8 @@ public:
void update_tweens(); void update_tweens();
void set_magnification(float scale);
void set_sky_model(const model* model); void set_sky_model(const model* model);
void set_moon_model(const model* model); void set_moon_model(const model* model);
void set_stars_model(const model* model); void set_stars_model(const model* model);
@ -72,6 +74,12 @@ public:
void set_atmosphere_radii(float inner, float outer); void set_atmosphere_radii(float inner, float outer);
void set_moon_position(const float3& position); void set_moon_position(const float3& position);
void set_moon_rotation(const math::quaternion<float>& rotation);
void set_moon_angular_radius(float angular_radius);
void set_moon_sunlight_direction(const float3& direction);
void set_moon_sunlight_illuminance(const float3& illuminance);
void set_moon_planetlight_direction(const float3& direction);
void set_moon_planetlight_illuminance(const float3& illuminance);
private: private:
virtual void handle_event(const mouse_moved_event& event); virtual void handle_event(const mouse_moved_event& event);
@ -93,10 +101,14 @@ private:
const gl::shader_input* atmosphere_radii_input; const gl::shader_input* atmosphere_radii_input;
gl::shader_program* moon_shader_program; gl::shader_program* moon_shader_program;
const gl::shader_input* moon_model_view_projection_input;
const gl::shader_input* moon_model_input;
const gl::shader_input* moon_view_projection_input;
const gl::shader_input* moon_normal_model_input; const gl::shader_input* moon_normal_model_input;
const gl::shader_input* moon_moon_position_input;
const gl::shader_input* moon_sun_position_input;
const gl::shader_input* moon_camera_position_input;
const gl::shader_input* moon_sunlight_direction_input;
const gl::shader_input* moon_sunlight_illuminance_input;
const gl::shader_input* moon_planetlight_direction_input;
const gl::shader_input* moon_planetlight_illuminance_input;
const model* sky_model; const model* sky_model;
const material* sky_material; const material* sky_material;
@ -151,7 +163,12 @@ private:
tween<math::quaternion<float>> icrf_to_eus_rotation; tween<math::quaternion<float>> icrf_to_eus_rotation;
tween<float3> moon_position_tween; tween<float3> moon_position_tween;
tween<math::quaternion<float>> moon_rotation_tween;
tween<float> moon_angular_radius_tween;
tween<float3> moon_sunlight_direction_tween;
tween<float3> moon_sunlight_illuminance_tween;
tween<float3> moon_planetlight_direction_tween;
tween<float3> moon_planetlight_illuminance_tween;
float sun_angular_radius; float sun_angular_radius;
float2 scale_height_rm; float2 scale_height_rm;
@ -159,6 +176,8 @@ private:
float3 mie_scattering; float3 mie_scattering;
float2 mie_anisotropy; float2 mie_anisotropy;
float3 atmosphere_radii; float3 atmosphere_radii;
float magnification;
}; };
} // namespace render } // namespace render

+ 19
- 0
src/resources/entity-archetype-loader.cpp View File

@ -23,6 +23,7 @@
#include "entity/components/atmosphere.hpp" #include "entity/components/atmosphere.hpp"
#include "entity/components/behavior.hpp" #include "entity/components/behavior.hpp"
#include "entity/components/collision.hpp" #include "entity/components/collision.hpp"
#include "entity/components/diffuse-reflector.hpp"
#include "entity/components/terrain.hpp" #include "entity/components/terrain.hpp"
#include "entity/components/transform.hpp" #include "entity/components/transform.hpp"
#include "entity/components/model.hpp" #include "entity/components/model.hpp"
@ -103,6 +104,7 @@ static bool load_component_celestial_body(entity::archetype& archetype, const js
component.pole_dec = 0.0; component.pole_dec = 0.0;
component.prime_meridian = 0.0; component.prime_meridian = 0.0;
component.rotation_period = 0.0; component.rotation_period = 0.0;
component.albedo = 0.0;
if (element.contains("radius")) if (element.contains("radius"))
component.radius = element["radius"].get<double>(); component.radius = element["radius"].get<double>();
@ -116,6 +118,8 @@ static bool load_component_celestial_body(entity::archetype& archetype, const js
component.prime_meridian = math::radians(element["prime_meridian"].get<double>()); component.prime_meridian = math::radians(element["prime_meridian"].get<double>());
if (element.contains("rotation_period")) if (element.contains("rotation_period"))
component.rotation_period = element["rotation_period"].get<double>(); component.rotation_period = element["rotation_period"].get<double>();
if (element.contains("albedo"))
component.albedo = element["albedo"].get<double>();
archetype.set<entity::component::celestial_body>(component); archetype.set<entity::component::celestial_body>(component);
@ -137,6 +141,19 @@ static bool load_component_collision(entity::archetype& archetype, resource_mana
return (component.mesh != nullptr); return (component.mesh != nullptr);
} }
static bool load_component_diffuse_reflector(entity::archetype& archetype, const json& element)
{
entity::component::diffuse_reflector component;
component.albedo = 0.0;
if (element.contains("albedo"))
component.albedo = element["albedo"].get<double>();
archetype.set<entity::component::diffuse_reflector>(component);
return true;
}
static bool load_component_model(entity::archetype& archetype, resource_manager& resource_manager, const json& element) static bool load_component_model(entity::archetype& archetype, resource_manager& resource_manager, const json& element)
{ {
entity::component::model component; entity::component::model component;
@ -236,6 +253,8 @@ static bool load_component(entity::archetype& archetype, resource_manager& resou
return load_component_celestial_body(archetype, element.value()); return load_component_celestial_body(archetype, element.value());
if (element.key() == "collision") if (element.key() == "collision")
return load_component_collision(archetype, resource_manager, element.value()); return load_component_collision(archetype, resource_manager, element.value());
if (element.key() == "diffuse_reflector")
return load_component_diffuse_reflector(archetype, element.value());
if (element.key() == "model") if (element.key() == "model")
return load_component_model(archetype, resource_manager, element.value()); return load_component_model(archetype, resource_manager, element.value());
if (element.key() == "orbit") if (element.key() == "orbit")

Loading…
Cancel
Save