Deep sky, jets and outflow, curvature grid, and a tidal stream that actually streams - #1
Merged
Merged
Conversation
The disruption never produced the wound ribbon a real event makes: the debris scattered, dived into the hole, and was gone within seconds. Four separate causes, each found by probing the simulation rather than the render. - The realistic plunge ran with the cinematic spiral's drag. A zero-energy parabolic orbit that bleeds velocity on the way in is no longer parabolic; its pericenter collapsed into the hole and took the stream with it. Drag is now per-body and exactly zero in realistic mode. - Debris copied the body's velocity vector. A particle offset a body-length inward along the strand got the same speed with far less angular momentum, so the inner half of every stream plunged. Debris is now launched onto the body's orbit at its own radius: same energy, same angular momentum, tangential speed L/r and the rest radial. - The tidal energy spread was applied along the direction of motion, which strips angular momentum too. It is now radial, which changes the specific energy while leaving L alone, so the bound half keeps the star's pericenter and swings back out. The bound/unbound split lands near the 50/50 real disruptions show, read back out of the energy. - Material was absorbed the first time it crossed the inner edge. A fresh stream is violently eccentric and whips through pericenter; it now has to circularize first, tested by speed against the local circular value. Radial velocity is the wrong test: it passes through zero at every pericenter no matter how eccentric the orbit is. Also: mass loss now begins while the body is merely stretching, at a small absolute rate that ramps with depth, so a still-intact star is connected to the hole by a thin leader before it comes apart. The rate is absolute rather than a fraction of the shedding rate, because realistic mode sheds at 0.9/s against cinematic's 0.08 and a fixed fraction stripped the star before it reached the shedding radius. The disruption and its debris now run on a compressed clock, the same trick the binary inspiral already used, because an orbit at 12 r_s takes ~370 time units and at 1:1 the debris never completes a lap. Unlike the binary's closed-form advance this one is numerical, so stepWorld walks it in substeps of at most 0.1 time units; a test asserts the body lands in the same place at x1 over 1200 ticks as at x20 over 60. New tests cover the stream's shape (survives first pericenter, spreads over a wide radial range, wraps past 90 degrees, still feeding hundreds of seconds later), the compressed clock, and the gravitational-wave state extracted from main.ts into its own pure module. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The background was three thin layers of grey dots. It is now a procedural deep field baked once into an HDR cubemap and lensed by the same geodesics as everything else: five star layers on a stellar-temperature sequence with a luminosity function skewed to faint stars, diffraction spikes on the bright ones, a warped galactic band whose dust lanes extinguish what lies behind them, emission nebulae in hydrogen red and oxygen teal, globular clusters that crowd stars into their cores, and sixteen galaxies with bulges, arms and dust lanes. Every noise lookup is rotated off the cubic lattice, because a cubemap face is axis-aligned with it and the lattice otherwise shows through as angular patches in the sky. New in the raymarch, all integrated inside the geodesic march so they bend with the light: - A relativistic jet with braided filaments. The brightness difference between the two cones is the real optically-thin Doppler boost, delta^3. - A super-Eddington outflow, wide and ragged and un-collimated, whose strength is driven by the disc's feed rate so it swells during fallback and dies with it. - The shredded body is now a teardrop rather than an ellipsoid, a bright head with a thin tail. That is not a quadric, so the bounding ellipsoid is solved analytically and the teardrop field is marched inside it. Its corona uses the same field, so it tapers along the tail. Flamm's paraboloid is drawn as a wireframe funnel (G), with the binary's quadrupole gravitational wave rippling outward across it: two crests per orbit wound into a trailing spiral, amplitude growing as 1/a and falling as 1/r. All of it is placed by the vertex shader, so an inspiral costs nothing on the CPU. Bloom fixes, both visible as artifacts: - The dual-filter kernel is a diamond, and with four levels its widest tail was still bright enough after tonemapping that the diamond's isoline drew straight-edged black polygons wherever a very bright region bordered a black one, most obviously around the shadow itself. Six levels now, and the upsample blends instead of summing so the extra levels do not multiply the total energy and wash the frame out. - The prefilter clamps its input. A beamed disc sample reaches a few thousand, which overflows a half-float target to Inf on the way down the chain, and Inf spread by the tent upsample becomes NaN, which the tonemap renders as flat black. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The panel was a flat list of folders with bare labels. It now follows the order someone actually uses: presets, then put something in the scene, then time, then everything else collapsed. Every control carries a hover description of what it does and what it will not do, each folder has a reset button, and there is a global one. - Six one-click scenes (a star devoured, spaghettification, a binary merger with waves, bare curved spacetime, a jetted quasar, a wallpaper frame). Presets are plain data; anything a preset does not mention is left as the user had it. - Cinematic mode (H) fades the panel and readout for a clean frame, with a toast saying how to get them back. G toggles the curvature grid. - The disruption clock is exposed as "Disruption speed", and the inspiral slider now says plainly that it does nothing without a second hole and that a wide pair barely moves at any setting, because the separation decays as 1/a^3. Fixes a frame-time bug that could freeze the simulation outright: the first frame's timestamp can predate the startup sky bake on a slow GPU, and that negative dt drove the fixed-step accumulator tens of seconds into debt, after which nothing moved until it climbed back out. The frame delta is now clamped at both ends. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two captures from the app, and a physics section covering what was added: the tidal-stream mechanics and why each decision is what it is, the optically-thin Doppler boost behind the jet's asymmetry, Flamm's paraboloid and the quadrupole ripple on it, the two compressed clocks and which one is exact, and the structure the procedural sky is modelled on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The spawn rate duplicated the phase rule that stepBody already owns, and the two had already drifted: mass loss carried massLossRate's radial ramp and the particle count did not, so particles-per-shed-mass was not constant and the disc-feed normalisation drifted with it. stepBody now returns the mass it shed and world.ts spawns strictly in proportion to it, so the rule exists once. shedRateFraction replaces spillFraction and covers every phase. The orbit reconstruction inside spawnFromBody is now sim/orbit.ts, with tests asserting the property the whole stream depends on: a particle launched onto the body's orbit at a different radius carries the same specific energy and angular momentum, so it keeps the body's pericenter. That was previously only visible in the emergent shape. Honesty fixes to the knobs and the panel: - TDE_TUNING.boundDrag was documented as bound-debris drag and read by nothing. Removed. - starTidalRadius and planetTidalRadius are assigned to rShed, with the actual tidal radius appearing only as a bare 1.5 multiplier in placeBody. Renamed to starShedRadius and planetShedRadius with stretchRadiusFactor named alongside them. - Four debug sliders (tidal radius, shed radius, body drag, mass-loss rate) are snapshotted into the Body when it is placed, so moving them changed nothing on screen, and the tidal-radius slider's range excluded its own shipped value. Dropped; the folder now holds only knobs read live. - Preset.look was typed as any Settings key, but applyPreset only re-fires side effects for sky and photon paths, so a preset setting quality or volume would silently do nothing. Narrowed to the keys the frame loop reads every frame. - Both clocks now default from config, and settings no longer hardcodes a number config already owns. The world tests state their clocks explicitly rather than inheriting a default that would multiply every duration they assert. - The auto-degrade note sat in the readout for the rest of the session. Substeps are capped at six. updatePool walks every live particle, so at the compression slider's maximum an uncapped count swept 48k particles ten times per frame. In the shaders: the three emission scales that decide whether a frame is fog or empty are named next to the geometry constants, the jet and wind reaches are clamped to the escape sphere (past a merger uRs grows and the tip fell outside the marched volume), and the teardrop's two ends had picked up opposite names in adjacent comments. Also repairs three comments left ungrammatical by the em-dash removal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Five commits. The headline is that the tidal disruption never produced the
wound ribbon a real event makes, and fixing that turned up three separate
bugs that were each independently fatal to it.
What changed
The tidal stream. Debris scattered, dived into the hole, and was gone
within seconds. Four causes, each found by probing the simulation rather
than staring at the render:
parabolic orbit that bleeds velocity on the way in is no longer parabolic;
its pericenter collapsed into the hole. Drag is now per-body and exactly
zero in realistic mode.
body-length inward got the same speed with far less angular momentum.
It is now launched onto the body's orbit at its own radius.
strips angular momentum too. Radial now, which changes energy and leaves
L alone.
to circularize first, tested by speed against the local circular value,
because radial velocity passes through zero at every pericenter no matter
how eccentric the orbit is.
Rendering. A procedural deep sky (five star layers on a stellar
temperature sequence, dust that extinguishes what is behind it, emission
nebulae, clusters, sixteen galaxies), a relativistic jet with real delta^3
Doppler beaming between its cones, a super-Eddington outflow driven by the
disc's feed rate, and the disrupted body drawn as a teardrop rather than an
ellipsoid.
Spacetime. Flamm's paraboloid as a wireframe funnel (
G), with thebinary's quadrupole gravitational wave rippling outward across it.
Interface. Six one-click presets, a cinematic mode (
H), tooltips onevery control, per-folder resets, and folders ordered the way the app is
actually used.
Bugs fixed that predate this work
diamond, and at four levels its widest tail was still bright enough after
tonemapping that the diamond's isoline drew straight edges wherever a very
bright region bordered a black one. Six levels now, blending instead of
summing on the way up.
thousand, which overflows to Inf down the bloom chain; Inf spread by the
tent upsample becomes NaN, which the tonemap renders as flat black. The
prefilter clamps.
timestamp predates the startup sky bake, and that negative dt drove the
fixed-step accumulator tens of seconds into debt.
Verification
tsc --noEmitclean, 51 tests passing (was 36). The new ones test propertiesrather than implementation: the stream survives its first pericenter and
wraps past 90 degrees, a compressed disruption clock lands the body in the
same place as an uncompressed one, debris launched onto an orbit carries the
same energy and angular momentum, and the quadrupole wave grows as 1/a and
decays after the merger.
Two beauty reviews were run against this branch and their findings are
folded in, including one real defect: the particle spawn rate had a second
copy of the phase rule that
stepBodyalready owned, and the two had drifted.🤖 Generated with Claude Code