45 observer_eid(entt::null),
46 reference_body_eid(entt::null),
47 transmittance_samples(0),
51 starlight_illuminance{0, 0, 0}
93 set_time(time_days + dt * time_scale);
96 if (observer_eid == entt::null || reference_body_eid == entt::null)
115 if (!reference_body || !reference_orbit)
124 update_icrf_to_eus(*reference_body, *reference_orbit);
129 [&](
entity::id entity_id,
const auto& body,
const auto& orbit,
auto& transform)
132 if (entity_id == reference_body_eid || orbit.parent == entt::null)
136 const math::dvec3 r_eus = icrf_to_eus * orbit.position;
141 const double body_prime_meridian =
math::polynomial::horner(body.prime_meridian.begin(), body.prime_meridian.end(), time_days);
156 transform.local.rotation =
math::fquat(rotation_eus);
157 transform.local.scale = {1.0f, 1.0f, 1.0f};
163 [&](
entity::id entity_id,
const auto& blackbody_body,
const auto& blackbody_orbit,
const auto& blackbody)
166 const math::dvec3 blackbody_position_eus = icrf_to_eus * blackbody_orbit.position;
169 const double observer_blackbody_distance =
math::length(blackbody_position_eus);
170 const math::dvec3 observer_blackbody_direction_eus = blackbody_position_eus / observer_blackbody_distance;
173 const double observer_blackbody_angular_radius =
astro::angular_radius(blackbody_body.radius, observer_blackbody_distance);
177 const math::dvec3 observer_blackbody_illuminance = blackbody.color * blackbody.luminance * observer_blackbody_solid_angle;
180 math::dvec3 observer_blackbody_transmitted_illuminance = observer_blackbody_illuminance;
181 if (reference_atmosphere)
187 math::dvec3 transmittance = integrate_transmittance(*observer, *reference_body, *reference_atmosphere, ray);
190 observer_blackbody_transmitted_illuminance *= transmittance;
194 if (sun_light !=
nullptr)
208 const auto max_component =
math::max(observer_blackbody_transmitted_illuminance);
209 if (max_component > 0.0)
230 [&](
entity::id entity_id,
const auto& reflector_body,
const auto& reflector_orbit,
const auto& reflector,
const auto& transform)
233 const math::dvec3 reflector_position_eus = icrf_to_eus * reflector_orbit.position;
236 const double observer_reflector_distance =
math::length(reflector_position_eus);
237 const math::dvec3 observer_reflector_direction_eus = reflector_position_eus / observer_reflector_distance;
240 math::dvec3 reflector_blackbody_direction_eus = blackbody_position_eus - reflector_position_eus;
241 const double reflector_blackbody_distance =
math::length(reflector_blackbody_direction_eus);
242 reflector_blackbody_direction_eus /= reflector_blackbody_distance;
245 const double reflector_blackbody_angular_radius =
astro::angular_radius(blackbody_body.radius, reflector_blackbody_distance);
249 const math::dvec3 reflector_blackbody_illuminance = blackbody.color * blackbody.luminance * reflector_blackbody_solid_angle;
252 const double observer_reflector_angular_radius =
astro::angular_radius(reflector_body.radius, observer_reflector_distance);
256 const double observer_reflector_phase_factor =
math::dot(observer_reflector_direction_eus, -reflector_blackbody_direction_eus) * 0.5 + 0.5;
259 const double reflector_observer_angular_radius =
astro::angular_radius(reference_body->radius, observer_reflector_distance);
263 const double reflector_observer_phase_factor =
math::dot(-observer_reflector_direction_eus, -observer_blackbody_direction_eus) * 0.5 + 0.5;
266 math::dvec3 observer_reflector_transmittance = {1, 1, 1};
267 if (reference_atmosphere)
274 const math::dvec3 reflector_observer_luminance = observer_blackbody_illuminance * reference_body->albedo * observer_reflector_transmittance * reflector_observer_phase_factor * math::inv_pi<double>;
277 const math::dvec3 reflector_observer_illuminance = reflector_observer_luminance * reflector_observer_solid_angle;
280 const math::dvec3 observer_reflector_luminance = (reflector_blackbody_illuminance * observer_reflector_phase_factor + reflector_observer_illuminance) * reflector.albedo * observer_reflector_transmittance * math::inv_pi<double>;
283 const math::dvec3 observer_reflector_illuminance = observer_reflector_luminance * observer_reflector_solid_angle;
303 const auto max_component =
math::max(observer_reflector_illuminance);
304 if (max_component > 0.0)
329 time_centuries = time_days * physics::time::jd::centuries_per_day<double>;
339 if (observer_eid != eid)
343 if (observer_eid != entt::null)
346 reference_body_eid = entt::null;
352 transmittance_samples = samples;
367 starlight_illuminance = illuminance;
372 this->sky_pass = pass;
376 if (observer_eid != entt::null)
384 if (reference_body_eid != entt::null)
405 if (entity_id == observer_eid)
411 if (entity_id == observer_eid)
417 if (entity_id == reference_body_eid)
418 reference_body_modified();
423 if (entity_id == reference_body_eid)
424 reference_body_modified();
429 if (entity_id == reference_body_eid)
430 reference_orbit_modified();
435 if (entity_id == reference_body_eid)
436 reference_orbit_modified();
441 if (entity_id == reference_body_eid)
442 reference_atmosphere_modified();
447 if (entity_id == reference_body_eid)
448 reference_atmosphere_modified();
451 void astronomy_system::observer_modified()
458 if (reference_body_eid != observer->reference_body_eid)
461 reference_body_eid = observer->reference_body_eid;
462 reference_body_modified();
463 reference_orbit_modified();
464 reference_atmosphere_modified();
467 if (reference_body_eid != entt::null)
474 update_bcbf_to_eus(*observer, *reference_body);
483 void astronomy_system::reference_body_modified()
495 update_bcbf_to_eus(*observer, *reference_body);
508 void astronomy_system::reference_orbit_modified()
513 void astronomy_system::reference_atmosphere_modified()
518 void astronomy_system::update_bcbf_to_eus(const ::observer_component& observer, const ::celestial_body_component& body)
523 body.radius + observer.elevation,
529 void astronomy_system::update_icrf_to_eus(const ::celestial_body_component& body, const ::orbit_component& orbit)
534 const double body_prime_meridian =
math::polynomial::horner(body.prime_meridian.begin(), body.prime_meridian.end(), time_days);
543 icrf_to_bcbf.
t = icrf_to_bcbf.
r * -orbit.position;
546 icrf_to_eus = icrf_to_bcbf * bcbf_to_eus;
563 math::dvec3 astronomy_system::integrate_transmittance(const ::observer_component& observer, const ::celestial_body_component& body, const ::atmosphere_component& atmosphere,
geom::ray<double, 3> ray)
const
568 ray.
origin.
y() += body.radius + observer.elevation;
572 atmosphere_sphere.
center = {0, 0, 0};
573 atmosphere_sphere.
radius = body.radius + atmosphere.upper_limit;
584 const double sqr_height = height * height;
585 const double height_cos_view_zenith = height * cos_view_zenith;
586 const double two_height_cos_view_zenith = 2.0 * height_cos_view_zenith;
589 const double sample_end_distance = std::get<1>(*
intersection);
593 double previous_sample_distance = 0.0;
594 for (std::size_t i = 0;
i < transmittance_samples; ++
i)
597 const double sample_distance = (
static_cast<double>(
i) + 0.5) /
static_cast<double>(transmittance_samples) * sample_end_distance;
598 const double sample_length = sample_distance - previous_sample_distance;
599 previous_sample_distance = sample_distance;
602 const double sample_height =
std::sqrt(sample_distance * sample_distance + sqr_height + two_height_cos_view_zenith * sample_distance);
603 const double sample_elevation = sample_height - body.radius;
613 densities.y() * atmosphere.mie_extinction +
614 densities.z() * atmosphere.ozone_absorption;
620 return transmittance;
void set_time(double t)
Sets the current time.
void set_moon_light(scene::directional_light *light)
virtual void update(float t, float dt)
Adds the timestep dt, scaled by set time scale, to the current time, then calculates apparent propert...
astronomy_system(entity::registry ®istry)
void set_time_scale(double scale)
Sets the factor by which the timestep dt will be scaled before being added to the current time.
void set_sky_pass(::render::sky_pass *pass)
void set_observer(entity::id eid)
Sets the observer entity.
void set_starlight_illuminance(const math::dvec3 &illuminance)
void set_sun_light(scene::directional_light *light)
void set_transmittance_samples(std::size_t samples)
Sets the number of samples to take when integrating atmospheric transmittance.
void set_moon_planetlight_direction(const math::fvec3 &direction)
void set_sun_position(const math::fvec3 &position)
void set_moon_sunlight_direction(const math::fvec3 &direction)
void set_observer_elevation(float elevation)
void set_moon_sunlight_illuminance(const math::fvec3 &illuminance)
void set_moon_rotation(const math::fquat &rotation)
void set_icrf_to_eus(const math::se3< float > &transformation)
void set_sun_illuminance(const math::fvec3 &illuminance, const math::fvec3 &transmitted_illuminance)
void set_moon_angular_radius(float angular_radius)
void set_moon_planetlight_illuminance(const math::fvec3 &illuminance)
void set_sun_angular_radius(float radius)
void set_moon_position(const math::fvec3 &position)
void set_moon_illuminance(const math::fvec3 &illuminance, const math::fvec3 &transmitted_illuminance)
void set_sun_luminance(const math::fvec3 &luminance)
void set_planet_radius(float radius)
Light source with parallel rays and constant intensity.
void set_illuminance(float illuminance) noexcept
Sets the illuminance of the light on a surface perpendicular to the light direction.
void set_color(const math::fvec3 &color) noexcept
Sets the color of the light.
void set_rotation(const quaternion_type &rotation)
Sets the rotation of the object.
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
T angular_radius(T radius, T distance)
Finds the angular radius of a celestial object, given its radius and distance.
entt::registry registry
Component registry type.
entt::entity id
Entity ID type.
T cone(T theta)
Calculates the solid angle of a cone.
constexpr std::optional< T > intersection(const ray< T, N > &ray, const hyperplane< T, N > &hyperplane) noexcept
Ray-hyperplane intersection test.
constexpr T horner(InputIt first, InputIt last, T x)
Evaluates a polynomial using Horner's method.
quat< float > fquat
Quaternion with single-precision floating-point scalars.
constexpr vector< T, N > max(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the maximum elements of two vectors.
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
T length(const quaternion< T > &q)
Calculates the length of a quaternion.
quaternion< T > look_rotation(const vec3< T > &forward, vec3< T > up)
Creates a unit quaternion rotation using forward and up vectors.
constexpr mat4< T > scale(const vec3< T > &v)
Constructs a scale matrix.
vector< T, N > sqrt(const vector< T, N > &x)
Takes the square root of each element.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
T exponential(T d0, T z, T sh)
Calculates the density of exponentially-distributed atmospheric particles at a given elevation.
T triangular(T d0, T z, T a, T b, T c)
Calculates the density of triangularly-distributed atmospheric particles at a given elevation.
T extinction(T scattering, T albedo)
Calculates an extinction coefficient.
math::se3< T > to_bci(T ra, T dec, T w)
Constructs an SE(3) transformation from a BCBF frame to a BCI frame.
math::se3< T > to_enu(T distance, T latitude, T longitude)
Constructs an SE(3) transformation from a BCBF frame to an ENU frame.
math::se3< T > to_bcbf(T ra, T dec, T w)
Constructs an SE(3) transformation from a BCI frame to a BCBF frame.
vector_type center
Hypersphere center.
T radius
Hypersphere radius.
Half of a line proceeding from an initial point.
vector_type direction
Ray direction vector.
vector_type origin
Ray origin position.
Quaternion composed of a real scalar part and imaginary vector part.
static quaternion rotate_x(scalar_type angle)
Returns a quaternion representing a rotation about the x-axis.
quaternion_type r
Quaternion representing the rotation component of the transformation.
vector_type t
Vector representing the translation component of the transformation.
constexpr element_type & y() noexcept
Returns a reference to the second element.