$darkmode
Suckless OGL 1.0.0
A lean, high-performance C11 PBR Renderer
nbody.h File Reference

N-body gravitational simulation (Velocity Verlet + Plummer softening). More...

#include "sphere_types.h"
#include <cglm/types.h>
#include <stdbool.h>
Include dependency graph for nbody.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  NBodyParticle
 A single gravitational body. More...
 
struct  NBodyImpact
 Records a confinement boundary hit for visual effects. More...
 
struct  NBodySim
 State container for the N-body simulation. More...
 

Enumerations

enum  { NBODY_MAX_BODIES = 32 }
 

Functions

void nbody_init_preset (NBodySim *sim)
 Initializes the simulation with a preset solar system configuration. More...
 
void nbody_step (NBodySim *sim, float delta_time)
 Advances the simulation by the given wall-clock delta time. More...
 
void nbody_write_instances (const NBodySim *sim, SphereInstance *out)
 Writes current body positions and materials into a SphereInstance array suitable for the instanced rendering pipeline. More...
 
int nbody_get_count (const NBodySim *sim)
 Returns the number of active bodies. More...
 
float nbody_total_energy (const NBodySim *sim)
 Computes the total energy (kinetic + gravitational potential). More...
 
float nbody_kinetic_energy (const NBodySim *sim)
 Computes kinetic energy only: Σ ½ m v². More...
 
float nbody_energy_drift (const NBodySim *sim)
 Returns the relative energy drift |E(t) - E₀| / |E₀|. More...
 
float nbody_energy_drift_signed (const NBodySim *sim)
 
void nbody_update_time_scale (NBodySim *sim, float delta_time)
 Smoothly transitions time_scale toward target_time_scale. More...
 

Variables

static const float NBODY_DEFAULT_G = 1.0F
 
static const float NBODY_SOFTENING_SQ = 0.25F
 
static const float NBODY_SOFTENING_FACTOR = 2.0F
 
static const float NBODY_FIXED_DT = 1.0F / 120.0F
 
static const float NBODY_MAX_ACCUMULATOR = 1.0F / 10.0F
 
static const float NBODY_CONFINEMENT_RADIUS = 25.0F
 
static const float NBODY_CONFINEMENT_K = 5.0F
 
static const float NBODY_CONFINEMENT_DAMPING = 20.0F
 
static const float NBODY_TIME_SCALE_RATE = 3.0F
 

Detailed Description

N-body gravitational simulation (Velocity Verlet + Plummer softening).

Manages a set of gravitational bodies with position, velocity, and mass. Uses a symplectic Velocity Verlet integrator with per-pair Plummer softening to guarantee long-term energy conservation without ad-hoc damping. Produces SphereInstance data for the instanced renderer.

See also
docs/nbody_physics.md for the full physics reference.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Maximum number of bodies in the simulation.

Enumerator
NBODY_MAX_BODIES 

Function Documentation

◆ nbody_energy_drift()

float nbody_energy_drift ( const NBodySim *  sim)

Returns the relative energy drift |E(t) - E₀| / |E₀|.

Returns 0 when initial_energy is zero (no reference).

Here is the call graph for this function:

◆ nbody_energy_drift_signed()

float nbody_energy_drift_signed ( const NBodySim *  sim)

Signed energy drift: negative = energy lost (damping), positive = energy gained (divergence).

Here is the call graph for this function:

◆ nbody_get_count()

int nbody_get_count ( const NBodySim *  sim)

Returns the number of active bodies.

◆ nbody_init_preset()

void nbody_init_preset ( NBodySim *  sim)

Initializes the simulation with a preset solar system configuration.

Parameters
simPointer to the simulation state.
Here is the call graph for this function:

◆ nbody_kinetic_energy()

float nbody_kinetic_energy ( const NBodySim *  sim)

Computes kinetic energy only: Σ ½ m v².

Here is the call graph for this function:

◆ nbody_step()

void nbody_step ( NBodySim *  sim,
float  delta_time 
)

Advances the simulation by the given wall-clock delta time.

Uses a fixed-timestep accumulator with Velocity Verlet integration.

Parameters
simPointer to the simulation state.
delta_timeWall-clock time elapsed since last call (seconds).
Here is the call graph for this function:

◆ nbody_total_energy()

float nbody_total_energy ( const NBodySim *  sim)

Computes the total energy (kinetic + gravitational potential).

Useful for stability diagnostics. With a symplectic integrator, this quantity oscillates with bounded amplitude around E₀.

Here is the call graph for this function:

◆ nbody_update_time_scale()

void nbody_update_time_scale ( NBodySim *  sim,
float  delta_time 
)

Smoothly transitions time_scale toward target_time_scale.

Called once per frame. Ramps at NBODY_TIME_SCALE_RATE units/s, producing a decelerate → pause → accelerate-in-reverse effect.

Parameters
simPointer to the simulation state.
delta_timeWall-clock frame delta (seconds).

◆ nbody_write_instances()

void nbody_write_instances ( const NBodySim *  sim,
SphereInstance *  out 
)

Writes current body positions and materials into a SphereInstance array suitable for the instanced rendering pipeline.

Parameters
simPointer to the simulation state.
outOutput array (must have capacity >= sim->body_count).

Variable Documentation

◆ NBODY_CONFINEMENT_DAMPING

const float NBODY_CONFINEMENT_DAMPING = 20.0F
static

Radial damping coefficient in the confinement zone. Effective damping is γ · (overshoot / r_max), so the base value must be large enough that bodies near the boundary still feel it. At r = 26 (overshoot 1): γ_eff = 20 × 1/25 = 0.8 At r = 30 (overshoot 5): γ_eff = 20 × 5/25 = 4.0 Only the radial (v·r̂) component is damped; tangential speed is preserved so angular momentum is not destroyed.

◆ NBODY_CONFINEMENT_K

const float NBODY_CONFINEMENT_K = 5.0F
static

Confinement stiffness — spring constant for the restoring force. Higher values = harder wall, lower = softer bounce. k·dt² ≈ 5·(1/120)² ≈ 0.0003 — well within stability limit.

◆ NBODY_CONFINEMENT_RADIUS

const float NBODY_CONFINEMENT_RADIUS = 25.0F
static

Confinement radius — bodies beyond this distance from the central star experience a quadratic restoring potential V = ½k(r - r_max)². The potential is conservative (Hamiltonian) so symplecticity is preserved.

◆ NBODY_DEFAULT_G

const float NBODY_DEFAULT_G = 1.0F
static

Default gravitational constant (tuned for visual scale ~20 units).

◆ NBODY_FIXED_DT

const float NBODY_FIXED_DT = 1.0F / 120.0F
static

Fixed physics timestep for stable integration (seconds).

◆ NBODY_MAX_ACCUMULATOR

const float NBODY_MAX_ACCUMULATOR = 1.0F / 10.0F
static

Maximum accumulated physics time per call to nbody_step. Prevents runaway integration after lag spikes or first frame. Set to 1/10s to support frame rates as low as ~10 FPS without losing simulation time (12 Verlet steps per frame for N=14).

◆ NBODY_SOFTENING_FACTOR

const float NBODY_SOFTENING_FACTOR = 2.0F
static

Per-pair softening multiplier. eps = F * (r_i + r_j). Higher values weaken close encounters and reduce chaotic 3-body slingshot effects at the cost of making gravity less Keplerian at short range.

◆ NBODY_SOFTENING_SQ

const float NBODY_SOFTENING_SQ = 0.25F
static

Minimum softening factor squared — prevents singularity at r→0. Actual softening per pair is max(this, (F*(r_i + r_j))²) so that bodies repel naturally before visually overlapping (Plummer softening).

◆ NBODY_TIME_SCALE_RATE

const float NBODY_TIME_SCALE_RATE = 3.0F
static

Rate at which time_scale transitions toward its target (units/s).