Browse Source

Make the observer position of the astronomy system relative to the radius of the reference body

master
C. J. Howard 3 years ago
parent
commit
d18988d9fd
3 changed files with 62 additions and 29 deletions
  1. +55
    -27
      src/ecs/systems/astronomy-system.cpp
  2. +6
    -1
      src/ecs/systems/astronomy-system.hpp
  3. +1
    -1
      src/game/states/play-state.cpp

+ 55
- 27
src/ecs/systems/astronomy-system.cpp View File

@ -57,9 +57,27 @@ astronomy_system::astronomy_system(ecs::registry& registry):
reference_orbit(nullptr), reference_orbit(nullptr),
reference_body(nullptr), reference_body(nullptr),
reference_atmosphere(nullptr), reference_atmosphere(nullptr),
observer_location{0, 0, 0},
sun_light(nullptr), sun_light(nullptr),
sky_pass(nullptr) sky_pass(nullptr)
{}
{
// Construct reference frame which transforms coordinates from SEZ to EZS
sez_to_ezs = physics::frame<double>
{
{0, 0, 0},
math::normalize
(
math::quaternion<double>::rotate_x(-math::half_pi<double>) *
math::quaternion<double>::rotate_z(-math::half_pi<double>)
)
};
// Construct reference frame which transforms coordinates from EZS to SEZ
ezs_to_sez = sez_to_ezs.inverse();
registry.on_construct<ecs::celestial_body_component>().connect<&astronomy_system::on_celestial_body_construct>(this);
registry.on_replace<ecs::celestial_body_component>().connect<&astronomy_system::on_celestial_body_replace>(this);
}
void astronomy_system::update(double t, double dt) 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; double3 blackbody_up_topocentric = inertial_to_topocentric.rotation * blackbody_up_inertial;
// Calculate distance from observer to blackbody // 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 // Calculate blackbody distance attenuation
double distance_attenuation = 1.0 / (blackbody_distance * blackbody_distance); 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 // Altitude of observer in meters
geom::ray<double> sample_ray; geom::ray<double> 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); sample_ray.direction = math::normalize(blackbody_position_topocentric);
geom::sphere<double> exosphere; geom::sphere<double> exosphere;
@ -188,8 +206,7 @@ void astronomy_system::update(double t, double dt)
); );
// Upload observer altitude to sky pass // 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 // Upload atmosphere params to sky pass
if (reference_atmosphere) if (reference_atmosphere)
@ -230,33 +247,14 @@ void astronomy_system::set_reference_body(ecs::entity entity)
if (registry.has<ecs::atmosphere_component>(reference_entity)) if (registry.has<ecs::atmosphere_component>(reference_entity))
reference_atmosphere = &registry.get<ecs::atmosphere_component>(reference_entity); reference_atmosphere = &registry.get<ecs::atmosphere_component>(reference_entity);
} }
update_bcbf_to_topocentric();
} }
void astronomy_system::set_observer_location(const double3& location) void astronomy_system::set_observer_location(const double3& location)
{ {
observer_location = location; observer_location = location;
// Construct reference frame which transforms coordinates from SEZ to EZS
sez_to_ezs = physics::frame<double>
{
{0, 0, 0},
math::normalize
(
math::quaternion<double>::rotate_x(-math::half_pi<double>) *
math::quaternion<double>::rotate_z(-math::half_pi<double>)
)
};
// 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) 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; 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 } // namespace ecs

+ 6
- 1
src/ecs/systems/astronomy-system.hpp View File

@ -73,7 +73,7 @@ public:
/** /**
* Sets the location of the observer using spherical coordinates in BCBF space. * 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); void set_observer_location(const double3& location);
@ -82,6 +82,11 @@ public:
void set_sky_pass(sky_pass* pass); void set_sky_pass(sky_pass* pass);
private: 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 universal_time;
double time_scale; double time_scale;

+ 1
- 1
src/game/states/play-state.cpp View File

@ -184,7 +184,7 @@ void play_state_enter(game_context* ctx)
// Set astronomy system observation parameters // Set astronomy system observation parameters
ctx->astronomy_system->set_reference_body(earth_entity); 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_sun_light(sun);
ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass); ctx->astronomy_system->set_sky_pass(ctx->overworld_sky_pass);

Loading…
Cancel
Save