1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Serialize, Deserialize)]
4pub struct Star {
5 pub hip: u32,
6 pub ra_deg: f64,
7 pub dec_deg: f64,
8 pub magnitude: f32,
9 pub bv_color: f32,
10 pub name: Option<&'static str>,
11}
12
13pub fn bv_to_rgb(bv: f32) -> [f32; 4] {
14 let bv = bv.clamp(-0.4, 2.0);
15 let t = (bv + 0.4) / 2.4;
16 let r = 1.0 - (t * 0.3).min(0.5);
17 let g = 1.0 - (t * 0.5).abs();
18 let b = 1.0 - ((1.0 - t) * 0.4).min(0.5);
19 let brightness = 1.0 - (bv.abs() * 0.1);
20 [r * brightness, g * brightness, b * brightness, 1.0]
21}
22
23pub fn mag_to_size(magnitude: f32) -> f32 {
24 ((6.5 - magnitude) / 6.5).max(0.1) * 2.0
25}
26
27pub fn celestial_to_cartesian(ra_deg: f64, dec_deg: f64, radius: f64) -> [f32; 3] {
28 let ra = ra_deg.to_radians();
29 let dec = dec_deg.to_radians();
30 let x = radius * dec.cos() * ra.cos();
31 let y = radius * dec.sin();
32 let z = radius * dec.cos() * ra.sin();
33 [x as f32, y as f32, z as f32]
34}
35
36pub static BRIGHT_STARS: &[Star] = &[
37 Star {
38 hip: 32349,
39 ra_deg: 101.287,
40 dec_deg: -16.716,
41 magnitude: -1.46,
42 bv_color: 0.0,
43 name: Some("Sirius"),
44 },
45 Star {
46 hip: 24608,
47 ra_deg: 95.676,
48 dec_deg: -52.696,
49 magnitude: -0.01,
50 bv_color: 0.71,
51 name: Some("Canopus"),
52 },
53 Star {
54 hip: 69673,
55 ra_deg: 213.915,
56 dec_deg: 19.182,
57 magnitude: 0.03,
58 bv_color: -0.01,
59 name: Some("Arcturus"),
60 },
61 Star {
62 hip: 91262,
63 ra_deg: 279.234,
64 dec_deg: 38.784,
65 magnitude: 0.08,
66 bv_color: 0.42,
67 name: Some("Vega"),
68 },
69 Star {
70 hip: 30438,
71 ra_deg: 79.172,
72 dec_deg: -45.999,
73 magnitude: 0.13,
74 bv_color: -0.16,
75 name: Some("Rigel Kentaurus"),
76 },
77 Star {
78 hip: 71683,
79 ra_deg: 219.484,
80 dec_deg: -60.834,
81 magnitude: 0.61,
82 bv_color: 1.23,
83 name: Some("Hadar"),
84 },
85 Star {
86 hip: 37826,
87 ra_deg: 116.109,
88 dec_deg: 28.072,
89 magnitude: 0.77,
90 bv_color: 0.42,
91 name: Some("Capella"),
92 },
93 Star {
94 hip: 57632,
95 ra_deg: 178.457,
96 dec_deg: -1.943,
97 magnitude: 0.85,
98 bv_color: -0.23,
99 name: Some("Procyon"),
100 },
101 Star {
102 hip: 97649,
103 ra_deg: 297.696,
104 dec_deg: 8.868,
105 magnitude: 0.97,
106 bv_color: 1.63,
107 name: Some("Altair"),
108 },
109 Star {
110 hip: 65378,
111 ra_deg: 200.981,
112 dec_deg: -54.058,
113 magnitude: 1.09,
114 bv_color: 0.09,
115 name: Some("Achernar"),
116 },
117 Star {
118 hip: 45555,
119 ra_deg: 138.299,
120 dec_deg: -58.976,
121 magnitude: 1.25,
122 bv_color: 1.17,
123 name: Some("Acrux"),
124 },
125 Star {
126 hip: 68702,
127 ra_deg: 211.097,
128 dec_deg: 49.313,
129 magnitude: 1.26,
130 bv_color: 0.03,
131 name: Some("Alkaid"),
132 },
133 Star {
134 hip: 80783,
135 ra_deg: 246.969,
136 dec_deg: -26.432,
137 magnitude: 1.33,
138 bv_color: 1.59,
139 name: Some("Antares"),
140 },
141 Star {
142 hip: 62956,
143 ra_deg: 194.294,
144 dec_deg: -63.099,
145 magnitude: 1.35,
146 bv_color: 0.07,
147 name: Some("Atria"),
148 },
149 Star {
150 hip: 92855,
151 ra_deg: 283.816,
152 dec_deg: -37.104,
153 magnitude: 1.50,
154 bv_color: 0.42,
155 name: Some("Nunki"),
156 },
157 Star {
158 hip: 53409,
159 ra_deg: 163.533,
160 dec_deg: 55.860,
161 magnitude: 1.58,
162 bv_color: 0.80,
163 name: Some("Alcaid"),
164 },
165 Star {
166 hip: 74624,
167 ra_deg: 228.071,
168 dec_deg: -58.749,
169 magnitude: 1.62,
170 bv_color: 0.09,
171 name: Some("Peacock"),
172 },
173 Star {
174 hip: 66006,
175 ra_deg: 203.841,
176 dec_deg: -42.367,
177 magnitude: 1.63,
178 bv_color: 1.17,
179 name: Some("Mimosa"),
180 },
181 Star {
182 hip: 62434,
183 ra_deg: 191.930,
184 dec_deg: -59.689,
185 magnitude: 1.68,
186 bv_color: 0.07,
187 name: Some("Acrux B"),
188 },
189 Star {
190 hip: 54061,
191 ra_deg: 166.259,
192 dec_deg: 56.537,
193 magnitude: 1.70,
194 bv_color: 0.22,
195 name: Some("Dubhe"),
196 },
197 Star {
198 hip: 67301,
199 ra_deg: 206.885,
200 dec_deg: 49.313,
201 magnitude: 1.77,
202 bv_color: 0.03,
203 name: Some("Mizar"),
204 },
205 Star {
206 hip: 53910,
207 ra_deg: 165.932,
208 dec_deg: 61.751,
209 magnitude: 1.79,
210 bv_color: 1.07,
211 name: Some("Polaris"),
212 },
213 Star {
214 hip: 33579,
215 ra_deg: 104.656,
216 dec_deg: -27.935,
217 magnitude: 1.80,
218 bv_color: 0.42,
219 name: Some("Alnilam"),
220 },
221 Star {
222 hip: 25428,
223 ra_deg: 80.627,
224 dec_deg: -1.943,
225 magnitude: 1.84,
226 bv_color: 0.42,
227 name: Some("Alnitab"),
228 },
229 Star {
230 hip: 36850,
231 ra_deg: 114.825,
232 dec_deg: -40.003,
233 magnitude: 1.85,
234 bv_color: 0.18,
235 name: Some("Mintaka"),
236 },
237 Star {
238 hip: 97649,
239 ra_deg: 297.696,
240 dec_deg: 8.868,
241 magnitude: 0.97,
242 bv_color: 1.63,
243 name: Some("Altair"),
244 },
245 Star {
246 hip: 102098,
247 ra_deg: 312.497,
248 dec_deg: -7.789,
249 magnitude: 1.74,
250 bv_color: 0.09,
251 name: Some("Sadr"),
252 },
253 Star {
254 hip: 98036,
255 ra_deg: 299.085,
256 dec_deg: 29.580,
257 magnitude: 1.81,
258 bv_color: 0.42,
259 name: Some("Deneb"),
260 },
261 Star {
262 hip: 113368,
263 ra_deg: 345.944,
264 dec_deg: -52.696,
265 magnitude: 1.74,
266 bv_color: 0.09,
267 name: Some("Suhail"),
268 },
269 Star {
270 hip: 113963,
271 ra_deg: 347.587,
272 dec_deg: -42.998,
273 magnitude: 1.83,
274 bv_color: 1.45,
275 name: Some("Wezen"),
276 },
277 Star {
278 hip: 11767,
279 ra_deg: 37.954,
280 dec_deg: 89.264,
281 magnitude: 1.98,
282 bv_color: 0.60,
283 name: Some("Polaris B"),
284 },
285 Star {
286 hip: 21421,
287 ra_deg: 68.980,
288 dec_deg: 16.510,
289 magnitude: 0.85,
290 bv_color: 0.42,
291 name: Some("Aldebaran"),
292 },
293 Star {
294 hip: 24436,
295 ra_deg: 75.244,
296 dec_deg: -1.943,
297 magnitude: 1.62,
298 bv_color: -0.22,
299 name: Some("Bellatrix"),
300 },
301 Star {
302 hip: 25930,
303 ra_deg: 81.573,
304 dec_deg: 6.350,
305 magnitude: 3.39,
306 bv_color: 0.13,
307 name: Some("Mintaka B"),
308 },
309 Star {
310 hip: 72607,
311 ra_deg: 222.720,
312 dec_deg: -47.288,
313 magnitude: 1.92,
314 bv_color: 1.13,
315 name: Some("Sargas"),
316 },
317 Star {
318 hip: 74824,
319 ra_deg: 228.539,
320 dec_deg: -58.749,
321 magnitude: 1.86,
322 bv_color: 0.09,
323 name: Some("Peacock B"),
324 },
325 Star {
326 hip: 42913,
327 ra_deg: 131.052,
328 dec_deg: -54.708,
329 magnitude: 1.86,
330 bv_color: 0.42,
331 name: Some("Avior"),
332 },
333 Star {
334 hip: 49669,
335 ra_deg: 151.830,
336 dec_deg: 16.399,
337 magnitude: 1.35,
338 bv_color: 0.42,
339 name: Some("Regulus"),
340 },
341 Star {
342 hip: 62184,
343 ra_deg: 191.279,
344 dec_deg: -62.672,
345 magnitude: 1.86,
346 bv_color: 0.07,
347 name: Some("Acrux C"),
348 },
349 Star {
350 hip: 87833,
351 ra_deg: 268.383,
352 dec_deg: -34.074,
353 magnitude: 1.92,
354 bv_color: 1.17,
355 name: Some("Kaus Australis"),
356 },
357 Star {
358 hip: 92848,
359 ra_deg: 283.274,
360 dec_deg: -26.432,
361 magnitude: 2.05,
362 bv_color: 1.38,
363 name: Some("Sargas B"),
364 },
365 Star {
366 hip: 95947,
367 ra_deg: 291.539,
368 dec_deg: -63.099,
369 magnitude: 1.91,
370 bv_color: 0.42,
371 name: Some("Atria B"),
372 },
373 Star {
374 hip: 98002,
375 ra_deg: 298.828,
376 dec_deg: 22.721,
377 magnitude: 2.23,
378 bv_color: 0.42,
379 name: Some("Sadr B"),
380 },
381 Star {
382 hip: 104732,
383 ra_deg: 318.234,
384 dec_deg: -9.482,
385 magnitude: 2.05,
386 bv_color: 1.17,
387 name: Some("Nunki B"),
388 },
389 Star {
390 hip: 108386,
391 ra_deg: 330.795,
392 dec_deg: -0.299,
393 magnitude: 2.74,
394 bv_color: 0.42,
395 name: Some("Sadalsuud"),
396 },
397 Star {
398 hip: 109074,
399 ra_deg: 333.820,
400 dec_deg: 1.765,
401 magnitude: 2.83,
402 bv_color: 0.42,
403 name: Some("Sadalmelik"),
404 },
405 Star {
406 hip: 109139,
407 ra_deg: 334.054,
408 dec_deg: 18.154,
409 magnitude: 3.27,
410 bv_color: 0.42,
411 name: Some("Enif"),
412 },
413 Star {
414 hip: 111841,
415 ra_deg: 341.373,
416 dec_deg: -5.099,
417 magnitude: 2.93,
418 bv_color: 1.45,
419 name: Some("Markab"),
420 },
421 Star {
422 hip: 112740,
423 ra_deg: 343.734,
424 dec_deg: -1.431,
425 magnitude: 3.53,
426 bv_color: 0.42,
427 name: Some("Algenib"),
428 },
429 Star {
430 hip: 113883,
431 ra_deg: 346.190,
432 dec_deg: -3.432,
433 magnitude: 2.49,
434 bv_color: 1.53,
435 name: Some("Diphda"),
436 },
437 Star {
438 hip: 43209,
439 ra_deg: 132.249,
440 dec_deg: -9.482,
441 magnitude: 3.53,
442 bv_color: 0.42,
443 name: Some("Zaurak"),
444 },
445 Star {
446 hip: 44816,
447 ra_deg: 136.999,
448 dec_deg: -9.482,
449 magnitude: 3.04,
450 bv_color: 0.42,
451 name: Some("Mirzam"),
452 },
453 Star {
454 hip: 57651,
455 ra_deg: 178.227,
456 dec_deg: -3.432,
457 magnitude: 2.90,
458 bv_color: 0.42,
459 name: Some("Alhena"),
460 },
461 Star {
462 hip: 63125,
463 ra_deg: 194.294,
464 dec_deg: -63.099,
465 magnitude: 2.81,
466 bv_color: 0.07,
467 name: Some("Atria C"),
468 },
469 Star {
470 hip: 71957,
471 ra_deg: 220.625,
472 dec_deg: -47.288,
473 magnitude: 2.39,
474 bv_color: 0.42,
475 name: Some("Sabik"),
476 },
477 Star {
478 hip: 72622,
479 ra_deg: 222.720,
480 dec_deg: -47.288,
481 magnitude: 2.43,
482 bv_color: 0.42,
483 name: Some("Sabik B"),
484 },
485 Star {
486 hip: 76267,
487 ra_deg: 233.672,
488 dec_deg: -26.432,
489 magnitude: 2.89,
490 bv_color: 1.17,
491 name: Some("Kaus Borealis"),
492 },
493 Star {
494 hip: 79593,
495 ra_deg: 243.454,
496 dec_deg: -34.074,
497 magnitude: 2.81,
498 bv_color: 1.17,
499 name: Some("Kaus Media"),
500 },
501 Star {
502 hip: 82396,
503 ra_deg: 251.498,
504 dec_deg: -34.074,
505 magnitude: 2.84,
506 bv_color: 1.17,
507 name: Some("Kaus Meridionalis"),
508 },
509 Star {
510 hip: 85927,
511 ra_deg: 262.688,
512 dec_deg: -34.074,
513 magnitude: 2.81,
514 bv_color: 1.17,
515 name: Some("Alnasl"),
516 },
517 Star {
518 hip: 86670,
519 ra_deg: 264.329,
520 dec_deg: -34.385,
521 magnitude: 3.32,
522 bv_color: 1.17,
523 name: Some("Albaldah"),
524 },
525];
526
527pub fn bright_stars_mesh(radius: f64) -> (Vec<[f32; 3]>, Vec<[f32; 4]>) {
528 let mut positions = Vec::new();
529 let mut colors = Vec::new();
530 for star in BRIGHT_STARS {
531 let pos = celestial_to_cartesian(star.ra_deg, star.dec_deg, radius);
532 positions.push(pos);
533 colors.push(bv_to_rgb(star.bv_color));
534 }
535 (positions, colors)
536}
537
538pub fn generate_synthetic_starfield(
539 count: u32,
540 radius: f64,
541 seed: u64,
542) -> (Vec<[f32; 3]>, Vec<[f32; 4]>) {
543 let mut positions = Vec::with_capacity(count as usize);
544 let mut colors = Vec::with_capacity(count as usize);
545 let mut state = seed;
546 for _ in 0..count {
547 state = state
548 .wrapping_mul(6364136223846793005)
549 .wrapping_add(1442695040888963407);
550 let u = ((state >> 32) as f64) / (u32::MAX as f64);
551 state = state
552 .wrapping_mul(6364136223846793005)
553 .wrapping_add(1442695040888963407);
554 let v = ((state >> 32) as f64) / (u32::MAX as f64);
555 let theta = 2.0 * std::f64::consts::PI * u;
556 let phi = (2.0 * v - 1.0).acos();
557 let x = radius * phi.sin() * theta.cos();
558 let y = radius * phi.cos();
559 let z = radius * phi.sin() * theta.sin();
560 positions.push([x as f32, y as f32, z as f32]);
561 state = state
562 .wrapping_mul(6364136223846793005)
563 .wrapping_add(1442695040888963407);
564 let bv = (((state >> 32) as f32) / (u32::MAX as f32)) * 2.0 - 0.4;
565 colors.push(bv_to_rgb(bv));
566 }
567 (positions, colors)
568}