Aetheria gravity: model page and body facts (map), prior-art research for the eight gravity forks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
c651938381
commit
0b86888f79
2 changed files with 135 additions and 0 deletions
65
docs/aetheria-gravity-map.md
Normal file
65
docs/aetheria-gravity-map.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<!-- Prose map for campaign aetheria-gravity. Step 0b (model page and body facts) by Imagination imagination-ag2-gravity-0b, session self-2026-10-14-ag2, read at master c6519383. Target in force: aetheria-gravity:target:r2. -->
|
||||
# Aetheria gravity: map
|
||||
|
||||
Target: `aetheria-gravity:target:r2` (rationale in `docs/aetheria-gravity-target.md`). Rulings in force: `aetheria-gravity:ruling:grid-shows-how-you-move`; from other campaigns, `aetheria-release:ruling:gravity-honest-wells-agreed`, `aetheria-fauna:ruling:ink-pillars-are-suns`, `aetheria-fauna:ruling:sim-knows-the-flow`, `aetheria-release:ruling:liquid-grid-from-sim-brushes`. Prior art: `docs/research/2026-10-14-gravity-prior-art.md`. Orbit measurements: `docs/research/2026-10-13-orbit-probe/report.md`.
|
||||
|
||||
## Body facts
|
||||
|
||||
All read at c6519383 in the detached worktree `C:\aeth-wt\ag2-docs` on 2026-10-14 unless marked. Scripts live in the Imagination scratchpad (`imagination-ag2-gravity-0b/`).
|
||||
|
||||
- **B1. Sim gravity today.** `Zone.GetHeight` (Zone.cs:631-658) sums the zone bowl `-PowerPulse(|p|/(2·Pack.Radius), ZoneDepthExponent)·ZoneDepth`, one PowerPulse well per `PlanetInstances` entry (radius `GravityWellRadius`, depth `GravityWellDepth`, exponent `BodyData.GravityDepthExponent`), and for every `GasGiant` (suns included) a `RadialWaves` ripple in zone time. `GetNormal` (:725-734) differences GetHeight at ±0.1; `GetForce` (:692-696) and `Ship.Update` (Ship.cs:133-135) feed the normal's xz to `GravityAcceleration` (:684-689), `S·R·(1/(1-|n|²)-1)` gated off at `|n|² <= .001`. Wells read `body.Orbit.Position`, which is float2.zero until the first `Zone.Update` (follow-up `zone-orbits-unplaced-before-first-tick`).
|
||||
- **B2. The bowl and the ripples are live in code.** The operator's ruling says the zone bowl is disabled and stays so, ripples likewise. At c6519383 neither is disabled: `Settings.asset` (the only asset carrying PlanetSettings) has `ZoneDepth: 64`, `ZoneDepthExponent: 2`, `WaveDepth 0.5·m^0.3`; GetHeight applies both unconditionally; the bowl is felt only in zones with radius under about 3117 (the force gate, probe F3) and the ripples are felt around every gas giant and sun (8 to 32% of peak force, probe wave table). The drawn grid shows both: the scene `Boundary` object (PowerBrush, layer Displacement, active) is driven each frame by `ZoneRenderer` (ZoneRenderer.cs:621-622) with ZoneDepth plus ZoneBoundaryFog (0), and the `Gravity Waves` objects in `Gas Giant.prefab` and `Sun.prefab` (layer FineDisplacement, active) carry the ripple. So `flatspace-no-bowl-no-ripples` is delivered by deletion in a cut, not already true.
|
||||
- **B3. The drawn grid is a second height owner.** It is not sampled from `Zone.GetHeight`. Camera `Surface Displacement` (ARPG.unity, culling layers 9 Displacement and 10 FineDisplacement) renders additive brush quads into `Assets/Resources/Fog Surface Displacement.renderTexture`, which `VolumeSampling.cs:63` publishes as the global `_NebulaSurfaceHeight`. Brushes on those layers:
|
||||
|
||||
| object (where) | layer | material and shader | sim counterpart |
|
||||
|---|---|---|---|
|
||||
| Gravity Well (Planet, Gas Giant, Sun prefabs) | 9 | Gravity Well, PowerBrush, `_Power 16` fixed in the material, `_Depth` set from `GravityWellDepth`, quad scaled by `GravityWellRadius` (ZoneRenderer.cs:500-503) | the well in GetHeight, but the exponent is the material's 16, not `BodyData.GravityDepthExponent`, and the shader's envelope adds `saturate(abs(x))-.001`, `min(_Cutoff, …)` and a `smoothstep(1,.95)` rim fade the sim lacks |
|
||||
| Gravity Waves (Gas Giant, Sun) | 10 | Gravity Waves, RadialWaveBrush, `_Power 8`, `_Cutoff .5` | the ripple in GetHeight |
|
||||
| Boundary (ARPG scene) | 9 | Sector Boundary, PowerBrush, `_Power` and `_Depth` driven by ZoneRenderer | the zone bowl |
|
||||
| Waves Small / Medium / Large (ARPG scene) | 10 | Sector Waves *, SimplexBrush, depths -16.75, 7.58, 2 | none: drawn, never felt |
|
||||
| Gravity Well, Gravity Pit, Gravity Waves (Wormhole 1 prefab) | 9 | Wormhole Gravity 1 (`_Depth 54`, `_Power 4`), Wormhole Gravity (`_Depth 2000`, `_Power 64`, `_Cutoff .15`), Wormhole Waves | none: the sim has no wormhole well |
|
||||
| Gravity Well (PlanetOutpost station prefab) | 9 | Gravity Well | none found; whether this prefab is instantiated in play was not checked |
|
||||
|
||||
Other cameras render the same layers into their own textures: `Patch Displacement` (layers 9, 10, 12), `Map Gravity` (9, the minimap; `MapView.cs`), `Slime Gravity Renderer` (9; `Slime.cs` binds it as `Heightmap`).
|
||||
- **B4. Readers of the drawn height (GPU).** `Volumetric.cginc:121-130` (gradient of `_NebulaSurfaceHeight`, the shader's slopeFlow and surface normal; `:174` surface displacement), `Asteroid.shader:31` (displacement), `Stardust.compute:134` (`gravHeight`), `VolumeRenderCustom.shader` (property), `Slime.compute` (Heightmap), the minimap gravity materials (`ZoneRenderer.MapGravityMaterials`, `_StartDepth`/`_DepthRange` at :623-628), and the editor verifier `FlowFieldParityVerify.cs:162,261`. Follow-up `aetheria-fauna:follow_up:flow-slope-gradient-parity` already names the slopeFlow mismatch.
|
||||
- **B5. Readers of the sim height and force (CPU).** Force: `Ship.Update` (Ship.cs:133-135, through GetNormal and GravityAcceleration directly, not GetForce), `Zone` floating bodies, clouds and mines (Zone.cs:411, 437, 451 via GetForce). Gradient for flow: `Zone.Flow` (:700-704). Height for placement: `Entity.cs:1849` (Position.y of non-ship entities), `Agents/States/Combat.cs:114` and `Behaviors/TurretController.cs:73` (predicted target height), `Gameplay/ItemPickup.cs:44`, `Gameplay/MineInstance.cs:59`, `ZoneRenderer.cs:545` (belt bounds) and `:581` (planet body height, minimap depth range). Ship tilt: `Ship.Update` builds Rotation from the same normal. Tests: `FloatingBodyTests.cs:187-209, 254` (pin the gate and the legacy law), `LootTests.cs:299-308`, `MineTests.cs:623-628`, `FlowFieldTests.cs` (zone with bowl as the slope source), `FireControlTests.cs:380`. Editor smoke: `FloatingItemsDrawnSmoke.cs:159`. No AI reader predicts gravity.
|
||||
- **B6. Rails.** `Orbit.Period = OrbitPeriod.Evaluate(Distance)` (Zone.cs:910), with `OrbitPeriod` = 1·d^1 + 0 in Settings.asset: period is a function of distance only, never of the parent. Other readers of the same curve: `Zone.cs:599` (an orbit added at run time, phase back-solved), `Zone.cs:822` (each asteroid of a belt), `Targeting/BeltTargets.cs:63` (belt target periods). `GetOrbitPosition` (:465-500) is the closed-form rail; the root orbit has no parent and sits at `FixedPosition`. Two commented-out period writers remain in `ZoneGenerator.cs:589, 650`.
|
||||
- **B7. Body well parameters.** `Planet.CalculateProperties` (Zone.cs:755-760): `BodyRadius`, `GravityWellRadius`, `GravityWellDepth` from PlanetSettings curves times per-body multipliers; `GasGiant` adds wave depth, radius, speed. The generator never writes any multiplier or `GravityDepthExponent` (no writer in ServerShared). `GasGiantData`'s wave fields reuse the JSON names `gravRadiusMul`, `depthMul` and `depthExp` (twice: `WaveDepthExponent` and `WaveSpeedMultiplier`) that `BodyData` already uses for its gravity fields; MessagePack keys differ (14-17 against 6-8), so the binary store is unambiguous and the JSON names are not. `WaveDepthExponent` is read by nothing (the sim hard-codes 8).
|
||||
- **B8. Ship scale, measured headless from `GameData/Aetheria.cc`** (CultCache Python runtime, `hulls.py`, `mass.py`). Hull Drag: Longinus 0.1/s, Smoke Test Hull 0.1, Djinni 0.2, stations and turret 0. Drag is linear: `Velocity = normalize(v)·v·exp(-Drag·dt)` (Ship.cs:128-129; `CultMath.decay`). Thrust ranges: Small Drive 60-90k, Medium 100-300k, Large 200-300k, Rugged 75-250k, Burn and High-Thrust 250k-1M, Racing 200k-1.5M. `Entity.Mass` starts at hull mass and changes as items are added and removed (Entity.cs:1251, 1407). Items weigh about 40-50 per schematic cell (median over gear, weapons, cargo bays); the Longinus schematic has 66 cells, the Djinni 166. So a Longinus with one Small Drive accelerates at 24-36 u/s² empty and about 11-16 u/s² fully packed (2500 + ~3000); a Djinni 6-9 empty, about 3.4-5 packed. "Fully packed" is an estimate from cell count times median density, not a generated loadout (LoadoutGenerator was not run). Agent TopSpeed defaults to 100 (`VelocityLimit`).
|
||||
- **B9. What drag means for orbits.** Holding a circular orbit at speed v costs a tangential thrust of Drag·v against drag, plus whatever radial thrust the field mismatch needs. At v = 6.3 (today's rail speed) that is 0.63 u/s² for a Longinus (2-6% of its range), 1.26 for a Djinni (14-37%); at v = 17.5 it is 1.75 (5-16%) and 3.5 (39-100%). No free orbit exists for any hull with Drag > 0; with honest wells a ship in orbit needs only the drag term, where today it also fights a radial mismatch of 17-30% of thrust (probe F2).
|
||||
- **B10. Tide under superposed 1/r tails** (computed, `hill.py`, over the probe's bodies). 2D tidal radius of a parent at R from its own parent: d_H = R·sqrt(c_p/(2c_g)). Fraction of the 17,864 children of non-root parents that orbit inside 0.5·d_H: 11% if c ∝ mass, 35% for m^0.5, 59% for m^0.25, 66% for m^0.175; children of planets 1%, 10%, 30%, 38%. Speeds: if a median sun's field is 0.5 u/s² at 610 u, v_circ = 17.5 u/s around it and 12.4 around a median planet (m^0.175).
|
||||
- **B11. The flow has curl.** `FlowField.Slope` (FlowField.cs:53-59) adds a swirl term, the downhill direction rotated 90 degrees, and `Global` is a noise field: neither is a gradient, so no height can show them as slopes. No ship reads `Zone.Flow`; it drives stardust and nebula (shader) and, by ruling, fauna.
|
||||
- **B12. A ruling in force contradicts the target.** `aetheria-release:ruling:one-gravity-law` (Defaulted, 2026-10-07) fixes the slope-squared law and "the feel ships have today". The target replaces both. Self supersedes it; this map does not.
|
||||
|
||||
## Model page
|
||||
|
||||
One row per kind this campaign touches. "Today" is c6519383; "target" is the shape under r2 with the recommended answers, marked where a question is open.
|
||||
|
||||
| kind | identity | lifecycle | authority (one owner per decision; forbidden writers) |
|
||||
|---|---|---|---|
|
||||
| **Zone potential** φ(p, t) | One per `Zone` instance, unnamed (a method, not a record). Not persisted: derived from the pack's bodies, orbits and PlanetSettings at zone time. Today it does not exist as such; GetHeight is a shaped heightfield (mass-neutral wells, probe Reading B). | Built when the zone is constructed; must be valid before the first Update (`zone-valid-before-tick`). Varies with body positions over zone time. No ripple term in flatspace (`flatspace-no-bowl-no-ripples`). Reference constant: zero at the root body's zone radius (proposal; log tails have no natural zero). | Owner: one ServerShared function (Zone's potential, likely a small pure module beside FlowField so shaders can lower it). Forbidden writers: `GravityAcceleration`'s slope-squared law and its gate, `GetNormal` as a force source, the zone bowl term, `RadialWaves`, any brush or shader that composes gravity on its own. |
|
||||
| **Force** a = -∇φ | Derived, never stored. | Per query. Analytic gradient (sum of per-well closed forms), not finite differences of the height. | Owner: the potential module. Every CPU force reader (B5) calls it: ships, floating bodies, clouds, mines. Forbidden: `Ship.Update`'s private normal-to-force path; the per-second `GravityReferenceRate` restatement (dies with the old law). |
|
||||
| **Body well parameters** (gravitational parameter c, softening radius R) | Derived per body from `BodyData.Mass` through PlanetSettings curves (today: `GravityDepth`, `GravityRadius`, `BodyRadius` × per-body multipliers). Names: per-body record key (`CultRecordRef<BodyData>`), injective. The JSON names of GasGiantData's wave fields collide with BodyData's (B7). | Computed once at Planet construction (`CalculateProperties`); never revised in play. Today's `GravityDepthExponent`, `GravityDepthMultiplier`, `GravityRadiusMultiplier` have no writer; the exponent dies under the target (no PowerPulse well); wave fields die in flatspace. | Owner of the curve: PlanetSettings in `Settings.asset` (open: well-strength-from-mass, softening-radius). Owner of the per-body value: `Planet` (or its successor) at construction. Forbidden writers: the brush material's `_Power 16` and `_Cutoff`, ZoneRenderer copying depth into materials, any shader constant. Cell not filled: whether per-body multipliers stay (no writer today; a pillar or authored body may want one). |
|
||||
| **Pillar** (Ink zones) | The zone's central body in a sun's role (`ink-pillars-are-suns`). Cell not filled: no record names a pillar today (no `Pillar` or `Adrasteia` anywhere under Assets/Scripts at c6519383); whether it becomes a `BodyData` kind is the Ink-zone work's decision. | Built with the zone like any body. | Owner: same law as a sun (`pillars-are-suns`); its strength comes from the same curve or an authored c. Pseudospace shenanigans are not in scope. |
|
||||
| **Orbit rail** (`OrbitData`: Distance, Phase, Parent, FixedPosition; runtime `Orbit`: Period, Position, PreviousPosition, Velocity) | `OrbitData` is a catalog/pack record keyed by `CultRecordKey`, parent by `CultRecordRef<OrbitData>`; root has no parent. Period is derived, not stored. | OrbitData created by ZoneGenerator or `Zone` (:596-611 back-solves phase); Period computed at `Orbit` construction; Position written by `GetOrbitPosition` each Update and float2.zero before the first (follow-up). Asteroids and belt targets recompute periods from the same curve (B6). | Today: `OrbitPeriod` curve owns period and ignores the field. Target (open: rails-vs-field, recommended field-owns-rails): period derived from the parent's c, T = 2πd/sqrt(c_parent), the same derivation for the four readers in B6. Forbidden writers then: `OrbitPeriod` as an independent authority, any per-reader period formula. Position placement moves to construction (`zone-valid-before-tick`). |
|
||||
| **Orbit placement** (child distances) | Generated `OrbitData.Distance` per body, authored ZoneGenerationSettings ranges. | Written once at generation; persisted in the zone pack. | Owner: ZoneGenerator. Open: moons-beyond-tidal-reach (whether the generator must keep children within their parent's tidal reach, which makes the generator read the strength curve). |
|
||||
| **Zone bowl** | PlanetSettings `ZoneDepth`, `ZoneDepthExponent`, `ZoneBoundaryFog`; scene `Boundary` brush. | Live today (B2). Target: gone from flatspace gravity. | Ruled (`grid-shows-how-you-move`, `flatspace-no-bowl-no-ripples`). Forbidden: the GetHeight term, ZoneRenderer's driving of the Boundary brush on a gravity layer, FlowFieldTests' use of the bowl as a slope source (tests need a well instead). Cell not filled: whether the zone needs a non-gravitational edge (nothing asked for one). |
|
||||
| **Ripples** (gas giant and sun waves) | PlanetSettings `WaveDepth`, `WaveRadius`, `WaveFrequency`, `WaveSpeed`; GasGiantData wave multipliers; Gravity Waves brush objects. | Live today (B2). Target: gone from flatspace. | Ruled. Forbidden: RadialWaves in the potential, the Gravity Waves objects on displacement layers. Pseudospace pulses (follow-up `pseudospace-flavours-campaign`) are a different kind, under the same grid invariant. |
|
||||
| **Exaggeration factor** K | Not present today (height is the only quantity). Target: one number, φ = K·h. | Authored; constant in play. | Open: exaggeration-scope (recommended one global value in PlanetSettings). Owner: PlanetSettings. Forbidden: per-class or per-material depth scales, ZoneRenderer's `_StartDepth/_DepthRange` as an independent mapping of depth (it may normalise the minimap, but from h, not from brush depths). |
|
||||
| **Drawn grid height** (`_NebulaSurfaceHeight` and the other displacement targets) | Render textures named in B3; global shader names. | Rendered every frame from brush quads. | Today: the brushes own it, independently of the sim (B3), which is the defect this campaign kills. Target: lowered from the sim's potential (h = φ/K), whether by an analytic shader function fed body parameters (as `FlowField` is lowered) or by brushes whose shapes are generated from the same law; the one owner is the ServerShared potential and the shader is a lowering with a parity check (as `FlowFieldParityVerify` does for flow). Forbidden: material constants (`_Power`, `_Cutoff`, `_Depth`), smoothstep rim fades, the wormhole and station gravity wells, and any brush on a gravity layer with no sim term. Open: grid-presentation-noise (what becomes of the Sector Waves noise and the liquid-grid detail). |
|
||||
| **Readers that place things at the height** (B5) | Call sites. | Every frame. | Readers only. They read h = φ/K + GridOffset. No change of owner; listed so a cut finds them all. |
|
||||
| **Flow** (FlowField) | PlanetSettings `Flow`; `Zone.Flow`; shader `globalFlow`/`slopeFlow`. | Zone time. | Owner: FlowField in ServerShared (`sim-knows-the-flow`). Its slope term must read the potential's gradient, not GetNormal of a separate heightfield. Open: flow-moves-ships (B11). |
|
||||
| **Ship motion under gravity** | `Ship.Update`. | Per tick: drag, then position, then gravity. | Reader of the force. Hull Drag owns damping (B8, B9). Forbidden: any gravity computation local to Ship. |
|
||||
|
||||
Cells not filled, plainly: whether per-body well multipliers survive (no writer today, no consumer asked); what record names an Ink pillar; whether the PlanetOutpost prefab's drawn well is ever instantiated; whether the zone needs a non-gravitational edge once the bowl is gone; real generated loadout masses (B8 is a bound, not a measurement).
|
||||
|
||||
## Rationale
|
||||
|
||||
- Why the drawn grid is a lowering, not an owner: `grid-shows-how-you-move` makes the slope a promise about motion. Six brush kinds on the gravity layers have no sim term or a different envelope (B3), so today the grid shows motion that does not happen (sector noise, wormholes, rim fades) and hides motion that does (the bowl in small zones is drawn at the same depth everywhere while felt only under the gate).
|
||||
- Why rails follow the field: every shipped game where ships feel gravity derives the rails from the same parameter (KSP) or simulates bodies (Outer Wilds); authored rails coexist only with no felt gravity (Elite, Starsector). See the prior-art doc, section 3.
|
||||
- Why strength, softening and tide are separate questions: a·r = v² ties felt strength to body speed (field-strength); c(mass) sets both readability and how many moons a ship can follow (well-strength-from-mass, B10); R sets the peak (softening-radius). Any two can be ruled without the third.
|
||||
- A constraint for pseudospace, not solved here: a push with curl (B11) has no height, so under `grid-shows-how-you-move` it either never moves ships, or is drawn by another channel, or is restricted to its gradient part.
|
||||
|
||||
## Cut sequence
|
||||
|
||||
Not yet written. Waits on the step-0b questions.
|
||||
70
docs/research/2026-10-14-gravity-prior-art.md
Normal file
70
docs/research/2026-10-14-gravity-prior-art.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<!-- Prior art for campaign aetheria-gravity, step 0b. Serves questions: aetheria-gravity:question:rails-vs-field, :well-strength-from-mass, :field-strength, :moons-beyond-tidal-reach, :softening-radius, :exaggeration-scope, :grid-presentation-noise, :flow-moves-ships. Imagination imagination-ag2-gravity-0b, session self-2026-10-14-ag2, at master c6519383. -->
|
||||
# Gravity prior art: 2D log wells, softening, and how games reconcile rails with felt gravity
|
||||
|
||||
A short pass, not a survey. Each section ends with what it advises for an Aetheria fork. Numbers marked "computed" come from scripts over the orbit probe's 31,640 generated bodies (`docs/research/2026-10-13-orbit-probe/data/bodies.csv`); the scripts are in the Imagination scratchpad and are restated in the map's body facts.
|
||||
|
||||
## 1. The physics: a point mass in a plane
|
||||
|
||||
- In two dimensions Gauss's law gives a = 2GM(<r)/r, the potential of a point mass is logarithmic, and circular speed v = sqrt(2GM) is the same at every radius (a flat rotation curve). Binney and Tremaine, *Galactic Dynamics*, treat the logarithmic potential and the Mestel disc as the standard flat-rotation-curve models. Today's OrbitPeriod rail (T = d, v = 2π for every body) is already this law, with one gravitational parameter c = v² = 4π² shared by every body regardless of mass (probe, "Point mass, disc").
|
||||
- Consequence that matters for design: a·r = v². In an honest field you cannot have strong felt gravity at an orbit and slow bodies on that orbit. At r = 610 (a median planet around a median sun), a = 5 u/s² (today's peak) means v = 55 u/s, T = 69 s; a = 0.5 means v = 17.5 u/s, T = 219 s; the rail's a = 0.065 means v = 6.3 u/s, T = 610 s (computed).
|
||||
- Log tails never end. Superposed, every body's tail reaches the whole zone, so the potential has no natural zero: a reference constant must be chosen (the map proposes zero at the zone's radius from the root body).
|
||||
- The rubber-sheet picture is this physics, not only a metaphor. A tensioned membrane under a point load deflects logarithmically (Laplace's equation in 2D), and marble orbits on it follow a Kepler-like law in the small-slope regime (White and Walker, AJP 2002; Middleton and Langston, [Circular orbits on a warped spandex fabric](https://arxiv.org/pdf/1312.3893), AJP 2014; [elliptical-like orbits](https://arxiv.org/pdf/1601.03996)). The fabric's own mass dominates for small central loads, which is today's zone bowl in physical form.
|
||||
|
||||
Advises: the target's "height = potential × exaggeration" is the established picture; the drawn grid is an embedding of φ, and its readability is set by the log, not by the factor (section 5).
|
||||
|
||||
## 2. Softening
|
||||
|
||||
- Plummer softening replaces 1/r with 1/sqrt(r² + ε²); in 2D the analogue is φ = GM ln(r² + ε²), force 2GM r/(r² + ε²): linear near the centre, approaching 2GM/r only for r ≫ ε (at r = ε it is half the point-mass value). It biases the field at all radii near ε ([Rodionov and Sotnikova 2005](https://arxiv.org/pdf/astro-ph/0504573); [Dehnen 2001](https://arxiv.org/abs/astro-ph/0011568)).
|
||||
- Dehnen found compact kernels (a density of finite extent, exactly Newtonian outside it) give about half the force error of Plummer at equal cost. The 2D compact kernel that matches the target's wording is the uniform disc: force 2GM r/R² inside, 2GM/r outside, potential quadratic inside and logarithmic outside, continuous in value and gradient at R (the force itself has a kink at R, which is harmless for integration at game time steps).
|
||||
- The softening length is the playability radius: it sets the peak force, c/R. Today's wells peak at the slope-peak radius (0.18 of the support radius: planetoid 104, planet 183, gas giant 310, sun 490), not at the body radius (7 to 33).
|
||||
|
||||
Advises: use the uniform-disc (compact) core, not Plummer, so the tail is exactly the point mass the target names; choose R as its own authored quantity (question softening-radius).
|
||||
|
||||
## 3. Rails versus felt gravity in games
|
||||
|
||||
| game | bodies move by | ships feel | reconciled how |
|
||||
|---|---|---|---|
|
||||
| Kerbal Space Program | Kepler rails (closed-form conics) | the same μ as the rails, one body at a time (patched conics, spheres of influence) | rails and ship physics share each body's μ; moons do not perturb a vessel in its parent's SOI ([KSP PatchedConics API](https://kerbalspaceprogram.com/ksp/api/class_patched_conics.html); [forum explainer](https://forum.kerbalspaceprogram.com/topic/124639-what-are-patched-conics)) |
|
||||
| Outer Wilds | real-time simulation, no rails ([Reverse Shot](https://reverseshot.org/features/2984/outer_wilds)) | the same field | exaggerated gravity, swift orbits; inverse square kept only for the sun, planets fall off more linearly because inverse square made escape too easy on island-sized planets ([PC Gamer](https://pcgamer.com/how-to-build-a-black-hole); [Vice](https://vice.com/en/article/how-outer-wilds-developers-mobius-digital-made-space-physics-fun)) |
|
||||
| Elite Dangerous | rails, no perturbations ([Frontier forum](https://forums.frontier.co.uk/threads/are-the-orbits-of-the-planets-physically-correct.394502/post-6203566)) | no gravitational force; supercruise speed is capped near mass | the conflict is avoided by not having felt gravity at all |
|
||||
| Starsector, most 2D space ARPGs | campaign-map rails | nothing | same as Elite |
|
||||
| Spacewar! (1962) | one fixed star | the star | no rails to reconcile |
|
||||
|
||||
Pattern: every game where ships feel gravity derives the rails from the same parameter the ship feels (KSP) or drops rails entirely (Outer Wilds). The only games with authored rails that disagree with the field are the ones where ships feel no field. Aetheria today is the one combination nobody ships: authored rails and a felt field 20 to 70 times stronger.
|
||||
|
||||
Outer Wilds is also the precedent for a non-physical falloff chosen for feel (planets ~linear). The target has already chosen 1/r (the 2D point mass), which is the stable, honest choice; the feel lever left is strength, not exponent.
|
||||
|
||||
Advises: rails-vs-field recommends field-owns-rails (KSP's arrangement): Orbit.Period is derived from the parent's gravitational parameter.
|
||||
|
||||
## 4. Hierarchy: moons inside a parent that is inside a sun's field
|
||||
|
||||
- KSP resolves hierarchy by truncation: inside a sphere of influence only that body pulls. That is exactly the rim the target abolishes (point-mass-tail, wells-superpose), so it is prior art for what we are not doing.
|
||||
- With superposed 1/r tails the sun's tide is strong, because its force falls only as 1/r. For a parent at R from its own parent, the 2D tidal (Jacobi-like) radius is d_H = R·sqrt(c_p / (2 c_g)) (rotating frame, flat rotation curve; derived the same way as Binney and Tremaine's Jacobi radius). Computed over the generated bodies, the fraction of children of non-root parents inside 0.5·d_H (where a prograde orbit is reliably bound) is: 11% if c ∝ mass, 35% for c ∝ m^0.5, 59% for m^0.25, 66% for m^0.175 (today's depth curve exponent). For children of planets it is 1%, 10%, 30% and 38%.
|
||||
- So under an honest superposed field, most moons orbit where a ship could not follow them. Rails keep the bodies moving regardless; a ship's free trajectory near a moon would be torn toward the sun.
|
||||
|
||||
Advises: questions well-strength-from-mass and moons-beyond-tidal-reach; recommended fix is to place children within reach at generation, with a compressed mass-to-strength curve.
|
||||
|
||||
## 5. Exaggeration and readability under a log
|
||||
|
||||
- Drawn depth of one well between radius R and distance D is (c/K)·ln(D/R), K being the exaggeration (u/s² per unit height). The ratio of a sun's well to a planetoid's at the same log span is c_sun/c_planetoid: 488 if c ∝ mass, 22 for m^0.5, 4.7 for m^0.25, 2.95 for m^0.175 (median masses 14152 and 29). The factor K scales every well together and cannot change that ratio.
|
||||
- Per-class factors would draw slopes that do not match the force, which breaks grid-shows-how-you-move. Data visualisation's usual move for wide dynamic range is a compressing transform (log scale); here the compression already lives in the physics if the strength curve is compressed, so the drawing can stay linear in φ.
|
||||
|
||||
Advises: exaggeration-scope recommends one global K; readability is decided by the strength curve (well-strength-from-mass).
|
||||
|
||||
## 6. Fields with curl cannot be drawn as slopes
|
||||
|
||||
- Helmholtz: a 2D vector field splits into a gradient part (which has a height) and a divergence-free rotational part (which has none), plus a harmonic remainder. A velocity-dependent push (drag toward a moving medium, a = -k(v - u)) is not a gradient of anything either.
|
||||
- Today's flow (`FlowField`: globalFlow noise plus slopeFlow swirl and slide) has a rotational part by construction (the swirl term is the gradient rotated 90 degrees). It moves stardust and nebula, and by `aetheria-fauna:ruling:sim-knows-the-flow` fauna; it does not move ships (no ship reads `Zone.Flow`).
|
||||
|
||||
Advises: flow-moves-ships recommends that in flatspace ships feel only the potential, so the grid can show everything that moves them; a pseudospace push with curl needs a second visual channel (stardust streaks already draw the flow) or must be restricted to its gradient part. Recorded as a constraint for pseudospace work, not solved here.
|
||||
|
||||
## Sources
|
||||
|
||||
- [Circular orbits on a warped spandex fabric (Middleton and Langston)](https://arxiv.org/pdf/1312.3893)
|
||||
- [Elliptical-like orbits on a warped spandex fabric](https://arxiv.org/pdf/1601.03996)
|
||||
- [Optimal choice of the softening length and time-step in N-body simulations (Rodionov and Sotnikova)](https://arxiv.org/pdf/astro-ph/0504573)
|
||||
- [Towards optimal softening in 3D N-body codes (Dehnen 2001)](https://arxiv.org/abs/astro-ph/0011568)
|
||||
- [KSP PatchedConics API](https://kerbalspaceprogram.com/ksp/api/class_patched_conics.html), [What are patched conics (KSP forum)](https://forum.kerbalspaceprogram.com/topic/124639-what-are-patched-conics)
|
||||
- [Recreating gravity in games is harder than you'd think (PC Gamer)](https://pcgamer.com/how-to-build-a-black-hole), [How Mobius made space physics fun (Vice)](https://vice.com/en/article/how-outer-wilds-developers-mobius-digital-made-space-physics-fun), [Reverse Shot on Outer Wilds](https://reverseshot.org/features/2984/outer_wilds), [An astrophysicist measures Outer Wilds](https://thephysicsmill.com/2024/09/20/an-astrophysicist-attempts-to-measure-the-physics-of-outer-wilds/)
|
||||
- [Are the orbits of the planets physically correct? (Frontier forum)](https://forums.frontier.co.uk/threads/are-the-orbits-of-the-planets-physically-correct.394502/post-6203566), [Elite Dangerous wiki](https://elite-dangerous.fandom.com/wiki/Anti_gravity)
|
||||
- Binney and Tremaine, *Galactic Dynamics* (2nd ed., 2008): logarithmic potential, Mestel disc, Jacobi radius. White and Walker, "The shape of 'the Spandex' and orbits upon its surface", Am. J. Phys. 70, 48 (2002), cited via Middleton and Langston.
|
||||
Loading…
Reference in a new issue