Skip to content

Commit f54230b

Browse files
committed
improved time calculations
1 parent 2e46977 commit f54230b

4 files changed

Lines changed: 48 additions & 51 deletions

File tree

src/astro.c

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,16 @@ double normalize_epoch(double epoch) {
6060
return (yy * 1000.0) + day_of_year;
6161
}
6262

63-
double epoch_to_gmst(double epoch) {
63+
// utility to convert normalized epoch format to unix time for sgp4 math
64+
double get_unix_from_epoch(double epoch) {
6465
epoch = normalize_epoch(epoch);
6566
int yy = (int)(epoch / 1000.0);
6667
double day = fmod(epoch, 1000.0);
67-
68-
double unix_time = ConvertEpochYearAndDayToUnix(yy, day);
68+
return ConvertEpochYearAndDayToUnix(yy, day);
69+
}
70+
71+
double epoch_to_gmst(double epoch) {
72+
double unix_time = get_unix_from_epoch(epoch);
6973
double jd = (unix_time / 86400.0) + 2440587.5;
7074

7175
double gmst = fmod(280.46061837 + 360.98564736629 * (jd - 2451545.0), 360.0);
@@ -134,6 +138,7 @@ void load_tle_data(const char* filename) {
134138
}
135139

136140
sat->epoch_days = parse_tle_double(line1, 18, 14);
141+
sat->epoch_unix = get_unix_from_epoch(sat->epoch_days); // precalculated for perf
137142
sat->inclination = parse_tle_double(line2, 8, 8) * DEG2RAD;
138143
sat->raan = parse_tle_double(line2, 17, 8) * DEG2RAD;
139144

@@ -152,18 +157,9 @@ void load_tle_data(const char* filename) {
152157
fclose(file);
153158
}
154159

155-
Vector3 calculate_position(Satellite* sat, double current_time_days) {
156-
current_time_days = normalize_epoch(current_time_days);
157-
158-
int cur_yy = (int)(current_time_days / 1000.0);
159-
double cur_day = fmod(current_time_days, 1000.0);
160-
double current_unix = ConvertEpochYearAndDayToUnix(cur_yy, cur_day);
161-
162-
int sat_yy = (int)(sat->epoch_days / 1000.0);
163-
double sat_day = fmod(sat->epoch_days, 1000.0);
164-
double sat_unix = ConvertEpochYearAndDayToUnix(sat_yy, sat_day);
165-
166-
double tsince = (current_unix - sat_unix) / 60.0;
160+
// precalculated unix time passed down to prevent excessyear/day conversions
161+
Vector3 calculate_position(Satellite* sat, double current_unix) {
162+
double tsince = (current_unix - sat->epoch_unix) / 60.0;
167163

168164
double ro[3] = {0};
169165
double vo[3] = {0};
@@ -197,17 +193,9 @@ void get_map_coordinates(Vector3 pos, double gmst_deg, float earth_offset, float
197193

198194
void get_apsis_2d(Satellite* sat, double current_time, bool is_apoapsis, double gmst_deg, float earth_offset, float map_w, float map_h, Vector2* out) {
199195
(void)gmst_deg;
200-
current_time = normalize_epoch(current_time);
201-
202-
int cur_yy = (int)(current_time / 1000.0);
203-
double cur_day = fmod(current_time, 1000.0);
204-
double current_unix = ConvertEpochYearAndDayToUnix(cur_yy, cur_day);
205196

206-
int sat_yy = (int)(sat->epoch_days / 1000.0);
207-
double sat_day = fmod(sat->epoch_days, 1000.0);
208-
double sat_unix = ConvertEpochYearAndDayToUnix(sat_yy, sat_day);
209-
210-
double delta_time_s = current_unix - sat_unix;
197+
double current_unix = get_unix_from_epoch(current_time);
198+
double delta_time_s = current_unix - sat->epoch_unix;
211199

212200
double M = fmod(sat->mean_anomaly + sat->mean_motion * delta_time_s, 2.0 * PI);
213201
if (M < 0) M += 2.0 * PI;
@@ -217,20 +205,16 @@ void get_apsis_2d(Satellite* sat, double current_time, bool is_apoapsis, double
217205
if (diff < 0) diff += 2.0 * PI;
218206

219207
double t_target = current_time + (diff / sat->mean_motion) / 86400.0;
220-
Vector3 pos3d = calculate_position(sat, t_target);
208+
double t_target_unix = get_unix_from_epoch(t_target);
209+
Vector3 pos3d = calculate_position(sat, t_target_unix);
221210
double gmst_target = epoch_to_gmst(t_target);
222211

223212
get_map_coordinates(pos3d, gmst_target, earth_offset, map_w, map_h, &out->x, &out->y);
224213
}
225214

226215
// i truly do hope this doesnt drift or something its so eyeballed istg
227216
Vector3 calculate_sun_position(double current_time_days) {
228-
current_time_days = normalize_epoch(current_time_days);
229-
230-
int yy = (int)(current_time_days / 1000.0);
231-
double day = fmod(current_time_days, 1000.0);
232-
233-
double unix_time = ConvertEpochYearAndDayToUnix(yy, day);
217+
double unix_time = get_unix_from_epoch(current_time_days);
234218
double jd = (unix_time / 86400.0) + 2440587.5;
235219
double n = jd - 2451545.0;
236220

@@ -260,12 +244,7 @@ Vector3 calculate_sun_position(double current_time_days) {
260244
}
261245

262246
Vector3 calculate_moon_position(double current_time_days) {
263-
current_time_days = normalize_epoch(current_time_days);
264-
265-
int yy = (int)(current_time_days / 1000.0);
266-
double day = fmod(current_time_days, 1000.0);
267-
268-
double unix_time = ConvertEpochYearAndDayToUnix(yy, day);
247+
double unix_time = get_unix_from_epoch(current_time_days);
269248
double jd = (unix_time / 86400.0) + 2440587.5;
270249
double D = jd - 2451545.0;
271250

src/astro.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ double epoch_to_gmst(double epoch);
88
void epoch_to_datetime_str(double epoch, char* buffer);
99
void load_tle_data(const char* filename);
1010
double normalize_epoch(double epoch);
11+
double get_unix_from_epoch(double epoch);
1112

1213
// orbit math stuff
1314
Vector3 calculate_sun_position(double current_time_days);
1415
void get_map_coordinates(Vector3 pos, double gmst_deg, float earth_offset, float map_w, float map_h, float* out_x, float* out_y);
15-
Vector3 calculate_position(Satellite* sat, double current_time_days);
16+
Vector3 calculate_position(Satellite* sat, double current_unix);
1617
Vector3 calculate_moon_position(double current_time_days);
17-
void get_map_coordinates(Vector3 pos, double gmst_deg, float earth_offset, float map_w, float map_h, float* out_x, float* out_y);
1818
void get_apsis_2d(Satellite* sat, double current_time, bool is_apoapsis, double gmst_deg, float earth_offset, float map_w, float map_h, Vector2* out);
1919

2020
#endif // ASTRO_H

src/main.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ static void update_orbit_cache(Satellite* sat, double current_epoch) {
161161
double time_step = period_days / (ORBIT_CACHE_SIZE - 1);
162162
for (int i = 0; i < ORBIT_CACHE_SIZE; i++) {
163163
double t = current_epoch + (i * time_step);
164-
sat->orbit_cache[i] = Vector3Scale(calculate_position(sat, t), 1.0f / DRAW_SCALE);
164+
double t_unix = get_unix_from_epoch(t);
165+
sat->orbit_cache[i] = Vector3Scale(calculate_position(sat, t_unix), 1.0f / DRAW_SCALE);
165166
}
166167
sat->orbit_cached = true;
167168
}
@@ -181,7 +182,8 @@ static void draw_orbit_3d(Satellite* sat, double current_epoch, bool is_highligh
181182

182183
for (int i = 0; i <= segments; i++) {
183184
double t = current_epoch + (i * time_step);
184-
Vector3 pos = Vector3Scale(calculate_position(sat, t), 1.0f / DRAW_SCALE);
185+
double t_unix = get_unix_from_epoch(t);
186+
Vector3 pos = Vector3Scale(calculate_position(sat, t_unix), 1.0f / DRAW_SCALE);
185187

186188
if (i > 0) DrawLine3D(prev_pos, pos, orbitColor);
187189
prev_pos = pos;
@@ -382,6 +384,15 @@ int main(void) {
382384
}
383385
}
384386

387+
double current_unix = get_unix_from_epoch(current_epoch);
388+
389+
// precalculate all satellite positions for the current frame
390+
for (int i = 0; i < sat_count; i++) {
391+
// don't waste time calculating if it's hidden and not selected
392+
if (hide_unselected && selected_sat != NULL && &satellites[i] != selected_sat) continue;
393+
satellites[i].current_pos = calculate_position(&satellites[i], current_unix);
394+
}
395+
385396
// fading math
386397
bool should_hide = (hide_unselected && selected_sat != NULL);
387398
if (should_hide) {
@@ -432,7 +443,6 @@ int main(void) {
432443
float hit_radius_pixels = 12.0f * cfg.ui_scale; // hitbox size in screen pixels
433444

434445
for (int i = 0; i < sat_count; i++) {
435-
satellites[i].current_pos = calculate_position(&satellites[i], current_epoch);
436446
// prevent raycasting on hidden satellites
437447
if (hide_unselected && selected_sat != NULL && &satellites[i] != selected_sat) continue;
438448

@@ -468,11 +478,13 @@ int main(void) {
468478
float closest_dist = 9999.0f;
469479

470480
for (int i = 0; i < sat_count; i++) {
471-
satellites[i].current_pos = calculate_position(&satellites[i], current_epoch);
472481
// Prevent raycasting on fading/hidden satellites
473482
if (hide_unselected && selected_sat != NULL && &satellites[i] != selected_sat) continue;
474483

475484
Vector3 draw_pos = Vector3Scale(satellites[i].current_pos, 1.0f / DRAW_SCALE);
485+
486+
// fast coarse culling via squared distance to avoid expensive sphere collision checks on distant satellites
487+
if (Vector3DistanceSqr(camera3d.target, draw_pos) > (camDistance * camDistance * 16.0f)) continue;
476488

477489
// adjust sphere radius based on distance to maintain consistent screen-size hitbox
478490
float distToCam = Vector3Distance(camera3d.position, draw_pos);
@@ -680,7 +692,8 @@ int main(void) {
680692

681693
for (int j = 0; j <= segments; j++) {
682694
double t = current_epoch + (j * time_step);
683-
get_map_coordinates(calculate_position(&satellites[i], t), epoch_to_gmst(t), cfg.earth_rotation_offset, map_w, map_h, &track_pts[j].x, &track_pts[j].y);
695+
double t_unix = get_unix_from_epoch(t);
696+
get_map_coordinates(calculate_position(&satellites[i], t_unix), epoch_to_gmst(t), cfg.earth_rotation_offset, map_w, map_h, &track_pts[j].x, &track_pts[j].y);
684697
}
685698

686699
for (int offset_i = -1; offset_i <= 1; offset_i++) {
@@ -816,9 +829,11 @@ int main(void) {
816829

817830
double t_peri = current_epoch + (diff_peri / active_sat->mean_motion) / 86400.0;
818831
double t_apo = current_epoch + (diff_apo / active_sat->mean_motion) / 86400.0;
832+
double t_peri_unix = get_unix_from_epoch(t_peri);
833+
double t_apo_unix = get_unix_from_epoch(t_apo);
819834

820-
Vector3 draw_p = Vector3Scale(calculate_position(active_sat, t_peri), 1.0f/DRAW_SCALE);
821-
Vector3 draw_a = Vector3Scale(calculate_position(active_sat, t_apo), 1.0f/DRAW_SCALE);
835+
Vector3 draw_p = Vector3Scale(calculate_position(active_sat, t_peri_unix), 1.0f/DRAW_SCALE);
836+
Vector3 draw_a = Vector3Scale(calculate_position(active_sat, t_apo_unix), 1.0f/DRAW_SCALE);
822837

823838
if (!IsOccludedByEarth(camera3d.position, draw_p, draw_earth_radius)) {
824839
Vector2 sp = GetWorldToScreen(draw_p, camera3d);
@@ -956,9 +971,11 @@ int main(void) {
956971

957972
double t_peri = current_epoch + (diff_peri / active_sat->mean_motion) / 86400.0;
958973
double t_apo = current_epoch + (diff_apo / active_sat->mean_motion) / 86400.0;
974+
double t_peri_unix = get_unix_from_epoch(t_peri);
975+
double t_apo_unix = get_unix_from_epoch(t_apo);
959976

960-
double real_rp = Vector3Length(calculate_position(active_sat, t_peri));
961-
double real_ra = Vector3Length(calculate_position(active_sat, t_apo));
977+
double real_rp = Vector3Length(calculate_position(active_sat, t_peri_unix));
978+
double real_ra = Vector3Length(calculate_position(active_sat, t_apo_unix));
962979
// hide the periapsis/apoapsis markers if they're currently behind the Earth in the 3D view, or just off the edge of the map in 2D
963980
if (is_2d_view) {
964981
Vector2 p2, a2;
@@ -974,8 +991,8 @@ int main(void) {
974991
periScreen = GetWorldToScreen2D(p2, camera2d);
975992
apoScreen = GetWorldToScreen2D(a2, camera2d);
976993
} else {
977-
Vector3 draw_p = Vector3Scale(calculate_position(active_sat, t_peri), 1.0f/DRAW_SCALE);
978-
Vector3 draw_a = Vector3Scale(calculate_position(active_sat, t_apo), 1.0f/DRAW_SCALE);
994+
Vector3 draw_p = Vector3Scale(calculate_position(active_sat, t_peri_unix), 1.0f/DRAW_SCALE);
995+
Vector3 draw_a = Vector3Scale(calculate_position(active_sat, t_apo_unix), 1.0f/DRAW_SCALE);
979996

980997
if (IsOccludedByEarth(camera3d.position, draw_p, draw_earth_radius)) show_peri = false;
981998
if (IsOccludedByEarth(camera3d.position, draw_a, draw_earth_radius)) show_apo = false;

src/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
typedef struct {
2222
char name[32];
2323
double epoch_days;
24+
double epoch_unix;
2425
double inclination;
2526
double raan;
2627
double eccentricity;

0 commit comments

Comments
 (0)