Draw the stars around wherever the view is, not only around the Sun
The star field draws a budget of the catalogue: everything within 25 pc of the Sun, then the brightest of the rest. That choice was made once, at load, around the Sun, and never again. On the Gaia catalogue it left most of the map empty wherever the view went: - a region 150 pc out drew 49 of the 442 stars within 25 pc of it; - a plotted route ran through stars no one could see or click. Sol to Almach at 8 pc passes 19 stars and drew 6, Sol to Mirfak 11 of 26; - a search for a faint star flew the camera to an empty point. The drawn set now follows the view. The scene chooses it again at the label cadence, once the orbit target has moved more than 5 pc or the pinned stars have changed. The budget goes, in order, to the selected star and the stars of a plotted route, then everything within 25 pc of where the view is centred, then the same around the Sun, then the brightest of the rest. The instance buffers hold the budget and are rewritten in place. Checked in Chromium on WebGPU, framing Mirfak from 12 pc: with the set chosen around the Sun, 122 of the 649 stars within 25 pc were drawn; following the view, all 649. At the opening view the drawn set is the same as before. A refocus takes 9 ms in the browser (5 ms of it choosing). The first version took 16-36 ms in the browser, a visible hitch during a flight. Most of that time went on walking the 423 651-star brightness order once per neighbourhood, out of catalogue order, and on recomputing 70 000 colours. Now both neighbourhoods are gathered in one pass in catalogue order and sorted on their own, and colours and sizes are computed once for the whole catalogue. The brightness order itself sorts a typed copy of the magnitudes, taking 83 ms at load instead of 104-139 ms. STAR_RENDER_BUDGET is now 70 000, and its comment gives the measurements behind it rather than "currently set to the whole catalogue", which stopped being true when Gaia landed. At 1920 x 1080 on a Ryzen 7700X: - on the RTX 4080, the whole catalogue costs the same 6.1 ms a frame as the budget; - on the processor's two-core Radeon, standing in for an entry-level laptop, every 100 000 stars costs about 4 ms: 112 fps at the budget, 44 at the whole catalogue, and the same under WebGL2; - drawn whole, the opening view turns into a grey wash that buries the labels and the host rings. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jxMkwA2rbicdGxHosecYi
This commit is contained in:
@@ -11,6 +11,7 @@ import { ExoplanetRecord } from '../../shared/models/exoplanet.model';
|
||||
import { StarRecord } from '../../shared/models/star.model';
|
||||
import { NavigationStore } from '../../shared/state/navigation.store';
|
||||
import { GalaxySystemSceneComponent } from './galaxy-system-scene.component';
|
||||
import { StarFieldRenderer } from './star-field-renderer';
|
||||
|
||||
// jsdom does not implement ResizeObserver; the component only uses it to react to real
|
||||
// layout changes, which never happen in this headless test.
|
||||
@@ -211,6 +212,33 @@ describe('GalaxySystemSceneComponent camera-flight transitions', () => {
|
||||
expect(navigationStore.viewLevel()).toBe('galaxy');
|
||||
});
|
||||
|
||||
it('chooses the drawn stars again once the view centre has moved, and not for a small drift', async () => {
|
||||
const component = fixture.componentInstance as unknown as { controls: { target: THREE.Vector3 } };
|
||||
const refocus = vi.spyOn(StarFieldRenderer.prototype, 'refocus');
|
||||
|
||||
component.controls.target.set(40, 0, 0);
|
||||
await advanceFrames(engine, 0.3);
|
||||
expect(refocus).toHaveBeenCalledTimes(1);
|
||||
expect(refocus.mock.calls[0][0].centre).toMatchObject({ x: 40, y: 0, z: 0 });
|
||||
|
||||
component.controls.target.set(42, 0, 0);
|
||||
await advanceFrames(engine, 0.3);
|
||||
expect(refocus).toHaveBeenCalledTimes(1);
|
||||
refocus.mockRestore();
|
||||
});
|
||||
|
||||
it('keeps the stars of a plotted route drawn, and the selected star', async () => {
|
||||
const component = fixture.componentInstance as unknown as { routeResult: { set(value: unknown): void } };
|
||||
const refocus = vi.spyOn(StarFieldRenderer.prototype, 'refocus');
|
||||
await advanceFrames(engine, 0.3);
|
||||
|
||||
component.routeResult.set({ stars: [{ id: SUN.id, name: 'Sol' }, { id: PROXIMA.id, name: 'Proxima Centauri' }], totalPc: 1.3, neededRangePc: null });
|
||||
await advanceFrames(engine, 0.3);
|
||||
|
||||
expect(refocus.mock.calls.at(-1)![0].pinnedIds).toEqual([SUN.id, PROXIMA.id]);
|
||||
refocus.mockRestore();
|
||||
});
|
||||
|
||||
it('flies the camera into a selected star system: hides the galaxy group, shows the system group, and switches to AU-scale near/far planes', async () => {
|
||||
navigationStore.selectStar(SUN.id);
|
||||
await flushAsync();
|
||||
|
||||
Reference in New Issue
Block a user