Browse Source

fix incorrect simulation time_step

We're not tracking sim_time and sim_speed on the GameState object,
and only updating sim_time when gs->running == true

Also updated the gooey with a Simulation Window to display the new
properties
main
cinnaboot 4 years ago
parent
commit
45fa17554c
  1. 36
      src/gooey.cpp
  2. 4
      src/gooey.h
  3. 53
      src/main.cpp
  4. 16
      src/orbits.cpp
  5. 10
      src/orbits.h

36
src/gooey.cpp

@ -41,18 +41,20 @@ gooProcessEvent(SDL_Event& e)
|| ImGui::GetIO().WantCaptureKeyboard); || ImGui::GetIO().WantCaptureKeyboard);
} }
void drawSimulationWindow(bool& running, u64 sim_time_ms, float& sim_speed);
void drawEllipseParameters(ellipse_parameters& ep); void drawEllipseParameters(ellipse_parameters& ep);
void drawGravitaationalBody(grav_body& body); void drawGravitaationalBody(grav_body& body);
void drawOrbitalElements(orbital_elements& el); void drawOrbitalElements(orbital_elements& el);
void drawSatelliteWindow(satellite& sat); void drawSatelliteWindow(satellite& sat);
void drawSystemWindow(system_2body& sys, bool& running); void drawSystemWindow(system_2body& sys);
const static int G_WIDTH = 300; const static int G_WIDTH = 300;
const static ImVec2 V_SPACER(0, 10); const static ImVec2 V_SPACER(0, 10);
const int H_FLAGS = ImGuiTreeNodeFlags_DefaultOpen; const int H_FLAGS = ImGuiTreeNodeFlags_DefaultOpen;
void 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_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(window); ImGui_ImplSDL2_NewFrame(window);
@ -64,7 +66,8 @@ gooDraw(SDL_Window* window, system_2body& sys, bool& running)
ImGui::SetNextWindowSize(ImVec2(G_WIDTH, y)); ImGui::SetNextWindowSize(ImVec2(G_WIDTH, y));
ImGui::Begin("Gooey"); ImGui::Begin("Gooey");
drawSystemWindow(sys, running); drawSimulationWindow(running, sim_time_ms, sim_speed);
drawSystemWindow(sys);
drawSatelliteWindow(sys.sat); drawSatelliteWindow(sys.sat);
drawGravitaationalBody(sys.body); drawGravitaationalBody(sys.body);
drawOrbitalElements(sys.elements); drawOrbitalElements(sys.elements);
@ -75,6 +78,21 @@ gooDraw(SDL_Window* window, system_2body& sys, bool& running)
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 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) void drawEllipseParameters(ellipse_parameters& ep)
{ {
if (ImGui::CollapsingHeader("Ellipse Parameters:", H_FLAGS)) { 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::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("orbital period: %f", sys.orbital_period);
ImGui::Text("epsilon, spec. orb. energy: %f", sys.epsilon); ImGui::Text("epsilon, spec. orb. energy: %f", sys.epsilon);
ImGui::Text("h, angular momentum: %f", sys.h); ImGui::Text("h, angular momentum: %f", sys.h);

4
src/gooey.h

@ -16,5 +16,5 @@ bool
gooProcessEvent(SDL_Event &e); gooProcessEvent(SDL_Event &e);
void 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);

53
src/main.cpp

@ -38,6 +38,10 @@ struct GameState
bool running; bool running;
MemoryArena* arena; 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... system_2body system; // FIXME: we're going to need more than 1 system...
Entity* satellite_entity; Entity* satellite_entity;
}; };
@ -181,9 +185,11 @@ loadScene(GameState* gs, RenderState* rs)
} }
void 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.gamma = orbitGetFlightPathAngle(sys.ep.e, sat.theta);
sat.r = orbitGetRadialDistance(sys.ep.e, sys.ep.p, sat.theta); sat.r = orbitGetRadialDistance(sys.ep.e, sys.ep.p, sat.theta);
sat.v = orbitGetVelocity(sys.epsilon, sys.body.mu, sat.r); sat.v = orbitGetVelocity(sys.epsilon, sys.body.mu, sat.r);
@ -193,7 +199,6 @@ updateSatelliteModel(const system_2body& sys, satellite& sat)
void void
updateSatelliteEntity(Entity* e, const satellite& sat) updateSatelliteEntity(Entity* e, const satellite& sat)
{ {
// TODO: decouple framerate from time_step
const static mat4 xform = const static mat4 xform =
glm::rotate(mat4(1.0), (float) M_PI_2, vec3(1, 0, 0)); glm::rotate(mat4(1.0), (float) M_PI_2, vec3(1, 0, 0));
const vec3& v = sat.position; const vec3& v = sat.position;
@ -222,39 +227,50 @@ preFrameCallback(RenderState* rs, void* user_data = nullptr)
bool gooey_wants = false; bool gooey_wants = false;
while (SDL_PollEvent(&e)) { while (SDL_PollEvent(&e)) {
// FIXME: we should check for escape key here first
gooey_wants = gooProcessEvent(e); gooey_wants = gooProcessEvent(e);
if (!gooey_wants) inputProcessEvent(&is, e); if (!gooey_wants) inputProcessEvent(&is, e);
} }
if (is.window_closed || is.escape) if (is.window_closed || is.escape)
rs->running = false; rs->running = false;
}
void // TODO: sim time stuff should have dedicated functions, and maybe a test
postFrameCallback(RenderState* rs, void* user_data = nullptr) // since it's pretty important that the simulation is accurate-ish
{ // TODO: verify time to apoapsis/periapsis are correct
assert(user_data != nullptr); assert(user_data != nullptr);
GameState* gs = (GameState*) user_data; 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) { 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); gs->system.ep = ellipseInitAE(gs->system.ep.a, gs->system.ep.e);
updateSatelliteEntity(gs->satellite_entity, gs->system.sat); updateSatelliteEntity(gs->satellite_entity, gs->system.sat);
//updateOrbit(gs->system, ellipse_entity); //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 int
main() main()
{ {
@ -274,6 +290,7 @@ main()
GameState gs = {0}; GameState gs = {0};
gs.arena = arenaInit(16); gs.arena = arenaInit(16);
gs.sim_speed = DEFAULT_SIM_SPEED;
loadScene(&gs, rs); loadScene(&gs, rs);
doRenderLoop(rs, 60, preFrameCallback, postFrameCallback, &gs); doRenderLoop(rs, 60, preFrameCallback, postFrameCallback, &gs);
gooFree(); gooFree();

16
src/orbits.cpp

@ -6,7 +6,7 @@ const static uint ELLIPSE_VERT_COUNT = 256;
system_2body system_2body
systemInit(grav_body gb, orbital_elements el, float time_step) systemInit(grav_body gb, orbital_elements el)
{ {
system_2body s = {0}; system_2body s = {0};
s.body = gb; 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.orbital_period = orbitGetPeriod(s.ep.a, gb.mu);
s.r_apoapsis = s.ep.a - s.ep.c; s.r_apoapsis = s.ep.a - s.ep.c;
s.r_periapsis = 2 * s.ep.a - s.r_apoapsis; s.r_periapsis = 2 * s.ep.a - s.r_apoapsis;
s.time_step = time_step;
return s; return s;
} }
@ -214,13 +213,14 @@ getNextTrialValue(double err, double ecc, double test_anom, double mean_anom)
double double
getPropagatedEccAnomaly(system_2body sys, getPropagatedEccAnomaly(system_2body sys,
double initial_anom) double initial_anom,
double time_step)
{ {
double e = sys.ep.e; double e = sys.ep.e;
double E1 = getEccAnomFromTrueAnom(e, initial_anom); double E1 = getEccAnomFromTrueAnom(e, initial_anom);
double M1 = getMeanAnomFromEccAnom(E1, e); double M1 = getMeanAnomFromEccAnom(E1, e);
double n = getMeanMotion(sys.body.mu, sys.elements.a); 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); double E2_1 = getInitialTrialValue(M2, e);
// test if guess is a solution to kepler's equation // test if guess is a solution to kepler's equation
@ -241,13 +241,15 @@ getPropagatedEccAnomaly(system_2body sys,
double double
getPropagatedTrueAnomaly(system_2body sys, 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 // 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; 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); return getTrueAnomFromEccAnom(sys.ep.e, ecc_anom);
} }

10
src/orbits.h

@ -67,16 +67,11 @@ struct system_2body
double r_apoapsis; // NOTE: apoapse distance from body center double r_apoapsis; // NOTE: apoapse distance from body center
double r_periapsis; // NOTE: periapsis distance from body center double r_periapsis; // NOTE: periapsis distance from body center
double orbital_period; // NOTE: in seconds double orbital_period; // NOTE: in seconds
double time_step;
}; };
#define DEFAULT_TIME_STEP 1
system_2body system_2body
systemInit(grav_body gb, systemInit(grav_body gb, orbital_elements el);
orbital_elements el,
float time_step = DEFAULT_TIME_STEP);
grav_body grav_body
gravBodyInit(double mu, double r); gravBodyInit(double mu, double r);
@ -152,7 +147,8 @@ orbitUpdate(orbital_elements& o, double a, double e);
*/ */
double double
getPropagatedTrueAnomaly(system_2body sys, getPropagatedTrueAnomaly(system_2body sys,
double initial_anom); double initial_anom,
double time_step); // NOTE: in seconds
// NOTE: aka) the trajectory equation (eq. 2.45) // NOTE: aka) the trajectory equation (eq. 2.45)
double double

Loading…
Cancel
Save