feat: 3 scene rendering setup
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { ACTIVE_SYSTEM_DETAIL_SCALE, PROJECTED_GALAXY_RADIUS } from "./viewerConstants";
|
||||
import { computeMoonLocalPosition, computePlanetLocalPosition, currentWorldTimeSeconds, scaleLocalVector } from "./viewerMath";
|
||||
import { rawObject } from "./viewerScenePrimitives";
|
||||
import type { PlanetVisual, ShipVisual, SystemSummaryVisual, SystemVisual, WorldState } from "./viewerTypes";
|
||||
import type { PlanetVisual, ShipVisual, SystemVisual, WorldState } from "./viewerTypes";
|
||||
|
||||
export function getAnimatedShipLocalPosition(visual: ShipVisual, now = performance.now()) {
|
||||
const elapsedMs = now - visual.receivedAtMs;
|
||||
@@ -26,23 +25,17 @@ export function resolveShipHeading(visual: ShipVisual, worldPosition: THREE.Vect
|
||||
export function updatePlanetPresentation(
|
||||
world: WorldState | undefined,
|
||||
worldTimeSyncMs: number,
|
||||
activeSystemId: string | undefined,
|
||||
systemFocusLocal: THREE.Vector3,
|
||||
planetVisuals: PlanetVisual[],
|
||||
) {
|
||||
const nowSeconds = currentWorldTimeSeconds(world, worldTimeSyncMs);
|
||||
// In systemScene all positions use scaleLocalVector * ACTIVE_SYSTEM_DETAIL_SCALE.
|
||||
// Star is always at origin (0,0,0); orbits are centered there.
|
||||
for (const visual of planetVisuals) {
|
||||
const scale = visual.systemId === activeSystemId ? ACTIVE_SYSTEM_DETAIL_SCALE : 1;
|
||||
const localPosition = scaleLocalVector(computePlanetLocalPosition(visual.planet, nowSeconds));
|
||||
const orbitOffset = visual.systemId === activeSystemId
|
||||
? systemFocusLocal.clone().multiplyScalar(-scale)
|
||||
: new THREE.Vector3();
|
||||
const position = visual.systemId === activeSystemId
|
||||
? localPosition.clone().sub(systemFocusLocal).multiplyScalar(scale)
|
||||
: localPosition.multiplyScalar(scale);
|
||||
const position = scaleLocalVector(computePlanetLocalPosition(visual.planet, nowSeconds))
|
||||
.multiplyScalar(ACTIVE_SYSTEM_DETAIL_SCALE);
|
||||
|
||||
visual.orbit.setScaleScalar(scale);
|
||||
visual.orbit.setPosition(orbitOffset);
|
||||
visual.orbit.setScaleScalar(ACTIVE_SYSTEM_DETAIL_SCALE);
|
||||
visual.orbit.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
visual.mesh.setPosition(position);
|
||||
visual.icon.setPosition(position);
|
||||
if (visual.ring) {
|
||||
@@ -51,56 +44,45 @@ export function updatePlanetPresentation(
|
||||
|
||||
for (const [moonIndex, moon] of visual.moons.entries()) {
|
||||
moon.orbit.setPosition(position);
|
||||
moon.orbit.setScaleScalar(scale);
|
||||
moon.orbit.setScaleScalar(ACTIVE_SYSTEM_DETAIL_SCALE);
|
||||
moon.mesh.setPosition(
|
||||
position.clone().add(
|
||||
scaleLocalVector(computeMoonLocalPosition(visual.planet, moonIndex, nowSeconds, world?.seed ?? 1)).multiplyScalar(scale),
|
||||
scaleLocalVector(computeMoonLocalPosition(visual.planet, moonIndex, nowSeconds, world?.seed ?? 1))
|
||||
.multiplyScalar(ACTIVE_SYSTEM_DETAIL_SCALE),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function updateSystemSummaryPresentation(
|
||||
systemSummaryVisuals: Map<string, SystemSummaryVisual>,
|
||||
camera: THREE.PerspectiveCamera,
|
||||
activeSystemId?: string,
|
||||
) {
|
||||
const distanceScale = activeSystemId ? 0.05 : 0.085;
|
||||
for (const [systemId, visual] of systemSummaryVisuals.entries()) {
|
||||
const worldPosition = visual.sprite.getWorldPosition(new THREE.Vector3());
|
||||
const distance = camera.position.distanceTo(worldPosition);
|
||||
const minimumScale = activeSystemId && systemId !== activeSystemId ? 1200 : 1400;
|
||||
const scale = Math.max(minimumScale, distance * distanceScale);
|
||||
rawObject(visual.sprite).scale.set(scale, scale * 0.3125, 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function updateSystemStarPresentation(
|
||||
systemVisuals: Map<string, SystemVisual>,
|
||||
activeSystemId: string | undefined,
|
||||
systemFocusLocal: THREE.Vector3,
|
||||
camera: THREE.PerspectiveCamera,
|
||||
galaxyCamera: THREE.PerspectiveCamera,
|
||||
setShellReticleOpacity: (sprite: SystemVisual["shellReticle"], opacity: number) => void,
|
||||
) {
|
||||
const activeSystem = activeSystemId ? systemVisuals.get(activeSystemId) : undefined;
|
||||
|
||||
for (const [systemId, visual] of systemVisuals.entries()) {
|
||||
visual.root.setPosition(visual.galaxyPosition);
|
||||
// galaxyRoot is always at the galaxy position of this system
|
||||
visual.galaxyRoot.setPosition(visual.galaxyPosition);
|
||||
visual.shellReticle.setScaleScalar(visual.shellReticleBaseScale);
|
||||
|
||||
if (!activeSystem) {
|
||||
visual.starCluster.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
// Galaxy view: show star dot, hide shell reticle
|
||||
visual.icon.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
visual.icon.setVisible(true);
|
||||
visual.shellReticle.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
visual.shellReticle.setVisible(false);
|
||||
setShellReticleOpacity(visual.shellReticle, 0);
|
||||
const dotWorldPos = visual.icon.getWorldPosition(new THREE.Vector3());
|
||||
visual.icon.setScaleScalar(galaxyCamera.position.distanceTo(dotWorldPos) * 0.01);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (systemId !== activeSystemId) {
|
||||
visual.starCluster.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
// Other systems in galaxy view while a system is active: show shell reticle projected to edge
|
||||
visual.icon.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
visual.icon.setVisible(false);
|
||||
visual.shellReticle.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
@@ -108,20 +90,19 @@ export function updateSystemStarPresentation(
|
||||
setShellReticleOpacity(visual.shellReticle, 1);
|
||||
const direction = visual.galaxyPosition.clone().sub(activeSystem.galaxyPosition);
|
||||
if (direction.lengthSq() > 0.0001) {
|
||||
visual.root.setPosition(
|
||||
visual.galaxyRoot.setPosition(
|
||||
activeSystem.galaxyPosition.clone().add(direction.normalize().multiplyScalar(PROJECTED_GALAXY_RADIUS)),
|
||||
);
|
||||
}
|
||||
const reticleWorldPosition = visual.root.getWorldPosition(new THREE.Vector3());
|
||||
const reticleDistance = camera.position.distanceTo(reticleWorldPosition);
|
||||
const reticleWorldPosition = visual.galaxyRoot.getWorldPosition(new THREE.Vector3());
|
||||
const reticleDistance = galaxyCamera.position.distanceTo(reticleWorldPosition);
|
||||
const reticleScale = Math.max(900, reticleDistance * 0.032);
|
||||
visual.shellReticle.setScaleScalar(reticleScale);
|
||||
continue;
|
||||
}
|
||||
|
||||
const offset = systemFocusLocal.clone().multiplyScalar(-ACTIVE_SYSTEM_DETAIL_SCALE);
|
||||
visual.starCluster.setPosition(offset);
|
||||
visual.icon.setPosition(offset);
|
||||
// Active system in galaxy view: show star dot, hide shell reticle
|
||||
visual.icon.setPosition(new THREE.Vector3(0, 0, 0));
|
||||
visual.icon.setVisible(true);
|
||||
visual.shellReticle.setVisible(false);
|
||||
setShellReticleOpacity(visual.shellReticle, 0);
|
||||
|
||||
Reference in New Issue
Block a user