update miletruth page
This commit is contained in:
191
src/components/optimization/HologramCity.tsx
Normal file
191
src/components/optimization/HologramCity.tsx
Normal file
@@ -0,0 +1,191 @@
|
||||
"use client";
|
||||
|
||||
import React, { useMemo, useRef } from "react";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import * as THREE from "three";
|
||||
import { COLORS } from "./constants";
|
||||
import { damp, lerp, seeded, smoothstep } from "./math";
|
||||
|
||||
type Props = {
|
||||
progress: React.RefObject<number>;
|
||||
count?: number;
|
||||
reduced?: boolean;
|
||||
};
|
||||
|
||||
const CYAN = new THREE.Color(COLORS.cyan);
|
||||
const RED = new THREE.Color(COLORS.red);
|
||||
const GREEN = new THREE.Color(COLORS.green);
|
||||
|
||||
// Generate deterministic cluster centers matching routes.ts
|
||||
const clusterCount = 5;
|
||||
const clusterCenters = Array.from({ length: clusterCount }, (_, c) => {
|
||||
const baseAngle = (c / clusterCount) * Math.PI * 2 + 0.3;
|
||||
const radius = 7 + seeded(c * 7 + 1) * 3;
|
||||
const cx = Math.cos(baseAngle) * radius;
|
||||
const cz = Math.sin(baseAngle) * radius;
|
||||
return new THREE.Vector3(cx, 0.1, cz);
|
||||
});
|
||||
|
||||
function HologramCity({ progress, reduced = false }: Props) {
|
||||
const mainWarehouseRef = useRef<THREE.Group>(null);
|
||||
const radarRefs = useRef<(THREE.Group | null)[]>([]);
|
||||
const corridorMats = useRef<(THREE.LineBasicMaterial | null)[]>([]);
|
||||
const zoneMats = useRef<(THREE.MeshBasicMaterial | null)[]>([]);
|
||||
const eased = useRef(0);
|
||||
|
||||
// Pre-generate corridor geometries (Warehouse [0, 0, 0] to Cluster Centers)
|
||||
const corridorGeometries = useMemo(() => {
|
||||
return clusterCenters.map((center) => {
|
||||
const pts = [
|
||||
new THREE.Vector3(0, 0.15, 0),
|
||||
new THREE.Vector3(center.x * 0.5, 0.6, center.z * 0.5), // arch up slightly in the middle
|
||||
new THREE.Vector3(center.x, 0.15, center.z),
|
||||
];
|
||||
return new THREE.CatmullRomCurve3(pts).getPoints(24);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useFrame((state, dt) => {
|
||||
const p = progress.current ?? 0;
|
||||
eased.current = damp(eased.current, p, 3, dt);
|
||||
const e = eased.current;
|
||||
const t = state.clock.elapsedTime;
|
||||
|
||||
// Animate Main Warehouse central beacon rotation
|
||||
if (mainWarehouseRef.current) {
|
||||
mainWarehouseRef.current.position.y = Math.sin(t * 1.2) * 0.04;
|
||||
}
|
||||
|
||||
// Rotate Radar dishes on top of the Regional Hubs
|
||||
radarRefs.current.forEach((radar, idx) => {
|
||||
if (radar) {
|
||||
radar.rotation.y = t * (0.8 + idx * 0.2);
|
||||
}
|
||||
});
|
||||
|
||||
// Animate corridor line opacity and color:
|
||||
// Under unoptimized states (chaos/scan) they are faint or red.
|
||||
// As optimization settles, they light up with active cyan/green.
|
||||
corridorMats.current.forEach((mat, idx) => {
|
||||
if (mat) {
|
||||
const activeColor = idx % 2 === 0 ? CYAN : GREEN;
|
||||
const colorFactor = smoothstep(0.45, 0.8, e);
|
||||
mat.color.copy(RED).lerp(activeColor, colorFactor);
|
||||
mat.opacity = lerp(0.12, 0.7, colorFactor) * (0.8 + Math.sin(t * 4 - idx * 0.5) * 0.2);
|
||||
}
|
||||
});
|
||||
|
||||
// Animate ground delivery zone circles
|
||||
zoneMats.current.forEach((mat, idx) => {
|
||||
if (mat) {
|
||||
const activeColor = idx % 2 === 0 ? CYAN : GREEN;
|
||||
const colorFactor = smoothstep(0.5, 0.82, e);
|
||||
mat.color.copy(RED).lerp(activeColor, colorFactor);
|
||||
mat.opacity = lerp(0.06, 0.22, colorFactor) * (0.85 + Math.sin(t * 3 - idx) * 0.15);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<group>
|
||||
{/* Sleek Dark Cyber Ground Grid */}
|
||||
<gridHelper
|
||||
args={[60, 48, COLORS.cyan, COLORS.cyan]}
|
||||
position={[0, -0.01, 0]}
|
||||
>
|
||||
<lineBasicMaterial
|
||||
attach="material"
|
||||
color={COLORS.cyan}
|
||||
transparent
|
||||
opacity={0.05}
|
||||
/>
|
||||
</gridHelper>
|
||||
|
||||
{/* Primary Transport Corridors (Warehouse to Cluster Hubs) */}
|
||||
{corridorGeometries.map((points, i) => (
|
||||
<line key={`corr${i}`}>
|
||||
<bufferGeometry>
|
||||
<float32BufferAttribute
|
||||
attach="attributes-position"
|
||||
args={[new Float32Array(points.flatMap(p => [p.x, p.y, p.z])), 3]}
|
||||
/>
|
||||
</bufferGeometry>
|
||||
<lineBasicMaterial
|
||||
ref={(el) => {
|
||||
corridorMats.current[i] = el;
|
||||
}}
|
||||
transparent
|
||||
opacity={0.15}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</line>
|
||||
))}
|
||||
|
||||
{/* CENTRAL LOGISTICS ASSET: Main Warehouse Hub */}
|
||||
<group ref={mainWarehouseRef} position={[0, 0, 0]}>
|
||||
{/* Core foundation structure */}
|
||||
<mesh position={[0, 0.35, 0]}>
|
||||
<boxGeometry args={[2.2, 0.7, 1.8]} />
|
||||
<meshBasicMaterial color={COLORS.ink} />
|
||||
</mesh>
|
||||
<mesh position={[0, 0.35, 0]}>
|
||||
<boxGeometry args={[2.2, 0.7, 1.8]} />
|
||||
<meshBasicMaterial color={COLORS.cyan} wireframe transparent opacity={0.65} />
|
||||
</mesh>
|
||||
|
||||
{/* Loading Docks */}
|
||||
{[-0.6, 0, 0.6].map((offset, i) => (
|
||||
<mesh key={i} position={[offset, 0.18, 0.91]}>
|
||||
<boxGeometry args={[0.3, 0.35, 0.06]} />
|
||||
<meshBasicMaterial color={COLORS.cyan} transparent opacity={0.8} />
|
||||
</mesh>
|
||||
))}
|
||||
|
||||
{/* Upper Level / Control Deck */}
|
||||
<mesh position={[0, 0.85, 0]}>
|
||||
<boxGeometry args={[1.2, 0.3, 1.0]} />
|
||||
<meshBasicMaterial color={COLORS.cyan} transparent opacity={0.15} />
|
||||
</mesh>
|
||||
<mesh position={[0, 0.85, 0]}>
|
||||
<boxGeometry args={[1.2, 0.3, 1.0]} />
|
||||
<meshBasicMaterial color={COLORS.cyan} wireframe transparent opacity={0.9} />
|
||||
</mesh>
|
||||
|
||||
{/* Rooftop Solar Panels */}
|
||||
{[-0.4, 0.4].map((offset, i) => (
|
||||
<mesh key={i} position={[offset, 0.71, -0.4]} rotation={[0.15, 0, 0]}>
|
||||
<boxGeometry args={[0.5, 0.03, 0.6]} />
|
||||
<meshBasicMaterial color="#1e293b" />
|
||||
</mesh>
|
||||
))}
|
||||
|
||||
{/* Central Communications Array / Tower */}
|
||||
<group position={[0, 1.0, 0]}>
|
||||
{/* Main rod */}
|
||||
<mesh position={[0, 0.4, 0]}>
|
||||
<cylinderGeometry args={[0.03, 0.03, 0.8, 8]} />
|
||||
<meshBasicMaterial color={COLORS.cyan} />
|
||||
</mesh>
|
||||
{/* Glowing Beacon */}
|
||||
<mesh position={[0, 0.8, 0]}>
|
||||
<sphereGeometry args={[0.12, 16, 16]} />
|
||||
<meshBasicMaterial color="#ffffff" />
|
||||
</mesh>
|
||||
</group>
|
||||
|
||||
{/* Pulsing ground base glow */}
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, 0.02, 0]}>
|
||||
<ringGeometry args={[1.8, 2.2, 32]} />
|
||||
<meshBasicMaterial
|
||||
color={COLORS.cyan}
|
||||
transparent
|
||||
opacity={0.3}
|
||||
blending={THREE.AdditiveBlending}
|
||||
/>
|
||||
</mesh>
|
||||
</group>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(HologramCity);
|
||||
Reference in New Issue
Block a user