@@ -23,6 +23,7 @@ SystemBodyData::SystemBodyData() :
2323 m_averageTemp(0 ),
2424 m_heightMapFractal(0 )
2525{
26+ m_starColor = Color (255 , 0 , 255 , 255 );
2627}
2728
2829void SystemBodyData::SaveToJson (Json &out)
@@ -98,6 +99,7 @@ void SystemBodyData::LoadFromJson(const Json &obj)
9899 m_inclination = obj.value <fixed>(" inclination" , 0 );
99100 m_argOfPeriapsis = obj.value <fixed>(" argOfPeriapsis" , 0 );
100101 m_averageTemp = obj.value <uint32_t >(" averageTemp" , 0 );
102+ GenerateStarColor ();
101103
102104 m_metallicity = obj.value <fixed>(" metallicity" , 0 );
103105 m_volcanicity = obj.value <fixed>(" volcanicity" , 0 );
@@ -129,6 +131,108 @@ void SystemBodyData::LoadFromJson(const Json &obj)
129131 m_heightMapFractal = std::min (m_heightMapFractal, uint32_t (1 ));
130132}
131133
134+ double GetPlanckBrightness (const double wavelength_nm, const int temperature)
135+ {
136+ // Planck's constant
137+ const double h = 6.62607015e-34 ; // kg*m^2*s^-1 (J*s)
138+
139+ // speed of light
140+ const double c = 299792458 ; // m*s^2
141+
142+ // Boltzmann's constant
143+ const double k = 1.380649e-23 ; // J/K
144+
145+ double wavelength = wavelength_nm * 1e-9 ;
146+
147+ double exponent = exp ((h*c) / (wavelength * k * temperature));
148+ return 2 * h * pow (c, 2 ) / (pow (wavelength, 5 ) * exponent);
149+ }
150+
151+ const vector3d nm_to_rgb[48 ] = {
152+ vector3d ( 0 .000000f , 0 .000000f , 0 .000001f ), // 360 nm
153+ vector3d ( 0 .000006f , 0 .000001f , 0 .000026f ), // 370 nm
154+ vector3d ( 0 .000160f , 0 .000017f , 0 .000705f ), // 380 nm
155+ vector3d ( 0 .002362f , 0 .000253f , 0 .010482f ), // 390 nm
156+ vector3d ( 0 .019110f , 0 .002004f , 0 .086011f ), // 400 nm
157+ vector3d ( 0 .084736f , 0 .008756f , 0 .389366f ), // 410 nm
158+ vector3d ( 0 .204492f , 0 .021391f , 0 .972542f ), // 420 nm
159+ vector3d ( 0 .314679f , 0 .038676f , 1 .553480f ), // 430 nm
160+ vector3d ( 0 .383734f , 0 .062077f , 1 .967280f ), // 440 nm
161+ vector3d ( 0 .370702f , 0 .089456f , 1 .994800f ), // 450 nm
162+ vector3d ( 0 .302273f , 0 .128201f , 1 .745370f ), // 460 nm
163+ vector3d ( 0 .195618f , 0 .185190f , 1 .317560f ), // 470 nm
164+ vector3d ( 0 .080507f , 0 .253589f , 0 .772125f ), // 480 nm
165+ vector3d ( 0 .016172f , 0 .339133f , 0 .415254f ), // 490 nm
166+ vector3d ( 0 .003816f , 0 .460777f , 0 .218502f ), // 500 nm
167+ vector3d ( 0 .037465f , 0 .606741f , 0 .112044f ), // 510 nm
168+ vector3d ( 0 .117749f , 0 .761757f , 0 .060709f ), // 520 nm
169+ vector3d ( 0 .236491f , 0 .875211f , 0 .030451f ), // 530 nm
170+ vector3d ( 0 .376772f , 0 .961988f , 0 .013676f ), // 540 nm
171+ vector3d ( 0 .529826f , 0 .991761f , 0 .003988f ), // 550 nm
172+ vector3d ( 0 .705224f , 0 .997340f , 0 .000000f ), // 560 nm
173+ vector3d ( 0 .878655f , 0 .955552f , 0 .000000f ), // 570 nm
174+ vector3d ( 1 .014160f , 0 .868934f , 0 .000000f ), // 580 nm
175+ vector3d ( 1 .118520f , 0 .777405f , 0 .000000f ), // 590 nm
176+ vector3d ( 1 .123990f , 0 .658341f , 0 .000000f ), // 600 nm
177+ vector3d ( 1 .030480f , 0 .527963f , 0 .000000f ), // 610 nm
178+ vector3d ( 0 .856297f , 0 .398057f , 0 .000000f ), // 620 nm
179+ vector3d ( 0 .647467f , 0 .283493f , 0 .000000f ), // 630 nm
180+ vector3d ( 0 .431567f , 0 .179828f , 0 .000000f ), // 640 nm
181+ vector3d ( 0 .268329f , 0 .107633f , 0 .000000f ), // 650 nm
182+ vector3d ( 0 .152568f , 0 .060281f , 0 .000000f ), // 660 nm
183+ vector3d ( 0 .081261f , 0 .031800f , 0 .000000f ), // 670 nm
184+ vector3d ( 0 .040851f , 0 .015905f , 0 .000000f ), // 680 nm
185+ vector3d ( 0 .019941f , 0 .007749f , 0 .000000f ), // 690 nm
186+ vector3d ( 0 .009577f , 0 .003718f , 0 .000000f ), // 700 nm
187+ vector3d ( 0 .004553f , 0 .001768f , 0 .000000f ), // 710 nm
188+ vector3d ( 0 .002175f , 0 .000846f , 0 .000000f ), // 720 nm
189+ vector3d ( 0 .001045f , 0 .000407f , 0 .000000f ), // 730 nm
190+ vector3d ( 0 .000508f , 0 .000199f , 0 .000000f ), // 740 nm
191+ vector3d ( 0 .000251f , 0 .000098f , 0 .000000f ), // 750 nm
192+ vector3d ( 0 .000126f , 0 .000050f , 0 .000000f ), // 760 nm
193+ vector3d ( 0 .000065f , 0 .000025f , 0 .000000f ), // 770 nm
194+ vector3d ( 0 .000033f , 0 .000013f , 0 .000000f ), // 780 nm
195+ vector3d ( 0 .000018f , 0 .000007f , 0 .000000f ), // 790 nm
196+ vector3d ( 0 .000009f , 0 .000004f , 0 .000000f ), // 800 nm
197+ vector3d ( 0 .000005f , 0 .000002f , 0 .000000f ), // 810 nm
198+ vector3d ( 0 .000003f , 0 .000001f , 0 .000000f ), // 820 nm
199+ vector3d ( 0 .000002f , 0 .000001f , 0 .000000f ) // 830 nm
200+ };
201+
202+ void SystemBodyData::GenerateStarColor ()
203+ {
204+ // https://www.shadertoy.com/view/NlGXzz
205+
206+ // [360-830 nm]
207+ vector3d rgb = vector3d (0 .f );
208+
209+ const matrix3x3d xyz2rgb = matrix3x3d::FromVectors (
210+ vector3d ( 3.2404542 ,-0.9692660 , 0.0556434 ),
211+ vector3d (-1.5371385 , 1.8760108 ,-0.2040259 ),
212+ vector3d (-0.4985314 , 0.0415560 , 1.0572252 )
213+ );
214+
215+ for (int i = 0 ; i < 48 ; i++) {
216+ double wavelength = 360 + (10 * i);
217+
218+ rgb += GetPlanckBrightness (wavelength, m_averageTemp) * (xyz2rgb * nm_to_rgb[i]);
219+ }
220+
221+ // normalize
222+ double max = std::max (std::max (rgb.x , rgb.y ), rgb.z );
223+ // black color
224+ if (max == 0 .f ) {
225+ rgb = vector3d (0 .f );
226+ } else {
227+ rgb /= (max / 255 );
228+ }
229+ rgb.x = std::max (rgb.x , 0.0 );
230+ rgb.y = std::max (rgb.y , 0.0 );
231+ rgb.z = std::max (rgb.z , 0.0 );
232+
233+ m_starColor = Color (rgb.x , rgb.y , rgb.z , 255 );
234+ }
235+
132236SystemBody::SystemBody (const SystemPath &path, StarSystem *system) :
133237 m_parent(nullptr ),
134238 m_system(system),
0 commit comments