"use client"; import { useEffect, useRef, useState } from "react"; export default function Temple3DPage() { const containerRef = useRef(null); const [selectedAgent, setSelectedAgent] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { if (!containerRef.current) return; let cancelled = false; import("three").then((THREE) => { if (cancelled || !containerRef.current) return; const container = containerRef.current; // Scene const scene = new THREE.Scene(); scene.background = new THREE.Color(0x0a0a1a); scene.fog = new THREE.FogExp2(0x0a0a1a, 0.015); // Camera const camera = new THREE.PerspectiveCamera(60, container.clientWidth / container.clientHeight, 0.1, 1000); camera.position.set(0, 15, 35); // Renderer const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.clientWidth, container.clientHeight); renderer.setPixelRatio(window.devicePixelRatio); renderer.shadowMap.enabled = true; container.appendChild(renderer.domElement); // Lighting const ambient = new THREE.AmbientLight(0xffd700, 0.3); scene.add(ambient); const sun = new THREE.DirectionalLight(0xfff5e0, 1.2); sun.position.set(50, 100, 50); sun.castShadow = true; sun.shadow.mapSize.width = 2048; sun.shadow.mapSize.height = 2048; scene.add(sun); const blueLight = new THREE.PointLight(0x40e0d0, 0.8, 100); blueLight.position.set(-30, 20, -20); scene.add(blueLight); const purpleLight = new THREE.PointLight(0x9b59b6, 0.5, 80); purpleLight.position.set(30, 15, 10); scene.add(purpleLight); // Materials const sandstone = new THREE.MeshStandardMaterial({ color: 0xc2a366, roughness: 0.9, metalness: 0.1 }); const darkSandstone = new THREE.MeshStandardMaterial({ color: 0x8b7355, roughness: 0.85, metalness: 0.1 }); const gold = new THREE.MeshStandardMaterial({ color: 0xffd700, metalness: 0.9, roughness: 0.2, emissive: 0xffd700, emissiveIntensity: 0.3 }); const lapis = new THREE.MeshStandardMaterial({ color: 0x1e3a5f, metalness: 0.3, roughness: 0.6 }); // Ground - sand const groundGeo = new THREE.PlaneGeometry(200, 200); const groundMat = new THREE.MeshStandardMaterial({ color: 0xd4b896, roughness: 1 }); const ground = new THREE.Mesh(groundGeo, groundMat); ground.rotation.x = -Math.PI / 2; ground.position.y = -0.1; ground.receiveShadow = true; scene.add(ground); // ============== KARNAK TEMPLE STRUCTURE ============== // First Pylon (massive gateway) - like Karnak const pylon1Geo = new THREE.BoxGeometry(40, 25, 5); const pylon1 = new THREE.Mesh(pylon1Geo, sandstone); pylon1.position.set(0, 12.5, 25); pylon1.castShadow = true; pylon1.receiveShadow = true; scene.add(pylon1); // Pylon decorations (pillars on pylon) for (let i = 0; i < 6; i++) { const pillarGeo = new THREE.BoxGeometry(2, 22, 2); const pillar = new THREE.Mesh(pillarGeo, darkSandstone); pillar.position.set(-18 + i * 7, 11, 28); pillar.castShadow = true; scene.add(pillar); } // Courtyard columns - Lotus columns like Karnak const columnPositions = [ [-15, 0], [-10, 0], [-5, 0], [0, 0], [5, 0], [10, 0], [15, 0], [-15, -10], [-10, -10], [-5, -10], [0, -10], [5, -10], [10, -10], [15, -10], ]; columnPositions.forEach(([x, z]) => { // Column shaft (bundled papyrus style) const shaftGeo = new THREE.CylinderGeometry(1.2, 1.3, 18, 16); const shaft = new THREE.Mesh(shaftGeo, sandstone); shaft.position.set(x, 9, z); shaft.castShadow = true; scene.add(shaft); // Column capital (open lotus) const capitalGeo = new THREE.ConeGeometry(2, 4, 16); const capital = new THREE.Mesh(capitalGeo, sandstone); capital.position.set(x, 20, z); capital.castShadow = true; scene.add(capital); }); // Hypostyle Hall (second section with smaller columns) const hypostyleCols = [ [-12, -18], [-6, -18], [0, -18], [6, -18], [12, -18], [-12, -22], [-6, -22], [0, -22], [6, -22], [12, -22], ]; hypostyleCols.forEach(([x, z]) => { const shaftGeo = new THREE.CylinderGeometry(0.8, 0.9, 14, 12); const shaft = new THREE.Mesh(shaftGeo, darkSandstone); shaft.position.set(x, 7, z); shaft.castShadow = true; scene.add(shaft); }); // Second Pylon const pylon2Geo = new THREE.BoxGeometry(30, 20, 4); const pylon2 = new THREE.Mesh(pylon2Geo, sandstone); pylon2.position.set(0, 10, -25); pylon2.castShadow = true; scene.add(pylon2); // Third Pylon const pylon3Geo = new THREE.BoxGeometry(25, 18, 3); const pylon3 = new THREE.Mesh(pylon3Geo, darkSandstone); pylon3.position.set(0, 9, -35); pylon3.castShadow = true; scene.add(pylon3); // Sacred Lake (water feature) const lakeGeo = new THREE.CircleGeometry(8, 32); const lakeMat = new THREE.MeshStandardMaterial({ color: 0x1e5f8f, metalness: 0.3, roughness: 0.2, transparent: true, opacity: 0.8 }); const lake = new THREE.Mesh(lakeGeo, lakeMat); lake.rotation.x = -Math.PI / 2; lake.position.set(-25, 0.1, 5); scene.add(lake); // Obelisks const obeliskGeo = new THREE.CylinderGeometry(0.5, 0.8, 20, 4); const obelisk1 = new THREE.Mesh(obeliskGeo, darkSandstone); obelisk1.position.set(-8, 10, -25); obelisk1.castShadow = true; scene.add(obelisk1); const obelisk2 = new THREE.Mesh(obeliskGeo, darkSandstone); obelisk2.position.set(8, 10, -25); obelisk2.castShadow = true; scene.add(obelisk2); // Golden pyramid cap on obelisks const capGeo = new THREE.ConeGeometry(1.2, 3, 4); const cap1 = new THREE.Mesh(capGeo, gold); cap1.position.set(-8, 21.5, -25); scene.add(cap1); const cap2 = new THREE.Mesh(capGeo, gold); cap2.position.set(8, 21.5, -25); scene.add(cap2); // Sphinx Avenue (ram-headed sphinxes leading to entrance) for (let i = 0; i < 6; i++) { // Body const sphinxGeo = new THREE.BoxGeometry(3, 2, 6); const sphinx = new THREE.Mesh(sphinxGeo, sandstone); sphinx.position.set(-12 + i * 5, 1, 40 + (i % 2) * 3); sphinx.castShadow = true; scene.add(sphinx); // Head const headGeo = new THREE.SphereGeometry(1.2, 16, 16); const head = new THREE.Mesh(headGeo, sandstone); head.position.set(-12 + i * 5, 2.5, 42 + (i % 2) * 3); head.castShadow = true; scene.add(head); } // Holy of Holies - Sanctuary (dark room at center) const sanctuaryGeo = new THREE.BoxGeometry(15, 12, 10); const sanctuary = new THREE.Mesh(sanctuaryGeo, darkSandstone); sanctuary.position.set(0, 6, -42); sanctuary.castShadow = true; scene.add(sanctuary); // Solar barque (boat) in sanctuary area const boatGeo = new THREE.BoxGeometry(12, 0.5, 3); const boat = new THREE.Mesh(boatGeo, lapis); boat.position.set(0, 0.5, -42); scene.add(boat); // Golden Eye of Horus at sanctuary entrance const eyeGeo = new THREE.TorusGeometry(3, 0.5, 8, 32); const eye = new THREE.Mesh(eyeGeo, gold); eye.position.set(0, 5, -36.5); scene.add(eye); // Eye center const eyeCenterGeo = new THREE.SphereGeometry(1.5, 16, 16); const eyeCenter = new THREE.Mesh(eyeCenterGeo, new THREE.MeshStandardMaterial({ color: 0x000000, emissive: 0xffd700, emissiveIntensity: 0.2 })); eyeCenter.position.set(0, 5, -36); scene.add(eyeCenter); // ============== EGYPTIAN AGENTS (Animated) ============== const agents = [ { name: "ANUBIS", symbol: "🐕", color: 0x1a1a1a, glow: 0xffd700, pos: [0, 1.5, 42], room: "AVENUE OF SPHINXES", role: "Guardian of Leads" }, { name: "PTAH", symbol: "🔨", color: 0xf5deb3, glow: 0xffd700, pos: [-12, 1.5, 0], room: "COURTYARD", role: "Builder" }, { name: "SESHAT", symbol: "📝", color: 0x228b22, glow: 0x228b22, pos: [-6, 1.5, 0], room: "COURTYARD", role: "Scribe" }, { name: "SEKHMET", symbol: "🦁", color: 0xb22222, glow: 0xb22222, pos: [6, 1.5, 0], room: "COURTYARD", role: "Warrior" }, { name: "THOTH", symbol: "🐦", color: 0xffffff, glow: 0x40e0d0, pos: [-6, 1.5, -18], room: "HYPOSTYLE HALL", role: "Knowledge Keeper" }, { name: "MAAT", symbol: "⚖️", color: 0x40e0d0, glow: 0x40e0d0, pos: [6, 1.5, -18], room: "HYPOSTYLE HALL", role: "Truth" }, { name: "CLEOPATRA", symbol: "👑", color: 0x9b59b6, glow: 0x9b59b6, pos: [0, 1.5, -22], room: "SECOND PYLON", role: "Voice of the Queen" }, { name: "HORUS", symbol: "👁️", color: 0xffd700, glow: 0xffd700, pos: [0, 4, -42], room: "HOLY OF HOLIES", role: "Lord of the Sky" }, ]; const agentMeshes: any[] = []; agents.forEach((agent, i) => { // Create Egyptian-styled agent (hieroglyphic figure shape) const group = new THREE.Group(); // Body (wrapped mummy style for some, human for others) const bodyGeo = new THREE.CylinderGeometry(0.3, 0.5, 1.5, 8); const bodyMat = new THREE.MeshStandardMaterial({ color: agent.color, emissive: agent.color, emissiveIntensity: 0.4, metalness: 0.2, roughness: 0.6 }); const body = new THREE.Mesh(bodyGeo, bodyMat); body.position.y = 0.75; group.add(body); // Head (sphere for all, representing hieroglyphic style) const headGeo = new THREE.SphereGeometry(0.5, 16, 16); const head = new THREE.Mesh(headGeo, bodyMat); head.position.y = 1.8; group.add(head); // Symbol on chest (floating element) const symbolGeo = new THREE.CircleGeometry(0.3, 16); const symbolMat = new THREE.MeshBasicMaterial({ color: agent.glow }); const symbol = new THREE.Mesh(symbolGeo, symbolMat); symbol.position.set(0, 1, 0.35); group.add(symbol); // Glow aura const glowGeo = new THREE.SphereGeometry(1.2, 16, 16); const glowMat = new THREE.MeshBasicMaterial({ color: agent.glow, transparent: true, opacity: 0.15 }); const glow = new THREE.Mesh(glowGeo, glowMat); glow.position.y = 1.2; group.add(glow); group.position.set(agent.pos[0], agent.pos[1], agent.pos[2]); group.userData = { name: agent.name, symbol: agent.symbol, role: agent.role, room: agent.room }; group.castShadow = true; scene.add(group); agentMeshes.push(group); }); // ============== ANIMATION ============== let time = 0; const clock = new THREE.Clock(); const animate = () => { if (cancelled) return; requestAnimationFrame(animate); const delta = clock.getDelta(); time += delta; // Animate agents - floating and bobbing motion agentMeshes.forEach((agent, i) => { const originalY = agents[i].pos[1]; const bobSpeed = 1 + i * 0.2; const bobAmount = 0.3; // Floating bob agent.position.y = originalY + Math.sin(time * bobSpeed) * bobAmount; // Gentle rotation agent.rotation.y = Math.sin(time * 0.5 + i) * 0.2; // Symbol pulsing glow const child = agent.children[2]; // symbol if (child && child.material) { child.material.opacity = 0.3 + Math.sin(time * 2 + i) * 0.2; } }); // Animate Eye of Horus eye.rotation.z = Math.sin(time * 0.3) * 0.1; eyeCenter.material.emissiveIntensity = 0.2 + Math.sin(time * 2) * 0.1; // Animate lake water lake.material.opacity = 0.7 + Math.sin(time * 0.5) * 0.1; renderer.render(scene, camera); }; animate(); // ============== CONTROLS ============== let isDragging = false; let theta = 0; let phi = Math.PI / 6; let target = new THREE.Vector3(0, 5, -20); let radius = 50; const updateCamera = () => { camera.position.x = target.x + radius * Math.sin(phi) * Math.cos(theta); camera.position.y = target.y + radius * Math.cos(phi); camera.position.z = target.z + radius * Math.sin(phi) * Math.sin(theta); camera.lookAt(target); }; const onPointerDown = (e: PointerEvent) => { isDragging = true; }; const onPointerUp = () => { isDragging = false; }; const onPointerMove = (e: PointerEvent) => { if (!isDragging) return; theta -= e.movementX * 0.005; phi = Math.max(0.1, Math.min(Math.PI / 2, phi + e.movementY * 0.005)); updateCamera(); }; const onWheel = (e: WheelEvent) => { radius = Math.max(20, Math.min(100, radius + e.deltaY * 0.05)); updateCamera(); }; container.addEventListener("pointerdown", onPointerDown); container.addEventListener("pointerup", onPointerUp); container.addEventListener("pointermove", onPointerMove); container.addEventListener("wheel", onWheel); // Click detection const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); const onClick = (e: MouseEvent) => { const rect = container.getBoundingClientRect(); mouse.x = ((e.clientX - rect.left) / container.clientWidth) * 2 - 1; mouse.y = -((e.clientY - rect.top) / container.clientHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(agentMeshes, true); // Find parent group for (const hit of intersects) { let obj: any = hit.object; while (obj.parent && !obj.userData.name) { obj = obj.parent; } if (obj.userData.name) { setSelectedAgent(obj.userData); break; } } }; container.addEventListener("click", onClick); updateCamera(); setLoading(false); // Handle resize const handleResize = () => { camera.aspect = container.clientWidth / container.clientHeight; camera.updateProjectionMatrix(); renderer.setSize(container.clientWidth, container.clientHeight); }; window.addEventListener("resize", handleResize); // Cleanup return () => { cancelled = true; window.removeEventListener("resize", handleResize); container.removeEventListener("pointerdown", onPointerDown); container.removeEventListener("pointerup", onPointerUp); container.removeEventListener("pointermove", onPointerMove); container.removeEventListener("wheel", onWheel); container.removeEventListener("click", onClick); if (container.contains(renderer.domElement)) { container.removeChild(renderer.domElement); } renderer.dispose(); }; }); }, []); return (
{/* Header */}

🏛️ TEMPLE OF AI - KARNAK

Drag to orbit • Scroll to zoom • Click agents for details

{/* Loading */} {loading && (
🏛️

Building Karnak Temple...

)} {/* 3D Canvas */}
{/* Agent Info Panel */} {selectedAgent && (
{selectedAgent.symbol}

{selectedAgent.name}

{selectedAgent.role}

Location

{selectedAgent.room}

)} {/* Bottom Legend */}

🏛️ Temple Map

Avenue of Sphinxes
First Pylon
Courtyard
Hypostyle Hall
Sanctuary
); }