feat: 3 scene rendering setup

This commit is contained in:
2026-03-18 08:49:51 -04:00
parent 933c6afd08
commit 358122a74a
33 changed files with 1094 additions and 1132 deletions

View File

@@ -3,6 +3,7 @@ import {
determineActiveSystemId,
focusOnSelection,
getCameraFocusWorldPosition,
getSystemCameraFocus,
resolveSelectionPosition,
seedSystemFocusLocal,
toDisplayLocalPosition,
@@ -10,9 +11,8 @@ import {
import {
syncFollowStateFromSelection,
updateFollowCamera,
updateSystemDetailVisibility,
} from "./viewerControls";
import { computeNodeLocalPosition, resolveBubblePosition, resolvePointPosition } from "./viewerWorldPresentation";
import { computeNodeLocalPosition, resolvePointPosition } from "./viewerWorldPresentation";
import { getAnimatedShipLocalPosition, resolveShipHeading } from "./viewerPresentation";
import type {
CameraMode,
@@ -22,7 +22,7 @@ import type {
ShipVisual,
SystemVisual,
WorldState,
ZoomLevel,
PovLevel,
} from "./viewerTypes";
export interface ViewerNavigationContext {
@@ -30,17 +30,19 @@ export interface ViewerNavigationContext {
getWorldTimeSyncMs: () => number;
getActiveSystemId: () => string | undefined;
setActiveSystemId: (value: string | undefined) => void;
onActiveSystemChanged: (oldId: string | undefined, newId: string | undefined) => void;
getCameraMode: () => CameraMode;
setCameraMode: (value: CameraMode) => void;
getCameraTargetShipId: () => string | undefined;
setCameraTargetShipId: (value: string | undefined) => void;
getCurrentDistance: () => number;
getZoomLevel: () => ZoomLevel;
getPovLevel: () => PovLevel;
getSelectedItems: () => Selectable[];
getOrbitYaw: () => number;
galaxyFocus: THREE.Vector3;
systemFocusLocal: THREE.Vector3;
camera: THREE.PerspectiveCamera;
galaxyAnchor: THREE.Vector3;
systemAnchor: THREE.Vector3;
galaxyCamera: THREE.PerspectiveCamera;
systemCamera: THREE.PerspectiveCamera;
shipVisuals: Map<string, ShipVisual>;
nodeVisuals: Map<string, NodeVisual>;
planetVisuals: PlanetVisual[];
@@ -66,14 +68,10 @@ export class ViewerNavigationController {
nodeVisuals: this.context.nodeVisuals,
planetVisuals: this.context.planetVisuals,
computeNodeLocalPosition: (node, timeSeconds) => computeNodeLocalPosition(this.context.createWorldPresentationContext(), node, timeSeconds),
resolveBubblePosition: (bubbleId) => {
const bubble = this.context.getWorld()?.localBubbles.get(bubbleId);
return bubble ? resolveBubblePosition(this.context.createWorldPresentationContext(), bubble) : undefined;
},
resolvePointPosition: (systemId, nodeId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemId, nodeId),
resolvePointPosition: (systemId, celestialId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemId, celestialId),
activeSystemId: this.context.getActiveSystemId(),
galaxyFocus: this.context.galaxyFocus,
systemFocusLocal: this.context.systemFocusLocal,
galaxyAnchor: this.context.galaxyAnchor,
systemAnchor: this.context.systemAnchor,
});
}
@@ -85,11 +83,7 @@ export class ViewerNavigationController {
nodeVisuals: this.context.nodeVisuals,
planetVisuals: this.context.planetVisuals,
computeNodeLocalPosition: (node, timeSeconds) => computeNodeLocalPosition(this.context.createWorldPresentationContext(), node, timeSeconds),
resolveBubblePosition: (bubbleId) => {
const bubble = this.context.getWorld()?.localBubbles.get(bubbleId);
return bubble ? resolveBubblePosition(this.context.createWorldPresentationContext(), bubble) : undefined;
},
resolvePointPosition: (systemId, nodeId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemId, nodeId),
resolvePointPosition: (systemId, celestialId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemId, celestialId),
});
}
@@ -100,9 +94,10 @@ export class ViewerNavigationController {
cameraTargetShipId: this.context.getCameraTargetShipId(),
currentDistance: this.context.getCurrentDistance(),
selectedItems: this.context.getSelectedItems(),
galaxyFocus: this.context.galaxyFocus,
galaxyAnchor: this.context.galaxyAnchor,
});
if (nextActiveSystemId === this.context.getActiveSystemId()) {
const previousSystemId = this.context.getActiveSystemId();
if (nextActiveSystemId === previousSystemId) {
return;
}
@@ -111,7 +106,7 @@ export class ViewerNavigationController {
}
this.context.setActiveSystemId(nextActiveSystemId);
this.updateSystemDetailVisibility();
this.context.onActiveSystemChanged(previousSystemId, nextActiveSystemId);
this.context.updatePanels();
this.context.updateGamePanel("Live");
}
@@ -123,16 +118,16 @@ export class ViewerNavigationController {
cameraTargetShipId: this.context.getCameraTargetShipId(),
shipVisuals: this.context.shipVisuals,
currentDistance: this.context.getCurrentDistance(),
camera: this.context.camera,
camera: this.context.systemCamera,
followCameraPosition: this.context.followCameraPosition,
followCameraFocus: this.context.followCameraFocus,
followCameraDirection: this.context.followCameraDirection,
followCameraDesiredDirection: this.context.followCameraDesiredDirection,
followCameraOffset: this.context.followCameraOffset,
systemFocusLocal: this.context.systemFocusLocal,
systemAnchor: this.context.systemAnchor,
delta,
getAnimatedShipLocalPosition,
toDisplayLocalPosition: (localPosition, systemId) => this.toDisplayLocalPosition(localPosition, systemId),
toDisplayLocalPosition: (localPosition) => toDisplayLocalPosition(localPosition),
resolveShipHeading: (visual, worldPosition) => resolveShipHeading(visual, worldPosition, this.context.getOrbitYaw()),
});
this.context.setCameraMode(nextState.cameraMode);
@@ -150,19 +145,16 @@ export class ViewerNavigationController {
this.context.setCameraTargetShipId(nextState.cameraTargetShipId);
}
updateSystemDetailVisibility() {
updateSystemDetailVisibility(this.context.systemVisuals, this.context.getActiveSystemId(), this.context.getZoomLevel());
}
getCameraFocusWorldPosition() {
return getCameraFocusWorldPosition({
world: this.context.getWorld(),
activeSystemId: this.context.getActiveSystemId(),
galaxyFocus: this.context.galaxyFocus,
systemFocusLocal: this.context.systemFocusLocal,
galaxyAnchor: this.context.galaxyAnchor,
});
}
getSystemCameraFocus() {
return getSystemCameraFocus(this.context.systemAnchor);
}
seedSystemFocusLocal(systemId: string) {
seedSystemFocusLocal({
world: this.context.getWorld(),
@@ -170,26 +162,21 @@ export class ViewerNavigationController {
cameraMode: this.context.getCameraMode(),
cameraTargetShipId: this.context.getCameraTargetShipId(),
selectedItems: this.context.getSelectedItems(),
systemFocusLocal: this.context.systemFocusLocal,
systemAnchor: this.context.systemAnchor,
worldTimeSyncMs: this.context.getWorldTimeSyncMs(),
nodeVisuals: this.context.nodeVisuals,
planetVisuals: this.context.planetVisuals,
computeNodeLocalPosition: (node, timeSeconds) => computeNodeLocalPosition(this.context.createWorldPresentationContext(), node, timeSeconds),
resolveBubblePosition: (bubbleId) => {
const bubble = this.context.getWorld()?.localBubbles.get(bubbleId);
return bubble ? resolveBubblePosition(this.context.createWorldPresentationContext(), bubble) : undefined;
},
resolvePointPosition: (systemIdValue, nodeId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemIdValue, nodeId),
resolvePointPosition: (systemIdValue, celestialId) => resolvePointPosition(this.context.createWorldPresentationContext(), systemIdValue, celestialId),
});
}
toDisplayLocalPosition(localPosition: THREE.Vector3, systemId?: string) {
return toDisplayLocalPosition({
world: this.context.getWorld(),
systemId,
activeSystemId: this.context.getActiveSystemId(),
localPosition,
systemFocusLocal: this.context.systemFocusLocal,
});
toDisplayLocalPosition(localPosition: THREE.Vector3) {
return toDisplayLocalPosition(localPosition);
}
/** Returns a display position for the system camera, derived from a raw local position in km. */
toSystemDisplayPosition(localPosition: THREE.Vector3) {
return toDisplayLocalPosition(localPosition);
}
}