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.
208 lines
7.7 KiB
208 lines
7.7 KiB
#include "physics.h" |
|
#include "simulation.h" |
|
#include "config_loader.h" |
|
#include "renderer.h" |
|
#include "ui_renderer.h" |
|
#include <cstdio> |
|
#include <cstring> |
|
#include <cstdlib> |
|
#include <cmath> |
|
|
|
// Configuration defaults - edit to change default run mode |
|
//#define DEFAULT_CONFIG_FILE "tests/test_moon_orbits.toml" |
|
#define DEFAULT_CONFIG_FILE "tests/test_maneuver_planning.toml" |
|
|
|
struct ProgramArgs { |
|
const char* config_file; |
|
}; |
|
|
|
void parse_command_line_args(int argc, char** argv, ProgramArgs* args) { |
|
args->config_file = DEFAULT_CONFIG_FILE; |
|
|
|
for (int i = 1; i < argc; i++) { |
|
if (argv[i][0] != '-') { |
|
args->config_file = argv[i]; |
|
} |
|
} |
|
} |
|
|
|
void print_startup_info(const ProgramArgs* args) { |
|
printf("=== Orbital Mechanics Simulation ===\n"); |
|
printf("Loading configuration: %s\n", args->config_file); |
|
} |
|
|
|
void run_gui_simulation(SimulationState* sim) { |
|
init_renderer(1600, 900, "Orbital Mechanics Simulation"); |
|
|
|
RenderState render_state; |
|
setup_camera(&render_state); |
|
|
|
// FIXME: too verbose, and/or should be an init function |
|
UIState ui_state; |
|
ui_state.body_list_scroll = 0; |
|
ui_state.body_list_active = -1; |
|
ui_state.selected_craft_index = -1; |
|
ui_state.maneuver_list_active = -1; |
|
ui_state.maneuver_list_scroll = 0; |
|
ui_state.selected_maneuver_index = -1; |
|
|
|
ui_state_init_buffers(&ui_state); |
|
|
|
ui_state.maneuver_dialog.open = false; |
|
ui_state.maneuver_dialog.active_tab = MD_TAB_CREATE; |
|
ui_state.maneuver_dialog.craft_index = -1; |
|
memset(ui_state.maneuver_dialog.name, 0, sizeof(ui_state.maneuver_dialog.name)); |
|
ui_state.maneuver_dialog.direction_active = 0; |
|
ui_state.maneuver_dialog.delta_v = 0.0; |
|
ui_state.maneuver_dialog.trigger_type_active = 0; |
|
ui_state.maneuver_dialog.trigger_value = 0.0; |
|
ui_state.maneuver_dialog.edit_maneuver_index = -1; |
|
ui_state.maneuver_dialog.target_body_index = 0; |
|
ui_state.maneuver_dialog.transfer_body_index = 0; |
|
ui_state.maneuver_dialog.show_hohmann_preview = false; |
|
ui_state.maneuver_dialog.show_preview = false; |
|
ui_state.maneuver_dialog.preview_valid = false; |
|
memset(&ui_state.maneuver_dialog.preview_elements, 0, sizeof(ui_state.maneuver_dialog.preview_elements)); |
|
memset(ui_state.maneuver_dialog.error_message, 0, sizeof(ui_state.maneuver_dialog.error_message)); |
|
ui_state.maneuver_dialog.show_error = false; |
|
|
|
// Find root body (body with parent_index == -1) |
|
int root_body_index = -1; |
|
for (int i = 0; i < sim->body_count; i++) { |
|
if (sim->bodies[i].parent_index == -1) { |
|
root_body_index = i; |
|
break; |
|
} |
|
} |
|
|
|
// Initialize render state |
|
render_state.selected_body_index = root_body_index >= 0 ? root_body_index : -1; |
|
render_state.camera_target_enabled = root_body_index >= 0; |
|
render_state.last_target_index = root_body_index >= 0 ? root_body_index : -1; |
|
render_state.camera_offset = (Vector3){ 0, 50, 100 }; |
|
|
|
// Initialize UI state |
|
ui_state.body_list_scroll = 0; // Initial scroll position |
|
ui_state.body_list_active = root_body_index >= 0 ? root_body_index : -1; // Sync with selected body |
|
gui_init(); |
|
|
|
bool paused = true; |
|
double speed_multiplier = 1.0; |
|
double min_multiplier = 1.0; |
|
int physics_steps_per_frame = 1; |
|
|
|
printf("\nSimulation started!\n"); |
|
printf("Controls:\n"); |
|
printf(" Arrow keys: Rotate and zoom camera\n"); |
|
printf(" Space: Pause/Resume\n"); |
|
printf(" +/-: Speed up/slow down simulation\n"); |
|
printf(" Select body from list to follow it\n"); |
|
printf(" ESC: Quit\n\n"); |
|
|
|
while (!WindowShouldClose()) { |
|
if (IsKeyPressed(KEY_SPACE)) { |
|
paused = !paused; |
|
printf("Simulation %s\n", paused ? "paused" : "resumed"); |
|
} |
|
|
|
if (IsKeyPressed(KEY_EQUAL) || IsKeyPressed(KEY_KP_ADD)) { |
|
speed_multiplier *= 2.0; |
|
printf("Speed multiplier: %.1fx\n", speed_multiplier); |
|
} |
|
|
|
if (IsKeyPressed(KEY_MINUS) || IsKeyPressed(KEY_KP_SUBTRACT)) { |
|
speed_multiplier /= 2.0; |
|
if (speed_multiplier < min_multiplier) speed_multiplier = min_multiplier; |
|
printf("Speed multiplier: %.1fx\n", speed_multiplier); |
|
} |
|
|
|
if (!paused) { |
|
int steps = (int)(physics_steps_per_frame * speed_multiplier); |
|
for (int i = 0; i < steps; i++) { |
|
update_simulation(sim); |
|
} |
|
} |
|
|
|
update_camera(&render_state, sim); |
|
|
|
begin_frame(); |
|
render_simulation(sim, &render_state); |
|
|
|
// Render UI panels |
|
render_info(sim); |
|
render_body_list_ui(sim, &render_state, &ui_state); |
|
render_body_info_ui(sim, &render_state, &ui_state); |
|
render_maneuver_list_ui(sim, &render_state, &ui_state); |
|
render_maneuver_dialog(sim, &render_state, &ui_state); |
|
|
|
// Handle keyboard shortcuts for maneuver dialog |
|
if (ui_state.maneuver_dialog.open) { |
|
if (IsKeyPressed(KEY_ESCAPE)) { |
|
if (ui_state.maneuver_dialog.show_delete_confirm) { |
|
ui_state.maneuver_dialog.show_delete_confirm = false; |
|
} else { |
|
ui_state.maneuver_dialog.open = false; |
|
} |
|
} |
|
|
|
if (IsKeyPressed(KEY_ENTER)) { |
|
if (ui_state.maneuver_dialog.show_delete_confirm) { |
|
// Confirm delete |
|
int edit_index = ui_state.maneuver_dialog.edit_maneuver_index; |
|
if (edit_index >= 0 && edit_index < sim->maneuver_count) { |
|
remove_maneuver_by_index(sim, edit_index); |
|
ui_state.maneuver_dialog.show_delete_confirm = false; |
|
ui_state.maneuver_dialog.open = false; |
|
} |
|
} else { |
|
// Confirm action based on tab |
|
switch (ui_state.maneuver_dialog.active_tab) { |
|
case MD_TAB_CREATE: |
|
create_maneuver_from_dialog(sim, &ui_state); |
|
break; |
|
case MD_TAB_HOHMANN: |
|
// Calculate button functionality - trigger calculation |
|
if (ui_state.maneuver_dialog.craft_index >= 0 && |
|
ui_state.maneuver_dialog.craft_index < sim->craft_count) { |
|
calculate_hohmann_for_dialog(sim, &ui_state); |
|
} |
|
break; |
|
case MD_TAB_EDIT: |
|
update_maneuver_from_dialog(sim, &ui_state); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
end_frame(); |
|
} |
|
|
|
close_renderer(&render_state); |
|
ui_state_free_buffers(&ui_state); |
|
printf("\nSimulation ended. Final time: %.2f days\n", sim->time / 86400.0); |
|
} |
|
|
|
int main(int argc, char** argv) { |
|
ProgramArgs args; |
|
parse_command_line_args(argc, argv, &args); |
|
print_startup_info(&args); |
|
|
|
// Create simulation with time step of 60 seconds |
|
const int MAX_BODIES = 100; |
|
const int MAX_SPACECRAFT = 50; |
|
const int MAX_MANEUVERS = 100; |
|
const double TIME_STEP = 60.0; // 60 seconds per step |
|
SimulationState* sim = create_simulation(MAX_BODIES, MAX_SPACECRAFT, MAX_MANEUVERS, TIME_STEP); |
|
|
|
// Load system configuration |
|
if (!load_system_config(sim, args.config_file)) { |
|
printf("Failed to load configuration file\n"); |
|
destroy_simulation(sim); |
|
return 1; |
|
} |
|
|
|
run_gui_simulation(sim); |
|
|
|
destroy_simulation(sim); |
|
return 0; |
|
}
|
|
|