Antkeeper  0.0.1
blackbody-system.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
24 #include <engine/config.hpp>
25 #include <engine/color/xyz.hpp>
26 #include <numeric>
27 
30 {
31  // Construct a range of sample wavelengths in the visible spectrum
32  m_visible_wavelengths_nm.resize(780 - 280);
33  std::iota(m_visible_wavelengths_nm.begin(), m_visible_wavelengths_nm.end(), 280);
34 
35  registry.on_construct<::blackbody_component>().connect<&blackbody_system::on_blackbody_construct>(this);
36  registry.on_update<::blackbody_component>().connect<&blackbody_system::on_blackbody_update>(this);
37 }
38 
40 {
41  registry.on_construct<::blackbody_component>().disconnect<&blackbody_system::on_blackbody_construct>(this);
42  registry.on_update<::blackbody_component>().disconnect<&blackbody_system::on_blackbody_update>(this);
43 }
44 
45 void blackbody_system::update(float t, float dt)
46 {}
47 
48 void blackbody_system::update_blackbody(entity::id entity_id)
49 {
50  // Get blackbody component
51  auto& blackbody = registry.get<blackbody_component>(entity_id);
52 
53  // Construct a lambda function which calculates the blackbody's RGB luminance of a given wavelength
54  auto rgb_spectral_luminance = [&](double wavelength_nm) -> math::dvec3
55  {
56  // Convert wavelength from nanometers to meters
57  const double wavelength_m = wavelength_nm * 1e-9;
58 
59  // Calculate the spectral radiance of the wavelength
60  const double spectral_radiance = physics::light::blackbody::spectral_radiance<double>(blackbody.temperature, wavelength_m);
61 
62  // Convert spectral radiance to spectral luminance
63  const double spectral_luminance = spectral_radiance * 1e-9 * physics::light::max_luminous_efficacy<double>;
64 
65  // Calculate the XYZ color of the wavelength using CIE color matching functions then transform to RGB
66  const auto color_xyz = color::xyz_match(wavelength_nm);
67  const auto color_rgb = config::scene_linear_color_space<double>.from_xyz * color_xyz;
68 
69  // Scale RGB color by spectral luminance
70  return color_rgb * spectral_luminance;
71  };
72 
73  // Integrate the blackbody RGB spectral luminance over wavelengths in the visible spectrum
74  const math::dvec3 rgb_luminance = math::quadrature::simpson(rgb_spectral_luminance, m_visible_wavelengths_nm.begin(), m_visible_wavelengths_nm.end());
75 
76  // Extract luminance and color from RGB luminance
77  blackbody.luminance = math::max(rgb_luminance);
78  blackbody.color = rgb_luminance / blackbody.luminance;
79 }
80 
81 void blackbody_system::on_blackbody_construct(entity::registry& registry, entity::id entity_id)
82 {
83  update_blackbody(entity_id);
84 }
85 
86 void blackbody_system::on_blackbody_update(entity::registry& registry, entity::id entity_id)
87 {
88  update_blackbody(entity_id);
89 }
void update(float t, float dt) override
Perform's a system's update() function.
blackbody_system(entity::registry &registry)
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
math::vec3< T > xyz_match(T lambda)
Fitted piecewise gaussian approximation to the CIE 1931 standard observer color matching function.
Definition: xyz.hpp:130
entt::registry registry
Component registry type.
Definition: registry.hpp:28
entt::entity id
Entity ID type.
Definition: id.hpp:28
constexpr T e
e.
Definition: numbers.hpp:37
std::invoke_result< UnaryOp, typename std::iterator_traits< InputIt >::value_type >::type simpson(UnaryOp f, InputIt first, InputIt last)
Approximates the definite integral of a function using Simpson's 1/3 rule.
Definition: quadrature.hpp:43
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.
Definition: vector.hpp:1328
T spectral_radiance(T t, T lambda, T c=constants::speed_of_light< T >)
Calculates the spectral radiance of a blackbody for the given wavelength.
Definition: blackbody.hpp:149
Blackbody radiator.
n-dimensional vector.
Definition: vector.hpp:44