Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>JARVIS 3D Holographic Armor Interface</title> <!-- Tailwind CSS --> <script src="https://cdn.tailwindcss.com"></script> <!-- Three.js and OrbitControls --> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script> <!-- FontAwesome Icons --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <!-- Google Fonts --> <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;800;900&family=Rajdhani:wght@500;600;700&display=swap" rel="stylesheet"> <style> * { user-select: none; -webkit-user-select: none; } body, html { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background-color: #020617; font-family: 'Rajdhani', sans-serif; color: #38bdf8; } .font-orbitron { font-family: 'Orbitron', sans-serif; } /* Glassmorphism HUD Style */ .hud-glass { background: rgba(8, 20, 42, 0.55); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(56, 189, 248, 0.25); box-shadow: 0 0 20px rgba(14, 165, 233, 0.15), inset 0 0 15px rgba(56, 189, 248, 0.08); } .hud-glass-gold { background: rgba(30, 20, 5, 0.55); backdrop-filter: blur(12px); border: 1px solid rgba(245, 158, 11, 0.35); box-shadow: 0 0 20px rgba(245, 158, 11, 0.2), inset 0 0 15px rgba(245, 158, 11, 0.1); } .hud-border-glow { box-shadow: 0 0 10px rgba(56, 189, 248, 0.4); } /* Scanline Overlay */ .scanline-bg { background: linear-gradient( to bottom, rgba(255,255,255,0), rgba(255,255,255,0) 50%, rgba(0, 200, 255, 0.04) 50%, rgba(0, 200, 255, 0.04) ); background-size: 100% 4px; } /* Hologram Grid Overlay */ #canvas-container { width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 1; } /* UI Overlays */ .hud-overlay { position: absolute; z-index: 10; transition: opacity 0.5s ease, transform 0.5s ease; pointer-events: auto; } .hud-hidden { opacity: 0 !important; pointer-events: none !important; transform: scale(0.98); } /* Custom Scrollbar */ ::-webkit-scrollbar { width: 4px; } ::-webkit-scrollbar-track { background: rgba(2, 6, 23, 0.6); } ::-webkit-scrollbar-thumb { background: rgba(56, 189, 248, 0.4); border-radius: 2px; } /* Pulse Animations */ @keyframes arcPulse { 0% { box-shadow: 0 0 5px #06b6d4, inset 0 0 5px #06b6d4; } 50% { box-shadow: 0 0 22px #38bdf8, inset 0 0 15px #38bdf8; } 100% { box-shadow: 0 0 5px #06b6d4, inset 0 0 5px #06b6d4; } } .arc-reactor-glow { animation: arcPulse 2.5s infinite ease-in-out; } /* Holographic Part Tooltip Pin */ .part-label { position: absolute; z-index: 20; transform: translate(-50%, -100%); pointer-events: none; transition: opacity 0.3s ease; } .range-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; border-radius: 50%; background: #38bdf8; cursor: pointer; box-shadow: 0 0 8px #38bdf8; } </style> </head> <body class="scanline-bg select-none overflow-hidden"> <!-- 3D WebGL Canvas Container --> <div id="canvas-container"></div> <!-- FOCUS MODE RESTORE HINT (Visible only when UI hidden) --> <div id="focus-restore-hint" class="fixed top-6 left-1/2 -translate-x-1/2 z-30 pointer-events-none opacity-0 transition-opacity duration-500 text-center"> <div class="hud-glass px-6 py-2 rounded-full border border-cyan-400/40 text-cyan-300 font-orbitron text-xs tracking-widest flex items-center gap-3"> <span class="w-2 h-2 rounded-full bg-cyan-400 animate-ping"></span> HOLOGRAM FOCUS MODE ACTIVE &bull; CLICK ANYWHERE OR SAY "SHOW HUD" </div> </div> <!-- TOP HEADER / JARVIS STATUS BAR --> <header id="hud-header" class="hud-overlay top-0 left-0 right-0 p-4 flex justify-between items-center border-b border-cyan-500/20 bg-slate-950/40"> <div class="flex items-center gap-4"> <div class="w-10 h-10 rounded-full border-2 border-cyan-400/60 flex items-center justify-center arc-reactor-glow bg-cyan-950/40"> <i class="fa-solid fa-atom text-cyan-300 text-lg animate-spin" style="animation-duration: 8s;"></i> </div> <div> <h1 class="font-orbitron text-lg font-bold tracking-widest text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-sky-200 to-amber-300"> STARK INDUSTRIES // MARK 85 </h1> <p class="text-xs text-cyan-400/70 tracking-wider flex items-center gap-2"> <span id="jarvis-status-dot" class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span> <span id="jarvis-status-text">JARVIS ONLINE &bull; VOICE SYSTEM ACTIVE</span> </p> </div> </div> <!-- Central Quick Actions --> <div class="hidden md:flex items-center gap-3"> <button onclick="triggerAssemble()" class="hud-glass hover:bg-cyan-500/20 text-cyan-300 px-3 py-1.5 rounded text-xs font-orbitron tracking-wider flex items-center gap-2 border border-cyan-500/40 transition"> <i class="fa-solid fa-cubes-stacked text-cyan-400"></i> ASSEMBLE SUIT </button> <button onclick="triggerExplode()" class="hud-glass hover:bg-amber-500/20 text-amber-300 px-3 py-1.5 rounded text-xs font-orbitron tracking-wider flex items-center gap-2 border border-amber-500/40 transition"> <i class="fa-solid fa-explosion text-amber-400"></i> EXPLODE PARTS </button> <button onclick="toggleFocusMode(true)" class="hud-glass hover:bg-sky-500/20 text-sky-200 px-3 py-1.5 rounded text-xs font-orbitron tracking-wider flex items-center gap-2 border border-sky-400/40 transition"> <i class="fa-solid fa-expand text-sky-400"></i> FOCUS HOLOGRAM </button> </div> <!-- Voice & Diagnostic Indicator --> <div class="flex items-center gap-3"> <button id="mic-btn" onclick="toggleVoiceRecognition()" class="relative p-2.5 rounded-full hud-glass border-cyan-400/50 text-cyan-300 hover:text-cyan-100 transition"> <i id="mic-icon" class="fa-solid fa-microphone text-base"></i> <span id="mic-pulse" class="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full hidden animate-ping"></span> </button> <div class="hidden lg:block text-right"> <div class="text-xs font-orbitron text-amber-300" id="power-output">PWR: 100% ARC CORE</div> <div class="text-[10px] text-cyan-400/60 font-mono" id="fps-display">FRAME RATE: 60 FPS</div> </div> </div> </header> <!-- LEFT SIDEBAR: PARTS ISOLATION & EXPLODED VIEW CONTROLS --> <aside id="hud-left-panel" class="hud-overlay top-20 left-4 bottom-6 w-80 hud-glass rounded-xl p-4 flex flex-col justify-between overflow-y-auto"> <div> <!-- Section Header --> <div class="flex justify-between items-center border-b border-cyan-500/30 pb-2 mb-4"> <span class="font-orbitron text-xs font-bold tracking-widest text-cyan-300 flex items-center gap-2"> <i class="fa-solid fa-layer-group text-cyan-400"></i> SUIT MODULE ISOLATION </span> <span class="text-[10px] bg-cyan-900/60 text-cyan-300 px-2 py-0.5 rounded font-mono border border-cyan-500/30">MK-85</span> </div> <!-- Exploded View Slider Controls --> <div class="mb-5 hud-glass p-3 rounded-lg border border-cyan-500/20"> <div class="flex justify-between text-xs font-orbitron text-cyan-200 mb-1"> <span>EXPLODED VIEW DISTANCE</span> <span id="explode-val-text" class="text-amber-400 font-mono">0%</span> </div> <input id="explode-slider" type="range" min="0" max="100" value="0" oninput="updateExplodeFromSlider(this.value)" class="w-full h-1.5 bg-slate-800 rounded-lg appearance-none cursor-pointer range-slider"> <div class="flex justify-between text-[10px] text-cyan-400/50 mt-1 font-mono"> <span>ASSEMBLED</span> <span>EXPANDED</span> </div> </div> <!-- Quick Part Selection List --> <p class="text-[11px] font-orbitron text-cyan-400/80 mb-2 uppercase tracking-wider">Modular Components</p> <div class="space-y-1.5 text-xs"> <button onclick="isolatePart('Helmet')" class="part-btn w-full text-left px-3 py-2 rounded hud-glass hover:border-cyan-400/80 transition flex items-center justify-between group"> <span class="group-hover:translate-x-1 transition-transform flex items-center gap-2"> <i class="fa-solid fa-helmet-safety text-cyan-400 text-xs"></i> Helmet & HUD Unit </span> <i class="fa-solid fa-chevron-right text-[10px] text-cyan-500"></i> </button> <button onclick="isolatePart('Chest')" class="part-btn w-full text-left px-3 py-2 rounded hud-glass hover:border-cyan-400/80 transition flex items-center justify-between group"> <span class="group-hover:translate-x-1 transition-transform flex items-center gap-2"> <i class="fa-solid fa-[#00ffff] fa-circle-radiation text-amber-400 text-xs"></i> Chestplate & Arc Core </span> <i class="fa-solid fa-chevron-right text-[10px] text-cyan-500"></i> </button> <button onclick="isolatePart('RightArm')" class="part-btn w-full text-left px-3 py-2 rounded hud-glass hover:border-cyan-400/80 transition flex items-center justify-between group"> <span class="group-hover:translate-x-1 transition-transform flex items-center gap-2"> <i class="fa-solid fa-hand-back-fist text-cyan-400 text-xs"></i> Right Arm & Repulsor </span> <i class="fa-solid fa-chevron-right text-[10px] text-cyan-500"></i> </button> <button onclick="isolatePart('LeftArm')" class="part-btn w-full text-left px-3 py-2 rounded hud-glass hover:border-cyan-400/80 transition flex items-center justify-between group"> <span class="group-hover:translate-x-1 transition-transform flex items-center gap-2"> <i class="fa-solid fa-hand-back-fist text-cyan-400 text-xs"></i> Left Arm & Repulsor </span> <i class="fa-solid fa-chevron-right text-[10px] text-cyan-500"></i> </button> <button onclick="isolatePart('Legs')" class="part-btn w-full text-left px-3 py-2 rounded hud-glass hover:border-cyan-400/80 transition flex items-center justify-between group"> <span class="group-hover:translate-x-1 transition-transform flex items-center gap-2"> <i class="fa-solid fa-socks text-cyan-400 text-xs"></i> Lower Armor & Thrusters </span> <i class="fa-solid fa-chevron-right text-[10px] text-cyan-500"></i> </button> <button onclick="resetIsolation()" class="w-full text-center px-3 py-2 mt-2 rounded border border-cyan-400/40 bg-cyan-500/10 hover:bg-cyan-500/30 text-cyan-200 font-orbitron text-xs tracking-wider transition"> <i class="fa-solid fa-arrows-rotate mr-1"></i> RESET FULL ASSEMBLY </button> </div> </div> <!-- Drag & Move Selected Part Details Box --> <div id="selected-part-box" class="hud-glass-gold p-3 rounded-lg border border-amber-500/30 mt-4"> <div class="flex justify-between items-center border-b border-amber-500/20 pb-1 mb-2"> <span id="selected-part-name" class="font-orbitron text-xs text-amber-300 font-bold">CLICK PART TO MOVE</span> <i class="fa-solid fa-arrows-up-down-left-right text-amber-400 text-xs"></i> </div> <p id="selected-part-desc" class="text-[11px] text-amber-200/70 mb-2">Select any armor piece with left click to adjust offset positions.</p> <div class="space-y-1.5 text-[11px]"> <div class="flex items-center gap-2"> <span class="w-4 font-mono text-cyan-400">X:</span> <input id="part-pos-x" type="range" min="-3" max="3" step="0.05" value="0" disabled oninput="manualPartOffset('x', this.value)" class="w-full h-1 bg-slate-800 rounded range-slider"> </div> <div class="flex items-center gap-2"> <span class="w-4 font-mono text-cyan-400">Y:</span> <input id="part-pos-y" type="range" min="-3" max="3" step="0.05" value="0" disabled oninput="manualPartOffset('y', this.value)" class="w-full h-1 bg-slate-800 rounded range-slider"> </div> <div class="flex items-center gap-2"> <span class="w-4 font-mono text-cyan-400">Z:</span> <input id="part-pos-z" type="range" min="-3" max="3" step="0.05" value="0" disabled oninput="manualPartOffset('z', this.value)" class="w-full h-1 bg-slate-800 rounded range-slider"> </div> </div> </div> </aside> <!-- RIGHT SIDEBAR: SYSTEM COMMANDS & DIAGNOSTICS --> <aside id="hud-right-panel" class="hud-overlay top-20 right-4 bottom-6 w-80 hud-glass rounded-xl p-4 flex flex-col justify-between overflow-y-auto"> <div> <!-- Section Header --> <div class="flex justify-between items-center border-b border-cyan-500/30 pb-2 mb-4"> <span class="font-orbitron text-xs font-bold tracking-widest text-cyan-300 flex items-center gap-2"> <i class="fa-solid fa-microchip text-cyan-400"></i> JARVIS PROTOCOLS </span> <span class="text-[10px] bg-amber-500/20 text-amber-300 px-2 py-0.5 rounded font-mono border border-amber-500/30">ONLINE</span> </div> <!-- Preset Commands Grid --> <div class="grid grid-cols-2 gap-2 mb-4"> <button onclick="triggerOverclock()" class="hud-glass p-2.5 rounded text-left hover:border-amber-400/70 border border-cyan-500/20 transition"> <i class="fa-solid fa-bolt text-amber-400 text-sm mb-1"></i> <div class="font-orbitron text-[11px] text-cyan-200">OVERCLOCK</div> <div class="text-[9px] text-cyan-400/60">Arc Matrix Boost</div> </button> <button onclick="triggerScanner()" class="hud-glass p-2.5 rounded text-left hover:border-cyan-400/70 border border-cyan-500/20 transition"> <i class="fa-solid fa-radar text-cyan-400 text-sm mb-1"></i> <div class="font-orbitron text-[11px] text-cyan-200">SCAN SUIT</div> <div class="text-[9px] text-cyan-400/60">Biometric Audit</div> </button> <button onclick="toggleWireframe()" class="hud-glass p-2.5 rounded text-left hover:border-cyan-400/70 border border-cyan-500/20 transition"> <i class="fa-solid fa-border-all text-cyan-400 text-sm mb-1"></i> <div class="font-orbitron text-[11px] text-cyan-200">WIREFRAME</div> <div class="text-[9px] text-cyan-400/60">Holo Mesh Mode</div> </button> <button onclick="toggleFocusMode(true)" class="hud-glass p-2.5 rounded text-left hover:border-sky-400/70 border border-cyan-500/20 transition"> <i class="fa-solid fa-eye text-sky-400 text-sm mb-1"></i> <div class="font-orbitron text-[11px] text-cyan-200">FOCUS MODE</div> <div class="text-[9px] text-cyan-400/60">Hide All HUDs</div> </button> </div> <!-- Voice Command Cheatsheet --> <div class="hud-glass p-3 rounded-lg border border-cyan-500/20 mb-4"> <div class="font-orbitron text-xs text-cyan-300 font-bold mb-2 flex items-center gap-1.5"> <i class="fa-solid fa-headset text-cyan-400"></i> VOICE COMMAND GUIDE </div> <div class="space-y-1 text-[11px] font-mono text-cyan-200/80"> <div class="flex justify-between border-b border-cyan-500/10 pb-0.5"> <span class="text-amber-300">"Jarvis Explode"</span> <span class="text-cyan-400/60">Explodes View</span> </div> <div class="flex justify-between border-b border-cyan-500/10 pb-0.5"> <span class="text-amber-300">"Assemble Suit"</span> <span class="text-cyan-400/60">Reset Armor</span> </div> <div class="flex justify-between border-b border-cyan-500/10 pb-0.5"> <span class="text-amber-300">"Isolate Helmet"</span> <span class="text-cyan-400/60">Focus Head</span> </div> <div class="flex justify-between border-b border-cyan-500/10 pb-0.5"> <span class="text-amber-300">"Isolate Chest"</span> <span class="text-cyan-400/60">Focus Core</span> </div> <div class="flex justify-between border-b border-cyan-500/10 pb-0.5"> <span class="text-amber-300">"Focus Hologram"</span> <span class="text-cyan-400/60">Clean Mode</span> </div> <div class="flex justify-between"> <span class="text-amber-300">"Overclock"</span> <span class="text-cyan-400/60">Energy Burst</span> </div> </div> </div> <!-- Diagnostic Live Speech Terminal Log --> <div class="hud-glass p-3 rounded-lg border border-cyan-500/20"> <div class="flex justify-between items-center mb-1.5"> <span class="font-orbitron text-[10px] text-cyan-400 tracking-wider">JARVIS LOG TERMINAL</span> <span class="w-1.5 h-1.5 rounded-full bg-cyan-400 animate-ping"></span> </div> <div id="voice-log" class="h-24 overflow-y-auto font-mono text-[10px] text-cyan-300/80 space-y-1 pr-1"> <p class="text-emerald-400">&gt; JARVIS v4.2 initialized successfully.</p> <p class="text-cyan-400/60">&gt; Waiting for user interaction or voice query...</p> </div> 1 </div> </div> 1 <!-- Audio Sound SFX Toggle Bar --> <div class="mt-4 pt-3 border-t border-cyan-500/20 flex justify-between items-center text-xs"> <span class="font-orbitron text-cyan-400 text-[11px]">AUDIO FX SYNTH</span> <button id="sfx-btn" onclick="toggleAudioSFX()" class="px-2.5 py-1 rounded bg-cyan-500/20 text-cyan-300 border border-cyan-400/40 text-[10px] font-orbitron"> AUDIO: ON </button> </div> </aside> <!-- FLOATING HOLOGRAM PART LABEL (Follows 3D Coordinates) --> <div id="holo-part-label" class="part-label opacity-0 pointer-events-none"> <div class="hud-glass-gold px-3 py-1.5 rounded border border-amber-400/60 text-amber-200 text-xs font-orbitron shadow-lg flex items-center gap-2"> <span class="w-2 h-2 rounded-full bg-amber-400 animate-pulse"></span> <span id="holo-label-text">HELMET MODULE</span> </div> </div> <!-- MAIN JAVASCRIPT LOGIC --> <script> /* ---------------------------------------------------- * GLOBAL STATE & VARIABLES * ---------------------------------------------------- */ let scene, camera, renderer, controls; let suitGroup, gridFloor, scanBeam, particleSystem; let suitParts = {}; // Map of individual suit meshes/groups let originalPositions = {}; // Stores default assembled coordinates let selectedPart = null; let isExploded = false; let explodeFactor = 0; // 0 (assembled) to 1 (full explosion) let isWireframe = false; let isOverclocked = false; let isFocusMode = false; // Audio & Speech let audioCtx = null; let isAudioEnabled = true; let hologramHumNode = null; let speechRecognition = null; let isListening = false; /* ---------------------------------------------------- * INITIALIZATION & THREE.JS SETUP * ---------------------------------------------------- */ window.addEventListener('load', () => { initThreeJS(); buildIronManSuit(); initParticleSystem(); initAudioEngine(); initSpeechRecognition(); animate(); // Resize Handler window.addEventListener('resize', onWindowResize); // Raycasting for individual part click and drag const container = document.getElementById('canvas-container'); container.addEventListener('click', onCanvasClick); // Focus Mode Dismiss Click window.addEventListener('click', (e) => { if (isFocusMode && e.target.tagName !== 'BUTTON' && e.target.tagName !== 'INPUT') { toggleFocusMode(false); } }); logTerminal("System ready. Say 'JARVIS' or click suit components."); }); function initThreeJS() { const container = document.getElementById('canvas-container'); // Scene Setup scene = new THREE.Scene(); scene.fog = new THREE.FogExp2(0x020617, 0.035); // Camera Setup camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100); camera.position.set(0, 1.2, 5.5); // Renderer Setup renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.shadowMap.enabled = true; renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.2; container.appendChild(renderer.domElement); // Orbit Controls controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.maxPolarAngle = Math.PI / 2 + 0.1; controls.minDistance = 2; controls.maxDistance = 12; controls.target.set(0, 0, 0); // Lighting Setup const ambientLight = new THREE.AmbientLight(0x082f49, 1.5); scene.add(ambientLight); const cyanLight = new THREE.PointLight(0x38bdf8, 3, 10); cyanLight.position.set(2, 3, 2); scene.add(cyanLight); const goldLight = new THREE.PointLight(0xf59e0b, 2, 8); goldLight.position.set(-2, 1, 2); scene.add(goldLight); const arcLight = new THREE.PointLight(0x06b6d4, 4, 5); arcLight.position.set(0, 0.4, 0.5); scene.add(arcLight); // Holographic Grid Floor const gridHelper = new THREE.GridHelper(20, 40, 0x38bdf8, 0x0284c7); gridHelper.position.y = -2; gridHelper.material.opacity = 0.35; gridHelper.material.transparent = true; scene.add(gridHelper); // Holographic Scanning Beam Ring const beamGeo = new THREE.RingGeometry(0.1, 2.5, 32); const beamMat = new THREE.MeshBasicMaterial({ color: 0x38bdf8, side: THREE.DoubleSide, transparent: true, opacity: 0.25, wireframe: true }); scanBeam = new THREE.Mesh(beamGeo, beamMat); scanBeam.rotation.x = Math.PI / 2; scanBeam.position.y = -1.95; scene.add(scanBeam); } /* ---------------------------------------------------- * PROCEDURAL IRON MAN MARK 85 ARMOR GEOMETRY ENGINE * ---------------------------------------------------- */ function buildIronManSuit() { suitGroup = new THREE.Group(); scene.add(suitGroup); // Hologram Material Generators const cyanHoloMat = new THREE.MeshStandardMaterial({ color: 0x0284c7, emissive: 0x0369a1, roughness: 0.2, metalness: 0.8, wireframe: false, transparent: true, opacity: 0.85 }); const goldHoloMat = new THREE.MeshStandardMaterial({ color: 0xd97706, emissive: 0xb45309, roughness: 0.3, metalness: 0.9, transparent: true, opacity: 0.85 }); const arcCoreMat = new THREE.MeshBasicMaterial({ color: 0x67e8f9, wireframe: true }); // 1. HELMET / FACEPLATE MODULE const helmetGroup = new THREE.Group(); const headGeo = new THREE.SphereGeometry(0.26, 16, 16); headGeo.scale(1, 1.15, 1); const headMesh = new THREE.Mesh(headGeo, cyanHoloMat); helmetGroup.add(headMesh); // Faceplate Shield const faceGeo = new THREE.BoxGeometry(0.24, 0.28, 0.15); const faceMesh = new THREE.Mesh(faceGeo, goldHoloMat); faceMesh.position.set(0, 0.02, 0.16); faceMesh.rotation.x = -0.1; helmetGroup.add(faceMesh); // Glowing Eyes const eyeGeo = new THREE.BoxGeometry(0.08, 0.02, 0.02); const eyeLeft = new THREE.Mesh(eyeGeo, arcCoreMat); const eyeRight = new THREE.Mesh(eyeGeo, arcCoreMat); eyeLeft.position.set(-0.07, 0.04, 0.23); eyeRight.position.set(0.07, 0.04, 0.23); helmetGroup.add(eyeLeft, eyeRight); helmetGroup.position.set(0, 1.2, 0); suitGroup.add(helmetGroup); registerPart('Helmet', helmetGroup, new THREE.Vector3(0, 1.6, 0)); // 2. CHESTPLATE & ARC REACTOR CORE MODULE const chestGroup = new THREE.Group(); const chestGeo = new THREE.CylinderGeometry(0.42, 0.3, 0.65, 8); const chestMesh = new THREE.Mesh(chestGeo, cyanHoloMat); chestGroup.add(chestMesh); // Gold Chest Trim Plates const trimGeo = new THREE.BoxGeometry(0.22, 0.35, 0.1); const trimL = new THREE.Mesh(trimGeo, goldHoloMat); const trimR = new THREE.Mesh(trimGeo, goldHoloMat); trimL.position.set(-0.16, 0.08, 0.18); trimL.rotation.z = -0.2; trimR.position.set(0.16, 0.08, 0.18); trimR.rotation.z = 0.2; chestGroup.add(trimL, trimR); // Arc Reactor Core (Triangular / Circular Housing) const arcGeo = new THREE.TorusGeometry(0.1, 0.025, 8, 24); const arcMesh = new THREE.Mesh(arcGeo, arcCoreMat); arcMesh.position.set(0, 0.1, 0.24); chestGroup.add(arcMesh); const arcInnerGeo = new THREE.OctahedronGeometry(0.06); const arcInnerMesh = new THREE.Mesh(arcInnerGeo, new THREE.MeshBasicMaterial({ color: 0xffffff })); arcInnerMesh.position.set(0, 0.1, 0.24); chestGroup.add(arcInnerMesh); chestGroup.position.set(0, 0.5, 0); suitGroup.add(chestGroup); registerPart('Chest', chestGroup, new THREE.Vector3(0, 0.8, 0)); // 3. RIGHT ARM & GAUNTLET MODULE const rightArmGroup = new THREE.Group(); const rShoulderGeo = new THREE.SphereGeometry(0.2, 12, 12); const rShoulder = new THREE.Mesh(rShoulderGeo, goldHoloMat); rShoulder.position.set(0, 0, 0); const rBicepGeo = new THREE.CylinderGeometry(0.11, 0.09, 0.35, 8); const rBicep = new THREE.Mesh(rBicepGeo, cyanHoloMat); rBicep.position.set(0, -0.22, 0); const rGauntletGeo = new THREE.CylinderGeometry(0.1, 0.08, 0.35, 8); const rGauntlet = new THREE.Mesh(rGauntletGeo, goldHoloMat); rGauntlet.position.set(0, -0.52, 0); // Repulsor Palm const rRepulsor = new THREE.Mesh(new THREE.CircleGeometry(0.04, 12), arcCoreMat); rRepulsor.position.set(0, -0.7, 0.05); rRepulsor.rotation.x = Math.PI / 2; rightArmGroup.add(rShoulder, rBicep, rGauntlet, rRepulsor); rightArmGroup.position.set(-0.52, 0.65, 0); suitGroup.add(rightArmGroup); registerPart('RightArm', rightArmGroup, new THREE.Vector3(-1.2, 0.5, 0)); // 4. LEFT ARM & GAUNTLET MODULE const leftArmGroup = new THREE.Group(); const lShoulder = new THREE.Mesh(rShoulderGeo, goldHoloMat); const lBicep = new THREE.Mesh(rBicepGeo, cyanHoloMat); lBicep.position.set(0, -0.22, 0); const lGauntlet = new THREE.Mesh(rGauntletGeo, goldHoloMat); lGauntlet.position.set(0, -0.52, 0); const lRepulsor = new THREE.Mesh(new THREE.CircleGeometry(0.04, 12), arcCoreMat); lRepulsor.position.set(0, -0.7, 0.05); lRepulsor.rotation.x = Math.PI / 2; leftArmGroup.add(lShoulder, lBicep, lGauntlet, lRepulsor); leftArmGroup.position.set(0.52, 0.65, 0); suitGroup.add(leftArmGroup); registerPart('LeftArm', leftArmGroup, new THREE.Vector3(1.2, 0.5, 0)); // 5. WAIST & LEGS MODULE const legsGroup = new THREE.Group(); const waistGeo = new THREE.CylinderGeometry(0.3, 0.25, 0.25, 8); const waist = new THREE.Mesh(waistGeo, goldHoloMat); waist.position.set(0, 0, 0); // Thighs const thighGeo = new THREE.CylinderGeometry(0.13, 0.1, 0.5, 8); const thighR = new THREE.Mesh(thighGeo, cyanHoloMat); const thighL = new THREE.Mesh(thighGeo, cyanHoloMat); thighR.position.set(-0.18, -0.32, 0); thighL.position.set(0.18, -0.32, 0); // Lower Legs / Boots const bootGeo = new THREE.CylinderGeometry(0.1, 0.08, 0.55, 8); const bootR = new THREE.Mesh(bootGeo, goldHoloMat); const bootL = new THREE.Mesh(bootGeo, goldHoloMat); bootR.position.set(-0.18, -0.82, 0); bootL.position.set(0.18, -0.82, 0); // Thruster Soles const soleR = new THREE.Mesh(new THREE.CircleGeometry(0.06, 12), arcCoreMat); const soleL = new THREE.Mesh(new THREE.CircleGeometry(0.06, 12), arcCoreMat); soleR.position.set(-0.18, -1.1, 0); soleR.rotation.x = Math.PI / 2; soleL.position.set(0.18, -1.1, 0); soleL.rotation.x = Math.PI / 2; legsGroup.add(waist, thighR, thighL, bootR, bootL, soleR, soleL); legsGroup.position.set(0, 0.05, 0); suitGroup.add(legsGroup); registerPart('Legs', legsGroup, new THREE.Vector3(0, -0.8, 0)); } // Helper to register modular part metadata function registerPart(name, groupObject, explodedOffset) { suitParts[name] = groupObject; groupObject.userData = { name: name, basePos: groupObject.position.clone(), explodedOffset: explodedOffset, manualOffset: new THREE.Vector3(0, 0, 0) }; originalPositions[name] = groupObject.position.clone(); } /* ---------------------------------------------------- * ADVANCED PARTICLE SYSTEM (Arc Core Energy Streams) * ---------------------------------------------------- */ function initParticleSystem() { const particleCount = 200; const geometry = new THREE.BufferGeometry(); const positions = new Float32Array(particleCount * 3); const colors = new Float32Array(particleCount * 3); for (let i = 0; i < particleCount; i++) { const radius = 0.3 + Math.random() * 1.5; const theta = Math.random() * Math.PI * 2; const y = (Math.random() - 0.5) * 3; positions[i * 3] = radius * Math.cos(theta); positions[i * 3 + 1] = y; positions[i * 3 + 2] = radius * Math.sin(theta); colors[i * 3] = 0.2; colors[i * 3 + 1] = 0.7; colors[i * 3 + 2] = 1.0; } geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); const material = new THREE.PointsMaterial({ size: 0.03, vertexColors: true, transparent: true, opacity: 0.6, blending: THREE.AdditiveBlending }); particleSystem = new THREE.Points(geometry, material); scene.add(particleSystem); } /* ---------------------------------------------------- * INTERACTIVE CLICK, SELECTION & RAYCASTING * ---------------------------------------------------- */ function onCanvasClick(event) { // Ignore click if in focus mode transition if (isFocusMode) return; const mouse = new THREE.Vector2( (event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1 ); const raycaster = new THREE.Raycaster(); raycaster.setFromCamera(mouse, camera); // Collect all interactive sub-meshes const interactiveMeshes = []; Object.values(suitParts).forEach(group => { group.traverse(child => { if (child.isMesh) { child.userData.parentPart = group.userData.name; interactiveMeshes.push(child); } }); }); const intersects = raycaster.intersectObjects(interactiveMeshes); if (intersects.length > 0) { const hitMesh = intersects[0].object; const partName = hitMesh.userData.parentPart; if (partName) { selectPart(partName); playLaserSFX(); } } } function selectPart(partName) { selectedPart = suitParts[partName]; if (!selectedPart) return; // Update UI Sidebar document.getElementById('selected-part-name').innerText = partName.toUpperCase() + ' MODULE'; document.getElementById('selected-part-desc').innerText = `Active sub-assembly selected. Use sliders or click & drag to adjust 3D offsets.`; // Enable position sliders ['x', 'y', 'z'].forEach(axis => { const input = document.getElementById(`part-pos-${axis}`); input.disabled = false; input.value = selectedPart.userData.manualOffset[axis]; }); // Update 3D Floating Tag updatePartLabelPosition(); speakJARVIS(`Inspecting ${partName} module, Boss.`); logTerminal(`Selected module: ${partName}`); } function manualPartOffset(axis, val) { if (!selectedPart) return; val = parseFloat(val); selectedPart.userData.manualOffset[axis] = val; updatePartTransforms(); } function updatePartTransforms() { Object.values(suitParts).forEach(part => { const base = part.userData.basePos; const explode = part.userData.explodedOffset; const manual = part.userData.manualOffset; // Interpolate target position based on explodedFactor part.position.x = THREE.MathUtils.lerp(base.x, explode.x, explodeFactor) + manual.x; part.position.y = THREE.MathUtils.lerp(base.y, explode.y, explodeFactor) + manual.y; part.position.z = THREE.MathUtils.lerp(base.z, explode.z, explodeFactor) + manual.z; }); } /* ---------------------------------------------------- * EXPLOEDED VIEW ENGINE & ISOLATION COMMANDS * ---------------------------------------------------- */ function updateExplodeFromSlider(val) { explodeFactor = val / 100; document.getElementById('explode-val-text').innerText = `${val}%`; updatePartTransforms(); } function triggerExplode() { let start = explodeFactor; let target = 1.0; animateValue(start, target, 800, (v) => { explodeFactor = v; document.getElementById('explode-slider').value = v * 100; document.getElementById('explode-val-text').innerText = `${Math.round(v * 100)}%`; updatePartTransforms(); }); speakJARVIS("Armor matrix disassembly initialized. Displaying exploded view."); logTerminal("Command executed: EXPLODE SUIT PARTS"); playScanSFX(); } function triggerAssemble() { let start = explodeFactor; let target = 0.0; // Reset manual offsets as well Object.values(suitParts).forEach(p => p.userData.manualOffset.set(0, 0, 0)); if (selectedPart) { ['x', 'y', 'z'].forEach(a => document.getElementById(`part-pos-${a}`).value = 0); } animateValue(start, target, 800, (v) => { explodeFactor = v; document.getElementById('explode-slider').value = v * 100; document.getElementById('explode-val-text').innerText = `${Math.round(v * 100)}%`; updatePartTransforms(); }); speakJARVIS("Reassembling Mark 85 components into combat stance."); logTerminal("Command executed: ASSEMBLE SUIT"); playScanSFX(); } function isolatePart(partName) { triggerExplode(); setTimeout(() => { selectPart(partName); }, 400); } function resetIsolation() { triggerAssemble(); selectedPart = null; document.getElementById('selected-part-name').innerText = 'CLICK PART TO MOVE'; document.getElementById('selected-part-desc').innerText = 'Select any armor piece with left click to adjust offset positions.'; ['x', 'y', 'z'].forEach(axis => { const input = document.getElementById(`part-pos-${axis}`); input.disabled = true; input.value = 0; }); document.getElementById('holo-part-label').classList.add('opacity-0'); } /* ---------------------------------------------------- * FOCUS HOLOGRAM MODE (UI CLEAN VIEW) * ---------------------------------------------------- */ function toggleFocusMode(enable) { isFocusMode = enable; const overlays = document.querySelectorAll('.hud-overlay'); const hint = document.getElementById('focus-restore-hint'); if (isFocusMode) { overlays.forEach(el => el.classList.add('hud-hidden')); hint.classList.remove('opacity-0'); speakJARVIS("Hologram Focus Mode engaged, Boss."); logTerminal("Focus mode ENABLED."); } else { overlays.forEach(el => el.classList.remove('hud-hidden')); hint.classList.add('opacity-0'); speakJARVIS("Restoring HUD primary interface display."); logTerminal("Focus mode DISABLED."); } } /* ---------------------------------------------------- * SYSTEM PROTOCOLS (OVERCLOCK, SCANNER, WIREFRAME) * ---------------------------------------------------- */ function triggerOverclock() { isOverclocked = !isOverclocked; playPulseSFX(); Object.values(suitParts).forEach(group => { group.traverse(child => { if (child.isMesh && child.material) { if (isOverclocked) { child.material.emissiveIntensity = 2.5; } else { child.material.emissiveIntensity = 1.0; } } }); }); if (isOverclocked) { speakJARVIS("Warning! Arc reactor overclocked to 150% output!"); logTerminal("OVERCLOCK ACTIVATED!"); document.getElementById('power-output').innerText = "PWR: 150% OVERCLOCK"; document.getElementById('power-output').classList.add('animate-pulse'); } else { speakJARVIS("Power output normalized."); logTerminal("OVERCLOCK DEACTIVATED."); document.getElementById('power-output').innerText = "PWR: 100% ARC CORE"; document.getElementById('power-output').classList.remove('animate-pulse'); } } function triggerScanner() { playScanSFX(); speakJARVIS("Initiating full suit biometric and structural audit."); logTerminal("Scanner active: All systems 100% operational."); // Animate scanning ring upward scanBeam.position.y = -2; let scanAnim = setInterval(() => { scanBeam.position.y += 0.08; if (scanBeam.position.y > 2) { scanBeam.position.y = -1.95; clearInterval(scanAnim); } }, 30); } function toggleWireframe() { isWireframe = !isWireframe; Object.values(suitParts).forEach(group => { group.traverse(child => { if (child.isMesh && child.material) { child.material.wireframe = isWireframe; } }); }); speakJARVIS(isWireframe ? "Wireframe holographic mesh enabled." : "Solid armor rendering restored."); logTerminal(`Wireframe mode: ${isWireframe ? 'ON' : 'OFF'}`); } /* ---------------------------------------------------- * WEB AUDIO API SYNTHESIS (NO EXTERNAL ASSETS) * ---------------------------------------------------- */ function initAudioEngine() { try { window.AudioContext = window.AudioContext || window.webkitAudioContext; audioCtx = new AudioContext(); } catch (e) { console.warn("Web Audio API not supported"); } } function toggleAudioSFX() { isAudioEnabled = !isAudioEnabled; document.getElementById('sfx-btn').innerText = isAudioEnabled ? "AUDIO: ON" : "AUDIO: OFF"; logTerminal(`Audio SFX system: ${isAudioEnabled ? 'ENABLED' : 'MUTED'}`); } function playLaserSFX() { if (!isAudioEnabled || !audioCtx) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = 'sine'; osc.frequency.setValueAtTime(800, audioCtx.currentTime); osc.frequency.exponentialRampToValueAtTime(150, audioCtx.currentTime + 0.15); gain.gain.setValueAtTime(0.3, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.15); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); osc.stop(audioCtx.currentTime + 0.15); } function playScanSFX() { if (!isAudioEnabled || !audioCtx) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = 'sawtooth'; osc.frequency.setValueAtTime(200, audioCtx.currentTime); osc.frequency.linearRampToValueAtTime(1200, audioCtx.currentTime + 0.4); gain.gain.setValueAtTime(0.2, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.4); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); osc.stop(audioCtx.currentTime + 0.4); } function playPulseSFX() { if (!isAudioEnabled || !audioCtx) return; const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = 'triangle'; osc.frequency.setValueAtTime(100, audioCtx.currentTime); osc.frequency.linearRampToValueAtTime(500, audioCtx.currentTime + 0.3); gain.gain.setValueAtTime(0.4, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.3); osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); osc.stop(audioCtx.currentTime + 0.3); } /* ---------------------------------------------------- * WEB SPEECH RECOGNITION & VOICE SYNTHESIS * ---------------------------------------------------- */ function initSpeechRecognition() { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (!SpeechRecognition) { logTerminal("Speech Recognition not supported in this browser.", true); return; } speechRecognition = new SpeechRecognition(); speechRecognition.continuous = true; speechRecognition.interimResults = false; speechRecognition.lang = 'en-US'; speechRecognition.onresult = (event) => { const transcript = event.results[event.results.length - 1][0].transcript.trim().toLowerCase(); logTerminal(`Voice input: "${transcript}"`); parseVoiceCommand(transcript); }; speechRecognition.onerror = (e) => { console.warn("Speech recognition error:", e.error); }; speechRecognition.onend = () => { if (isListening) speechRecognition.start(); // Keep listening active }; } function toggleVoiceRecognition() { if (!speechRecognition) { alert("Web Speech API is not supported in this browser. Please use Chrome/Edge."); return; } const btn = document.getElementById('mic-btn'); const pulse = document.getElementById('mic-pulse'); if (!isListening) { try { speechRecognition.start(); isListening = true; btn.classList.add('border-red-500', 'text-red-400'); pulse.classList.remove('hidden'); speakJARVIS("Voice recognition activated. Listening for commands."); logTerminal("JARVIS listening for voice commands..."); } catch (err) { console.error(err); } } else { speechRecognition.stop(); isListening = false; btn.classList.remove('border-red-500', 'text-red-400'); pulse.classList.add('hidden'); speakJARVIS("Voice system offline."); logTerminal("JARVIS voice recognition stopped."); } } function parseVoiceCommand(cmd) { if (cmd.includes('explode') || cmd.includes('disassemble')) { triggerExplode(); } else if (cmd.includes('assemble') || cmd.includes('suit up')) { triggerAssemble(); } else if (cmd.includes('helmet') || cmd.includes('head')) { isolatePart('Helmet'); } else if (cmd.includes('chest') || cmd.includes('arc') || cmd.includes('core')) { isolatePart('Chest'); } else if (cmd.includes('arm') || cmd.includes('hand')) { isolatePart('RightArm'); } else if (cmd.includes('leg') || cmd.includes('boot')) { isolatePart('Legs'); } else if (cmd.includes('focus') || cmd.includes('hologram only')) { toggleFocusMode(true); } else if (cmd.includes('hud') || cmd.includes('show ui')) { toggleFocusMode(false); } else if (cmd.includes('overclock') || cmd.includes('power')) { triggerOverclock(); } else if (cmd.includes('scan')) { triggerScanner(); } else if (cmd.includes('jarvis')) { speakJARVIS("At your service, Boss."); } } function speakJARVIS(text) { if ('speechSynthesis' in window) { window.speechSynthesis.cancel(); // Stop current speech const utterance = new SpeechSynthesisUtterance(text); // Find a sleek male voice if available const voices = window.speechSynthesis.getVoices(); const jarvisVoice = voices.find(v => v.name.includes('Natural') || v.name.includes('David') || v.name.includes('Google UK English Male')); if (jarvisVoice) utterance.voice = jarvisVoice; utterance.pitch = 0.9; utterance.rate = 1.0; window.speechSynthesis.speak(utterance); } } /* ---------------------------------------------------- * UTILITIES & RENDER LOOP * ---------------------------------------------------- */ function updatePartLabelPosition() { const label = document.getElementById('holo-part-label'); if (!selectedPart) { label.classList.add('opacity-0'); return; } const worldPos = new THREE.Vector3(); selectedPart.getWorldPosition(worldPos); // Project 3D vector to 2D screen coordinates const projected = worldPos.clone().project(camera); const x = (projected.x * 0.5 + 0.5) * window.innerWidth; const y = (-(projected.y * 0.5) + 0.5) * window.innerHeight; label.style.left = `${x}px`; label.style.top = `${y}px`; document.getElementById('holo-label-text').innerText = `${selectedPart.userData.name.toUpperCase()} MODULE`; label.classList.remove('opacity-0'); } function animate() { requestAnimationFrame(animate); // Rotate main hologram gently if (suitGroup) { suitGroup.rotation.y += 0.003; } // Animate Particles if (particleSystem) { particleSystem.rotation.y += 0.002; } // Pulse Scan Beam if (scanBeam) { scanBeam.rotation.z += 0.01; } // Update Label Tracker if (selectedPart) { updatePartLabelPosition(); } controls.update(); renderer.render(scene, camera); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animateValue(start, end, duration, callback) { let startTimestamp = null; const step = (timestamp) => { if (!startTimestamp) startTimestamp = timestamp; const progress = Math.min((timestamp - startTimestamp) / duration, 1); const currentVal = start + progress * (end - start); callback(currentVal); if (progress < 1) { window.requestAnimationFrame(step); } }; window.requestAnimationFrame(step); } function logTerminal(msg, isError = false) { const logBox = document.getElementById('voice-log'); if (!logBox) return; const p = document.createElement('p'); p.className = isError ? "text-red-400 font-bold" : "text-cyan-300/80"; p.innerText = `> ${msg}`; logBox.appendChild(p); logBox.scrollTop = logBox.scrollHeight; } </script> </body> </html><!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HOLO SUIT - FROM IMAGE</title> <style> body{margin:0;background:#000;overflow:hidden;font-family:monospace;color:#00f0ff} #video{position:fixed;top:0;left:0;width:100vw;height:100vh;object-fit:cover;transform:scaleX(-1);z-index:1} #canvas{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2} .hud{position:fixed;z-index:5;width:100vw;height:100vh;padding:10px;box-sizing:border-box;border:2px solid #00f0ff;pointer-events:none} .top{display:flex;justify-content:space-between;font-size:11px;border-bottom:1px solid #00f0ff;padding-bottom:5px;background:rgba(0,0,0,0.6)} .suit-container{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:3;display:flex;align-items:center;justify-content:center;pointer-events:none} #h
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

10

Requests

6

Domains

499KB

Transfer Size

1347KB

Content Size

535.0ms

Dom Content Loaded

816.0ms

First Paint

713.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...