"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; 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(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 ( {/* Sleek Dark Cyber Ground Grid */} {/* Primary Transport Corridors (Warehouse to Cluster Hubs) */} {corridorGeometries.map((points, i) => ( [p.x, p.y, p.z])), 3]} /> { corridorMats.current[i] = el; }} transparent opacity={0.15} depthWrite={false} /> ))} {/* CENTRAL LOGISTICS ASSET: Main Warehouse Hub */} {/* Core foundation structure */} {/* Loading Docks */} {[-0.6, 0, 0.6].map((offset, i) => ( ))} {/* Upper Level / Control Deck */} {/* Rooftop Solar Panels */} {[-0.4, 0.4].map((offset, i) => ( ))} {/* Central Communications Array / Tower */} {/* Main rod */} {/* Glowing Beacon */} {/* Pulsing ground base glow */} ); } export default React.memo(HologramCity);