Browse Source

Refactor main.cpp into focused functions

Extract argument parsing, headless simulation, and GUI simulation into
separate functions. Add initial state capture for comparison in headless mode.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
main
cinnaboot 6 months ago
parent
commit
e5da7aa202
  1. 254
      src/main.cpp

254
src/main.cpp

@ -8,9 +8,9 @@
#include <cmath>
// 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;
}

Loading…
Cancel
Save