From d18988d9fde12fa692f3345ab2009ac6d385c7f6 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 3 Jun 2021 17:31:22 +0800 Subject: [PATCH] Make the observer position of the astronomy system relative to the radius of the reference body --- src/ecs/systems/astronomy-system.cpp | 82 +++++++++++++++++++--------- src/ecs/systems/astronomy-system.hpp | 7 ++- src/game/states/play-state.cpp | 2 +- 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/ecs/systems/astronomy-system.cpp b/src/ecs/systems/astronomy-system.cpp index fba0e1c..b2b7749 100644 --- a/src/ecs/systems/astronomy-system.cpp +++ b/src/ecs/systems/astronomy-system.cpp @@ -57,9 +57,27 @@ astronomy_system::astronomy_system(ecs::registry& registry): reference_orbit(nullptr), reference_body(nullptr), reference_atmosphere(nullptr), + observer_location{0, 0, 0}, sun_light(nullptr), sky_pass(nullptr) -{} +{ + // Construct reference frame which transforms coordinates from SEZ to EZS + sez_to_ezs = physics::frame + { + {0, 0, 0}, + math::normalize + ( + math::quaternion::rotate_x(-math::half_pi) * + math::quaternion::rotate_z(-math::half_pi) + ) + }; + + // Construct reference frame which transforms coordinates from EZS to SEZ + ezs_to_sez = sez_to_ezs.inverse(); + + registry.on_construct().connect<&astronomy_system::on_celestial_body_construct>(this); + registry.on_replace().connect<&astronomy_system::on_celestial_body_replace>(this); +} void astronomy_system::update(double t, double dt) { @@ -110,7 +128,7 @@ void astronomy_system::update(double t, double dt) double3 blackbody_up_topocentric = inertial_to_topocentric.rotation * blackbody_up_inertial; // Calculate distance from observer to blackbody - double blackbody_distance = math::length(blackbody_position_topocentric); + double blackbody_distance = math::length(blackbody_position_topocentric) - celestial_body.radius; // Calculate blackbody distance attenuation double distance_attenuation = 1.0 / (blackbody_distance * blackbody_distance); @@ -123,7 +141,7 @@ void astronomy_system::update(double t, double dt) { // Altitude of observer in meters geom::ray sample_ray; - sample_ray.origin = {0, observer_location[0], 0}; + sample_ray.origin = {0, reference_body->radius + observer_location[0], 0}; sample_ray.direction = math::normalize(blackbody_position_topocentric); geom::sphere exosphere; @@ -188,8 +206,7 @@ void astronomy_system::update(double t, double dt) ); // Upload observer altitude to sky pass - float observer_altitude = observer_location[0] - reference_body->radius; - sky_pass->set_observer_altitude(observer_altitude); + sky_pass->set_observer_altitude(observer_location[0]); // Upload atmosphere params to sky pass if (reference_atmosphere) @@ -230,33 +247,14 @@ void astronomy_system::set_reference_body(ecs::entity entity) if (registry.has(reference_entity)) reference_atmosphere = ®istry.get(reference_entity); } + + update_bcbf_to_topocentric(); } void astronomy_system::set_observer_location(const double3& location) { observer_location = location; - - // Construct reference frame which transforms coordinates from SEZ to EZS - sez_to_ezs = physics::frame - { - {0, 0, 0}, - math::normalize - ( - math::quaternion::rotate_x(-math::half_pi) * - math::quaternion::rotate_z(-math::half_pi) - ) - }; - - // Construct reference frame which transforms coordinates from EZS to SEZ - ezs_to_sez = sez_to_ezs.inverse(); - - // Construct reference frame which transforms coordinates from BCBF space to topocentric space - bcbf_to_topocentric = physics::orbit::bcbf::to_topocentric - ( - observer_location[0], // Radial distance - observer_location[1], // Latitude - observer_location[2] // Longitude - ) * sez_to_ezs; + update_bcbf_to_topocentric(); } void astronomy_system::set_sun_light(scene::directional_light* light) @@ -269,4 +267,34 @@ void astronomy_system::set_sky_pass(::sky_pass* pass) this->sky_pass = pass; } +void astronomy_system::on_celestial_body_construct(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body) +{ + if (entity == reference_entity) + update_bcbf_to_topocentric(); +} + +void astronomy_system::on_celestial_body_replace(ecs::registry& registry, ecs::entity entity, ecs::celestial_body_component& celestial_body) +{ + if (entity == reference_entity) + update_bcbf_to_topocentric(); +} + +void astronomy_system::update_bcbf_to_topocentric() +{ + double radial_distance = observer_location[0]; + + if (reference_body) + { + radial_distance += reference_body->radius; + } + + // Construct reference frame which transforms coordinates from BCBF space to topocentric space + bcbf_to_topocentric = physics::orbit::bcbf::to_topocentric + ( + radial_distance, + observer_location[1], + observer_location[2] + ) * sez_to_ezs; +} + } // namespace ecs diff --git a/src/ecs/systems/astronomy-system.hpp b/src/ecs/systems/astronomy-system.hpp index ea09563..f57bfd4 100644 --- a/src/ecs/systems/astronomy-system.hpp +++ b/src/ecs/systems/astronomy-system.hpp @@ -73,7 +73,7 @@ public: /** * Sets the location of the observer using spherical coordinates in BCBF space. * - * @param location Spherical coordinates of the observer, in reference body BCBF space, in the ISO order of radial distance, polar angle (radians), and azimuthal angle (radians). + * @param location Spherical coordinates of the observer, in reference body BCBF space, in the ISO order of altitude (meters), latitude (radians), and longitude (radians). */ void set_observer_location(const double3& location); @@ -82,6 +82,11 @@ public: void set_sky_pass(sky_pass* pass); private: + 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); + + void update_bcbf_to_topocentric(); + double universal_time; double time_scale; diff --git a/src/game/states/play-state.cpp b/src/game/states/play-state.cpp index 3a18c30..18bff5b 100644 --- a/src/game/states/play-state.cpp +++ b/src/game/states/play-state.cpp @@ -184,7 +184,7 @@ void play_state_enter(game_context* ctx) // Set astronomy system observation parameters ctx->astronomy_system->set_reference_body(earth_entity); - ctx->astronomy_system->set_observer_location(double3{6.3781e6, math::radians(0.0f), math::radians(0.0f)}); + ctx->astronomy_system->set_observer_location(double3{0.0, 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);