Million-Particle
GPU Physics Engine
High-performance N-body simulation with CUDA acceleration, real-time OpenGL visualization, and three force calculation algorithms. Simulate up to 1 million particles at 60+ FPS.
Force Calculation Algorithms
Choose the right algorithm for your simulation needs
Direct N²
O(N²)Exact pairwise force calculation
Barnes-Hut
O(N log N)Hierarchical octree approximation
Spatial Hash
O(N)Grid-based short-range forces
Performance Benchmarks
Real-time FPS on NVIDIA RTX 3080, CUDA 11.8
| Particles | Direct N² | Barnes-Hut | Spatial Hash |
|---|---|---|---|
| 10K | 60 FPS | 120 FPS | 120 FPS |
| 100K | 10 FPS | 60 FPS | 90 FPS |
| 1M | 1 FPS | 25 FPS | 60 FPS |
FPS Comparison (Higher is Better)
Memory footprint: ~52 bytes per particle + algorithm overhead. Best for Large Scale: Barnes-Hut for gravitational, Spatial Hash for short-range forces.
Key Features
Everything you need for high-performance particle simulation
GPU Accelerated
CUDA parallel processing with one thread per particle
Three Algorithms
Direct N², Barnes-Hut O(N log N), Spatial Hash O(N)
Zero-Copy Rendering
CUDA-OpenGL interop eliminates CPU↔GPU data transfer
Energy Conserving
Velocity Verlet symplectic integration
Real-time 60+ FPS
Smooth visualization for up to 1 million particles
Cross-Platform
Linux, Windows, macOS with NVIDIA GPU
System Architecture
High-level overview of the simulation system components
Design Patterns
- Strategy — Runtime algorithm switching
- Bridge — CUDA-OpenGL interop abstraction
- Facade — Simple ParticleSystem API
Memory Layout
- Structure of Arrays (SoA) — GPU coalescing
- Shared VBO — Zero-copy rendering
- Shared Memory — Kernel caching
Quick Start
Get started with N-Body simulation in minutes
#include "nbody/particle_system.hpp"
using namespace nbody;
int main() {
// Configure simulation
SimulationConfig config;
config.particle_count = 100'000;
config.force_method = ForceMethod::BARNES_HUT;
config.dt = 0.001f;
config.init_distribution = InitDistribution::SPHERICAL;
// Initialize and run
ParticleSystem system;
system.initialize(config);
for (int step = 0; step < 10'000; ++step) {
system.update(system.getTimeStep());
// Save checkpoints
if (step % 1000 == 0) {
system.saveState("checkpoint_" + std::to_string(step) + ".nbody");
}
}
return 0;
}
Open Source
Join the community on GitHub
Found a bug or have a feature request?
Open an Issue