feat: production chain
This commit is contained in:
@@ -24,8 +24,10 @@ import {
|
||||
starHaloOpacity,
|
||||
toThreeVector,
|
||||
} from "./viewerMath";
|
||||
import { createSceneNode } from "./viewerScenePrimitives";
|
||||
import type { SceneNode } from "./viewerScenePrimitives";
|
||||
|
||||
export function createNodeMesh(node: ResourceNodeSnapshot): THREE.Mesh {
|
||||
export function createNodeMesh(node: ResourceNodeSnapshot): SceneNode {
|
||||
const isGas = node.sourceKind === "gas-cloud" || node.itemId === "gas";
|
||||
const mesh = new THREE.Mesh(
|
||||
isGas ? new THREE.SphereGeometry(18, 14, 14) : new THREE.IcosahedronGeometry(12, 0),
|
||||
@@ -39,12 +41,12 @@ export function createNodeMesh(node: ResourceNodeSnapshot): THREE.Mesh {
|
||||
);
|
||||
mesh.position.copy(toThreeVector(node.localPosition));
|
||||
mesh.scale.setScalar(0.8 + (node.oreRemaining / Math.max(node.maxOre, 1)) * 0.6);
|
||||
return mesh;
|
||||
return createSceneNode(mesh);
|
||||
}
|
||||
|
||||
export function createSpatialNodeMesh(node: SpatialNodeSnapshot, spatialNodeColor: (kind: string) => string): THREE.Mesh {
|
||||
export function createSpatialNodeMesh(node: SpatialNodeSnapshot, spatialNodeColor: (kind: string) => string): SceneNode {
|
||||
const color = spatialNodeColor(node.kind);
|
||||
return new THREE.Mesh(
|
||||
return createSceneNode(new THREE.Mesh(
|
||||
new THREE.OctahedronGeometry(10, 0),
|
||||
new THREE.MeshStandardMaterial({
|
||||
color,
|
||||
@@ -52,14 +54,14 @@ export function createSpatialNodeMesh(node: SpatialNodeSnapshot, spatialNodeColo
|
||||
roughness: 0.35,
|
||||
metalness: 0.45,
|
||||
}),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export function createBubbleRing(
|
||||
bubble: LocalBubbleSnapshot,
|
||||
localPosition: THREE.Vector3,
|
||||
createCirclePoints: (radius: number, segments: number) => THREE.Vector3[],
|
||||
): THREE.LineLoop {
|
||||
): SceneNode {
|
||||
const ring = new THREE.LineLoop(
|
||||
new THREE.BufferGeometry().setFromPoints(createCirclePoints(Math.max(bubble.radius, 60), 64)),
|
||||
new THREE.LineBasicMaterial({
|
||||
@@ -69,11 +71,11 @@ export function createBubbleRing(
|
||||
}),
|
||||
);
|
||||
ring.position.copy(localPosition);
|
||||
return ring;
|
||||
return createSceneNode(ring);
|
||||
}
|
||||
|
||||
export function createClaimMesh(claim: ClaimSnapshot): THREE.Mesh {
|
||||
return new THREE.Mesh(
|
||||
export function createClaimMesh(claim: ClaimSnapshot): SceneNode {
|
||||
return createSceneNode(new THREE.Mesh(
|
||||
new THREE.ConeGeometry(9, 20, 4),
|
||||
new THREE.MeshStandardMaterial({
|
||||
color: claim.state === "active" ? 0xff7f50 : 0xff5b5b,
|
||||
@@ -81,11 +83,11 @@ export function createClaimMesh(claim: ClaimSnapshot): THREE.Mesh {
|
||||
roughness: 0.4,
|
||||
metalness: 0.28,
|
||||
}),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export function createConstructionSiteMesh(site: ConstructionSiteSnapshot): THREE.Mesh {
|
||||
return new THREE.Mesh(
|
||||
export function createConstructionSiteMesh(site: ConstructionSiteSnapshot): SceneNode {
|
||||
return createSceneNode(new THREE.Mesh(
|
||||
new THREE.TorusKnotGeometry(7, 2.2, 54, 8),
|
||||
new THREE.MeshStandardMaterial({
|
||||
color: site.state === "completed" ? 0x46d37f : 0x9df29c,
|
||||
@@ -93,10 +95,10 @@ export function createConstructionSiteMesh(site: ConstructionSiteSnapshot): THRE
|
||||
roughness: 0.34,
|
||||
metalness: 0.48,
|
||||
}),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export function createStarCluster(system: SystemSnapshot): THREE.Group {
|
||||
export function createStarCluster(system: SystemSnapshot): SceneNode {
|
||||
const root = new THREE.Group();
|
||||
const renderedStarSize = celestialRenderRadius(system.starSize, STAR_RENDER_SCALE, 8, 1.02);
|
||||
const offsets = system.starCount > 1
|
||||
@@ -123,22 +125,22 @@ export function createStarCluster(system: SystemSnapshot): THREE.Group {
|
||||
root.add(star, halo);
|
||||
}
|
||||
|
||||
return root;
|
||||
return createSceneNode(root);
|
||||
}
|
||||
|
||||
export function createPlanetOrbit(planet: PlanetSnapshot): THREE.LineLoop {
|
||||
export function createPlanetOrbit(planet: PlanetSnapshot): SceneNode {
|
||||
const points = Array.from({ length: 120 }, (_, index) => {
|
||||
const phaseDegrees = (index / 120) * 360;
|
||||
return computePlanetLocalPosition(planet, 0, phaseDegrees);
|
||||
});
|
||||
|
||||
return new THREE.LineLoop(
|
||||
return createSceneNode(new THREE.LineLoop(
|
||||
new THREE.BufferGeometry().setFromPoints(points),
|
||||
new THREE.LineBasicMaterial({ color: 0x17314d, transparent: true, opacity: 0.22 }),
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export function createPlanetRing(planet: PlanetSnapshot): THREE.Mesh {
|
||||
export function createPlanetRing(planet: PlanetSnapshot): SceneNode {
|
||||
const renderedPlanetRadius = celestialRenderRadius(planet.size, PLANET_RENDER_SCALE, 7, 1.06);
|
||||
const ring = new THREE.Mesh(
|
||||
new THREE.RingGeometry(renderedPlanetRadius * 1.35, renderedPlanetRadius * 2.15, 48),
|
||||
@@ -151,7 +153,7 @@ export function createPlanetRing(planet: PlanetSnapshot): THREE.Mesh {
|
||||
);
|
||||
ring.rotation.x = Math.PI / 2;
|
||||
ring.rotation.z = THREE.MathUtils.degToRad(planet.orbitInclination * 0.25);
|
||||
return ring;
|
||||
return createSceneNode(ring);
|
||||
}
|
||||
|
||||
export function createMoonVisuals(planet: PlanetSnapshot, seed: number): MoonVisual[] {
|
||||
@@ -185,23 +187,23 @@ export function createMoonVisuals(planet: PlanetSnapshot, seed: number): MoonVis
|
||||
}),
|
||||
);
|
||||
|
||||
moons.push({ mesh, orbit });
|
||||
moons.push({ systemId: "", planetIndex: -1, mesh: createSceneNode(mesh), orbit: createSceneNode(orbit) });
|
||||
}
|
||||
|
||||
return moons;
|
||||
}
|
||||
|
||||
export function createStationMesh(station: StationSnapshot): THREE.Mesh {
|
||||
export function createStationMesh(station: StationSnapshot): SceneNode {
|
||||
const mesh = new THREE.Mesh(
|
||||
new THREE.CylinderGeometry(24, 24, 18, 10),
|
||||
new THREE.MeshStandardMaterial({ color: station.color, emissive: new THREE.Color(station.color).multiplyScalar(0.1) }),
|
||||
);
|
||||
mesh.rotation.x = Math.PI / 2;
|
||||
mesh.position.copy(toThreeVector(station.localPosition));
|
||||
return mesh;
|
||||
return createSceneNode(mesh);
|
||||
}
|
||||
|
||||
export function createShipMesh(ship: ShipSnapshot, size: number, length: number, color: string): THREE.Mesh {
|
||||
export function createShipMesh(ship: ShipSnapshot, size: number, length: number, color: string): SceneNode {
|
||||
const geometry = new THREE.ConeGeometry(size, length, 7);
|
||||
geometry.rotateX(Math.PI / 2);
|
||||
const mesh = new THREE.Mesh(
|
||||
@@ -212,7 +214,7 @@ export function createShipMesh(ship: ShipSnapshot, size: number, length: number,
|
||||
}),
|
||||
);
|
||||
mesh.position.copy(toThreeVector(ship.localPosition));
|
||||
return mesh;
|
||||
return createSceneNode(mesh);
|
||||
}
|
||||
|
||||
export function createBackdropStars(): THREE.Points {
|
||||
@@ -324,7 +326,7 @@ export function createNebulaClouds(texture: THREE.Texture): THREE.Sprite[] {
|
||||
});
|
||||
}
|
||||
|
||||
export function createTacticalIcon(documentRef: Document, color: string, size: number): THREE.Sprite {
|
||||
export function createTacticalIcon(documentRef: Document, color: string, size: number): SceneNode {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
canvas.width = 64;
|
||||
canvas.height = 64;
|
||||
@@ -356,7 +358,7 @@ export function createTacticalIcon(documentRef: Document, color: string, size: n
|
||||
}));
|
||||
sprite.scale.setScalar(size);
|
||||
sprite.visible = false;
|
||||
return sprite;
|
||||
return createSceneNode(sprite);
|
||||
}
|
||||
|
||||
export function createSystemSummaryVisual(documentRef: Document, anchor: THREE.Vector3): SystemSummaryVisual {
|
||||
@@ -364,18 +366,18 @@ export function createSystemSummaryVisual(documentRef: Document, anchor: THREE.V
|
||||
canvas.width = 512;
|
||||
canvas.height = 160;
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
const sprite = new THREE.Sprite(new THREE.SpriteMaterial({
|
||||
const sprite = createSceneNode(new THREE.Sprite(new THREE.SpriteMaterial({
|
||||
map: texture,
|
||||
transparent: true,
|
||||
depthWrite: false,
|
||||
depthTest: false,
|
||||
}));
|
||||
sprite.scale.set(520, 160, 1);
|
||||
sprite.visible = false;
|
||||
})));
|
||||
sprite.object.scale.set(520, 160, 1);
|
||||
sprite.setVisible(false);
|
||||
return { sprite, texture, anchor };
|
||||
}
|
||||
|
||||
export function createShellReticle(documentRef: Document, color: string, size: number): THREE.Sprite {
|
||||
export function createShellReticle(documentRef: Document, color: string, size: number): SceneNode {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
canvas.width = 128;
|
||||
canvas.height = 128;
|
||||
@@ -412,9 +414,9 @@ export function createShellReticle(documentRef: Document, color: string, size: n
|
||||
blending: THREE.AdditiveBlending,
|
||||
fog: false,
|
||||
});
|
||||
const sprite = new THREE.Sprite(material);
|
||||
sprite.scale.setScalar(size);
|
||||
sprite.visible = false;
|
||||
sprite.renderOrder = 1000;
|
||||
const sprite = createSceneNode(new THREE.Sprite(material));
|
||||
sprite.setScaleScalar(size);
|
||||
sprite.setVisible(false);
|
||||
sprite.setRenderOrder(1000);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user