Browse Source

Fix bug related to invalid pointers to reference entity components in astronomy system

master
C. J. Howard 3 years ago
parent
commit
d436a85745
5 changed files with 44 additions and 53 deletions
  1. +30
    -38
      src/entity/systems/astronomy.cpp
  2. +0
    -3
      src/entity/systems/astronomy.hpp
  3. +4
    -3
      src/game/states/forage.cpp
  4. +1
    -1
      src/game/states/loading.cpp
  5. +9
    -8
      src/resources/entity-archetype-loader.cpp

+ 30
- 38
src/entity/systems/astronomy.cpp View File

@ -55,9 +55,6 @@ astronomy::astronomy(entity::registry& registry):
universal_time(0.0), universal_time(0.0),
time_scale(1.0), time_scale(1.0),
reference_entity(entt::null), reference_entity(entt::null),
reference_orbit(nullptr),
reference_body(nullptr),
reference_atmosphere(nullptr),
observer_location{0, 0, 0}, observer_location{0, 0, 0},
sun_light(nullptr), sun_light(nullptr),
sky_pass(nullptr) sky_pass(nullptr)
@ -85,19 +82,25 @@ void astronomy::update(double t, double dt)
// 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);
// Abort if no reference body
if (reference_entity == entt::null)
return;
// Abort if either reference body or orbit have not been set // Abort if either reference body or orbit have not been set
if (!reference_orbit || !reference_body)
if (!registry.has<entity::component::orbit>(reference_entity) || !registry.has<entity::component::celestial_body>(reference_entity))
return; return;
const entity::component::orbit& reference_orbit = registry.get<entity::component::orbit>(reference_entity);
const entity::component::celestial_body& reference_body = registry.get<entity::component::celestial_body>(reference_entity);
// Determine axial rotation at current time // Determine axial rotation at current time
const double reference_axial_rotation = reference_body->axial_rotation + reference_body->angular_frequency * universal_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 inertial_to_bcbf = physics::orbit::inertial::to_bcbf
( (
reference_orbit->state.r,
reference_orbit->elements.i,
reference_body->axial_tilt,
reference_orbit.state.r,
reference_orbit.elements.i,
reference_body.axial_tilt,
reference_axial_rotation reference_axial_rotation
); );
@ -120,7 +123,7 @@ void astronomy::update(double t, double dt)
[&](entity::id entity_id, const auto& celestial_body, const auto& orbit, const auto& blackbody) [&](entity::id entity_id, const auto& celestial_body, const auto& orbit, const auto& blackbody)
{ {
// Calculate blackbody inertial basis // 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}; double3 blackbody_up_inertial = {0, 0, 1};
// Transform blackbody inertial position and basis into topocentric space // Transform blackbody inertial position and basis into topocentric space
@ -138,16 +141,18 @@ void astronomy::update(double t, double dt)
double3 atmospheric_transmittance = {1.0, 1.0, 1.0}; double3 atmospheric_transmittance = {1.0, 1.0, 1.0};
// Get atmosphere component of reference body (if any) // Get atmosphere component of reference body (if any)
if (reference_atmosphere)
if (this->registry.has<entity::component::atmosphere>(reference_entity))
{ {
const entity::component::atmosphere& reference_atmosphere = registry.get<entity::component::atmosphere>(reference_entity);
// Altitude of observer in meters // Altitude of observer in meters
geom::ray<double> sample_ray; geom::ray<double> sample_ray;
sample_ray.origin = {0, reference_body->radius + 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;
exosphere.center = {0, 0, 0}; exosphere.center = {0, 0, 0};
exosphere.radius = reference_body->radius + reference_atmosphere->exosphere_altitude;
exosphere.radius = reference_body.radius + reference_atmosphere.exosphere_altitude;
auto intersection_result = geom::ray_sphere_intersection(sample_ray, exosphere); auto intersection_result = geom::ray_sphere_intersection(sample_ray, exosphere);
@ -156,11 +161,11 @@ void astronomy::update(double t, double dt)
double3 sample_start = sample_ray.origin; double3 sample_start = sample_ray.origin;
double3 sample_end = sample_ray.extrapolate(std::get<2>(intersection_result)); double3 sample_end = sample_ray.extrapolate(std::get<2>(intersection_result));
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_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; double optical_depth_o = 0.0;
atmospheric_transmittance = transmittance(optical_depth_r, optical_depth_k, optical_depth_o, reference_atmosphere->rayleigh_scattering, reference_atmosphere->mie_scattering);
atmospheric_transmittance = transmittance(optical_depth_r, optical_depth_k, optical_depth_o, reference_atmosphere.rayleigh_scattering, reference_atmosphere.mie_scattering);
} }
} }
@ -217,12 +222,14 @@ void astronomy::update(double t, double dt)
sky_pass->set_observer_altitude(observer_location[0]); sky_pass->set_observer_altitude(observer_location[0]);
// Upload atmosphere params to sky pass // Upload atmosphere params to sky pass
if (reference_atmosphere)
if (registry.has<entity::component::atmosphere>(reference_entity))
{ {
sky_pass->set_scale_heights(reference_atmosphere->rayleigh_scale_height, reference_atmosphere->mie_scale_height);
sky_pass->set_scattering_coefficients(math::type_cast<float>(reference_atmosphere->rayleigh_scattering), math::type_cast<float>(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);
const entity::component::atmosphere& reference_atmosphere = registry.get<entity::component::atmosphere>(reference_entity);
sky_pass->set_scale_heights(reference_atmosphere.rayleigh_scale_height, reference_atmosphere.mie_scale_height);
sky_pass->set_scattering_coefficients(math::type_cast<float>(reference_atmosphere.rayleigh_scattering), math::type_cast<float>(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,22 +247,6 @@ void astronomy::set_time_scale(double scale)
void astronomy::set_reference_body(entity::id entity_id) void astronomy::set_reference_body(entity::id entity_id)
{ {
reference_entity = entity_id; reference_entity = entity_id;
reference_orbit = nullptr;
reference_body = nullptr;
reference_atmosphere = nullptr;
if (reference_entity != entt::null)
{
if (registry.has<entity::component::orbit>(reference_entity))
reference_orbit = &registry.get<entity::component::orbit>(reference_entity);
if (registry.has<entity::component::celestial_body>(reference_entity))
reference_body = &registry.get<entity::component::celestial_body>(reference_entity);
if (registry.has<entity::component::atmosphere>(reference_entity))
reference_atmosphere = &registry.get<entity::component::atmosphere>(reference_entity);
}
update_bcbf_to_topocentric(); update_bcbf_to_topocentric();
} }
@ -291,9 +282,10 @@ void astronomy::update_bcbf_to_topocentric()
{ {
double radial_distance = observer_location[0]; double radial_distance = observer_location[0];
if (reference_body)
if (reference_entity)
{ {
radial_distance += reference_body->radius;
if (registry.has<entity::component::celestial_body>(reference_entity))
radial_distance += registry.get<entity::component::celestial_body>(reference_entity).radius;
} }
// Construct reference frame which transforms coordinates from BCBF space to topocentric space // Construct reference frame which transforms coordinates from BCBF space to topocentric space

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

@ -92,9 +92,6 @@ private:
double time_scale; double time_scale;
entity::id reference_entity; entity::id reference_entity;
const entity::component::orbit* reference_orbit;
const entity::component::celestial_body* reference_body;
const entity::component::atmosphere* reference_atmosphere;
double3 observer_location; double3 observer_location;

+ 4
- 3
src/game/states/forage.cpp View File

@ -76,7 +76,7 @@ void enter(game::context* ctx)
ctx->entity_registry->assign<entity::component::observer>(observer_eid, observer); ctx->entity_registry->assign<entity::component::observer>(observer_eid, observer);
// Set reference location of astronomy system // Set reference location of astronomy system
ctx->astronomy_system->set_reference_body(planet_eid);
//ctx->astronomy_system->set_reference_body(planet_eid);
ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude}); ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
} }
@ -250,8 +250,9 @@ void setup_tools(game::context* ctx)
auto [window_w, window_h] = ctx->app->get_viewport_dimensions(); auto [window_w, window_h] = ctx->app->get_viewport_dimensions();
entity::id planet_eid = ctx->entities["planet"]; entity::id planet_eid = ctx->entities["planet"];
entity::component::celestial_body& body = ctx->entity_registry->get<entity::component::celestial_body>(planet_eid);
body.axial_tilt = math::radians(360.0f) * ((float)mouse_x / (float)window_w);
entity::component::celestial_body body = ctx->entity_registry->get<entity::component::celestial_body>(planet_eid);
body.axial_rotation = math::radians(360.0f) * ((float)mouse_x / (float)window_w);
ctx->entity_registry->replace<entity::component::celestial_body>(planet_eid, body);
}; };
ctx->entity_registry->assign<entity::component::tool>(tool_eid, tool); ctx->entity_registry->assign<entity::component::tool>(tool_eid, tool);

+ 1
- 1
src/game/states/loading.cpp View File

@ -126,7 +126,7 @@ void exit(game::context* ctx)
{} {}
void load_controls(game::context* ctx) void load_controls(game::context* ctx)
{
{
// If a control profile is set in the config file // If a control profile is set in the config file
if (ctx->config->contains("control_profile")) if (ctx->config->contains("control_profile"))
{ {

+ 9
- 8
src/resources/entity-archetype-loader.cpp View File

@ -104,11 +104,11 @@ static bool load_component_celestial_body(entity::archetype& archetype, const js
if (element.contains("radius")) if (element.contains("radius"))
component.radius = element["radius"].get<double>(); component.radius = element["radius"].get<double>();
if (element.contains("axial_tilt")) if (element.contains("axial_tilt"))
component.axial_tilt = element["axial_tilt"].get<double>();
component.axial_tilt = math::radians(element["axial_tilt"].get<double>());
if (element.contains("axial_rotation")) if (element.contains("axial_rotation"))
component.axial_rotation = element["axial_rotation"].get<double>();
component.axial_rotation = math::radians(element["axial_rotation"].get<double>());
if (element.contains("angular_frequency")) if (element.contains("angular_frequency"))
component.angular_frequency = element["angular_frequency"].get<double>();
component.angular_frequency = math::radians(element["angular_frequency"].get<double>());
archetype.set<entity::component::celestial_body>(component); archetype.set<entity::component::celestial_body>(component);
@ -162,13 +162,13 @@ static bool load_component_orbit(entity::archetype& archetype, const json& eleme
if (element.contains("a")) if (element.contains("a"))
component.elements.a = element["a"].get<double>(); component.elements.a = element["a"].get<double>();
if (element.contains("i")) if (element.contains("i"))
component.elements.i = element["i"].get<double>();
component.elements.i = math::radians(element["i"].get<double>());
if (element.contains("raan")) if (element.contains("raan"))
component.elements.raan = element["raan"].get<double>();
component.elements.raan = math::radians(element["raan"].get<double>());
if (element.contains("w")) if (element.contains("w"))
component.elements.w = element["w"].get<double>();
component.elements.w = math::radians(element["w"].get<double>());
if (element.contains("ta")) if (element.contains("ta"))
component.elements.ta = element["ta"].get<double>();
component.elements.ta = math::radians(element["ta"].get<double>());
archetype.set<entity::component::orbit>(component); archetype.set<entity::component::orbit>(component);
@ -205,7 +205,8 @@ static bool load_component_transform(entity::archetype& archetype, const json& e
component.local.scale.y = translation[1].get<float>(); component.local.scale.y = translation[1].get<float>();
component.local.scale.z = translation[2].get<float>(); component.local.scale.z = translation[2].get<float>();
} }
component.world = component.local;
archetype.set<entity::component::transform>(component); archetype.set<entity::component::transform>(component);
return true; return true;

Loading…
Cancel
Save