Skip to content

Commit 2cdf852

Browse files
committed
reverted orbital mechanics changes and improved peri/apo markers
1 parent 915404b commit 2cdf852

3 files changed

Lines changed: 76 additions & 53 deletions

File tree

resources/smallmark.png

454 Bytes
Loading

src/astro.c

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -123,48 +123,29 @@ void load_tle_data(const char* filename) {
123123
fclose(file);
124124
}
125125

126-
// figure out where the satellite is right now (with j2 spheroid perturbations)
126+
// figure out where the satellite is right now
127127
Vector3 calculate_position(Satellite* sat, double current_time_days) {
128128
double delta_time_s = (current_time_days - sat->epoch_days) * 86400.0;
129-
130-
// earth oblateness (j2) effects
131-
double e2 = sat->eccentricity * sat->eccentricity;
132-
double p = sat->semi_major_axis * (1.0 - e2);
133-
134-
// j2 math constants
135-
const double J2 = 0.00108262668;
136-
const double RE = EARTH_RADIUS_KM; // earth radius in km
137-
138-
double n_J2_Re2_p2 = sat->mean_motion * J2 * (RE * RE) / (p * p);
139-
double raan_dot = -1.5 * n_J2_Re2_p2 * cos(sat->inclination);
140-
double arg_perigee_dot = 0.75 * n_J2_Re2_p2 * (4.0 - 5.0 * pow(sin(sat->inclination), 2));
141-
142-
double current_raan = sat->raan + raan_dot * delta_time_s;
143-
double current_arg_perigee = sat->arg_perigee + arg_perigee_dot * delta_time_s;
144-
145129
double M = sat->mean_anomaly + sat->mean_motion * delta_time_s;
146130
M = fmod(M, 2.0 * PI);
147-
if (M < 0.0) M += 2.0 * PI;
131+
if (M < 0) M += 2.0 * PI;
148132

149-
// improved guess for kepler's equation
150-
double E = M + sat->eccentricity * sin(M);
151-
double sinE, cosE;
133+
double E = M;
152134
for (int i = 0; i < 10; i++) {
153-
sinE = sin(E);
154-
cosE = cos(E);
155-
double delta = (E - sat->eccentricity * sinE - M) / (1.0 - sat->eccentricity * cosE);
135+
double delta = (E - sat->eccentricity * sin(E) - M) / (1.0 - sat->eccentricity * cos(E));
156136
E -= delta;
157137
if (fabs(delta) < 1e-6) break;
158138
}
159139

160-
// bypass true anomaly calculation
161-
double sqrt_1_minus_e2 = sqrt(1.0 - e2);
162-
double x_orb = sat->semi_major_axis * (cosE - sat->eccentricity);
163-
double y_orb = sat->semi_major_axis * sqrt_1_minus_e2 * sinE;
140+
double nu = 2.0 * atan2(sqrt(1.0 + sat->eccentricity) * sin(E / 2.0),
141+
sqrt(1.0 - sat->eccentricity) * cos(E / 2.0));
142+
143+
double r = sat->semi_major_axis * (1.0 - sat->eccentricity * cos(E));
144+
double x_orb = r * cos(nu);
145+
double y_orb = r * sin(nu);
164146

165-
// use perturbed angles for orientation
166-
double cw = cos(current_arg_perigee), sw = sin(current_arg_perigee);
167-
double cO = cos(current_raan), sO = sin(current_raan);
147+
double cw = cos(sat->arg_perigee), sw = sin(sat->arg_perigee);
148+
double cO = cos(sat->raan), sO = sin(sat->raan);
168149
double ci = cos(sat->inclination), si = sin(sat->inclination);
169150

170151
Vector3 pos;

src/main.c

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ static AppConfig cfg = {
1919
.bg_color = {0, 0, 0, 255}, .text_main = {255, 255, 255, 255}
2020
};
2121

22-
23-
2422
static Font customFont;
2523
static Texture2D satIcon, markerIcon, earthTexture, moonTexture;
24+
static Texture2D periMark, apoMark; // New textures
2625
static Model earthModel, moonModel;
2726

2827
// safely modifies the alpha channel without relying on raylib's Fade()
@@ -149,8 +148,13 @@ int main(void) {
149148

150149
satIcon = LoadTexture("resources/sat_icon.png");
151150
markerIcon = LoadTexture("resources/marker_icon.png");
151+
periMark = LoadTexture("resources/smallmark.png");
152+
apoMark = LoadTexture("resources/smallmark.png");
153+
152154
SetTextureFilter(satIcon, TEXTURE_FILTER_BILINEAR);
153155
SetTextureFilter(markerIcon, TEXTURE_FILTER_BILINEAR);
156+
SetTextureFilter(periMark, TEXTURE_FILTER_BILINEAR);
157+
SetTextureFilter(apoMark, TEXTURE_FILTER_BILINEAR);
154158

155159
load_tle_data("resources/data.tle");
156160

@@ -428,7 +432,7 @@ int main(void) {
428432

429433
float m_size_2d = 24.0f * cfg.ui_scale / camera2d.zoom;
430434
float m_text_2d = 16.0f * cfg.ui_scale / camera2d.zoom;
431-
float marker_radius_2d = fmaxf(1.0f, 4.0f * cfg.ui_scale / camera2d.zoom);
435+
float mark_size_2d = 32.0f * cfg.ui_scale / camera2d.zoom;
432436

433437
if (is_2d_view) {
434438
// drawing the flat map
@@ -534,8 +538,11 @@ int main(void) {
534538
Vector2 peri2d, apo2d;
535539
get_apsis_2d(&satellites[i], current_epoch, false, gmst_deg, cfg.earth_rotation_offset, map_w, map_h, &peri2d);
536540
get_apsis_2d(&satellites[i], current_epoch, true, gmst_deg, cfg.earth_rotation_offset, map_w, map_h, &apo2d);
537-
DrawCircleV((Vector2){peri2d.x + x_off, peri2d.y}, marker_radius_2d, ApplyAlpha(cfg.periapsis, sat_alpha));
538-
DrawCircleV((Vector2){apo2d.x + x_off, apo2d.y}, marker_radius_2d, ApplyAlpha(cfg.apoapsis, sat_alpha));
541+
542+
DrawTexturePro(periMark, (Rectangle){0,0,periMark.width,periMark.height},
543+
(Rectangle){peri2d.x + x_off, peri2d.y, mark_size_2d, mark_size_2d}, (Vector2){mark_size_2d/2.f, mark_size_2d/2.f}, 0.0f, ApplyAlpha(cfg.periapsis, sat_alpha));
544+
DrawTexturePro(apoMark, (Rectangle){0,0,apoMark.width,apoMark.height},
545+
(Rectangle){apo2d.x + x_off, apo2d.y, mark_size_2d, mark_size_2d}, (Vector2){mark_size_2d/2.f, mark_size_2d/2.f}, 0.0f, ApplyAlpha(cfg.apoapsis, sat_alpha));
539546
}
540547
}
541548

@@ -602,24 +609,42 @@ int main(void) {
602609
if (is_hl) {
603610
Vector3 draw_pos = Vector3Scale(satellites[i].current_pos, 1.0f / DRAW_SCALE);
604611
DrawLine3D(Vector3Zero(), draw_pos, ApplyAlpha(cfg.orbit_highlighted, sat_alpha));
605-
606-
double rp = satellites[i].semi_major_axis * (1.0 - satellites[i].eccentricity);
607-
double ra = satellites[i].semi_major_axis * (1.0 + satellites[i].eccentricity);
608-
double cw = cos(satellites[i].arg_perigee), sw = sin(satellites[i].arg_perigee);
609-
double cO = cos(satellites[i].raan), sO = sin(satellites[i].raan);
610-
double ci = cos(satellites[i].inclination), si = sin(satellites[i].inclination);
611-
612-
Vector3 periVec = { (cO*cw - sO*sw*ci)*rp, (sw*si)*rp, -((sO*cw + cO*sw*ci)*rp) };
613-
Vector3 apoVec = { (cO*cw - sO*sw*ci)*(-ra), (sw*si)*(-ra), -((sO*cw + cO*sw*ci)*(-ra)) };
614-
615-
DrawSphere(Vector3Scale(periVec, 1.0f/DRAW_SCALE), 0.08f*cfg.ui_scale, ApplyAlpha(cfg.periapsis, sat_alpha));
616-
DrawSphere(Vector3Scale(apoVec, 1.0f/DRAW_SCALE), 0.08f*cfg.ui_scale, ApplyAlpha(cfg.apoapsis, sat_alpha));
617612
}
618613
}
619614
EndMode3D();
615+
616+
// marker scale and occlusion
620617

621618
float m_size_3d = 24.0f * cfg.ui_scale;
622619
float m_text_3d = 16.0f * cfg.ui_scale;
620+
float mark_size_3d = 32.0f * cfg.ui_scale;
621+
622+
if (active_sat) {
623+
bool is_unselected = (selected_sat != NULL && active_sat != selected_sat);
624+
float sat_alpha = is_unselected ? unselected_fade : 1.0f;
625+
626+
double rp = active_sat->semi_major_axis * (1.0 - active_sat->eccentricity);
627+
double ra = active_sat->semi_major_axis * (1.0 + active_sat->eccentricity);
628+
double cw = cos(active_sat->arg_perigee), sw = sin(active_sat->arg_perigee);
629+
double cO = cos(active_sat->raan), sO = sin(active_sat->raan);
630+
double ci = cos(active_sat->inclination), si = sin(active_sat->inclination);
631+
632+
Vector3 periVec = { (cO*cw - sO*sw*ci)*rp, (sw*si)*rp, -((sO*cw + cO*sw*ci)*rp) };
633+
Vector3 apoVec = { (cO*cw - sO*sw*ci)*(-ra), (sw*si)*(-ra), -((sO*cw + cO*sw*ci)*(-ra)) };
634+
Vector3 draw_p = Vector3Scale(periVec, 1.0f/DRAW_SCALE);
635+
Vector3 draw_a = Vector3Scale(apoVec, 1.0f/DRAW_SCALE);
636+
637+
if (!IsOccludedByEarth(camera3d.position, draw_p, draw_earth_radius)) {
638+
Vector2 sp = GetWorldToScreen(draw_p, camera3d);
639+
DrawTexturePro(periMark, (Rectangle){0,0,periMark.width,periMark.height},
640+
(Rectangle){sp.x, sp.y, mark_size_3d, mark_size_3d}, (Vector2){mark_size_3d/2.f, mark_size_3d/2.f}, 0.0f, ApplyAlpha(cfg.periapsis, sat_alpha));
641+
}
642+
if (!IsOccludedByEarth(camera3d.position, draw_a, draw_earth_radius)) {
643+
Vector2 sp = GetWorldToScreen(draw_a, camera3d);
644+
DrawTexturePro(apoMark, (Rectangle){0,0,apoMark.width,apoMark.height},
645+
(Rectangle){sp.x, sp.y, mark_size_3d, mark_size_3d}, (Vector2){mark_size_3d/2.f, mark_size_3d/2.f}, 0.0f, ApplyAlpha(cfg.apoapsis, sat_alpha));
646+
}
647+
}
623648

624649
for (int i = 0; i < sat_count; i++) {
625650
bool is_unselected = (selected_sat != NULL && &satellites[i] != selected_sat);
@@ -719,6 +744,10 @@ int main(void) {
719744
double rp = active_sat->semi_major_axis * (1.0 - active_sat->eccentricity);
720745
double ra = active_sat->semi_major_axis * (1.0 + active_sat->eccentricity);
721746
Vector2 periScreen, apoScreen;
747+
748+
bool show_peri = true;
749+
bool show_apo = true;
750+
722751
if (is_2d_view) {
723752
Vector2 p2, a2;
724753
get_apsis_2d(active_sat, current_epoch, false, gmst_deg, cfg.earth_rotation_offset, map_w, map_h, &p2);
@@ -738,11 +767,22 @@ int main(void) {
738767
double ci = cos(active_sat->inclination), si = sin(active_sat->inclination);
739768
Vector3 periVec = { (cO*cw - sO*sw*ci)*rp, (sw*si)*rp, -((sO*cw + cO*sw*ci)*rp) };
740769
Vector3 apoVec = { (cO*cw - sO*sw*ci)*(-ra), (sw*si)*(-ra), -((sO*cw + cO*sw*ci)*(-ra)) };
741-
periScreen = GetWorldToScreen(Vector3Scale(periVec, 1.0f/DRAW_SCALE), camera3d);
742-
apoScreen = GetWorldToScreen(Vector3Scale(apoVec, 1.0f/DRAW_SCALE), camera3d);
770+
Vector3 draw_p = Vector3Scale(periVec, 1.0f/DRAW_SCALE);
771+
Vector3 draw_a = Vector3Scale(apoVec, 1.0f/DRAW_SCALE);
772+
773+
if (IsOccludedByEarth(camera3d.position, draw_p, draw_earth_radius)) show_peri = false;
774+
if (IsOccludedByEarth(camera3d.position, draw_a, draw_earth_radius)) show_apo = false;
775+
776+
periScreen = GetWorldToScreen(draw_p, camera3d);
777+
apoScreen = GetWorldToScreen(draw_a, camera3d);
743778
}
744-
DrawUIText(TextFormat("Peri: %.0f km", rp-EARTH_RADIUS_KM), periScreen.x, periScreen.y-(15*cfg.ui_scale), 16*cfg.ui_scale, cfg.periapsis);
745-
DrawUIText(TextFormat("Apo: %.0f km", ra-EARTH_RADIUS_KM), apoScreen.x, apoScreen.y-(15*cfg.ui_scale), 16*cfg.ui_scale, cfg.apoapsis);
779+
780+
float text_size = 16.0f * cfg.ui_scale;
781+
float x_offset = 20.0f * cfg.ui_scale;
782+
float y_offset = text_size / 2.2f;
783+
784+
if (show_peri) DrawUIText(TextFormat("Peri: %.0f km", rp-EARTH_RADIUS_KM), periScreen.x + x_offset, periScreen.y - y_offset, text_size, cfg.periapsis);
785+
if (show_apo) DrawUIText(TextFormat("Apo: %.0f km", ra-EARTH_RADIUS_KM), apoScreen.x + x_offset, apoScreen.y - y_offset, text_size, cfg.apoapsis);
746786
}
747787

748788
// performance stats :3
@@ -755,11 +795,13 @@ int main(void) {
755795
// cleanup time before closing
756796
UnloadTexture(satIcon);
757797
UnloadTexture(markerIcon);
798+
UnloadTexture(periMark);
799+
UnloadTexture(apoMark);
758800
UnloadTexture(earthTexture);
759801
UnloadModel(earthModel);
760802
UnloadTexture(moonTexture);
761803
UnloadModel(moonModel);
762804
UnloadFont(customFont);
763805
CloseWindow();
764806
return 0;
765-
}
807+
}

0 commit comments

Comments
 (0)