From bfcd5f14e2ba3ec97b67062198d8050c8b530107 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 3 Jun 2021 15:04:06 +0800 Subject: [PATCH] Re-add celestial body component, separate blackbody functionality out of astronomy system into new blackbody system --- CMakeLists.txt | 1 - src/ecs/components/blackbody-component.hpp | 3 - .../components/celestial-body-component.hpp | 43 ++++++ src/ecs/systems/astronomy-system.cpp | 135 ++++++------------ src/ecs/systems/astronomy-system.hpp | 34 ++--- src/ecs/systems/blackbody-system.cpp | 111 ++++++++++++++ src/ecs/systems/blackbody-system.hpp | 59 ++++++++ src/game/bootloader.cpp | 5 + src/game/game-context.hpp | 2 + src/game/states/play-state.cpp | 21 ++- 10 files changed, 296 insertions(+), 118 deletions(-) create mode 100644 src/ecs/components/celestial-body-component.hpp create mode 100644 src/ecs/systems/blackbody-system.cpp create mode 100644 src/ecs/systems/blackbody-system.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index af368e1..d4aa351 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.7) - option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) diff --git a/src/ecs/components/blackbody-component.hpp b/src/ecs/components/blackbody-component.hpp index 68e4370..18cfbbd 100644 --- a/src/ecs/components/blackbody-component.hpp +++ b/src/ecs/components/blackbody-component.hpp @@ -28,9 +28,6 @@ struct blackbody_component /// Effective temperature, in Kelvin. double temperature; - /// Blackbody radius, in meters. - double radius; - /// (Dependent) RGB luminous intensity, in candela. double3 luminous_intensity; }; diff --git a/src/ecs/components/celestial-body-component.hpp b/src/ecs/components/celestial-body-component.hpp new file mode 100644 index 0000000..5ae1613 --- /dev/null +++ b/src/ecs/components/celestial-body-component.hpp @@ -0,0 +1,43 @@ +/* + * 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 . + */ + +#ifndef ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP +#define ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP + +namespace ecs { + +/// A simple celestial body. +struct celestial_body_component +{ + /// Body radius, in meters. + double radius; + + /// Angle between the body's rotational axis and its orbital axis, in radians. + double axial_tilt; + + /// Angle of rotation about the body's rotational axis at epoch, in radians. + double axial_rotation; + + /// Angular frequency, in radians per day. + double angular_frequency; +}; + +} // namespace ecs + +#endif // ANTKEEPER_ECS_CELESTIAL_BODY_COMPONENT_HPP diff --git a/src/ecs/systems/astronomy-system.cpp b/src/ecs/systems/astronomy-system.cpp index 7ffbfed..b728376 100644 --- a/src/ecs/systems/astronomy-system.cpp +++ b/src/ecs/systems/astronomy-system.cpp @@ -19,20 +19,16 @@ #include "ecs/systems/astronomy-system.hpp" #include "astro/apparent-size.hpp" -#include "ecs/components/orbit-component.hpp" #include "ecs/components/blackbody-component.hpp" -#include "ecs/components/atmosphere-component.hpp" #include "ecs/components/transform-component.hpp" #include "geom/intersection.hpp" #include "color/color.hpp" #include "physics/orbit/orbit.hpp" #include "physics/time/ut1.hpp" -#include "physics/light/blackbody.hpp" #include "physics/light/photometry.hpp" #include "physics/light/luminosity.hpp" #include "physics/light/refraction.hpp" #include "physics/atmosphere.hpp" -#include "math/quadrature.hpp" #include "geom/cartesian.hpp" #include @@ -57,9 +53,10 @@ astronomy_system::astronomy_system(ecs::registry& registry): entity_system(registry), universal_time(0.0), time_scale(1.0), - reference_body(entt::null), - reference_body_axial_tilt(0.0), - reference_body_axial_rotation(0.0), + reference_entity(entt::null), + reference_orbit(nullptr), + reference_body(nullptr), + reference_atmosphere(nullptr), sun_light(nullptr), sky_pass(nullptr) { @@ -67,9 +64,6 @@ astronomy_system::astronomy_system(ecs::registry& registry): rgb_wavelengths_nm = {602.224, 541.069, 448.143}; rgb_wavelengths_m = rgb_wavelengths_nm * 1e-9; - registry.on_construct().connect<&astronomy_system::on_blackbody_construct>(this); - registry.on_replace().connect<&astronomy_system::on_blackbody_replace>(this); - registry.on_construct().connect<&astronomy_system::on_atmosphere_construct>(this); registry.on_replace().connect<&astronomy_system::on_atmosphere_replace>(this); } @@ -79,35 +73,28 @@ void astronomy_system::update(double t, double dt) // Add scaled timestep to current time set_universal_time(universal_time + dt * time_scale); - // Abort if reference body has not been set - if (reference_body == entt::null) - return; - - // Abort if reference body has no orbit component - if (!registry.has(reference_body)) + // Abort if either reference body or orbit have not been set + if (!reference_orbit || !reference_body) return; - // Update axial rotation of reference body - reference_body_axial_rotation = physics::time::ut1::era(universal_time); - - // Get orbit component of reference body - const auto& reference_orbit = registry.get(reference_body); + // Determine axial rotation at current time + const double reference_axial_rotation = reference_body->axial_rotation + reference_body->angular_frequency * universal_time; - /// Construct reference frame which transforms coordinates from inertial space to reference body BCBF space + // Construct reference frame which transforms coordinates from inertial space to reference body BCBF space inertial_to_bcbf = physics::orbit::inertial::to_bcbf ( - reference_orbit.state.r, - reference_orbit.elements.i, - reference_body_axial_tilt, - reference_body_axial_rotation + reference_orbit->state.r, + reference_orbit->elements.i, + reference_body->axial_tilt, + reference_axial_rotation ); - /// Construct reference frame which transforms coordinates from inertial space to reference body topocentric space + // Construct reference frame which transforms coordinates from inertial space to reference body topocentric space inertial_to_topocentric = inertial_to_bcbf * bcbf_to_topocentric; // Set the transform component translations of orbiting bodies to their topocentric positions registry.view().each( - [&](ecs::entity entity, auto& orbit, auto& transform) + [&](ecs::entity entity, const auto& orbit, auto& transform) { // Transform Cartesian position vector (r) from inertial space to topocentric space const math::vector3 r_topocentric = inertial_to_topocentric * orbit.state.r; @@ -116,14 +103,12 @@ void astronomy_system::update(double t, double dt) transform.local.translation = math::type_cast(r_topocentric); }); - const double earth_radius = 6.3781e6; - // Update blackbody lighting - registry.view().each( - [&](ecs::entity entity, auto& blackbody, auto& orbit) + registry.view().each( + [&](ecs::entity entity, const auto& celestial_body, const auto& orbit, const auto& blackbody) { // Calculate blackbody inertial basis - double3 blackbody_forward_inertial = math::normalize(reference_orbit.state.r - orbit.state.r); + double3 blackbody_forward_inertial = math::normalize(reference_orbit->state.r - orbit.state.r); double3 blackbody_up_inertial = {0, 0, 1}; // Transform blackbody inertial position and basis into topocentric space @@ -141,10 +126,8 @@ void astronomy_system::update(double t, double dt) double3 atmospheric_transmittance = {1.0, 1.0, 1.0}; // Get atmosphere component of reference body (if any) - if (this->registry.has(reference_body)) + if (reference_atmosphere) { - const ecs::atmosphere_component& atmosphere = this->registry.get(reference_body); - // Altitude of observer in meters geom::ray sample_ray; sample_ray.origin = {0, observer_location[0], 0}; @@ -152,7 +135,7 @@ void astronomy_system::update(double t, double dt) geom::sphere exosphere; exosphere.center = {0, 0, 0}; - exosphere.radius = earth_radius + atmosphere.exosphere_altitude; + exosphere.radius = reference_body->radius + reference_atmosphere->exosphere_altitude; auto intersection_result = geom::ray_sphere_intersection(sample_ray, exosphere); @@ -161,11 +144,11 @@ void astronomy_system::update(double t, double dt) double3 sample_start = sample_ray.origin; double3 sample_end = sample_ray.extrapolate(std::get<2>(intersection_result)); - double optical_depth_r = physics::atmosphere::optical_depth(sample_start, sample_end, earth_radius, atmosphere.rayleigh_scale_height, 32); - double optical_depth_k = physics::atmosphere::optical_depth(sample_start, sample_end, earth_radius, atmosphere.mie_scale_height, 32); + double optical_depth_r = physics::atmosphere::optical_depth(sample_start, sample_end, reference_body->radius, reference_atmosphere->rayleigh_scale_height, 32); + double optical_depth_k = physics::atmosphere::optical_depth(sample_start, sample_end, reference_body->radius, reference_atmosphere->mie_scale_height, 32); double optical_depth_o = 0.0; - atmospheric_transmittance = transmittance(optical_depth_r, optical_depth_k, optical_depth_o, atmosphere.rayleigh_scattering, atmosphere.mie_scattering); + atmospheric_transmittance = transmittance(optical_depth_r, optical_depth_k, optical_depth_o, reference_atmosphere->rayleigh_scattering, reference_atmosphere->mie_scattering); } } @@ -192,7 +175,7 @@ void astronomy_system::update(double t, double dt) this->sky_pass->set_sun_position(math::type_cast(blackbody_position_topocentric)); this->sky_pass->set_sun_color(math::type_cast(blackbody.luminous_intensity * distance_attenuation)); - double blackbody_angular_radius = std::asin((blackbody.radius * 2.0) / (blackbody_distance * 2.0)); + double blackbody_angular_radius = std::asin((celestial_body.radius * 2.0) / (blackbody_distance * 2.0)); this->sky_pass->set_sun_angular_radius(static_cast(blackbody_angular_radius)); } } @@ -212,18 +195,16 @@ void astronomy_system::update(double t, double dt) ); // Upload observer altitude to sky pass - float observer_altitude = observer_location[0] - earth_radius; + float observer_altitude = observer_location[0] - reference_body->radius; sky_pass->set_observer_altitude(observer_altitude); // Upload atmosphere params to sky pass - if (this->registry.has(reference_body)) + if (reference_atmosphere) { - const ecs::atmosphere_component& atmosphere = this->registry.get(reference_body); - - sky_pass->set_scale_heights(atmosphere.rayleigh_scale_height, atmosphere.mie_scale_height); - sky_pass->set_scattering_coefficients(math::type_cast(atmosphere.rayleigh_scattering), math::type_cast(atmosphere.mie_scattering)); - sky_pass->set_mie_anisotropy(atmosphere.mie_anisotropy); - sky_pass->set_atmosphere_radii(earth_radius, earth_radius + atmosphere.exosphere_altitude); + sky_pass->set_scale_heights(reference_atmosphere->rayleigh_scale_height, reference_atmosphere->mie_scale_height); + sky_pass->set_scattering_coefficients(math::type_cast(reference_atmosphere->rayleigh_scattering), math::type_cast(reference_atmosphere->mie_scattering)); + sky_pass->set_mie_anisotropy(reference_atmosphere->mie_anisotropy); + sky_pass->set_atmosphere_radii(reference_body->radius, reference_body->radius + reference_atmosphere->exosphere_altitude); } } } @@ -240,12 +221,22 @@ void astronomy_system::set_time_scale(double scale) void astronomy_system::set_reference_body(ecs::entity entity) { - reference_body = entity; -} - -void astronomy_system::set_reference_body_axial_tilt(double angle) -{ - reference_body_axial_tilt = angle; + reference_entity = entity; + reference_orbit = nullptr; + reference_body = nullptr; + reference_atmosphere = nullptr; + + if (reference_entity != entt::null) + { + if (registry.has(reference_entity)) + reference_orbit = ®istry.get(reference_entity); + + if (registry.has(reference_entity)) + reference_body = ®istry.get(reference_entity); + + if (registry.has(reference_entity)) + reference_atmosphere = ®istry.get(reference_entity); + } } void astronomy_system::set_observer_location(const double3& location) @@ -285,40 +276,6 @@ void astronomy_system::set_sky_pass(::sky_pass* pass) this->sky_pass = pass; } -void astronomy_system::on_blackbody_construct(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody) -{ - on_blackbody_replace(registry, entity, blackbody); -} - -void astronomy_system::on_blackbody_replace(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody) -{ - // Calculate the surface area of a spherical blackbody - const double surface_area = 4.0 * math::pi * blackbody.radius * blackbody.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 - { - // Convert wavelength from nanometers to meters - const double wavelength_m = wavelength_nm * 1e-9; - - // Calculate the spectral intensity of the wavelength - const double spectral_intensity = physics::light::blackbody::spectral_intensity(blackbody.temperature, surface_area, wavelength_m); - - // Calculate the ACEScg color of the wavelength using CIE color matching functions - double3 spectral_color = color::xyz::to_acescg(color::xyz::match(wavelength_nm)); - - // Scale the spectral color by spectral intensity - return spectral_color * spectral_intensity * 1e-9 * physics::light::max_luminous_efficacy; - }; - - // Construct a range of sample wavelengths in the visible spectrum - std::vector samples(780 - 280); - std::iota(samples.begin(), samples.end(), 280); - - // Integrate the blackbody RGB luminous intensity over wavelengths in the visible spectrum - blackbody.luminous_intensity = math::quadrature::simpson(rgb_luminous_intensity, samples.begin(), samples.end()); -} - void astronomy_system::on_atmosphere_construct(ecs::registry& registry, ecs::entity entity, ecs::atmosphere_component& atmosphere) { on_atmosphere_replace(registry, entity, atmosphere); diff --git a/src/ecs/systems/astronomy-system.hpp b/src/ecs/systems/astronomy-system.hpp index 20a8fd3..dc3230a 100644 --- a/src/ecs/systems/astronomy-system.hpp +++ b/src/ecs/systems/astronomy-system.hpp @@ -26,8 +26,9 @@ #include "utility/fundamental-types.hpp" #include "physics/frame.hpp" #include "renderer/passes/sky-pass.hpp" -#include "ecs/components/blackbody-component.hpp" #include "ecs/components/atmosphere-component.hpp" +#include "ecs/components/celestial-body-component.hpp" +#include "ecs/components/orbit-component.hpp" namespace ecs { @@ -63,19 +64,12 @@ public: void set_time_scale(double scale); /** - * Sets the reference body, from which observations are taking place. + * Sets the reference body entity, from which observations are taking place. * * @param entity Entity of the reference body. */ void set_reference_body(ecs::entity entity); - /** - * Sets the axial tilt of the reference body. - * - * @param angle Angle between the reference body's rotational axis and its orbital axis, in radians. - */ - void set_reference_body_axial_tilt(double angle); - /** * Sets the location of the observer using spherical coordinates in BCBF space. * @@ -88,21 +82,21 @@ public: void set_sky_pass(sky_pass* pass); private: - void on_blackbody_construct(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody); - void on_blackbody_replace(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody); - void on_atmosphere_construct(ecs::registry& registry, ecs::entity entity, ecs::atmosphere_component& atmosphere); void on_atmosphere_replace(ecs::registry& registry, ecs::entity entity, ecs::atmosphere_component& atmosphere); - double universal_time; double time_scale; - ecs::entity reference_body; - double reference_body_axial_tilt; - double reference_body_axial_rotation; + + double3 rgb_wavelengths_nm; + double3 rgb_wavelengths_m; + + ecs::entity reference_entity; + const ecs::orbit_component* reference_orbit; + const ecs::celestial_body_component* reference_body; + const ecs::atmosphere_component* reference_atmosphere; + double3 observer_location; - scene::directional_light* sun_light; - sky_pass* sky_pass; physics::frame inertial_to_bcbf; physics::frame bcbf_to_topocentric; @@ -110,8 +104,8 @@ private: physics::frame sez_to_ezs; physics::frame ezs_to_sez; - double3 rgb_wavelengths_nm; - double3 rgb_wavelengths_m; + scene::directional_light* sun_light; + sky_pass* sky_pass; }; } // namespace ecs diff --git a/src/ecs/systems/blackbody-system.cpp b/src/ecs/systems/blackbody-system.cpp new file mode 100644 index 0000000..dfde8ef --- /dev/null +++ b/src/ecs/systems/blackbody-system.cpp @@ -0,0 +1,111 @@ +/* + * 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 . + */ + +#include "ecs/systems/blackbody-system.hpp" +#include "color/color.hpp" +#include "physics/light/blackbody.hpp" +#include "physics/light/photometry.hpp" +#include "math/quadrature.hpp" + +namespace ecs { + +blackbody_system::blackbody_system(ecs::registry& registry): + entity_system(registry) +{ + // RGB wavelengths determined by matching wavelengths to XYZ, transforming XYZ to ACEScg, then selecting the max wavelengths for R, G, and B. + rgb_wavelengths_nm = {602.224, 541.069, 448.143}; + rgb_wavelengths_m = rgb_wavelengths_nm * 1e-9; + + // Construct a range of sample wavelengths in the visible spectrum + visible_wavelengths_nm.resize(780 - 280); + std::iota(visible_wavelengths_nm.begin(), visible_wavelengths_nm.end(), 280); + + registry.on_construct().connect<&blackbody_system::on_blackbody_construct>(this); + registry.on_replace().connect<&blackbody_system::on_blackbody_replace>(this); + + registry.on_construct().connect<&blackbody_system::on_celestial_body_construct>(this); + registry.on_replace().connect<&blackbody_system::on_celestial_body_replace>(this); +} + +void blackbody_system::update(double t, double dt) +{} + +void blackbody_system::update_luminous_intensity(ecs::entity entity) +{ + // Abort if entity has no blackbody component + if (!registry.has(entity)) + return; + + // Get blackbody component of the entity + blackbody_component& blackbody = registry.get(entity); + + // Clear luminous intensity + blackbody.luminous_intensity = {0, 0, 0}; + + // Abort if entity has no celestial body component + if (!registry.has(entity)) + return; + + // Get celestial body component of the entity + const celestial_body_component& celestial_body = registry.get(entity); + + // Calculate (spherical) surface area of the celestial body + const double surface_area = 4.0 * math::pi * 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 + { + // Convert wavelength from nanometers to meters + const double wavelength_m = wavelength_nm * 1e-9; + + // Calculate the spectral intensity of the wavelength + const double spectral_intensity = physics::light::blackbody::spectral_intensity(blackbody.temperature, surface_area, wavelength_m); + + // Calculate the ACEScg color of the wavelength using CIE color matching functions + double3 spectral_color = color::xyz::to_acescg(color::xyz::match(wavelength_nm)); + + // Scale the spectral color by spectral intensity + return spectral_color * spectral_intensity * 1e-9 * physics::light::max_luminous_efficacy; + }; + + // 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()); +} + +void blackbody_system::on_blackbody_construct(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody) +{ + update_luminous_intensity(entity); +} + +void blackbody_system::on_blackbody_replace(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody) +{ + update_luminous_intensity(entity); +} + +void blackbody_system::on_celestial_body_construct(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body) +{ + update_luminous_intensity(entity); +} + +void blackbody_system::on_celestial_body_replace(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body) +{ + update_luminous_intensity(entity); +} + +} // namespace ecs diff --git a/src/ecs/systems/blackbody-system.hpp b/src/ecs/systems/blackbody-system.hpp new file mode 100644 index 0000000..4715cdd --- /dev/null +++ b/src/ecs/systems/blackbody-system.hpp @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +#ifndef ANTKEEPER_ECS_BLACKBODY_SYSTEM_HPP +#define ANTKEEPER_ECS_BLACKBODY_SYSTEM_HPP + +#include "entity-system.hpp" +#include "ecs/entity.hpp" +#include "utility/fundamental-types.hpp" +#include "ecs/components/blackbody-component.hpp" +#include "ecs/components/celestial-body-component.hpp" +#include + +namespace ecs { + +/** + * Calculates the RGB luminous intensity of blackbody radiators. + */ +class blackbody_system: + public entity_system +{ +public: + blackbody_system(ecs::registry& registry); + + virtual void update(double t, double dt); + +private: + void update_luminous_intensity(ecs::entity entity); + + void on_blackbody_construct(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody); + void on_blackbody_replace(ecs::registry& registry, ecs::entity entity, ecs::blackbody_component& blackbody); + + void on_celestial_body_construct(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body); + void on_celestial_body_replace(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body); + + double3 rgb_wavelengths_nm; + double3 rgb_wavelengths_m; + std::vector visible_wavelengths_nm; +}; + +} // namespace ecs + +#endif // ANTKEEPER_ECS_BLACKBODY_SYSTEM_HPP diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index aafc153..53515eb 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -74,6 +74,7 @@ #include "ecs/systems/tracking-system.hpp" #include "ecs/systems/painting-system.hpp" #include "ecs/systems/astronomy-system.hpp" +#include "ecs/systems/blackbody-system.hpp" #include "ecs/systems/orbit-system.hpp" #include "ecs/components/marker-component.hpp" #include "ecs/commands.hpp" @@ -860,6 +861,9 @@ void setup_systems(game_context* ctx) // Setup solar system ctx->orbit_system = new ecs::orbit_system(*ctx->ecs_registry); + // Setup blackbody system + ctx->blackbody_system = new ecs::blackbody_system(*ctx->ecs_registry); + // Setup astronomy system ctx->astronomy_system = new ecs::astronomy_system(*ctx->ecs_registry); @@ -1255,6 +1259,7 @@ void setup_callbacks(game_context* ctx) ctx->tool_system->update(t, dt); ctx->orbit_system->update(t, dt); + ctx->blackbody_system->update(t, dt); ctx->astronomy_system->update(t, dt); ctx->spatial_system->update(t, dt); ctx->constraint_system->update(t, dt); diff --git a/src/game/game-context.hpp b/src/game/game-context.hpp index b9169ce..6a12136 100644 --- a/src/game/game-context.hpp +++ b/src/game/game-context.hpp @@ -83,6 +83,7 @@ namespace ecs class tracking_system; class painting_system; class astronomy_system; + class blackbody_system; class orbit_system; class behavior_system; class collision_system; @@ -247,6 +248,7 @@ struct game_context ecs::spatial_system* spatial_system; ecs::tracking_system* tracking_system; ecs::painting_system* painting_system; + ecs::blackbody_system* blackbody_system; ecs::astronomy_system* astronomy_system; ecs::orbit_system* orbit_system; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index cbedfdf..55f4329 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -33,6 +33,7 @@ #include "ecs/components/camera-follow-component.hpp" #include "ecs/components/orbit-component.hpp" #include "ecs/components/blackbody-component.hpp" +#include "ecs/components/celestial-body-component.hpp" #include "ecs/components/atmosphere-component.hpp" #include "ecs/components/light-component.hpp" #include "ecs/commands.hpp" @@ -96,6 +97,12 @@ void play_state_enter(game_context* ctx) // Create sun auto sun_entity = ecs_registry.create(); { + ecs::celestial_body_component body; + body.radius = 6.957e+8; + body.axial_tilt = math::radians(0.0); + body.axial_rotation = math::radians(0.0); + body.angular_frequency = math::radians(0.0); + ecs::orbit_component orbit; orbit.elements.a = 0.0; orbit.elements.e = 0.0; @@ -106,12 +113,12 @@ void play_state_enter(game_context* ctx) ecs::blackbody_component blackbody; blackbody.temperature = 5777.0; - blackbody.radius = 6.957e+8; ecs::transform_component transform; transform.local = math::identity_transform; transform.warp = true; + ecs_registry.assign(sun_entity, body); ecs_registry.assign(sun_entity, orbit); ecs_registry.assign(sun_entity, blackbody); ecs_registry.assign(sun_entity, transform); @@ -120,6 +127,12 @@ void play_state_enter(game_context* ctx) // Create Earth auto earth_entity = ecs_registry.create(); { + ecs::celestial_body_component body; + body.radius = 6.3781e6; + body.axial_tilt = math::radians(23.4393); + body.axial_rotation = math::radians(280.46061837504); + body.angular_frequency = math::radians(360.9856122880876128); + ecs::orbit_component orbit; orbit.elements.a = 1.496e+11; orbit.elements.e = 0.01671123; @@ -131,12 +144,10 @@ void play_state_enter(game_context* ctx) ecs::atmosphere_component atmosphere; atmosphere.exosphere_altitude = 65e3; - atmosphere.index_of_refraction = 1.000293; atmosphere.rayleigh_density = 2.545e25; - atmosphere.mie_density = 14.8875; - atmosphere.rayleigh_scale_height = 8000.0; + atmosphere.mie_density = 14.8875; atmosphere.mie_scale_height = 1200.0; atmosphere.mie_anisotropy = 0.8; @@ -144,6 +155,7 @@ void play_state_enter(game_context* ctx) transform.local = math::identity_transform; transform.warp = true; + ecs_registry.assign(earth_entity, body); ecs_registry.assign(earth_entity, orbit); ecs_registry.assign(earth_entity, atmosphere); ecs_registry.assign(earth_entity, transform); @@ -172,7 +184,6 @@ void play_state_enter(game_context* ctx) // Set astronomy system observation parameters ctx->astronomy_system->set_reference_body(earth_entity); - ctx->astronomy_system->set_reference_body_axial_tilt(math::radians(23.4393)); ctx->astronomy_system->set_observer_location(double3{6.3781e6, math::radians(0.0f), math::radians(0.0f)}); ctx->astronomy_system->set_sun_light(sun); ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass);