Physics simulation for rock trajectory - global N-body gravity and local ray marching - EPITECH G-CNA-400 Project
- Overview
- Compilation
- Usage
- The TOML configuration file
- Output format
- Bonus: RK4 integrator
- Bonus: Real-time viewer
- Project architecture
- Exploration: Non-Euclidean raymarching in H³
Interstonar simulates the trajectory of a thrown rock in two distinct modes:
- Global mode - computes the rock's path through a planetary scene under Newtonian gravity, using Euler integration. Celestial bodies can collide and merge during the simulation.
- Local mode - determines which shape (if any) the rock intersects in a local scene, using sphere-assisted ray marching and Signed Distance Functions (SDF).
Subject is in G-CNA-400_interstonar.pdf.
# Compile in release mode
cargo build --release
# Run unit tests
cargo test
# The binary will be at
./target/release/interstonar./interstonar [--global | --local] CONFIG_FILE [-d TIME | --delta=TIME] Px Py Pz Vx Vy Vz| Argument | Description |
|---|---|
--global |
Launch in global scene mode (massive moving bodies) |
--local |
Launch in local scene mode (massless motionless shapes) |
CONFIG_FILE |
TOML configuration file describing the scene |
-d TIME, --delta=TIME |
Delta time in seconds - global mode only |
Px Py Pz |
Initial position of the rock (SI units) |
Vx Vy Vz |
Initial velocity vector of the rock |
Examples:
# Global: rock collides the Sun after 3 steps
./interstonar --global scene.toml --delta=3600 1 2 3 4 5 6
# Local: find which shape the rock hits
./interstonar --local shapes.toml 10 0 35 -1 0 -2All entries use [[body]] tables. Every value is in SI base units.
Each body requires: name, position, direction, mass, radius.
[[body]]
name = "Sun"
position = {x = 1.81899E+8, y = 9.83630E+8, z = -1.58778E+8}
direction = {x = -1.12474E+1, y = 7.54876E+0, z = 2.68723E-1}
mass = 1.98854e30
radius = 696_342_000
[[body]]
name = "Earth"
position = {x = 0, y = 1.496E+11, z = 0}
direction = {x = -2.978E+4, y = 0, z = 0}
mass = 5.972E+24
radius = 6_371_000Simulation rules:
- Gravitation follows Newton's law:
F = G·m₁·m₂/r², withG = 6.674×10⁻¹¹ m³·kg⁻¹·s⁻² - Rock mass is fixed at 1,000 kg
- Positions updated via Euler integration
- Stops after a collision or 1,000 deltas
- If two bodies (not the rock) collide, they merge: masses sum, radius from combined volume, position/velocity are mass-weighted means, name is ASCII-sorted concatenation with
-
Each body requires: type, position, and shape-specific properties. name is optional (defaults to TYPE_N).
[[body]]
name = "s1"
type = "sphere"
position = {x = 0, y = 0, z = 0}
radius = 1
[[body]]
type = "cylinder"
position = {x = 0, y = 0, z = 0}
radius = 1
height = 100 # optional - infinite if omitted
[[body]]
type = "box"
position = {x = 0, y = 0, z = 0}
sides = {x = 10, y = 10, z = 10}
[[body]]
name = "t1"
type = "torus"
position = {x = 0, y = 0, z = 0}
inner_radius = 3
outer_radius = 1Supported shapes: sphere, cylinder, box, torus.
Ray marching rules:
- Intersection when SDF ≤ 0.1
- No intersection if > 1,000 steps or distance to closest object > 1,000
Rock coordinates (x y z) are:
t = 0: (Px Py Pz)
t = 1: (...)
...
Collision between rock and <name> ← if collision
Mission success ← collision occurred
Mission failure ← 1000 steps reached without collision
Rock thrown at the point (Px, Py, Pz) and parallel to the vector (Vx, Vy, Vz)
<shape description line per shape>
Step 1: (x, y, z)
...
Result: Intersection with <NAME> ← hit
Result: Out of scene ← diverged
Result: Steps limit reached ← 1000 steps, no hit
The --rk4 flag replaces the default Euler integrator with a 4th-order Runge-Kutta integrator in global mode.
./interstonar --global scene.toml --delta=3600 --rk4 1 2 3 4 5 6
--rk4is only available in--globalmode.
| Integrator | Derivative evaluations / step | Error per step |
|---|---|---|
| Euler | 1 | O(Δt²) |
| RK4 | 4 | O(Δt⁵) |
Euler accumulates O(Δt) global error and visibly drifts on orbital trajectories (spiralling inward or outward). RK4 keeps orbits stable over the same number of steps.
For each step RK4 computes four slope estimates and combines them:
k1 = f(t, y)
k2 = f(t + h/2, y + h/2 · k1)
k3 = f(t + h/2, y + h/2 · k2)
k4 = f(t + h, y + h · k3)
y(t+h) = y + h/6 · (k1 + 2·k2 + 2·k3 + k4)
where y = (position, velocity) and f = gravitational accelerations. Both the rock and all celestial bodies are integrated simultaneously so each intermediate evaluation uses a coherent snapshot of all positions.
The --view flag activates a real-time 3D viewer for local scenes rendered with CPU sphere-traced ray marching.
./interstonar --local shapes.toml --view Px Py Pz Vx Vy Vz
--viewis only available in--localmode. The rock position and velocity arguments are still required but are ignored when the viewer is active.
The viewer renders the scene once into a 1920 × 1080 framebuffer, then enters an event loop until the window is closed.
| Property | Value |
|---|---|
| Position | (0, 2, -8) |
| Direction | +Z |
| Field of view | 60° |
| Max ray distance | 200 |
| Max ray steps | 256 |
Each shape type is assigned a fixed base colour, then shaded with an ambient + diffuse lighting model (ambient = 0.15, light at (0.5, 1.0, -0.5) normalised). Surface normals are estimated by central differences on the scene SDF.
| Shape | RGB (normalised) | Appearance |
|---|---|---|
| Sphere | (0.20, 0.60, 1.00) |
Blue |
| Box | (1.00, 0.50, 0.20) |
Orange |
| Cylinder | (0.30, 0.90, 0.40) |
Green |
| Torus | (0.90, 0.30, 0.60) |
Pink |
| Action | Effect |
|---|---|
Escape |
Close the viewer |
| Click window × | Close the viewer |
make view CONFIG=shapes.toml PX=0 PY=0 PZ=0 VX=0 VY=0 VZ=1The current ray marching operates in flat Euclidean space: rays travel in straight lines and distances are the standard Euclidean norm. It is possible to extend this to hyperbolic space H³, where space has a constant negative curvature — objects in the distance shrink exponentially, parallel lines diverge, and the angles of a triangle sum to less than 180°.
H³ is modelled as a surface in ℝ⁴ with the Minkowski metric:
H³ = { x ∈ ℝ⁴ | ⟨x, x⟩_M = -1, x₀ > 0 }
⟨u, v⟩_M = -u₀v₀ + u₁v₁ + u₂v₂ + u₃v₃
Three Euclidean operations are replaced:
| Operation | Euclidean | Hyperbolic H³ |
|---|---|---|
| Ray step | p + t·d |
cosh(t)·p + sinh(t)·d |
| Distance | ‖p − q‖ |
acosh(-⟨p, q⟩_M) |
| SDF sphere | ‖p − c‖ − r |
acosh(-⟨p, c⟩_M) − r |
The direction vector is also parallel-transported at each step (it rotates as the ray follows the curved geodesic) and both position and direction are periodically renormalized to prevent numerical drift off the H³ surface.
src/vec3.rs— add aVec4type withmink()(Minkowski dot product),lift_to_h3(),lift_direction(), andhyp_dist().src/local/shape.rs— addsdf_sphere_h3andsdf_cylinder_h3using hyperbolic distances, plus asdf_scene_h3dispatcher.src/local/raymarching.rs— addraymarching_h3replacing the linear step with the geodesic formula and transport.
.
├── src/
│ ├── main.rs # Entry point, mode dispatch
│ ├── args.rs # CLI argument parsing (clap)
│ ├── config.rs # TOML deserialization
│ ├── vec3.rs # 3D vector math
│ ├── global/
│ │ ├── body.rs # Celestial body struct + merging logic
│ │ └── simulation.rs # Euler integration, collision detection
│ └── local/
│ ├── shape.rs # Shape types + SDF implementations
│ ├── raymarching.rs# Sphere-assisted ray marching
│ └── viewer.rs # Real-time ray marching viewer (bonus)
├── tests/
│ └── unit_tests/ # Unit tests per module
├── Cargo.toml
└── G-CNA-400_interstonar.pdf