diff --git a/src/main.cpp b/src/main.cpp index ad92683..38d1453 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,9 +8,9 @@ #include // Configuration defaults - edit to change default run mode -#define DEFAULT_CONFIG_FILE "configs/solar_system.txt" -#define DEFAULT_HEADLESS 0 // 0 = GUI mode, 1 = headless mode -#define DEFAULT_READABLE 0 // 0 = scientific notation, 1 = human-readable (AU, km/s) +#define DEFAULT_CONFIG_FILE "configs/test_simple.txt" +#define DEFAULT_HEADLESS 1 // 0 = GUI mode, 1 = headless mode +#define DEFAULT_READABLE 1 // 0 = scientific notation, 1 = human-readable (AU, km/s) #define DEFAULT_SIM_DAYS 365 // Default simulation duration for headless mode // Unit conversion constants @@ -46,133 +46,142 @@ void print_body_readable(CelestialBody* body) { print_velocity_readable(body->name, body->velocity); } -int main(int argc, char** argv) { - // Parse command line arguments (start with macro defaults) - const char* config_file = DEFAULT_CONFIG_FILE; - bool headless = DEFAULT_HEADLESS; - bool readable = DEFAULT_READABLE; - int sim_duration_days = DEFAULT_SIM_DAYS; +struct ProgramArgs { + const char* config_file; + bool headless; + bool readable; + int sim_duration_days; +}; + +void parse_command_line_args(int argc, char** argv, ProgramArgs* args) { + args->config_file = DEFAULT_CONFIG_FILE; + args->headless = DEFAULT_HEADLESS; + args->readable = DEFAULT_READABLE; + args->sim_duration_days = DEFAULT_SIM_DAYS; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--headless") == 0 || strcmp(argv[i], "-h") == 0) { - headless = true; + args->headless = true; } else if (strcmp(argv[i], "--readable") == 0 || strcmp(argv[i], "-r") == 0) { - readable = true; + args->readable = true; } else if (strcmp(argv[i], "--days") == 0 && i + 1 < argc) { - sim_duration_days = atoi(argv[++i]); + args->sim_duration_days = atoi(argv[++i]); } else if (argv[i][0] != '-') { - config_file = argv[i]; + args->config_file = argv[i]; } } +} +void print_startup_info(const ProgramArgs* args) { printf("=== Orbital Mechanics Simulation ===\n"); - printf("Loading configuration: %s\n", config_file); - if (headless) { + printf("Loading configuration: %s\n", args->config_file); + if (args->headless) { printf("Mode: Headless (terminal output only)\n"); - printf("Duration: %d days\n", sim_duration_days); - if (readable) { + printf("Duration: %d days\n", args->sim_duration_days); + if (args->readable) { printf("Output: Human-readable units (AU, km/s)\n"); } } +} - // Create simulation with time step of 60 seconds - const int MAX_BODIES = 100; - const double TIME_STEP = 60.0; // 60 seconds per step - SimulationState* sim = create_simulation(MAX_BODIES, TIME_STEP); +void run_headless_simulation(SimulationState* sim, const ProgramArgs* args) { + const double SECONDS_PER_DAY = 86400.0; + const double total_time = args->sim_duration_days * SECONDS_PER_DAY; + const double output_interval = SECONDS_PER_DAY; + double next_output_time = 0.0; - // Load system configuration - if (!load_system_config(sim, config_file)) { - printf("Failed to load configuration file\n"); - destroy_simulation(sim); - return 1; + CelestialBody* initial_state = (CelestialBody*)malloc(sim->body_count * sizeof(CelestialBody)); + for (int i = 0; i < sim->body_count; i++) { + initial_state[i] = sim->bodies[i]; } - // If headless mode, run simulation without rendering - if (headless) { - const double SECONDS_PER_DAY = 86400.0; - const double total_time = sim_duration_days * SECONDS_PER_DAY; - const double output_interval = SECONDS_PER_DAY; // Print status once per day - double next_output_time = 0.0; - - printf("\n=== Initial State ===\n"); - for (int i = 0; i < sim->body_count; i++) { - CelestialBody* body = &sim->bodies[i]; - if (readable) { - print_body_readable(body); - } else { - printf("%s:\n", body->name); - printf(" Position: (%.3e, %.3e, %.3e) m\n", - body->position.x, body->position.y, body->position.z); - printf(" Velocity: (%.3e, %.3e, %.3e) m/s\n", - body->velocity.x, body->velocity.y, body->velocity.z); - } + printf("\n=== Initial State ===\n"); + for (int i = 0; i < sim->body_count; i++) { + CelestialBody* body = &sim->bodies[i]; + if (args->readable) { + print_body_readable(body); + } else { + printf("%s:\n", body->name); + printf(" Position: (%.3e, %.3e, %.3e) m\n", + body->position.x, body->position.y, body->position.z); + printf(" Velocity: (%.3e, %.3e, %.3e) m/s\n", + body->velocity.x, body->velocity.y, body->velocity.z); } + } - printf("\n=== Running Simulation ===\n"); - while (sim->time < total_time) { - update_simulation(sim); - - // Print periodic updates - if (sim->time >= next_output_time) { - printf("Day %.1f: ", sim->time / SECONDS_PER_DAY); - for (int i = 0; i < sim->body_count && i < 3; i++) { - Vec3 pos = sim->bodies[i].position; - double dist = vec3_magnitude(pos); - if (readable) { - double angle_rad = atan2(pos.y, pos.x); - double angle_deg = angle_rad * 180.0 / M_PI; - if (angle_deg < 0.0) angle_deg += 360.0; - printf("%s(r=%.4f AU, θ=%.1f°) ", sim->bodies[i].name, dist / AU, angle_deg); - } else { - printf("%s=%.3e m ", sim->bodies[i].name, dist); - } + printf("\n=== Running Simulation ===\n"); + while (sim->time < total_time) { + update_simulation(sim); + + if (sim->time >= next_output_time) { + printf("Day %.1f: ", sim->time / SECONDS_PER_DAY); + for (int i = 0; i < sim->body_count && i < 3; i++) { + Vec3 pos = sim->bodies[i].position; + double dist = vec3_magnitude(pos); + if (args->readable) { + double angle_rad = atan2(pos.y, pos.x); + double angle_deg = angle_rad * 180.0 / M_PI; + if (angle_deg < 0.0) angle_deg += 360.0; + printf("%s(r=%.4f AU, θ=%.1f°) ", sim->bodies[i].name, dist / AU, angle_deg); + } else { + printf("%s=%.3e m ", sim->bodies[i].name, dist); } - printf("\n"); - next_output_time += output_interval; } + printf("\n"); + next_output_time += output_interval; } + } - printf("\n=== Final State (Day %.1f) ===\n", sim->time / SECONDS_PER_DAY); - for (int i = 0; i < sim->body_count; i++) { - CelestialBody* body = &sim->bodies[i]; - if (readable) { - print_body_readable(body); - } else { - printf("%s:\n", body->name); - printf(" Position: (%.3e, %.3e, %.3e) m\n", - body->position.x, body->position.y, body->position.z); - printf(" Velocity: (%.3e, %.3e, %.3e) m/s\n", - body->velocity.x, body->velocity.y, body->velocity.z); - } + printf("\n=== Initial State (Day 0.0) ===\n"); + for (int i = 0; i < sim->body_count; i++) { + CelestialBody* body = &initial_state[i]; + if (args->readable) { + print_body_readable(body); + } else { + printf("%s:\n", body->name); + printf(" Position: (%.3e, %.3e, %.3e) m\n", + body->position.x, body->position.y, body->position.z); + printf(" Velocity: (%.3e, %.3e, %.3e) m/s\n", + body->velocity.x, body->velocity.y, body->velocity.z); } + } - destroy_simulation(sim); - return 0; - } else { - // Graphical mode - // Initialize renderer - init_renderer(1280, 720, "Orbital Mechanics Simulation"); - - // Setup rendering state - RenderState render_state; - setup_camera(&render_state); - - // Simulation control variables - bool paused = false; - double speed_multiplier = 1.0; - int physics_steps_per_frame = 100; // Multiple physics steps per frame for stability - - 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(" I: Toggle info display\n"); - printf(" ESC: Quit\n\n"); - - // Main loop - while (!WindowShouldClose()) { - // Handle input + printf("\n=== Final State (Day %.1f) ===\n", sim->time / SECONDS_PER_DAY); + for (int i = 0; i < sim->body_count; i++) { + CelestialBody* body = &sim->bodies[i]; + if (args->readable) { + print_body_readable(body); + } else { + printf("%s:\n", body->name); + printf(" Position: (%.3e, %.3e, %.3e) m\n", + body->position.x, body->position.y, body->position.z); + printf(" Velocity: (%.3e, %.3e, %.3e) m/s\n", + body->velocity.x, body->velocity.y, body->velocity.z); + } + } + + free(initial_state); +} + +void run_gui_simulation(SimulationState* sim) { + init_renderer(1280, 720, "Orbital Mechanics Simulation"); + + RenderState render_state; + setup_camera(&render_state); + + bool paused = false; + double speed_multiplier = 1.0; + int physics_steps_per_frame = 100; + + 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(" I: Toggle info display\n"); + printf(" ESC: Quit\n\n"); + + while (!WindowShouldClose()) { if (IsKeyPressed(KEY_SPACE)) { paused = !paused; printf("Simulation %s\n", paused ? "paused" : "resumed"); @@ -189,10 +198,8 @@ int main(int argc, char** argv) { printf("Speed multiplier: %.1fx\n", speed_multiplier); } - // Update camera update_camera(&render_state); - // Update physics (multiple steps per frame) if (!paused) { int steps = (int)(physics_steps_per_frame * speed_multiplier); for (int i = 0; i < steps; i++) { @@ -200,15 +207,36 @@ int main(int argc, char** argv) { } } - // Render - render_simulation(sim, &render_state); - } + render_simulation(sim, &render_state); + } + + close_renderer(); + 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); - // Cleanup - close_renderer(); + // Create simulation with time step of 60 seconds + const int MAX_BODIES = 100; + const double TIME_STEP = 60.0; // 60 seconds per step + SimulationState* sim = create_simulation(MAX_BODIES, 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; + } - printf("\nSimulation ended. Final time: %.2f days\n", sim->time / 86400.0); - return 0; + if (args.headless) { + run_headless_simulation(sim, &args); + } else { + run_gui_simulation(sim); } + + destroy_simulation(sim); + return 0; }