A real-time 3D gravitational physics simulator built in C with OpenGL and SDL3.
- Real-time gravitational force calculations using F = GMm/r²
- J2 Perturbation
- Verlet Integration
- Collision Detection
- Adjustable simulation speed
-
Propulsion:
- Thrust with configurable specific impulse
- Fuel consumption based on mass flow rate
- Variable throttle control (0-100%)
-
Attitude Control:
- Quaternion-based 3D orientation system
- Automatic attitude control during burns
- Configurable moment of inertia and nozzle gimbal range
-
Burn Planning:
- Schedule multiple burns with precise start times and durations
- Tangent: Aligns thrust with velocity vector (prograde/retrograde burns)
- Absolute: Burns relative to the inertial reference frame (space coordinates)
- Normal: Perpendicular to orbit -- currently unsupported :(
- Each burn type can be configured with a rotation heading offset
- Auto-Targeting: Automatically calculate optimal burns to reach target orbital parameters (semi-major axis, eccentricity, inclination, etc.)
- Schedule multiple burns with precise start times and durations
- Right Mouse Button + Drag: Rotate camera around the scene
- Mouse Wheel Up: Zoom in
- Mouse Wheel Down: Zoom out
The program features a command-line interface at the bottom of the window. Available commands:
| Command | Description |
|---|---|
load |
Load simulation from simulation_data.json |
pause or p |
Pause the simulation |
resume or r |
Resume the simulation |
reset |
Reset the simulation to initial state |
step <value> |
Set simulation time step (e.g., step 0.01) |
enable/disable guidance-lines |
Toggles lines between celestial bodies |
enable/disable export |
Toggles writing of planetary kinematic data to a CSV file |
sample-period <value> |
Set CSV export sampling period in seconds |
auto <spacecraft_name> |
Create optimal burn to reach target orbital parameters |
Note: Type commands in the console at the bottom of the window and press Enter to execute.
The simulation is configured via simulation_data.json:
{
"bodies": [
{
"name": "Earth",
"mass": 5.972e24,
"pos_x": 0,
"pos_y": 0,
"pos_z": 0,
"vel_x": 0,
"vel_y": 0,
"vel_z": 0,
"radius": 6371000,
"equatorial_radius": 6378137,
"rotational_v": 7.2921159e-5,
"attitude_axis_x": 1.0,
"attitude_axis_y": 0.0,
"attitude_axis_z": 0.0,
"attitude_angle": 0.4101524,
"gravitational_parameter": 3.986004418e14,
"J2": 0.00108263
}
]
}Parameters:
name: Display namemass: Mass in kilogramspos_x,pos_y,pos_z: Position in meters (m) from the originvel_x,vel_y,vel_z: Initial velocity in meters per secondradius: Body radius in metersequatorial_radius: Equatorial radius for J2 calculations (m) (optional)rotational_v: Angular velocity (rad/s) (optional)attitude_axis_x,attitude_axis_y,attitude_axis_z: Rotation axis (optional)attitude_angle: Initial rotation angle (radians) (optional)gravitational_parameter: Standard gravitational parameter μ (m³/s²) (optional)J2: Oblateness coefficient for perturbation effects (optional)
{
"spacecraft": [
{
"name": "Example Craft",
"position_relative_to": "Earth",
"pos_x": 6671000.0,
"pos_y": 0.0,
"pos_z": 0.0,
"vel_x": 0.0,
"vel_y": 7700.0,
"vel_z": 0.0,
"dry_mass": 5500.0,
"fuel_mass": 18000.0,
"thrust": 450000.0,
"specific_impulse": 314.0,
"mass_flow_rate": 146.0,
"attitude": 0.0,
"moment_of_inertia": 20000.0,
"nozzle_gimbal_range": 0.105,
"nozzle_velocity": 1000.0,
"burns": [
{
"burn_target": "Earth",
"burn_type": "tangent",
"start_time": 3600.0,
"duration": 1000.0,
"heading": 0.0,
"throttle": 1.0
}
],
"auto_orbit_target": "Earth",
"semi-major-axis": 6671000.0,
"eccentricity": 0.0,
"inclination": 0.0,
"ra_of_ascending_node": 0,
"argument_of_periapsis": 0
}
]
}Spacecraft Parameters:
- Position/Velocity: 3D coordinates (m) and velocities (m/s)
position_relative_to: Reference body for position/velocity (optional, defaults to absolute coordinates)pos_x,pos_y,pos_z: Initial positionvel_x,vel_y,vel_z: Initial velocity
- Mass Properties:
dry_mass: Spacecraft mass without fuel (kg)fuel_mass: Available propellant (kg)
- Propulsion:
thrust: Maximum engine thrust (N)specific_impulse: Engine efficiency (s)mass_flow_rate: Fuel consumption rate (kg/s)nozzle_velocity: Nozzle exhaust velocity (m/s)
- Attitude:
attitude: Initial rotation angle about Z-axis (radians)moment_of_inertia: Rotational inertia (kg⋅m²)nozzle_gimbal_range: Thrust vectoring limit (radians)
Burn Parameters:
burn_target: Name of reference body (must match body name exactly -- case sensitive)burn_type: Burn reference frame type"tangent": Thrust aligned with velocity vector relative to target body"absolute": Thrust in absolute inertial reference frame"normal": Currently unsupported
start_time: Burn start time (seconds from T+0)duration: Burn length (seconds)heading: Rotation offset from base burn direction (radians)throttle: Engine power (0.0 to 1.0)
Note: Due to the nature of time step based simulation, the craft burn time may not start on the "exact" time that it is expected to. Variations in accuracy in this regard can be attributed having too high of a time step during burns.
- SDL3: Window management and OpenGL context creation
- OpenGL: 3D graphics rendering
- GLEW: OpenGL extension loading library
- cJSON: JSON parsing library
- pthreads: Multi-threading support (or PThreads4W on Windows)
- Note: better Windows multi-threading support will be added in the future. Major slowdowns on Windows should be expected.
- Shader files:
shaders/simple.vertandshaders/simple.frag - Font file:
font.ttf(placed in build directory) - Configuration:
simulation_data.json
Use CMake to build the project:
The build system automatically copies required assets (shaders, fonts, data files) to the build directory.
mkdir build
cd build
conan install .. --build=missing -s build_type=Release -pr ../web/conan_profile
# Use either
# Windows:
# call .\Release\generators\conanbuild.bat
# cmake .. -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
# Or
# Linux:
# source ./Release/generators/conanbuild.sh
# cmake .. -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .For local testing of the WebAssembly build with pthreads, the repository includes a small helper server that sets the required COOP/COEP headers and opens the page automatically.
Usage examples:
python ./web/serve_web.py— auto-detects the build folder and opens OrbitSimulation.html on 127.0.0.1:8000python ./web/serve_web.py --port 8080— choose a different port
The server adds these headers on every response so that threads are enabled in the browser:
- Cross-Origin-Opener-Policy: same-origin
- Cross-Origin-Embedder-Policy: require-corp