@ -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 ( " \n Simulation 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 ( " \n Simulation 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 ( " \n Simulation 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 ( " \n Simulation 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 ;
}