A 3D gravitational N-body simulation built with Rust and the Bevy game engine. This project simulates the gravitational interactions between multiple celestial bodies with real-time visualization and interactive camera controls.
Stardrift is an experimental side project for personal enjoyment and learning. The project explores gravitational physics simulation while learning Rust and Bevy. Development happens in spare time without specific goals or timeline.
This project also serves as an exploration of AI capabilities in software development. Its development involves use of AI assistance.
Note: This is not intended for scientific or research purposes. The project remains experimental and subject to significant changes.
- N-body gravitational physics: Gravitational force calculations between all bodies
- Barnes-Hut octree algorithm: O(N log N) gravitational force calculations using spatial partitioning
- Double precision: Uses f64 floating-point arithmetic
- Custom physics engine: Component-based physics system for n-body simulation
- Multiple numerical integrators: Various integration methods including symplectic and Runge-Kutta schemes. Run
stardrift --list-integratorsto see all available methods. - Parallel processing: Multi-threaded physics calculations
- Dynamic barycenter tracking: Real-time calculation and visualization of the system's center of mass
- 3D rendering: Real-time visualization with Bevy's rendering pipeline
- Camera controls: Pan, orbit, and zoom
- Touch support: Touch controls for mobile and tablet devices
- Visual effects: Bloom effects and tone mapping
- Screenshot capture: Take screenshots without UI elements
- Automatic UI and HUD hiding during capture
- Configurable save directory and filename format
- Timestamp-based filenames
- PNG format with full window resolution
- Dynamic trails: Fading trails for celestial bodies
- Time-based trail length management
- Multiple fade curves (Linear, Exponential, SmoothStep, EaseInOut)
- Configurable width with tapering options
- Bloom effects and additive blending
- Automatically pauses when simulation is paused
- Barycenter visualization: Cross-hair indicator showing the system's center of mass with toggle controls
- Octree visualization: Real-time wireframe rendering of the spatial partitioning structure
- Interactive visualization controls: Toggle octree, barycenter visualization
- Real-time diagnostics HUD: On-screen display showing:
- Frame rate (FPS)
- Frame count
- Body count
- Pause/Resume functionality: Space bar to pause and resume the simulation
- Interactive UI buttons:
- Octree toggle button: Show/hide octree visualization
- Barycenter gizmo toggle button: Show/hide barycenter cross-hair indicator
- Trails toggle button: Show/hide celestial body trails
- Diagnostics HUD toggle button: Show/hide the FPS and frame count display
- Restart simulation button: Generate new random bodies and restart the simulation
- Screenshot button: Capture the current view without UI elements
- Native desktop: Windows, macOS, and Linux support
- WebAssembly (WASM): Browser-based version with WebGL2 support
The following features are planned for future development (no planned timeline):
- Enhanced Diagnostics - Comprehensive physics accuracy monitoring including energy conservation (Hamiltonian), angular momentum tracking, virial ratio, and performance profiling
- Collision Detection - Implement collision detection and response between bodies with configurable restitution
- Configurable Simulation Speed - Time scaling controls for faster or slower simulation playback
- UI rework - Replacing the current provisional UI with something more friendly and comprehensive
- Advanced Integrators - Support for specialized integration schemes (Yoshida symplectic methods, etc.)
Pre-built packages are available from the releases page:
- Portable:
.tar.gzarchives for x86_64 and ARM64
- Portable:
.ziparchives for x86_64 and ARM64
- Disk Image:
.dmgfor Intel and Apple Silicon - Portable:
.tar.gzarchives for manual installation
- WebAssembly: Pre-built WASM packages for web deployment
All packages include SHA256 checksums for verification.
- Rust: Install from rustup.rs
- Git: For cloning the repository
git clone https://github.com/emilyst/stardrift.git
cd stardrift# Development build (faster compilation)
cargo run -p stardrift
# Release build (with compiler optimizations)
cargo run -p stardrift --releasestardrift [OPTIONS]Common options:
--bodies COUNT- Set number of bodies to simulate--seed SEED- Use specific random seed for reproducible simulations--paused- Start simulation in paused state--prevent-screen-sleep- Prevent display from sleeping during simulation (enabled by default)--list-integrators- List all available integration methods
Run stardrift --help for complete options including integrator selection, color schemes, and configuration overrides.
# Run with specific configuration
stardrift --bodies 50 --seed 123 --color-scheme viridis
# Try different integrators
stardrift --integrator velocity_verlet --bodies 100
# Generate identical simulations with different colors
for scheme in viridis plasma inferno turbo; do
stardrift --seed 42 --bodies 50 --color-scheme $scheme
doneThe project uses trunk for WebAssembly builds:
# Install trunk if not present
cargo install trunk
# Development build with hot-reloading
trunk serve
# Release build
trunk build --releaseThe built files will be in the dist/ directory for deployment. Trunk automatically handles:
- WASM compilation and optimization
- Asset bundling and injection
- Development server with hot-reloading
- Gzip compression for release builds
| Key/Action | Function |
|---|---|
| Mouse | Pan and orbit camera around the simulation |
| Mouse Wheel | Zoom in/out |
| Space | Pause/Resume simulation |
| N | New simulation with new random bodies |
| O | Toggle octree visualization on/off |
| C | Toggle barycenter gizmo visibility on/off |
| T | Toggle trail visibility on/off |
| D | Toggle diagnostics HUD visibility on/off |
| S | Take screenshot (hides UI and HUD) |
| Escape | Quit application |
| Touch | Pan, orbit, and zoom (mobile/tablet) |
The simulation includes comprehensive automated screenshot capabilities for UI testing and validation:
# Take a single screenshot after 2 seconds
stardrift --screenshot-after 2 --exit-after-screenshots
# Take 5 screenshots at 1-second intervals
stardrift --screenshot-interval 1 --screenshot-count 5 --exit-after-screenshots
# Use frame-based timing for deterministic captures
stardrift --screenshot-after 120 --screenshot-use-frames| Option | Description |
|---|---|
--screenshot-after N |
Take screenshot after N seconds (or frames with --screenshot-use-frames) |
--screenshot-interval N |
Take screenshots every N seconds/frames |
--screenshot-count N |
Number of screenshots to take (default: 1) |
--screenshot-use-frames |
Use frame counting instead of time |
--screenshot-dir PATH |
Output directory (creates if needed) |
--screenshot-name NAME |
Base filename without extension |
--screenshot-sequential |
Use sequential numbering (e.g., test_0001.png) |
--screenshot-no-timestamp |
Disable timestamps for predictable names |
--screenshot-list-paths |
Output file paths to stdout |
--exit-after-screenshots |
Exit after all screenshots taken |
# Deterministic capture for regression testing
stardrift --seed 42 --bodies 100 \
--screenshot-after 60 --screenshot-use-frames \
--screenshot-dir ./test_output \
--screenshot-name ui_state \
--screenshot-no-timestamp \
--screenshot-list-paths
# Output: SCREENSHOT_PATH: ./test_output/ui_state.pngNote: Automated screenshots preserve UI visibility for validation, unlike manual screenshots (key 'S') which hide UI elements.
- The camera automatically follows the barycenter (center of mass) of the system
- Pan and orbit controls allow you to view the simulation from different angles
- The camera tracks the movement of the gravitational system
The simulation uses a TOML-based configuration file.
| Field | Type | Default | Description |
|---|---|---|---|
gravitational_constant |
f64 |
0.01 |
Strength of gravitational attraction between bodies |
body_count |
usize |
100 |
Number of celestial bodies to simulate |
octree_theta |
f64 |
0.5 |
Barnes-Hut accuracy parameter (0.0-2.0). Lower = more accurate, slower |
octree_leaf_threshold |
usize |
4 |
Maximum bodies per octree leaf before subdivision |
body_distribution_sphere_radius_multiplier |
f32 |
100.0 |
Multiplier for initial body distribution radius |
body_distribution_min_distance |
f32 |
0.001 |
Minimum distance between bodies at spawn |
min_body_radius |
f32 |
1.0 |
Minimum radius for generated bodies |
max_body_radius |
f32 |
2.0 |
Maximum radius for generated bodies |
force_calculation_min_distance |
f64 |
2.0 |
Minimum distance for force calculations (prevents singularities) |
force_calculation_max_force |
f64 |
10000.0 |
Maximum force magnitude to prevent instabilities |
initial_seed |
Option<u64> |
None |
Random seed for deterministic generation. None = random |
barycentric_drift_correction |
bool |
true |
Enable automatic recentering around barycenter. False = pure physics |
integrator.type |
string |
"velocity_verlet" |
Numerical integration method (see Integrator Types below) |
| Field | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
true |
Whether bodies spawn with initial velocities |
min_speed |
f64 |
10.0 |
Minimum initial speed |
max_speed |
f64 |
100.0 |
Maximum initial speed |
velocity_mode |
string |
"random" |
Velocity distribution mode (see below) |
tangential_bias |
f64 |
0.7 |
Bias toward tangential motion (0.0-1.0) when using Random mode |
Integrator Types: (use snake_case in config)
"explicit_euler"- 1st order explicit integrator, non-symplectic (alias:"forward_euler")"symplectic_euler"- 1st order symplectic integrator (aliases:"euler","semi_implicit_euler")"velocity_verlet"- 2nd order symplectic integrator, excellent energy conservation (alias:"verlet")"heun"- 2nd order explicit integrator, also known as Improved Euler (alias:"improved_euler")"runge_kutta_second_order_midpoint"- 2nd order explicit integrator (aliases:"rk2","midpoint")"runge_kutta_fourth_order"- 4th order explicit integrator, highest accuracy (alias:"rk4")"pefrl"- 4th order symplectic integrator, superior long-term energy conservation (alias:"forest_ruth")
The choice of integrator significantly affects simulation accuracy, stability, and performance. Here's a detailed guide:
Symplectic Integrators (Energy-conserving, ideal for long-term simulations):
-
symplectic_euler(1st order)- Pros: Fast, simple, better energy conservation than explicit Euler
- Cons: Low accuracy, requires small timesteps
- Use Case: Quick visualizations where accuracy isn't critical
- Algorithm: Updates velocity before position to preserve phase space volume
-
velocity_verlet(2nd order) - RECOMMENDED DEFAULT- Pros: Excellent energy conservation, time-reversible, good stability
- Cons: Requires force recalculation (2 evaluations per step)
- Use Case: General n-body simulations, especially long-term orbital mechanics
- Algorithm: Uses average of accelerations at start and end of timestep
-
pefrl(4th order)- Pros: Superior long-term energy conservation, high accuracy, symplectic
- Cons: Most expensive (4 force evaluations per step)
- Use Case: Scientific simulations requiring long-term stability
- Algorithm: Optimized Forest-Ruth composition with minimal error coefficients
Explicit Integrators (General-purpose, not energy-conserving):
-
explicit_euler(1st order) - WARNING: For educational/comparison use only- Pros: Simplest possible integrator, fast computation
- Cons: Poor energy conservation, unstable for oscillatory systems, energy drift
- Use Case: Educational comparisons, debugging, very short simulations
- Algorithm: Updates position before velocity using current state values
- Warning: Energy grows/decays exponentially - unsuitable for orbital mechanics
-
heun(2nd order)- Pros: Better accuracy than Euler, predictor-corrector approach
- Cons: Energy drift in long simulations
- Use Case: Short-term simulations with smooth forces
- Algorithm: Averages derivatives at start and predicted endpoint
-
runge_kutta_second_order_midpoint(2nd order)- Pros: Good accuracy for smooth problems
- Cons: Energy drift, not suitable for long-term simulations
- Use Case: Non-Hamiltonian systems or short integration periods
- Algorithm: Evaluates derivative at the midpoint of timestep
-
runge_kutta_fourth_order(4th order)- Pros: High accuracy for smooth functions
- Cons: Energy drift, expensive (4 evaluations), can be unstable for stiff problems
- Use Case: High-accuracy requirements over short timeframes
- Algorithm: Weighted average of 4 intermediate derivative evaluations
Performance vs. Accuracy Trade-offs:
| Integrator | Order | Force Evals/Step | Energy Conservation | Relative Speed |
|---|---|---|---|---|
explicit_euler |
1 | 1 | Very Poor | Fastest |
symplectic_euler |
1 | 1 | Good | Fastest |
heun |
2 | 2 | Poor | Fast |
runge_kutta_second_order_midpoint |
2 | 2 | Poor | Fast |
velocity_verlet |
2 | 2 | Excellent | Fast |
runge_kutta_fourth_order |
4 | 4 | Poor | Slow |
pefrl |
4 | 4 | Superior | Slow |
Choosing Guidelines:
- Default Choice: Use
velocity_verletfor most n-body simulations - Long-term stability: Use
pefrlfor scientific accuracy over extended periods - Performance critical: Use
symplectic_eulerwith smaller timesteps - High accuracy, short-term: Use
runge_kutta_fourth_order - Energy conservation important: Always choose symplectic integrators
Velocity Modes: (use snake_case in config, e.g. "random", "orbital")
"random"- Random velocity vectors with optional tangential bias"orbital"- Circular orbital velocities around barycenter"tangential"- Pure tangential motion perpendicular to radius"radial"- Pure radial motion toward/away from barycenter
| Field | Type | Default | Description |
|---|---|---|---|
color_scheme |
string |
"black_body" |
Color scheme for bodies (see Color Schemes section below) |
min_temperature |
f32 |
3000.0 |
Minimum stellar temperature in Kelvin (for "black_body" scheme) |
max_temperature |
f32 |
15000.0 |
Maximum stellar temperature in Kelvin (for "black_body" scheme) |
bloom_intensity |
f32 |
250.0 |
Intensity of bloom visual effect |
saturation_intensity |
f32 |
3.0 |
Color saturation multiplier |
camera_radius_multiplier |
f32 |
4.0 |
Camera distance multiplier relative to system size |
The simulation supports multiple color schemes for celestial bodies, grouped into categories:
Physics-Based:
black_body(default) - Colors based on black body radiation temperatures. Smaller bodies appear hotter (blue-white), larger bodies appear cooler (red-orange)
Colorblind-Safe Palettes:
deuteranopia_safe- Optimized for red-green colorblindness (most common, ~8% of males). Uses blue, orange, yellow, and teal colorsprotanopia_safe- Optimized for red-blindness. Uses blue, yellow, and teal colorstritanopia_safe- Optimized for blue-yellow colorblindness (rare). Uses red, green, and magentahigh_contrast- Maximum distinguishability with widely separated hues and high saturation differences
Scientific Colormaps (Perceptually Uniform):
viridis- Purple-blue-green-yellow gradient. Industry standard for scientific visualization, colorblind-safeplasma- Magenta-purple-pink-yellow gradient with high visual appealinferno- Black-red-yellow-white heat map for intensity visualizationturbo- Google's improved rainbow colormap with better perceptual properties than standard rainbow
Aesthetic Themes:
rainbow- Random vibrant colors using the full HSL spectrum with high saturationpastel- Soft, low-saturation colors (S: 0.3-0.5, L: 0.7-0.85)neon- High saturation cyberpunk-style colors with limited hue rangesmonochrome- Grayscale variations (excludes pure black and white for visibility)vaporwave- Retrofuturistic pink-purple-cyan palette with weighted distribution for authentic 80s aesthetic
Pride Flag Themes:
bisexual- Bisexual pride flag colors (pink-purple-blue) with smooth gradient interpolation maintaining 2:1:2 proportionstransgender- Transgender pride flag colors (light blue-pink-white) designed by Monica Helmslesbian- Lesbian pride flag colors using the 2018 orange-to-pink sunset flag designpansexual- Pansexual pride flag colors (pink-yellow-blue) representing attraction regardless of gendernonbinary- Non-binary pride flag colors (yellow-white-purple-black) created by Kye Rowanasexual- Asexual pride flag colors (black-gray-white-purple) representing the ace spectrumgenderfluid- Genderfluid pride flag colors (pink-white-purple-black-blue) representing gender fluidityaromantic- Aromantic pride flag colors (green-white-gray-black) for the aromantic spectrumagender- Agender pride flag colors (black-gray-white-green) in symmetric pattern
Trail visualization configuration options.
| Field | Type | Default | Description |
|---|---|---|---|
trail_length_seconds |
f32 |
10.0 |
How long trails persist in seconds |
update_interval_seconds |
f32 |
0.03333 |
How often to add trail points (default: 30 FPS) |
max_points_per_trail |
usize |
10000 |
Maximum trail points per body |
base_width |
f32 |
1.0 |
Base trail width |
width_relative_to_body |
bool |
false |
Scale trail width relative to body size |
body_size_multiplier |
f32 |
2.0 |
Trail width multiplier when relative to body |
enable_fading |
bool |
true |
Enable trail fade-out effect |
fade_curve |
string |
"exponential" |
Fade curve type (see below) |
min_alpha |
f32 |
0.0 |
Minimum trail transparency (0.0-1.0) |
max_alpha |
f32 |
0.3333 |
Maximum trail transparency (0.0-1.0) |
enable_tapering |
bool |
true |
Enable trail width tapering |
taper_curve |
string |
"linear" |
Taper curve type (see below) |
min_width_ratio |
f32 |
0.2 |
Minimum width ratio at trail end |
bloom_factor |
f32 |
1.0 |
Trail bloom intensity multiplier |
use_additive_blending |
bool |
true |
Use additive blending for trails |
Fade Curves: (use snake_case in config)
"linear"- Linear fade from head to tail"exponential"- Exponential fade (aggressive)"smooth_step"- Smooth interpolation curve"ease_in_out"- Ease in and out curve
Taper Curves: (use snake_case in config)
"linear"- Linear width reduction"exponential"- Exponential width reduction"smooth_step"- Smooth width transition
| Field | Type | Default | Description |
|---|---|---|---|
directory |
Option<String> |
None |
Save directory. None = current directory |
filename_prefix |
String |
"stardrift_screenshot" |
Filename prefix for screenshots |
include_timestamp |
bool |
true |
Add timestamp to filenames |
notification_enabled |
bool |
true |
Log screenshot captures |
hide_ui_frame_delay |
u32 |
2 |
Frames to wait before capture (ensures UI is hidden) |
| Field | Type | Default | Description |
|---|---|---|---|
prevent_screen_sleep |
bool |
true |
Prevent display from sleeping or dimming during simulation (cross-platform) |
The configuration is automatically loaded from the platform-specific config directory:
- Linux:
~/.config/Stardrift/config.toml - macOS:
~/Library/Application Support/Stardrift/config.toml - Windows:
%APPDATA%\Stardrift\config.toml
If no configuration file exists, the application uses default values.
- Engine: Bevy 0.16.1 (Entity Component System game engine)
- Physics: Custom ECS-based physics with f64 precision and parallel processing
- Spatial Optimization: Barnes-Hut octree algorithm with configurable theta parameter for accuracy/performance balance
- Rendering: Bevy's PBR (Physically Based Rendering) pipeline with octree wireframe visualization
- Random Number Generation: ChaCha8 PRNG algorithm
- Mathematical Utilities: Sphere surface distribution algorithms and statistical validation
- Build Profiles:
- Development: Reduced optimizations for faster compilation
- Release: Compiler optimizations enabled with debug info stripped
- Distribution: Link-time optimization (LTO) and single codegen unit
- Algorithmic Efficiency: Barnes-Hut octree reduces gravitational calculations from O(N²) to O(N log N)
- Parallel Processing: Multi-threaded physics calculations
- Integrator Benchmarks: Benchmark suite evaluating integrators across:
- Raw performance (operations per second)
- Accuracy (error vs analytical solutions)
- Convergence order verification
- Energy conservation over long simulations
- Work-precision tradeoffs
- N-body scenarios
Built with Bevy game engine and community plugins. See Cargo.toml for the complete dependency list.
For WebAssembly builds, install trunk:
cargo install trunk- WebGL2 & WebAssembly support: Required for 3D rendering and application execution
- Minimum browser versions:
- Chrome 57+ (WebAssembly requirement)
- Firefox 52+ (WebAssembly requirement)
- Safari 15+ (WebGL2 requirement)
- Edge 79+ (Chromium-based Edge)
- Hardware acceleration: Required for better performance
Stardrift uses a plugin-based architecture built on Bevy ECS (Entity Component System).
The project follows a plugin-based architecture where each major feature is self-contained:
- Simulation Plugin - Core physics and body management
- Controls Plugin - Input handling and UI
- Visualization Plugin - Debug rendering (octree, barycenter)
- Trails Plugin - Particle trail rendering
- Camera Plugin - 3D camera controls
- Diagnostics Plugin - Performance metrics
Plugins communicate through events and shared resources using Bevy's ECS patterns.
The physics module implements:
- Barnes-Hut Algorithm - Octree-based force calculation for O(n log n) performance
- Multiple Integrators - Symplectic and Runge-Kutta methods
- Collision Detection - Body merging on contact
- Barycenter Tracking - System center of mass calculation
- Plugin-Based Architecture: Each plugin is completely self-contained with internal systems, components, and clear boundaries
- Event-Driven Communication: Plugins communicate exclusively through
SimulationCommandevents - Zero Orchestration: No external coordination or management of plugin internals
- Scalable Organization: Large plugins use internal submodules for code organization
- Resource Management: Global state is managed through Bevy's resource system
- Configuration-Driven: Centralized configuration system for runtime customization
- Clear Feature Boundaries: Plugin boundaries enforce architectural constraints
WASM build fails: Ensure you have the latest version of trunk:
cargo install trunk --forceWebGL2 not supported: Use a supported browser or enable hardware acceleration in browser settings.
Poor performance: Try the native build for better performance, or reduce the number of bodies in the simulation.
Build errors: Ensure you have the latest Rust toolchain:
rustup updateThis project is dedicated to the public domain under the CC0 1.0 Universal license.
You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See the LICENSE file for details.
All release binaries include cryptographic attestations that prove they were built by the official GitHub Actions workflow. This provides supply chain security and ensures binaries haven't been tampered with.
To verify a downloaded binary:
# Install GitHub CLI if needed
# https://cli.github.com/
# Verify a release binary (example with version)
gh attestation verify stardrift-0.0.15-x86_64-unknown-linux-gnu.tar.gz \
--repo emilyst/stardrift
# The command will confirm the binary was built from the official repositoryAttestations use Sigstore and follow the SLSA standard for software supply chain security.
This project uses cargo-release for automated release management following semantic versioning principles.
Following Rust ecosystem conventions:
- 0.0.x - Early experimental releases with frequent breaking changes
- 0.x.y - Pre-1.0 development phase where the API may still evolve
- 1.0.0 - First stable release with a commitment to API stability
-
Ensure all changes are committed:
git status # Should show a clean working directory -
Review changes since last release:
cargo release changes
-
Perform a dry run (recommended):
cargo release patch # Shows what would happen cargo release minor # For feature releases
-
Execute the release:
cargo release patch --execute
-
Push to GitHub:
git push origin main git push origin --tags
The cargo-release tool automatically:
- Updates the version in
Cargo.toml - Updates
CHANGELOG.mdwith the new version and current date - Creates a signed git commit with message "chore: release vX.Y.Z"
- Tags the commit with "vX.Y.Z" (also signed)
- Updates
Cargo.lockwith the new version
Release behavior is configured in Cargo.toml under [package.metadata.release]:
- Commits and tags are signed if GPG is configured
- Publishing to crates.io is disabled (private project)
- Releases are only allowed from the
mainbranch - Changelog format follows Keep a Changelog conventions
- Built with Bevy game engine
- Camera controls provided by bevy_panorbit_camera