You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

271 lines
6.5 KiB

#include <GL/glew.h>
#include <imgui.h>
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_sdl.h>
using namespace ImGui;
#include "gooey.h"
#include "orbits.h"
const static int G_WIDTH = 400;
const static ImVec2 V_SPACER(0, 10);
const int H_FLAGS = ImGuiTreeNodeFlags_DefaultOpen;
// forward declarations
void drawSimulationWindow(bool& running, u64 sim_time_ms, float& sim_speed);
void drawOrbitWindow(GameState* gs);
void drawEllipseParameters(EllipseParameters& ep);
void drawGravitationalBody(GravBody& body);
void drawOrbitalElements(OrbitalElements& el);
void drawSatelliteWindow(Satellite& sat);
void drawSystemWindow(TwoBodySystem& sys);
void drawManeuverWindow(GameState* gs);
// interface
bool
gooInit(SDL_Window* window, SDL_GLContext gl_context)
{
IMGUI_CHECKVERSION();
CreateContext();
ImGuiIO& io = GetIO();
io.IniFilename = NULL; // don't save window state to imgui.ini
StyleColorsDark();
bool ret = true;
ret = ret && ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ret = ret && ImGui_ImplOpenGL3_Init();
return ret;
}
void
gooFree()
{
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
DestroyContext();
}
bool
gooProcessEvent(SDL_Event& e)
{
ImGui_ImplSDL2_ProcessEvent(&e);
return (GetIO().WantCaptureMouse
|| GetIO().WantCaptureKeyboard);
}
void
gooDraw(SDL_Window* window, GameState* gs)
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(window);
NewFrame();
int x = 0, y = 0;
SDL_GetWindowSize(window, &x, &y);
SetNextWindowPos(ImVec2(x - G_WIDTH, 0));
SetNextWindowSize(ImVec2(G_WIDTH, y));
Begin("Gooey");
drawSimulationWindow(gs->running, gs->sim_time_ms, gs->sim_speed);
Separator();
// FIXME: slit up orbit window into function calls here
drawOrbitWindow(gs);
BeginChild("impulsive maneuver", ImVec2(G_WIDTH - 20, 300), true);
drawManeuverWindow(gs);
EndChild();
#if 0
assert(gs->orbits[0].in_use);
TwoBodySystem& sys = gs->orbits[0].system;
drawSystemWindow(sys);
drawSatelliteWindow(sys.sat);
drawGravitationalBody(sys.body);
drawOrbitalElements(sys.elements);
drawEllipseParameters(sys.ep);
#endif
End();
Render();
ImGui_ImplOpenGL3_RenderDrawData(GetDrawData());
}
// internal
void drawSimulationWindow(bool& running, u64 sim_time_ms, float& sim_speed)
{
if (Button("||")) running = false;
SameLine();
if (Button("|>")) running = true;
SameLine();
Text("running: %s", (running > 0) ? "true" : "false");
Text("sim time: %.2f s",
double(double(sim_time_ms) / 1000));
InputFloat("sim speed", &sim_speed, 0.1, 4.0, "%.1f");
}
void drawOrbitWindow(GameState* gs)
{
Text("Orbit Selection");
BeginChild("orbit selection", ImVec2(G_WIDTH - 20, 100), true);
static u32 selected = UINT_MAX;
for (u32 i = 0; i < gs->num_orbits; i++) {
GameOrbit& orbit = gs->orbits[i];
if (orbit.in_use) {
static const u32 label_len = 128;
char label[label_len];
snprintf(label, label_len, "Orbit %d", i);
if (Selectable(label, selected == i)) {
selected = i;
selectOrbit(gs, &orbit);
}
}
}
EndChild();
if (selected < gs->num_orbits
&& gs->orbits[selected].in_use)
{
TwoBodySystem& sys = gs->orbits[selected].system;
BeginChild("orbit details", ImVec2(G_WIDTH - 20, 400), true);
Text("Selected Orbit#: %d", selected);
//Text("Orbital Period: %.2fs", sys.orbital_period);
drawSystemWindow(sys);
Separator();
drawGravitationalBody(sys.body);
Separator();
drawSatelliteWindow(sys.sat);
EndChild();
}
}
void drawEllipseParameters(EllipseParameters& ep)
{
Text("semi_major axis, a: %f km", ep.a);
Text("semi_minor axis, b: %f km", ep.b);
Text("eccentricity, e: %f ", ep.e);
Text("linear eccentricity, c: %f km", ep.c);
Text("semilatus rectum, p: %f km", ep.p);
}
void drawGravitationalBody(GravBody& body)
{
Text("Grav Body:");
Indent();
Text("mu, gravitational parameter: %.3f", body.mu);
Text("r, radius in km: %.3f", body.radius);
Unindent();
}
void drawOrbitalElements(OrbitalElements& el)
{
if (CollapsingHeader("Orbital Elements", H_FLAGS)) {
Text("semi_major axis, a: %f km", el.a);
Text("eccentricity, e: %f", el.e);
Text("iota, inclination: %f", el.iota);
Text("ohm, longitude ascending node: %f", el.ohm);
Text("omega, argument of periapsis: %f", el.omega);
Text("nu, true anomaly at T0: %f", el.nu);
}
}
void
drawSatelliteWindow(Satellite& sat)
{
Text("Satellite Parameters:");
Indent();
Text("theta, true anomaly: %f", sat.theta);
Text("r, radial distance: %f km", sat.r);
Text("position:");
Indent();
Text("x: %f km", sat.position.x);
Text("y: %f km", sat.position.y);
Text("z: %f km", sat.position.z);
Unindent();
Text("velocity, km/s: %f", sat.v);
Text("flight path angle: %f", sat.gamma);
Unindent();
}
void drawSystemWindow(TwoBodySystem& sys)
{
Text("System Info:");
Indent();
Text("orbital period: %.2f s", sys.orbital_period);
Text("epsilon, spec. orb. energy: %f", sys.epsilon);
Text("h, angular momentum: %f", sys.h);
Text("r_apoapsis: %f km", sys.r_apoapsis);
Text("r_periapsis: %f km", sys.r_periapsis);
// FIXME: not ideal to call into orbit interface from the gooey
double tof_apoapse = orbitGetTimeOfFlight(sys, sys.sat.theta, M_PI);
Text("time to apoapsis: %.2f s", tof_apoapse);
double tof_periapse =
orbitGetTimeOfFlight(sys, sys.sat.theta, 2 * M_PI);
Text("time to periapsis: %.2f s", tof_periapse);
Unindent();
}
void
drawManeuverWindow(GameState* gs)
{
GameOrbit* orbit = getSelectedOrbit(gs);
static int item_current_idx = 0;
static double anom = 0.f;
static float dv = 0.f;
if (orbit) {
if (orbit->maneuver.active) {
Text("Orbital Maneuver");
Indent();
Text("true anomaly: %f", orbit->maneuver.true_anomaly);
Text("impulse dv: %f km/s", orbit->maneuver.impulse_delta_v);
Unindent();
if (Button("remove")) {
removeManeuver(orbit);
item_current_idx = 0;
anom = 0.f;
dv = 0.f;
}
} else {
Text("Add orbital maneuver");
const double min_anom = -M_PI, max_anom = M_PI;
SliderScalar("maneuver anomaly", ImGuiDataType_Double, &anom,
&min_anom, &max_anom, "%.19f");
// select maneuver vector
const char* items[] = {
"prograde",
"retrograde",
"some other vector"
};
Combo("thrust vector", &item_current_idx, items,
IM_ARRAYSIZE(items));
InputFloat("impulse dv, km/s", &dv, 0.1, 4.0, "%.1f");
if (Button("apply")) {
if (!addManeuver(orbit, anom, vec3(), dv)) {
// flash a color or something?
}
}
}
}
}