diff --git a/src/gooey.cpp b/src/gooey.cpp index 9aeea30..8382758 100644 --- a/src/gooey.cpp +++ b/src/gooey.cpp @@ -41,18 +41,20 @@ gooProcessEvent(SDL_Event& e) || ImGui::GetIO().WantCaptureKeyboard); } +void drawSimulationWindow(bool& running, u64 sim_time_ms, float& sim_speed); void drawEllipseParameters(ellipse_parameters& ep); void drawGravitaationalBody(grav_body& body); void drawOrbitalElements(orbital_elements& el); void drawSatelliteWindow(satellite& sat); -void drawSystemWindow(system_2body& sys, bool& running); +void drawSystemWindow(system_2body& sys); const static int G_WIDTH = 300; const static ImVec2 V_SPACER(0, 10); const int H_FLAGS = ImGuiTreeNodeFlags_DefaultOpen; void -gooDraw(SDL_Window* window, system_2body& sys, bool& running) +gooDraw(SDL_Window* window, system_2body& sys, + bool& running, u64 sim_time_ms, float& sim_speed) { ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL2_NewFrame(window); @@ -64,7 +66,8 @@ gooDraw(SDL_Window* window, system_2body& sys, bool& running) ImGui::SetNextWindowSize(ImVec2(G_WIDTH, y)); ImGui::Begin("Gooey"); - drawSystemWindow(sys, running); + drawSimulationWindow(running, sim_time_ms, sim_speed); + drawSystemWindow(sys); drawSatelliteWindow(sys.sat); drawGravitaationalBody(sys.body); drawOrbitalElements(sys.elements); @@ -75,6 +78,21 @@ gooDraw(SDL_Window* window, system_2body& sys, bool& running) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } +void drawSimulationWindow(bool& running, u64 sim_time_ms, float& sim_speed) +{ + if (ImGui::CollapsingHeader("Simulation:", H_FLAGS)) { + if (ImGui::Button("||")) running = false; + ImGui::SameLine(); + if (ImGui::Button("|>")) running = true; + ImGui::SameLine(); + ImGui::Text("running: %s", (running > 0) ? "true" : "false"); + + ImGui::Text("sim time: %.3f s", + double(double(sim_time_ms) / 1000)); + ImGui::Text("sim speed: %.1f x", sim_speed); + } +} + void drawEllipseParameters(ellipse_parameters& ep) { if (ImGui::CollapsingHeader("Ellipse Parameters:", H_FLAGS)) { @@ -126,19 +144,9 @@ drawSatelliteWindow(satellite& sat) } } -void drawSystemWindow(system_2body& sys, bool& running) +void drawSystemWindow(system_2body& sys) { if (ImGui::CollapsingHeader("2 Body System:", H_FLAGS)) { - if (ImGui::Button("||")) running = false; - ImGui::SameLine(); - if (ImGui::Button("|>")) running = true; - ImGui::SameLine(); - ImGui::Text("running: %s", (running > 0) ? "true" : "false"); - - ImGui::Text("time_step:"); - ImGui::SameLine(); - ImGui::InputDouble("##", &sys.time_step, 5); - ImGui::Text("orbital period: %f", sys.orbital_period); ImGui::Text("epsilon, spec. orb. energy: %f", sys.epsilon); ImGui::Text("h, angular momentum: %f", sys.h); diff --git a/src/gooey.h b/src/gooey.h index 153f45d..26ba73a 100644 --- a/src/gooey.h +++ b/src/gooey.h @@ -16,5 +16,5 @@ bool gooProcessEvent(SDL_Event &e); void -gooDraw(SDL_Window* window, system_2body& sys, bool& running); - +gooDraw(SDL_Window* window, system_2body& sys, + bool& running, u64 sim_time_ms, float& sim_speed); diff --git a/src/main.cpp b/src/main.cpp index bcb70fe..59e8320 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,6 +38,10 @@ struct GameState bool running; MemoryArena* arena; + u64 game_time_ms; + u64 sim_time_ms; + float sim_speed; + system_2body system; // FIXME: we're going to need more than 1 system... Entity* satellite_entity; }; @@ -181,9 +185,11 @@ loadScene(GameState* gs, RenderState* rs) } void -updateSatelliteModel(const system_2body& sys, satellite& sat) +updateSatelliteModel(const system_2body& sys, + satellite& sat, + double time_step) { - sat.theta = getPropagatedTrueAnomaly(sys, sat.theta); + sat.theta = getPropagatedTrueAnomaly(sys, sat.theta, time_step); sat.gamma = orbitGetFlightPathAngle(sys.ep.e, sat.theta); sat.r = orbitGetRadialDistance(sys.ep.e, sys.ep.p, sat.theta); sat.v = orbitGetVelocity(sys.epsilon, sys.body.mu, sat.r); @@ -193,7 +199,6 @@ updateSatelliteModel(const system_2body& sys, satellite& sat) void updateSatelliteEntity(Entity* e, const satellite& sat) { - // TODO: decouple framerate from time_step const static mat4 xform = glm::rotate(mat4(1.0), (float) M_PI_2, vec3(1, 0, 0)); const vec3& v = sat.position; @@ -222,39 +227,50 @@ preFrameCallback(RenderState* rs, void* user_data = nullptr) bool gooey_wants = false; while (SDL_PollEvent(&e)) { + // FIXME: we should check for escape key here first gooey_wants = gooProcessEvent(e); if (!gooey_wants) inputProcessEvent(&is, e); } if (is.window_closed || is.escape) rs->running = false; -} -void -postFrameCallback(RenderState* rs, void* user_data = nullptr) -{ + // TODO: sim time stuff should have dedicated functions, and maybe a test + // since it's pretty important that the simulation is accurate-ish + // TODO: verify time to apoapsis/periapsis are correct assert(user_data != nullptr); GameState* gs = (GameState*) user_data; - gooDraw(rs->handles.window, gs->system, gs->running); + u64 last_sdl_tick = gs->game_time_ms; + gs->game_time_ms = SDL_GetTicks64(); + u64 current_tick = gs->game_time_ms - last_sdl_tick; + // NOTE: update sim time base on time since last frame * sim_speed if (gs->running) { - updateSatelliteModel(gs->system, gs->system.sat); + u64 last_game_tick = gs->sim_time_ms; + gs->sim_time_ms = gs->sim_time_ms + current_tick * gs->sim_speed; + u32 diff_ms = gs->sim_time_ms - last_game_tick; + double time_step = double(diff_ms) / 1000; + + updateSatelliteModel(gs->system, gs->system.sat, time_step); gs->system.ep = ellipseInitAE(gs->system.ep.a, gs->system.ep.e); updateSatelliteEntity(gs->satellite_entity, gs->system.sat); //updateOrbit(gs->system, ellipse_entity); } +} - // FIXME: testing sim time - u64 ticks = SDL_GetTicks64(); - static u32 last_T; - u32 T = ticks / 1000; - - if (T != last_T) { - LOGF(Debug, "seconds since sim start: %d\n", T); - last_T = T; - } +void +postFrameCallback(RenderState* rs, void* user_data = nullptr) +{ + assert(user_data != nullptr); + GameState* gs = (GameState*) user_data; + gooDraw(rs->handles.window, + gs->system, + gs->running, + gs->sim_time_ms, + gs->sim_speed); } +#define DEFAULT_SIM_SPEED 100 int main() { @@ -274,6 +290,7 @@ main() GameState gs = {0}; gs.arena = arenaInit(16); + gs.sim_speed = DEFAULT_SIM_SPEED; loadScene(&gs, rs); doRenderLoop(rs, 60, preFrameCallback, postFrameCallback, &gs); gooFree(); diff --git a/src/orbits.cpp b/src/orbits.cpp index f09a9d6..c465fab 100644 --- a/src/orbits.cpp +++ b/src/orbits.cpp @@ -6,7 +6,7 @@ const static uint ELLIPSE_VERT_COUNT = 256; system_2body -systemInit(grav_body gb, orbital_elements el, float time_step) +systemInit(grav_body gb, orbital_elements el) { system_2body s = {0}; s.body = gb; @@ -18,7 +18,6 @@ systemInit(grav_body gb, orbital_elements el, float time_step) s.orbital_period = orbitGetPeriod(s.ep.a, gb.mu); s.r_apoapsis = s.ep.a - s.ep.c; s.r_periapsis = 2 * s.ep.a - s.r_apoapsis; - s.time_step = time_step; return s; } @@ -214,13 +213,14 @@ getNextTrialValue(double err, double ecc, double test_anom, double mean_anom) double getPropagatedEccAnomaly(system_2body sys, - double initial_anom) + double initial_anom, + double time_step) { double e = sys.ep.e; double E1 = getEccAnomFromTrueAnom(e, initial_anom); double M1 = getMeanAnomFromEccAnom(E1, e); double n = getMeanMotion(sys.body.mu, sys.elements.a); - double M2 = getPropagatedMeanAnom(M1, n, sys.time_step); + double M2 = getPropagatedMeanAnom(M1, n, time_step); double E2_1 = getInitialTrialValue(M2, e); // test if guess is a solution to kepler's equation @@ -241,13 +241,15 @@ getPropagatedEccAnomaly(system_2body sys, double getPropagatedTrueAnomaly(system_2body sys, - double initial_anom) + double initial_anom, + double time_step) { + // FIXME: I don't think we need this now that we have gs->running? // NOTE: 'pause' simulation when time_step is set close to 0 - if (sys.time_step < 1e-8 && sys.time_step > -1e-8) + if (time_step < 1e-8 && time_step > -1e-8) return initial_anom; - double ecc_anom = getPropagatedEccAnomaly(sys, initial_anom); + double ecc_anom = getPropagatedEccAnomaly(sys, initial_anom, time_step); return getTrueAnomFromEccAnom(sys.ep.e, ecc_anom); } diff --git a/src/orbits.h b/src/orbits.h index 2328c2a..0ca1e86 100644 --- a/src/orbits.h +++ b/src/orbits.h @@ -67,16 +67,11 @@ struct system_2body double r_apoapsis; // NOTE: apoapse distance from body center double r_periapsis; // NOTE: periapsis distance from body center double orbital_period; // NOTE: in seconds - - double time_step; }; -#define DEFAULT_TIME_STEP 1 system_2body -systemInit(grav_body gb, - orbital_elements el, - float time_step = DEFAULT_TIME_STEP); +systemInit(grav_body gb, orbital_elements el); grav_body gravBodyInit(double mu, double r); @@ -152,7 +147,8 @@ orbitUpdate(orbital_elements& o, double a, double e); */ double getPropagatedTrueAnomaly(system_2body sys, - double initial_anom); + double initial_anom, + double time_step); // NOTE: in seconds // NOTE: aka) the trajectory equation (eq. 2.45) double