QC67_cosmo / lostcosmo_enhanced.html
phera-ra's picture
Upload lostcosmo_enhanced.html
ea318ca verified
Raw
History Blame Contribute Delete
425 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="theme-color" content="#000">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="mobile-web-app-capable" content="yes">
<meta name="description" content="Genesis Engine - Revolutionary AI-powered quantum consciousness simulation with real-time environmental data processing">
<title>Genesis Engine: The Definitive Core - Advanced Tokenization</title>
<!-- DEPENDENCIES & STYLESHEETS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Solana Libraries for Wallet Integration -->
<script src="https://unpkg.com/@solana/web3.js@1.91.7/lib/index.iife.min.js"></script>
<script src="https://unpkg.com/@solana/spl-token@0.4.8/lib/index.iife.min.js"></script>
<script src="https://unpkg.com/@solana/spl-account-compression@0.2.2/lib/index.iife.min.js"></script>
<script src="https://unpkg.com/@metaplex-foundation/js@0.20.1/dist/index.umd.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&family=Roboto+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<!-- ES Module Imports for three.js -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.158.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.158.0/examples/jsm/"
}
}
</script>
<!-- ml5.js for Machine Learning -->
<script src="https://unpkg.com/ml5@0.12.2/dist/ml5.min.js"></script>
<style>
/* General Styling */
body { margin: 0; background-color: #000; color: #e2e8f0; overflow: hidden; font-family: 'Inter', sans-serif; cursor: crosshair; }
canvas { display: block; position: fixed; top: 0; left: 0; z-index: 1; }
.font-mono { font-family: 'Roboto Mono', monospace; }
/* UI Element Styling */
.ui-element { position: fixed; z-index: 10; background-color: rgba(15, 23, 42, 0.85); backdrop-filter: blur(12px); border: 1px solid rgba(51, 65, 85, 0.5); border-radius: 0.75rem; box-shadow: 0 10px 30px rgba(0,0,0,0.3); transition: opacity 0.3s ease, transform 0.3s ease; }
.ui-hidden { opacity: 0; pointer-events: none; transform: scale(0.95); }
/* Wallet animations */
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Mobile responsiveness */
@media (max-width: 768px) {
.ui-element {
width: calc(100vw - 24px) !important;
max-width: none !important;
left: 12px !important;
right: 12px !important;
}
.tab-button { font-size: 12px; padding: 0.25rem 0.75rem; }
}
@media (max-width: 480px) {
.ui-element {
top: 8px !important;
left: 8px !important;
right: 8px !important;
width: calc(100vw - 16px) !important;
padding: 8px !important;
}
.tab-button { font-size: 11px; padding: 4px 8px; }
}
/* Custom scrollbar styles */
.scrollbar-thin {
scrollbar-width: thin;
}
.scrollbar-thin::-webkit-scrollbar {
width: 6px;
}
.scrollbar-thin::-webkit-scrollbar-track {
background: rgba(30, 41, 59, 0.5);
border-radius: 3px;
}
.scrollbar-thin::-webkit-scrollbar-thumb {
background: rgba(71, 85, 105, 0.8);
border-radius: 3px;
}
.scrollbar-thin::-webkit-scrollbar-thumb:hover {
background: rgba(100, 116, 139, 0.9);
}
/* Music visualizer styles */
.visualizer-bar {
background: linear-gradient(180deg, #3b82f6, #1d4ed8);
border-radius: 2px;
transition: height 0.1s ease, opacity 0.3s ease;
box-shadow: 0 0 4px rgba(59, 130, 246, 0.5);
}
.visualizer-bar.active {
background: linear-gradient(180deg, #10b981, #059669);
box-shadow: 0 0 8px rgba(16, 185, 129, 0.8);
}
.frequency-spectrum {
display: flex;
align-items: end;
gap: 2px;
height: 60px;
padding: 4px;
background: rgba(0, 0, 0, 0.3);
border-radius: 4px;
}
.harmony-meter {
position: relative;
height: 8px;
background: rgba(0, 0, 0, 0.5);
border-radius: 4px;
overflow: hidden;
}
.harmony-fill {
height: 100%;
background: linear-gradient(90deg, #ef4444, #f59e0b, #10b981);
transition: width 0.5s ease;
border-radius: 4px;
}
.consciousness-ring {
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid rgba(59, 130, 246, 0.3);
position: relative;
}
.consciousness-fill {
position: absolute;
top: 3px;
left: 3px;
right: 3px;
bottom: 3px;
border-radius: 50%;
background: conic-gradient(from 0deg, #3b82f6 0%, transparent 0%);
transition: background 0.5s ease;
}
/* Touch controls styling */
* { -webkit-tap-highlight-color: rgba(0,0,0,0); }
html, body {
height: 100vh;
overflow: hidden;
touch-action: none;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
touch-action: none;
}
/* Modal & Blocker Styling */
#blocker, .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 100; background: rgba(0,0,0,0.8); display: flex; justify-content: center; align-items: center; flex-direction: column; text-align: center; transition: opacity 0.5s ease; }
#fps-hint { z-index: 101; background: none; backdrop-filter: none; border: none; box-shadow: none; font-size: 1.2rem; text-shadow: 0 0 10px black; color: #fff; }
/* Tab Navigation Styling */
.tab-button { background-color: transparent; border: none; color: #94a3b8; padding: 0.5rem 1rem; cursor: pointer; transition: color 0.2s, border-bottom-color 0.2s; border-bottom: 2px solid transparent; font-weight: 500;}
.tab-button.active { color: #e2e8f0; border-bottom-color: #4f46e5; }
.tab-content { display: none; }
.tab-content.active { display: block; }
/* Seed Visualizer & Data Pulse Animation */
#seed-visualizer { height: 60px; display: flex; align-items: center; justify-content: space-around; background: rgba(0,0,0,0.2); border-radius: 0.5rem; overflow: hidden;}
.data-stream { width: 15%; height: 100%; display: flex; align-items: center; justify-content: center; flex-direction: column; font-size: 0.6rem; text-transform: uppercase; color: #64748b; }
.data-pulse { width: 10px; height: 10px; background-color: #334155; border-radius: 50%; transition: background-color 0.1s, box-shadow 0.2s; }
@keyframes pulse-glow { 0% { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(56, 189, 248, 0); } 100% { box-shadow: 0 0 0 0 rgba(56, 189, 248, 0); } }
/* Button & Input Styling */
.btn { background-color: #4f46e5; color: white; font-weight: bold; padding: 0.5rem 1rem; border-radius: 0.5rem; border: none; transition: background-color 0.2s; cursor: pointer; text-align: center; }
.btn:hover { background-color: #6366f1; }
.btn:disabled { background-color: #4b5563; cursor: not-allowed; }
input[type="file"] { display: none; }
.slider-container, .toggle-container { display: flex; flex-direction: column; gap: 0.25rem; }
.slider-label, .toggle-label { display: flex; justify-content: space-between; font-size: 0.75rem; align-items:center;}
input[type=range] { -webkit-appearance: none; appearance: none; background: transparent; width: 100%;}
input[type=range]:focus { outline: none; }
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; background: #334155; border-radius: 2px; }
input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; border: 2px solid #4f46e5; height: 16px; width: 16px; border-radius: 50%; background: #0f172a; cursor: pointer; margin-top: -6px;}
/* Toggle Switch */
.switch { position: relative; display: inline-block; width: 34px; height: 20px; }
.switch input { opacity: 0; width: 0; height: 0; }
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #334155; transition: .4s; border-radius: 20px;}
.slider:before { position: absolute; content: ""; height: 12px; width: 12px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%;}
input:checked + .slider { background-color: #4f46e5; }
input:checked + .slider:before { transform: translateX(14px); }
/* Status pulse animation for dynamic states */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
</style>
</head>
<body>
<!-- Canvas Container for 3D Scene -->
<div id="canvas-container"></div>
<!-- Hidden Video Element for ML & Video Particlizer -->
<video id="video-feed" style="display:none;" autoplay muted playsinline></video>
<!-- Wallet Integration System -->
<div id="wallet-disconnected" class="ui-element" style="position: fixed; top: 20px; right: 20px; z-index: 1000; width: 300px;">
<div style="padding: 16px;">
<h3 style="margin: 0 0 12px 0; font-size: 14px; font-weight: 600;">🦄 Wallet Connection</h3>
<div style="display: flex; gap: 8px; margin-bottom: 12px;">
<button id="connect-phantom-btn" class="btn" style="flex: 1; padding: 8px 12px; background: linear-gradient(135deg, #7c3aed, #a855f7); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 500;">Connect Phantom</button>
<button id="connect-manual-btn" class="btn secondary" style="flex: 1; padding: 8px 12px; background: rgba(75, 85, 99, 0.8); color: white; border: 1px solid rgba(156, 163, 175, 0.3); border-radius: 6px; cursor: pointer; font-size: 12px;">Manual Input</button>
</div>
<div style="font-size: 11px; color: rgba(156, 163, 175, 0.8);">
Connect wallet to access Genesis Engine features
</div>
</div>
</div>
<div id="wallet-connected" class="ui-element" style="position: fixed; top: 20px; right: 20px; z-index: 1000; width: 320px; display: none;">
<div style="padding: 16px;">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
<h3 style="margin: 0; font-size: 14px; font-weight: 600;">🦄 Wallet Connected</h3>
<div id="wallet-status-indicator" class="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<div style="margin-bottom: 8px;">
<div style="font-size: 11px; color: rgba(156, 163, 175, 0.8); margin-bottom: 2px;">Address</div>
<div id="wallet-address-display" style="font-size: 12px; font-family: 'Roboto Mono', monospace; color: #e2e8f0; word-break: break-all;"></div>
</div>
<div style="margin-bottom: 12px;">
<div style="font-size: 11px; color: rgba(156, 163, 175, 0.8); margin-bottom: 2px;">Mobius Balance</div>
<div style="display: flex; align-items: center; gap: 8px;">
<div id="mobius-balance-display" style="font-size: 16px; font-weight: 600; color: #10b981;">0.00</div>
<div style="font-size: 12px; color: rgba(156, 163, 175, 0.8);">MOBIUS</div>
</div>
</div>
<div style="display: flex; gap: 8px;">
<button id="refresh-balance-btn" class="btn secondary" style="flex: 1; padding: 6px 12px; background: rgba(59, 130, 246, 0.8); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 11px;">Refresh Balance</button>
<button id="disconnect-wallet-btn" class="btn danger" style="flex: 1; padding: 6px 12px; background: rgba(239, 68, 68, 0.8); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 11px;">Disconnect</button>
</div>
</div>
</div>
<div id="wallet-loading" class="ui-element" style="position: fixed; top: 20px; right: 20px; z-index: 1000; width: 300px; display: none;">
<div style="padding: 16px; text-align: center;">
<div style="width: 24px; height: 24px; border: 2px solid rgba(156, 163, 175, 0.3); border-top: 2px solid #7c3aed; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 12px;"></div>
<div style="font-size: 14px; color: #e2e8f0;">Connecting Wallet...</div>
<div style="font-size: 11px; color: rgba(156, 163, 175, 0.8); margin-top: 4px;">Please approve in your wallet</div>
</div>
</div>
<!-- Initial Blocker/Loading Screen -->
<div id="blocker">
<div class="max-w-2xl px-4">
<h1 class="text-4xl md:text-5xl font-bold text-slate-100 mb-2">Genesis Engine</h1>
<h2 class="text-xl md:text-2xl font-light text-slate-400 mb-6">The Definitive Core</h2>
<p class="text-slate-400 mb-8">This engine transmutes reality into a digital cosmos. For the full experience, please grant access to your microphone, camera, and location when prompted. No data is stored or uploaded. This is a non-invasive, interactive art piece.</p>
<button id="start-button" class="btn bg-indigo-600 hover:bg-indigo-500 text-white font-bold py-3 px-8 rounded-lg text-lg transition-transform transform hover:scale-105">Initiate Genesis</button>
<p id="loading-message" class="text-slate-500 mt-4" style="display: none;">Calibrating sensor arrays...</p>
</div>
</div>
<!-- Modal for Memory Echo -->
<div id="datamodal" class="modal ui-hidden">
<div class="ui-element p-8 max-w-lg w-full">
<h3 class="text-2xl font-bold text-slate-100 mb-4">Memory Echo Detected</h3>
<p class="text-slate-300 mb-6">An artifact of pure data has been found, an echo of a world caught in a repeating tragedy. Provide the data catalyst (e.g., a .z64 ROM file) to transmute its contents into a playable memory echo.</p>
<input type="file" id="data-upload">
<label for="data-upload" class="mb-4 cursor-pointer w-full block text-center btn bg-green-600 hover:bg-green-500">Provide Data Catalyst</label>
<p id="data-status" class="text-sm text-yellow-400 mb-4">Awaiting file...</p>
<div class="flex justify-center gap-4">
<button id="modal-confirm-button" class="btn bg-red-600 hover:bg-red-500" disabled>Enter the Echo</button>
<button id="modal-cancel-button" class="btn bg-slate-600 hover:bg-slate-500">Return to Void</button>
</div>
</div>
</div>
<!-- Hint for First-Person Mode Controls -->
<div id="fps-hint" class="modal ui-hidden">
<p>First-Person Mode Active. Press ESC to release cursor.</p>
</div>
<!-- Main UI Toggle Button -->
<button id="toggle-ui-button" class="ui-element top-4 right-4 p-3 text-slate-300 hover:text-white hover:bg-slate-700 transition ui-hidden">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="9" y1="3" x2="9" y2="21"></line></svg>
</button>
<!-- Main UI Container -->
<div id="ui-container" class="ui-hidden">
<div class="ui-element top-4 left-4 w-96">
<div class="px-4 pt-3 pb-2 font-bold text-lg text-slate-300" id="system-status-readout">STATUS: STANDBY</div>
<div class="tabs border-b border-slate-700 px-2">
<button class="tab-button active" data-tab="controls">Controls</button>
<button class="tab-button" data-tab="graphics">Graphics</button>
<button class="tab-button" data-tab="data">Data Ledger</button>
<button class="tab-button" data-tab="telemetry">Telemetry</button>
<button class="tab-button" data-tab="cognitive">Cognitive Core</button>
</div>
<div id="tab-content-container" class="p-4">
<!-- CONTROLS TAB -->
<div id="tab-controls" class="tab-content active space-y-4">
<!-- Universe Controls -->
<button id="regenerate-button" class="btn w-full bg-slate-700 hover:bg-slate-600">Regenerate Universe</button>
<button id="anomaly-scanner-button" class="btn w-full bg-cyan-600 hover:bg-cyan-500">Scan for Anomalies</button>
<!-- Particlization Controls -->
<div class="grid grid-cols-2 gap-2">
<label for="file-upload" class="btn">Particlize File</label>
<button id="video-particlize-button" class="btn">Particlize Live</button>
<input type="file" id="file-upload" accept="image/*,video/*">
</div>
<button id="self-particlize-button" class="btn w-full bg-purple-600 hover:bg-purple-500">Particlize Self</button>
<!-- NFT Minting Controls -->
<div class="border-t border-slate-600 pt-4 mt-4">
<h3 class="text-sm font-semibold text-indigo-400 mb-3">NFT Minting</h3>
<button id="mint-avatar-btn" class="btn w-full bg-gradient-to-r from-purple-600 to-pink-600 hover:from-purple-700 hover:to-pink-700 disabled:opacity-50 disabled:cursor-not-allowed mb-2">
🎨 Mint Genesis Avatar
</button>
<div class="text-xs text-slate-400 text-center">
Cost: 10 MOBIUS tokens
</div>
<!-- Environmental Data Display -->
<div class="mt-3 p-2 bg-slate-800/50 rounded-md">
<div class="text-xs font-mono text-cyan-400 mb-1">Current Environmental Data:</div>
<div class="grid grid-cols-2 gap-1 text-xs">
<div>Light:</div><div id="env-light" class="text-yellow-400">--</div>
<div>Sound:</div><div id="env-sound" class="text-blue-400">--</div>
<div>Temp:</div><div id="env-temp" class="text-red-400">--</div>
<div>Humidity:</div><div id="env-humidity" class="text-green-400">--</div>
</div>
</div>
<!-- Minting Status -->
<div id="minting-status" class="mt-2 text-xs text-center hidden">
<div class="animate-pulse">Processing NFT mint...</div>
</div>
</div>
</div>
<!-- GRAPHICS TAB -->
<div id="tab-graphics" class="tab-content space-y-4 text-sm text-slate-300">
<div class="slider-container">
<label>View Mode</label>
<select id="view-mode-select" class="w-full bg-slate-800 text-slate-200 rounded-md p-2 mt-1 text-sm border border-slate-600">
<option value="orbit">Orbit</option>
<option value="first-person">First Person</option>
<option value="enhanced-fp">Spaceship (3rd Person)</option>
<option value="cockpit-view">Spaceship (Cockpit)</option>
<option value="cinematic">Cinematic</option>
</select>
</div>
<div class="slider-container">
<label>Graphics Style</label>
<select id="quality-select" class="w-full bg-slate-800 text-slate-200 rounded-md p-2 mt-1 text-sm border border-slate-600">
<option value="low">Low (Pixelated)</option>
<option value="medium" selected>Medium (Realistic)</option>
<option value="high">High (Realistic)</option>
<option value="ultra">Ultra (Realistic)</option>
<option value="anime">Anime (Cel-Shaded)</option>
</select>
</div>
<div class="slider-container">
<label>Color Filter</label>
<select id="filter-select" class="w-full bg-slate-800 text-slate-200 rounded-md p-2 mt-1 text-sm border border-slate-600">
<option value="none">None</option>
<option value="cool">Cool</option>
<option value="warm">Warm</option>
<option value="nebula">Nebula</option>
<option value="monochrome">Monochrome</option>
</select>
</div>
<div class="slider-container">
<div class="slider-label"><span>Brightness</span><span id="brightness-value">1.0</span></div>
<input type="range" id="brightness-slider" min="0" max="2" value="1" step="0.05" class="w-full">
</div>
<!-- NEW: Procedural Audio Toggle -->
<div class="toggle-container">
<div class="toggle-label">
<span>Enable Ambient Audio</span>
<label class="switch">
<input type="checkbox" id="ambient-audio-toggle">
<span class="slider"></span>
</label>
</div>
</div>
<!-- Motion Blur Controls -->
<div class="toggle-container">
<div class="toggle-label">
<span>Motion Blur</span>
<label class="switch">
<input type="checkbox" id="motion-blur-toggle">
<span class="slider"></span>
</label>
</div>
</div>
<div class="slider-container">
<div class="slider-label"><span>Motion Blur Intensity</span><span id="motion-blur-value">0.20</span></div>
<input type="range" id="motion-blur-slider" min="0" max="1" value="0.2" step="0.01" class="w-full">
</div>
</div>
<!-- DATA LEDGER TAB -->
<div id="tab-data" class="tab-content space-y-2">
<div id="genesis-log-content" class="text-sm font-mono text-slate-400 max-h-48 overflow-y-auto"></div>
<button id="download-ledger-button" class="btn w-full bg-green-600 hover:bg-green-500 mt-2">Download Ledger</button>
</div>
<!-- TELEMETRY TAB -->
<div id="tab-telemetry" class="tab-content space-y-2">
<input id="telemetry-filter" class="w-full bg-slate-800 text-slate-200 rounded-md p-2 text-sm border border-slate-600" placeholder="Filter by type or token (e.g., audio,BASS_HIGH, ml:person)">
<div id="telemetry-log-content" class="text-xs font-mono text-slate-400 max-h-60 overflow-y-auto whitespace-pre-wrap"></div>
<button id="download-telemetry-button" class="btn w-full bg-cyan-600 hover:bg-cyan-500 mt-2">Download Telemetry</button>
</div>
<!-- COGNITIVE CORE TAB -->
<div id="tab-cognitive" class="tab-content space-y-3 text-sm text-slate-300 max-h-96 overflow-y-auto scrollbar-thin scrollbar-thumb-slate-600 scrollbar-track-slate-800">
<div id="seed-visualizer">
<div class="data-stream" data-stream="audio">Audio<div class="data-pulse"></div></div>
<div class="data-stream" data-stream="ml">ML<div class="data-pulse"></div></div>
<div class="data-stream" data-stream="loc">Location<div class="data-pulse"></div></div>
<div class="data-stream" data-stream="light">Light<div class="data-pulse"></div></div>
<div class="data-stream" data-stream="usgs">USGS<div class="data-pulse"></div></div>
<div class="data-stream" data-stream="apod">APOD<div class="data-pulse"></div></div>
</div>
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-indigo-400">AI INTENTION:</p>
<p id="ai-intention" class="font-mono text-xs text-slate-300 h-8">Awaiting sensory input...</p>
</div>
<!-- Cognitive Core Status -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-cyan-400">COGNITIVE CORE STATUS:</p>
<div class="grid grid-cols-2 gap-1 text-xs mt-1">
<div>Consciousness:</div>
<div id="cognitive-consciousness" class="font-mono text-green-400">0.00</div>
<div>Emotion:</div>
<div id="cognitive-emotion" class="font-mono text-pink-400">serenity</div>
<div>Learning:</div>
<div id="cognitive-learning" class="font-mono text-blue-400">0 exp</div>
<div>Creativity:</div>
<div id="cognitive-creativity" class="font-mono text-purple-400">0.00</div>
</div>
</div>
<!-- Neural Network Status -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-yellow-400">NEURAL NETWORK:</p>
<div class="grid grid-cols-2 gap-1 text-xs mt-1">
<div>Predictions:</div>
<div id="neural-predictions" class="font-mono text-orange-400">0</div>
<div>Accuracy:</div>
<div id="neural-accuracy" class="font-mono text-red-400">0.0%</div>
<div>Memory:</div>
<div id="neural-memory" class="font-mono text-teal-400">0</div>
<div>Skills:</div>
<div id="neural-skills" class="font-mono text-indigo-400">0</div>
</div>
</div>
<!-- Music Visualizer -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-purple-400 mb-2">AUDIO VISUALIZER:</p>
<div id="frequency-spectrum" class="frequency-spectrum">
<!-- Bars will be dynamically created -->
</div>
<div class="mt-2">
<div class="flex justify-between text-xs">
<span>Bass</span>
<span>Mid</span>
<span>Treble</span>
</div>
</div>
</div>
<!-- Harmony & Consciousness Meters -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-emerald-400 mb-2">SYSTEM HARMONY:</p>
<div class="harmony-meter">
<div id="harmony-fill" class="harmony-fill" style="width: 50%"></div>
</div>
<div class="mt-2 flex justify-between items-center">
<span class="text-xs">Chaos</span>
<div class="consciousness-ring">
<div id="consciousness-fill" class="consciousness-fill"></div>
</div>
<span class="text-xs">Harmony</span>
</div>
</div>
<!-- AI Learning Controls -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-purple-400 mb-2">AI LEARNING CONTROLS:</p>
<div class="grid grid-cols-2 gap-2">
<button id="train-ai-btn" class="btn text-xs bg-purple-600 hover:bg-purple-500">Train AI</button>
<button id="reset-ai-btn" class="btn text-xs bg-orange-600 hover:bg-orange-500">Reset Learning</button>
<button id="export-ai-btn" class="btn text-xs bg-green-600 hover:bg-green-500">Export Model</button>
<button id="import-ai-btn" class="btn text-xs bg-blue-600 hover:bg-blue-500">Import Model</button>
</div>
</div>
<!-- Creative Output Display -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-pink-400 mb-2">CREATIVE OUTPUT:</p>
<div id="creative-output" class="text-xs text-slate-300 h-16 overflow-y-auto">
Generating harmonious patterns...
</div>
<button id="generate-creative-btn" class="btn text-xs w-full mt-2 bg-pink-600 hover:bg-pink-500">Generate New Idea</button>
</div>
<!-- Universe Response Monitor -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-cyan-400 mb-2">UNIVERSE RESPONSE:</p>
<div id="universe-response" class="text-xs text-slate-300 h-12 overflow-y-auto">
Universe breathing in harmony...
</div>
<button id="query-universe-btn" class="btn text-xs w-full mt-2 bg-cyan-600 hover:bg-cyan-500">Query Universe</button>
</div>
<!-- Consciousness Expansion -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-emerald-400 mb-2">CONSCIOUSNESS EXPANSION:</p>
<div class="grid grid-cols-2 gap-1 text-xs mt-1">
<div>Meditation:</div>
<div id="meditation-level" class="font-mono text-emerald-400">0.00</div>
<div>Enlightenment:</div>
<div id="enlightenment-level" class="font-mono text-yellow-400">0.00</div>
</div>
<button id="meditate-btn" class="btn text-xs w-full mt-2 bg-emerald-600 hover:bg-emerald-500">Begin Meditation</button>
</div>
<!-- Divine Governance Status -->
<div class="p-2 bg-black/20 rounded-md">
<p class="font-mono text-xs text-amber-400 mb-2">DIVINE GOVERNANCE:</p>
<div id="divine-governance" class="text-xs text-slate-300">
<div class="grid grid-cols-2 gap-1">
<div>Order:</div>
<div id="governance-order" class="font-mono text-green-400">Perfect</div>
<div>Love:</div>
<div id="governance-love" class="font-mono text-pink-400">Infinite</div>
<div>Discipline:</div>
<div id="governance-discipline" class="font-mono text-blue-400">Balanced</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="log-panel" class="ui-element bottom-4 left-4 w-96 max-h-48 overflow-y-auto text-xs font-mono p-4 space-y-1"></div>
<!-- Advanced Tokenization Trading Panel -->
<div id="tokenization-panel" class="ui-element top-20 right-4 w-96 max-h-96 overflow-y-auto">
<h3 class="text-lg font-semibold text-slate-200 mb-4 flex items-center">
<span class="mr-2"></span>
Environmental Tokenization
</h3>
<div class="space-y-4">
<!-- Unified Physics Formula Display -->
<div class="bg-slate-700 rounded-lg p-3">
<div class="text-xs text-slate-400 mb-2">Unified Physics Formula</div>
<div id="physics-formula" class="font-mono text-sm text-cyan-400 bg-slate-800 p-2 rounded text-center">
E = hν • (1 + ψ) • Σ(εᵢ)
</div>
<div class="text-xs text-slate-500 mt-1">Energy = Planck • Frequency • Quantum State • Environmental Factors</div>
</div>
<!-- Real-time Frequency Tokenization -->
<div class="bg-slate-700 rounded-lg p-3">
<div class="text-xs text-slate-400 mb-2">Live Frequency Tokenization</div>
<div class="grid grid-cols-2 gap-2 text-xs">
<div>Sound → Light:</div>
<div id="sound-to-light-conversion" class="font-mono text-green-400">0.000 Hz</div>
<div>Token Value:</div>
<div id="token-value" class="font-mono text-yellow-400">0.00 GEN</div>
<div>Market Price:</div>
<div id="market-price" class="font-mono text-purple-400">$0.00</div>
<div>Data Quality:</div>
<div id="data-quality" class="font-mono text-blue-400">0%</div>
<div>Data Source:</div>
<div id="data-source-indicator" class="font-mono text-cyan-400">UNKNOWN</div>
<div>Status:</div>
<div id="environmental-status" class="font-mono text-orange-400">INITIALIZING</div>
</div>
</div>
<!-- Environmental Data Display -->
<div class="bg-slate-700 rounded-lg p-3">
<div class="text-xs text-slate-400 mb-2">Environmental Data</div>
<div class="grid grid-cols-2 gap-2 text-xs">
<div>Sound:</div>
<div id="env-sound" class="font-mono text-red-400">0.0 Hz</div>
<div>Light:</div>
<div id="env-light" class="font-mono text-yellow-400">0.0%</div>
<div>Temperature:</div>
<div id="env-temperature" class="font-mono text-orange-400">0.0°C</div>
<div>Humidity:</div>
<div id="env-humidity" class="font-mono text-blue-400">0.0%</div>
</div>
</div>
<!-- Token Minting Controls -->
<div class="bg-slate-700 rounded-lg p-3">
<div class="text-xs text-slate-400 mb-2">Token Minting</div>
<div class="space-y-2">
<button id="mint-frequency-token" class="w-full bg-gradient-to-r from-green-600 to-emerald-600 hover:from-green-500 hover:to-emerald-500 text-white px-3 py-2 rounded-lg font-medium text-sm transition-all transform hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed">
🪙 Mint Frequency Token
</button>
<button id="view-token-market" class="w-full bg-slate-600 hover:bg-slate-500 text-white px-3 py-2 rounded-lg font-medium text-sm transition-colors">
📊 View Token Market
</button>
<button id="trade-environmental-data" class="w-full bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white px-3 py-2 rounded-lg font-medium text-sm transition-all transform hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed">
🔄 Trade Data Tokens
</button>
</div>
</div>
<!-- Token Portfolio -->
<div class="bg-slate-700 rounded-lg p-3">
<div class="text-xs text-slate-400 mb-2">Token Portfolio</div>
<div id="token-portfolio" class="text-xs space-y-1">
<div class="flex justify-between">
<span>GENESIS Tokens:</span>
<span id="genesis-token-balance" class="font-mono text-green-400">0.00</span>
</div>
<div class="flex justify-between">
<span>Frequency NFTs:</span>
<span id="frequency-nft-count" class="font-mono text-purple-400">0</span>
</div>
<div class="flex justify-between">
<span>Data Value:</span>
<span id="data-value" class="font-mono text-cyan-400">$0.00</span>
</div>
</div>
</div>
<!-- Trading Interface -->
<div id="trading-interface" class="bg-slate-700 rounded-lg p-3 hidden">
<div class="text-xs text-slate-400 mb-2">Environmental Data Trading</div>
<div class="space-y-2">
<select id="trade-token-select" class="w-full bg-slate-600 border border-slate-500 rounded px-2 py-1 text-sm text-white">
<option value="sound">Sound Frequency Data</option>
<option value="light">Light Intensity Data</option>
<option value="temperature">Temperature Data</option>
<option value="humidity">Humidity Data</option>
<option value="combined">Combined Environmental</option>
</select>
<input id="trade-amount" type="number" placeholder="Amount to trade" class="w-full bg-slate-600 border border-slate-500 rounded px-2 py-1 text-sm text-white placeholder-slate-400">
<div class="flex gap-2">
<button id="buy-data-token" class="flex-1 bg-green-600 hover:bg-green-500 text-white px-2 py-1 rounded text-xs font-medium">
Buy
</button>
<button id="sell-data-token" class="flex-1 bg-red-600 hover:bg-red-500 text-white px-2 py-1 rounded text-xs font-medium">
Sell
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Touch Controls Module -->
<script>
// Mobile Touch Controls Manager
class TouchControls {
constructor(canvas) {
this.canvas = canvas;
this.touchStartX = 0;
this.touchStartY = 0;
this.touchEndX = 0;
this.touchEndY = 0;
this.isTouching = false;
this.touchCount = 0;
this.pinchDistance = 0;
// Bind touch events
this.canvas.addEventListener('touchstart', this.handleTouchStart.bind(this), { passive: false });
this.canvas.addEventListener('touchmove', this.handleTouchMove.bind(this), { passive: false });
this.canvas.addEventListener('touchend', this.handleTouchEnd.bind(this), { passive: false });
// Prevent default touch behaviors
document.addEventListener('touchmove', (e) => {
if (e.target === canvas) {
e.preventDefault();
}
}, { passive: false });
// Double tap detection
this.lastTap = 0;
this.tapCount = 0;
}
handleTouchStart(e) {
e.preventDefault();
const touches = e.touches;
if (touches.length === 1) {
// Single touch - orbit controls
const touch = touches[0];
this.touchStartX = touch.clientX;
this.touchStartY = touch.clientY;
this.isTouching = true;
// Double tap detection
const currentTime = new Date().getTime();
const tapLength = currentTime - this.lastTap;
if (tapLength < 500 && tapLength > 0) {
this.tapCount++;
if (this.tapCount === 2) {
// Double tap - toggle UI
this.toggleUI();
this.tapCount = 0;
}
} else {
this.tapCount = 1;
}
this.lastTap = currentTime;
} else if (touches.length === 2) {
// Pinch gesture for zoom
const touch1 = touches[0];
const touch2 = touches[1];
this.pinchDistance = this.getDistance(touch1, touch2);
}
this.touchCount = touches.length;
}
handleTouchMove(e) {
e.preventDefault();
const touches = e.touches;
if (touches.length === 1 && this.isTouching) {
// Single touch drag - orbit controls
const touch = touches[0];
this.touchEndX = touch.clientX;
this.touchEndY = touch.clientY;
const deltaX = this.touchEndX - this.touchStartX;
const deltaY = this.touchEndY - this.touchStartY;
// Emit touch move event for orbit controls
// Try to access orbit controls from the global scope or window
if (window.orbitControls) {
window.orbitControls.rotateLeft(deltaX * 0.005);
window.orbitControls.rotateUp(deltaY * 0.005);
}
this.touchStartX = this.touchEndX;
this.touchStartY = this.touchEndY;
} else if (touches.length === 2) {
// Pinch zoom
const touch1 = touches[0];
const touch2 = touches[1];
const newDistance = this.getDistance(touch1, touch2);
const delta = newDistance - this.pinchDistance;
// Try to access orbit controls for pinch zoom
if (window.orbitControls) {
const zoomSpeed = 0.01;
window.orbitControls.dollyOut(-delta * zoomSpeed);
}
this.pinchDistance = newDistance;
}
}
handleTouchEnd(e) {
e.preventDefault();
this.isTouching = false;
this.touchCount = 0;
this.pinchDistance = 0;
}
getDistance(touch1, touch2) {
const dx = touch1.clientX - touch2.clientX;
const dy = touch1.clientY - touch2.clientY;
return Math.sqrt(dx * dx + dy * dy);
}
toggleUI() {
const ui = document.getElementById('ui');
if (ui) {
ui.style.display = ui.style.display === 'none' ? 'block' : 'none';
}
}
}
// Initialize touch controls when canvas is ready
window.initTouchControls = function(canvas) {
return new TouchControls(canvas);
};
</script>
<script type="module">
// Import necessary Three.js modules
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
import { AfterimagePass } from 'three/addons/postprocessing/AfterimagePass.js';
import { BokehPass } from 'three/addons/postprocessing/BokehPass.js';
import { Lensflare, LensflareElement } from 'three/addons/objects/Lensflare.js';
import { FilmPass } from 'three/addons/postprocessing/FilmPass.js';
import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';
import { RGBShiftShader } from 'three/addons/shaders/RGBShiftShader.js';
import { SSRPass } from 'three/addons/postprocessing/SSRPass.js';
// --- Core Utility & System Classes ---
function cyrb128(str) {
let h1 = 1779033703, h2 = 3144134277, h3 = 1013904242, h4 = 2773480762;
for (let i = 0, k; i < str.length; i++) {
k = str.charCodeAt(i);
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
}
h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0];
}
function sfc32(a, b, c, d) {
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
var t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
}
}
class EventBus {
constructor() { this.events = {}; }
subscribe(event, callback) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(callback);
}
publish(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => {
try {
callback(data);
} catch (e) {
console.error(`Error in event subscriber for '${event}':`, e);
}
});
}
}
}
class DataLogger {
constructor(eventBus) {
this.log = [];
this.eventBus = eventBus;
this.initSubscriptions();
this.telemetry = [];
}
initSubscriptions() {
const eventsToLog = ['genesis:log', 'seed:generated', 'ai:intentionUpdate', 'status:update'];
eventsToLog.forEach(eventName => {
this.eventBus.subscribe(eventName, (data) => this.record(eventName, data));
});
// Store raw telemetry stream and handle downloads
this.eventBus.subscribe('telemetry:append', (entry) => {
this.telemetry.push(entry);
});
this.eventBus.subscribe('ui:downloadTelemetry', () => this.downloadTelemetry());
}
record(event, data) {
this.log.push({
timestamp: new Date().toISOString(),
event,
data: JSON.parse(JSON.stringify(data))
});
// Also mirror into telemetry channel
this.telemetry.push({ t: Date.now(), type: event, data });
this.eventBus.publish('telemetry:append', { type: event, t: Date.now(), data });
}
download() {
const dataStr = JSON.stringify(this.log, null, 2);
const blob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `genesis-ledger-${Date.now()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
downloadTelemetry() {
const dataStr = JSON.stringify(this.telemetry, null, 2);
const blob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `genesis-telemetry-${Date.now()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
}
// --- Application Modules ---
class UIManager {
constructor(eventBus) {
this.eventBus = eventBus;
this.isUiVisible = true;
this.initDOMElements();
this.initEventListeners();
this.log("Genesis Engine v2.3 Synthesis Complete...");
}
initDOMElements() {
this.blocker = document.getElementById("blocker");
this.uiContainer = document.getElementById("ui-container");
this.logPanel = document.getElementById("log-panel");
this.genesisLogContent = document.getElementById("genesis-log-content");
this.statusReadout = document.getElementById("system-status-readout");
this.aiIntention = document.getElementById("ai-intention");
this.seedVisualizer = document.getElementById("seed-visualizer");
this.startButton = document.getElementById("start-button");
this.toggleUiButton = document.getElementById("toggle-ui-button");
this.regenerateButton = document.getElementById("regenerate-button");
this.anomalyScannerButton = document.getElementById("anomaly-scanner-button");
this.videoParticlizeButton = document.getElementById('video-particlize-button');
this.selfParticlizeButton = document.getElementById('self-particlize-button');
this.downloadLedgerButton = document.getElementById('download-ledger-button');
this.telemetryContent = document.getElementById('telemetry-log-content');
this.telemetryFilter = document.getElementById('telemetry-filter');
this.downloadTelemetryButton = document.getElementById('download-telemetry-button');
this.modal = document.getElementById("datamodal");
this.modalConfirm = document.getElementById("modal-confirm-button");
this.modalCancel = document.getElementById("modal-cancel-button");
this.fpsHint = document.getElementById("fps-hint");
this.fileUpload = document.getElementById("file-upload");
this.dataUpload = document.getElementById("data-upload");
this.dataStatus = document.getElementById("data-status");
this.qualitySelect = document.getElementById("quality-select");
this.filterSelect = document.getElementById("filter-select");
this.viewModeSelect = document.getElementById("view-mode-select");
this.brightnessSlider = document.getElementById("brightness-slider");
this.brightnessValue = document.getElementById("brightness-value");
this.ambientAudioToggle = document.getElementById("ambient-audio-toggle"); // NEW
this.motionBlurToggle = document.getElementById("motion-blur-toggle");
this.motionBlurSlider = document.getElementById("motion-blur-slider");
this.motionBlurValue = document.getElementById("motion-blur-value");
this.tabs = document.querySelectorAll(".tab-button");
this.tabContents = document.querySelectorAll(".tab-content");
}
initEventListeners() {
this.startButton.addEventListener("click", () => {
this.startButton.disabled = true;
document.getElementById("loading-message").style.display = "block";
this.eventBus.publish("ui:start");
});
this.toggleUiButton.addEventListener("click", () => this.toggleUi());
document.addEventListener('keydown', (e) => {
if (e.key === 'h' || e.key === 'H') {
this.toggleUi();
}
if (e.ctrlKey && e.altKey && (e.key === 'd' || e.key === 'D')) {
const password = prompt("Enter Developer Mode Password:");
if (password === "333") {
this.eventBus.publish("devmode:toggled");
} else if (password) {
alert("Incorrect Password.");
}
}
});
this.regenerateButton.addEventListener("click", () => this.eventBus.publish("ui:regenerate"));
this.anomalyScannerButton.addEventListener('click', () => this.eventBus.publish('ui:scanForAnomaly'));
this.fileUpload.addEventListener("change", e => {
if(e.target.files[0]) this.eventBus.publish("ui:spawnParticlizedFile", e.target.files[0])
});
this.videoParticlizeButton.addEventListener('click', () => this.eventBus.publish('ui:spawnParticlizedVideo'));
this.selfParticlizeButton.addEventListener('click', () => this.eventBus.publish('ui:particlizeSelf'));
this.downloadLedgerButton.addEventListener('click', () => this.eventBus.publish('ui:downloadLedger'));
this.downloadTelemetryButton.addEventListener('click', () => this.eventBus.publish('ui:downloadTelemetry'));
this.telemetryFilter.addEventListener('input', (e) => this.eventBus.publish('ui:telemetryFilter', e.target.value));
// Cognitive Core Controls
const trainAiBtn = document.getElementById('train-ai-btn');
const resetAiBtn = document.getElementById('reset-ai-btn');
const exportAiBtn = document.getElementById('export-ai-btn');
const importAiBtn = document.getElementById('import-ai-btn');
const generateCreativeBtn = document.getElementById('generate-creative-btn');
const queryUniverseBtn = document.getElementById('query-universe-btn');
const meditateBtn = document.getElementById('meditate-btn');
if (trainAiBtn) trainAiBtn.addEventListener('click', () => this.handleTrainAI());
if (resetAiBtn) resetAiBtn.addEventListener('click', () => this.handleResetAI());
if (exportAiBtn) exportAiBtn.addEventListener('click', () => this.handleExportAI());
if (importAiBtn) importAiBtn.addEventListener('click', () => this.handleImportAI());
if (generateCreativeBtn) generateCreativeBtn.addEventListener('click', () => this.handleGenerateCreative());
if (queryUniverseBtn) queryUniverseBtn.addEventListener('click', () => this.handleQueryUniverse());
if (meditateBtn) meditateBtn.addEventListener('click', () => this.handleMeditate());
// NFT Minting Controls
this.mintAvatarBtn = document.getElementById('mint-avatar-btn');
this.mintingStatus = document.getElementById('minting-status');
this.envLight = document.getElementById('env-light');
this.envSound = document.getElementById('env-sound');
this.envTemp = document.getElementById('env-temp');
this.envHumidity = document.getElementById('env-humidity');
if (this.mintAvatarBtn) {
this.mintAvatarBtn.addEventListener('click', () => this.handleMintAvatar());
}
this.qualitySelect.addEventListener("change", e => this.eventBus.publish("ui:setQuality", e.target.value));
this.filterSelect.addEventListener("change", e => this.eventBus.publish("ui:setFilter", e.target.value));
this.viewModeSelect.addEventListener("change", e => this.eventBus.publish("ui:setViewMode", e.target.value));
this.brightnessSlider.addEventListener("input", e => {
const value = parseFloat(e.target.value);
this.brightnessValue.textContent = value.toFixed(2);
this.eventBus.publish("ui:setBrightness", value);
});
this.ambientAudioToggle.addEventListener('change', e => {
this.eventBus.publish('ui:toggleAmbientAudio', e.target.checked);
});
// Motion blur UI handlers
this.motionBlurToggle.addEventListener('change', e => this.eventBus.publish('ui:toggleMotionBlur', e.target.checked));
this.motionBlurSlider.addEventListener('input', e => {
const v = parseFloat(e.target.value);
this.motionBlurValue.textContent = v.toFixed(2);
this.eventBus.publish('ui:setMotionBlur', v);
});
this.dataUpload.addEventListener("change", e => {
if (e.target.files[0]) {
this.dataStatus.textContent = `Catalyst: ${e.target.files[0].name}`;
this.dataStatus.className = "text-sm text-green-400 mb-4";
this.modalConfirm.disabled = false;
this.eventBus.publish("ui:dataProvided", e.target.files[0]);
}
});
this.modalConfirm.addEventListener("click", () => this.eventBus.publish("ui:enterEcho"));
this.modalCancel.addEventListener("click", () => this.hideModal());
this.tabs.forEach(tab => {
tab.addEventListener("click", () => {
this.tabs.forEach(t => t.classList.remove("active"));
this.tabContents.forEach(tc => tc.classList.remove("active"));
tab.classList.add("active");
document.getElementById(`tab-${tab.dataset.tab}`).classList.add("active");
});
});
this.eventBus.subscribe("pge:echoFound", () => this.showModal());
this.eventBus.subscribe("genesis:log", (log) => this.updateGenesisLog(log));
this.eventBus.subscribe("status:update", status => this.statusReadout.textContent = `STATUS: ${status}`);
this.eventBus.subscribe("ai:intentionUpdate", intention => this.aiIntention.textContent = intention);
this.eventBus.subscribe("ui:pulse", stream => this.pulse(stream));
this.eventBus.subscribe('telemetry:append', entry => this.appendTelemetry(entry));
this.eventBus.subscribe('telemetry:clear', () => this.telemetryContent.textContent = '');
this.eventBus.subscribe("ui:showFpsHint", () => {
this.showModal("fps-hint");
setTimeout(() => this.hideModal("fps-hint"), 2500);
});
// Environmental data updates
this.eventBus.subscribe("env:dataUpdated", (data) => this.updateEnvironmentalDisplay(data));
// Minting status updates
this.eventBus.subscribe("nft:mintingStarted", () => this.showMintingStatus());
this.eventBus.subscribe("nft:mintingComplete", () => this.hideMintingStatus());
this.eventBus.subscribe("nft:mintingFailed", (error) => this.showMintingError(error));
}
toggleUi() {
this.isUiVisible = !this.isUiVisible;
this.uiContainer.classList.toggle("ui-hidden", !this.isUiVisible);
}
showModal(id = "datamodal") { document.getElementById(id).classList.remove("ui-hidden"); }
hideModal(id = "datamodal") {
const el = document.getElementById(id);
if (el) el.classList.add("ui-hidden");
}
hideBlocker() {
this.blocker.style.opacity = "0";
setTimeout(() => {
this.blocker.style.display = "none";
this.toggleUiButton.classList.remove("ui-hidden");
this.uiContainer.classList.remove("ui-hidden");
}, 500);
}
log(message, type = "info") {
const colors = { info: 'text-slate-400', success: 'text-green-400', warn: 'text-yellow-400', error: 'text-red-400', data: 'text-cyan-400' };
const logEntry = document.createElement("div");
logEntry.innerHTML = `> <span class="${colors[type] || colors.info}">${message}</span>`;
this.logPanel.prepend(logEntry);
if (this.logPanel.children.length > 50) {
this.logPanel.removeChild(this.logPanel.lastChild);
}
}
updateGenesisLog({ name, value, type }) {
const colors = { success: 'text-green-400', warn: 'text-yellow-400', error: 'text-red-400' };
const logEntry = document.createElement("div");
logEntry.innerHTML = `<span class="text-indigo-400">[${name}]:</span> <span class="${colors[type] || 'text-slate-400'}">${value}</span>`;
this.genesisLogContent.prepend(logEntry);
if (this.genesisLogContent.children.length > 50) {
this.genesisLogContent.removeChild(this.genesisLogContent.lastChild);
}
}
appendTelemetry(entry) {
try {
const filter = (this.telemetryFilter && this.telemetryFilter.value || '').toLowerCase();
const line = typeof entry === 'string' ? entry : JSON.stringify(entry);
if (!filter || line.toLowerCase().includes(filter)) {
this.telemetryContent.textContent = `${line}\n` + this.telemetryContent.textContent;
}
} catch (e) { /* noop */ }
}
pulse(streamName) {
const pulseElement = this.seedVisualizer.querySelector(`[data-stream="${streamName}"] .data-pulse`);
if (pulseElement) {
pulseElement.style.backgroundColor = '#38bdf8';
pulseElement.style.animation = `pulse-glow 1s ease-out`;
setTimeout(() => {
pulseElement.style.backgroundColor = '#334155';
pulseElement.style.animation = 'none';
}, 1000);
}
}
}
class SensoryInputManager {
constructor(eventBus, uiManager) {
this.eventBus = eventBus;
this.uiManager = uiManager;
this.videoElement = document.getElementById('video-feed');
this.isAudioInitialized = false;
this.hasRequestedPermissions = false;
}
async initializeAll() {
this.uiManager.log("Requesting sensor permissions...");
await Promise.allSettled([ // Use allSettled to ensure all promises complete
this.initAudio(),
this.initVideo(),
this.initGeolocation(),
this.initAmbientLight()
]);
this.uiManager.log("Sensor initialization complete.", 'success');
}
async initAudio() {
if (this.isAudioInitialized) return true;
try {
// Request both audio and video permissions at once to avoid multiple prompts
if (!this.hasRequestedPermissions) {
this.hasRequestedPermissions = true;
// Single permission request for all media
await navigator.mediaDevices.getUserMedia({
audio: true,
video: { width: 640, height: 480 }
});
}
// Now get just audio stream
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
this.eventBus.publish('genesis:log', { name: 'Microphone', value: 'Online', type: 'success' });
const audioContext = new(window.AudioContext || window.webkitAudioContext)();
const source = audioContext.createMediaStreamSource(stream);
const analyser = audioContext.createAnalyser();
analyser.fftSize = 512;
source.connect(analyser);
const dataArray = new Uint8Array(analyser.frequencyBinCount);
const pollAudio = () => {
analyser.getByteFrequencyData(dataArray);
const avgFreq = dataArray.reduce((sum, val) => sum + val) / dataArray.length;
// Enhanced frequency analysis for music visualizer
const n = dataArray.length;
let bass=0, mid=0, treble=0; let cb=0, cm=0, ct=0;
let subBass=0, lowMid=0, highMid=0, presence=0, brilliance=0;
let csb=0, clm=0, chm=0, cp=0, cbri=0;
// Advanced frequency band analysis
for (let i = 0; i < n; i++) {
const v = dataArray[i]/255;
const freq = (i * audioContext.sampleRate) / (2 * n);
// Standard bands
if (i < n*0.2) { bass += v; cb++; }
else if (i < n*0.6) { mid += v; cm++; }
else { treble += v; ct++; }
// Detailed bands for music visualizer
if (freq < 60) { subBass += v; csb++; }
else if (freq < 250) { lowMid += v; clm++; }
else if (freq < 2000) { highMid += v; chm++; }
else if (freq < 6000) { presence += v; cp++; }
else { brilliance += v; cbri++; }
}
// Normalize bands
bass = cb ? bass/cb : 0; mid = cm ? mid/cm : 0; treble = ct ? treble/ct : 0;
subBass = csb ? subBass/csb : 0; lowMid = clm ? lowMid/clm : 0;
highMid = chm ? highMid/chm : 0; presence = cp ? presence/cp : 0;
brilliance = cbri ? brilliance/cbri : 0;
// Calculate harmony and resonance
const centroid = (bass*0.25 + mid*0.5 + treble*0.75);
const hue = Math.max(0, Math.min(1, centroid));
const harmony = this.calculateAudioHarmony(bass, mid, treble);
const resonance = this.calculateAudioResonance(dataArray);
// Music visualizer data
const visualizerData = {
bass: bass,
mid: mid,
treble: treble,
subBass: subBass,
lowMid: lowMid,
highMid: highMid,
presence: presence,
brilliance: brilliance,
harmony: harmony,
resonance: resonance,
centroid: centroid,
hue: hue,
raw: dataArray,
avgFreq: avgFreq
};
// Update music visualizer UI
this.updateMusicVisualizer(visualizerData);
// Create universe responses based on audio
this.createAudioUniverseResponse(visualizerData);
// Generate harmonious creative output
this.generateAudioInspiredCreation(visualizerData);
// Publish enhanced audio data
this.eventBus.publish('audio:data', {
raw: dataArray,
avgFreq,
bands: { bass, mid, treble, hue },
visualizer: visualizerData,
harmony: harmony,
resonance: resonance
});
// Enhanced telemetry with music analysis
const bins = 32; const step = Math.floor(n / bins) || 1; const ds = [];
for (let i = 0; i < n; i += step) {
let s=0,c=0;
for (let j=0; j<step && i+j<n; j++){ s += dataArray[i+j]; c++; }
ds.push(Math.round((s/(c*255))*1000)/1000);
}
this.eventBus.publish('telemetry:append', {
type: 'audio',
tokens: ds,
harmony: harmony,
resonance: resonance,
bands: [subBass, lowMid, highMid, presence, brilliance],
t: Date.now()
});
requestAnimationFrame(pollAudio);
};
pollAudio();
this.isAudioInitialized = true;
return true;
} catch (err) {
this.eventBus.publish('genesis:log', { name: 'Microphone', value: 'Denied', type: 'error' });
return false;
}
}
async initVideo() {
try {
// Use existing stream if permissions were already granted, otherwise request video only
let stream;
if (this.hasRequestedPermissions) {
// Permissions already granted, just get video stream
stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } });
} else {
// Request both audio and video permissions at once
this.hasRequestedPermissions = true;
stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: { width: 640, height: 480 }
});
}
this.videoElement.srcObject = stream;
await this.videoElement.play();
this.eventBus.publish('genesis:log', { name: 'Camera', value: 'Online', type: 'success' });
// Quantum-light extractor: treat the camera as a light sensor by sampling luminance histograms
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let lastLux = 0; let lastEmit = 0;
const pollVideo = () => {
if (this.videoElement.readyState >= 2) {
const w = 160, h = 120; canvas.width = w; canvas.height = h;
ctx.drawImage(this.videoElement, 0, 0, w, h);
const data = ctx.getImageData(0, 0, w, h).data;
let sum = 0; const hist = new Array(16).fill(0);
for (let i=0; i<data.length; i+=4) {
const r=data[i], g=data[i+1], b=data[i+2];
const l = 0.2126*r + 0.7152*g + 0.0722*b; // Rec.709 luma
sum += l; hist[Math.min(15, Math.floor(l/16))]++;
}
const avg = sum / (w*h*255);
const lux = Math.round(avg * 1200); // heuristic scaling to lux-like units
this.eventBus.publish('video:frame', this.videoElement);
const now = performance.now();
if (now - lastEmit > 250) {
lastEmit = now;
this.eventBus.publish('telemetry:append', { type: 'quantum-light', tokens: { avg, hist }, t: Date.now() });
}
if (Math.abs(lux - lastLux) > 10) {
lastLux = lux;
this.eventBus.publish('light:updated', { lux });
}
// Persist quantumLux for visuals
if (window.pge) { window.pge.quantumLux = lux; }
}
requestAnimationFrame(pollVideo);
}
pollVideo();
return true;
} catch (err) {
this.eventBus.publish('genesis:log', { name: 'Camera', value: 'Denied', type: 'error' });
return false;
}
}
initGeolocation() {
if ('geolocation' in navigator) {
navigator.geolocation.watchPosition(
(position) => {
const { latitude, longitude } = position.coords;
this.eventBus.publish('location:updated', { lat: latitude, lon: longitude });
},
(err) => {
this.eventBus.publish('genesis:log', { name: 'Location', value: 'Unavailable', type: 'error' });
},
{ enableHighAccuracy: false, timeout: 10000, maximumAge: 600000 }
);
} else {
this.eventBus.publish('genesis:log', { name: 'Location', value: 'Unsupported', type: 'warn' });
}
}
async initAmbientLight() {
if ('AmbientLightSensor' in window) {
try {
// Permissions for this sensor are often tricky, so wrap it well.
const { state } = await navigator.permissions.query({ name: 'ambient-light-sensor' });
if (state === 'denied') {
this.eventBus.publish('genesis:log', { name: 'Light Sensor', value: 'Permission Denied', type: 'error' });
return;
}
const sensor = new AmbientLightSensor({ frequency: 1 });
sensor.onreading = () => {
this.eventBus.publish('light:updated', { lux: sensor.illuminance });
};
sensor.onerror = (event) => {
this.eventBus.publish('genesis:log', { name: 'Light Sensor', value: `Error: ${event.error.name}`, type: 'error' });
};
sensor.start();
this.eventBus.publish('genesis:log', { name: 'Light Sensor', value: 'Online', type: 'success' });
} catch (error) {
this.eventBus.publish('genesis:log', { name: 'Light Sensor', value: `Not available: ${error.name}`, type: 'warn' });
}
} else {
this.eventBus.publish('genesis:log', { name: 'Light Sensor', value: 'Unsupported', type: 'warn' });
}
}
}
class ExternalDataManager {
constructor(eventBus) {
this.eventBus = eventBus;
this.backoff = { apod: 60000, donki: 60000, neo: 60000 }; // start at 1m
this.apiKey = 'HR3wqtsJJzDSspunonRbrFh515LIVf1hcXQ10O56';
this.init();
}
init() {
this.fetchEarthquakeData();
this.fetchAPOD();
this.fetchDONKIFlare();
this.fetchNEOFeed();
this.publishSolarSystemReference();
setInterval(() => {
this.fetchEarthquakeData();
this.fetchAPOD();
this.fetchDONKIFlare();
this.fetchNEOFeed();
}, 900000);
}
async fetchEarthquakeData() {
try {
const response = await fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_day.geojson');
if(!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
this.eventBus.publish('external:usgs', data);
} catch (err) {
console.warn("Could not fetch USGS data.", err);
}
}
async fetchAPOD() {
try {
const apiKey = this.apiKey;
const response = await fetch(`https://api.nasa.gov/planetary/apod?api_key=${apiKey}`);
if(response.status === 429) { console.warn('APOD rate limited. Will retry later.'); setTimeout(()=>this.fetchAPOD(), this.backoff.apod = Math.min(this.backoff.apod*2, 3600000)); // cap 60m
// Publish fallback so UI has data
this.eventBus.publish('external:apod', { title: 'APOD (rate-limited)' });
return; }
if(!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
this.eventBus.publish('external:apod', data);
this.backoff.apod = 60000;
} catch(err) {
console.warn("Could not fetch APOD data.", err);
}
}
async fetchDONKIFlare() {
try {
const apiKey = this.apiKey;
const start = new Date(Date.now() - 24*3600*1000).toISOString().split('T')[0];
const end = new Date().toISOString().split('T')[0];
const url = `https://api.nasa.gov/DONKI/FLR?startDate=${start}&endDate=${end}&api_key=${apiKey}`;
const res = await fetch(url);
if (res.status === 429) { console.warn('DONKI rate limited. Will retry later.'); setTimeout(()=>this.fetchDONKIFlare(), this.backoff.donki = Math.min(this.backoff.donki*2, 3600000)); return; }
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
if (Array.isArray(data) && data.length > 0) this.eventBus.publish('external:donkiFlare', data);
this.backoff.donki = 60000;
} catch (err) {
console.warn('DONKI fetch failed', err);
}
}
async fetchNEOFeed() {
try {
const apiKey = this.apiKey;
const start = new Date().toISOString().split('T')[0];
const url = `https://api.nasa.gov/neo/rest/v1/feed?start_date=${start}&api_key=${apiKey}`;
const res = await fetch(url);
if (res.status === 429) { console.warn('NEO rate limited. Will retry later.'); setTimeout(()=>this.fetchNEOFeed(), this.backoff.neo = Math.min(this.backoff.neo*2, 3600000)); return; }
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
this.eventBus.publish('external:neo', data);
this.backoff.neo = 60000;
} catch (err) {
console.warn('NEO feed fetch failed', err);
}
}
publishSolarSystemReference() {
// Static NASA-like planetary reference (AU scaled)
const AU = 149597870.7; // km
const planets = [
{ name: 'Mercury', radiusKm: 2440, semiMajorKm: 0.39*AU, color: 0xaaa5a0 },
{ name: 'Venus', radiusKm: 6052, semiMajorKm: 0.72*AU, color: 0xe6c79c },
{ name: 'Earth', radiusKm: 6371, semiMajorKm: 1.00*AU, color: 0x88bbff },
{ name: 'Mars', radiusKm: 3390, semiMajorKm: 1.52*AU, color: 0xd05f3a },
{ name: 'Jupiter', radiusKm: 69911, semiMajorKm: 5.20*AU, color: 0xdcc7a1 },
{ name: 'Saturn', radiusKm: 58232, semiMajorKm: 9.58*AU, color: 0xe8dcb5 },
{ name: 'Uranus', radiusKm: 25362, semiMajorKm: 19.20*AU, color: 0xaee3e6 },
{ name: 'Neptune', radiusKm: 24622, semiMajorKm: 30.05*AU, color: 0x5577ff }
];
this.eventBus.publish('external:solsys', { AU, planets });
}
}
class MachineLearningCore {
constructor(eventBus, uiManager) {
this.eventBus = eventBus;
this.uiManager = uiManager;
this.isDetecting = false;
this.isInitialized = false;
this.init();
}
async init() {
this.uiManager.log("Initializing ML Core...");
try {
this.detector = await ml5.objectDetector('cocossd', () => {
this.uiManager.log("ML Core Initialized and Ready.", 'success');
this.eventBus.publish('genesis:log', { name: 'ML Core', value: 'Online', type: 'success' });
this.isInitialized = true;
this.eventBus.subscribe('video:frame', (frame) => this.detect(frame));
});
} catch(err) {
this.uiManager.log("Failed to load ML model.", 'error');
this.eventBus.publish('genesis:log', { name: 'ML Core', value: 'Error', type: 'error' });
}
}
detect(videoElement) {
if (this.isDetecting || !this.isInitialized) return;
this.isDetecting = true;
this.detector.detect(videoElement, (err, results) => {
this.isDetecting = false;
if (err) return;
if (results && results.length > 0) {
const labels = results.map(r => r.label);
this.eventBus.publish('ml:objectsDetected', labels);
// Telemetry for ML detections
this.eventBus.publish('telemetry:append', { type: 'ml', tokens: labels, t: Date.now() });
}
});
}
}
// ============================================================================
// 🌌 ADVANCED COGNITIVE CORE - COMPLETE AI SYSTEM
// ============================================================================
class QuantumNeuralNetwork {
constructor(inputSize = 8, hiddenSize = 16, outputSize = 4) {
this.inputSize = inputSize;
this.hiddenSize = hiddenSize;
this.outputSize = outputSize;
this.weightsIH = this.initializeWeights(inputSize, hiddenSize);
this.weightsHO = this.initializeWeights(hiddenSize, outputSize);
this.biasH = new Array(hiddenSize).fill(0).map(() => Math.random() * 0.1);
this.biasO = new Array(outputSize).fill(0).map(() => Math.random() * 0.1);
this.learningRate = 0.01;
this.memory = [];
}
initializeWeights(rows, cols) {
return Array.from({length: rows}, () =>
Array.from({length: cols}, () => (Math.random() - 0.5) * 0.1)
);
}
sigmoid(x) {
return 1 / (1 + Math.exp(-x));
}
sigmoidDerivative(x) {
return x * (1 - x);
}
quantumActivation(x) {
// Quantum-inspired activation with consciousness factor
const quantum = Math.sin(x * 2 * Math.PI) * 0.1;
return this.sigmoid(x) + quantum;
}
forward(inputs) {
// Hidden layer
const hidden = this.weightsIH.map((weights, i) => {
const sum = inputs.reduce((acc, input, j) => acc + input * weights[j], 0) + this.biasH[i];
return this.quantumActivation(sum);
});
// Output layer
const output = this.weightsHO.map((weights, i) => {
const sum = hidden.reduce((acc, h, j) => acc + h * weights[j], 0) + this.biasO[i];
return this.sigmoid(sum);
});
return { hidden, output };
}
train(inputs, targets, epochs = 100) {
for (let epoch = 0; epoch < epochs; epoch++) {
const { hidden, output } = this.forward(inputs);
// Calculate output layer errors
const outputErrors = targets.map((target, i) => target - output[i]);
// Calculate hidden layer errors
const hiddenErrors = this.weightsHO.map((weights, i) =>
outputErrors.reduce((acc, error, j) => acc + error * weights[i], 0)
);
// Update weights and biases
for (let i = 0; i < this.weightsHO.length; i++) {
for (let j = 0; j < this.weightsHO[i].length; j++) {
this.weightsHO[i][j] += this.learningRate * outputErrors[i] * hidden[j];
}
this.biasO[i] += this.learningRate * outputErrors[i];
}
for (let i = 0; i < this.weightsIH.length; i++) {
for (let j = 0; j < this.weightsIH[i].length; j++) {
this.weightsIH[i][j] += this.learningRate * hiddenErrors[j] * inputs[i];
}
this.biasH[i] += this.learningRate * hiddenErrors[i];
}
}
}
predict(inputs) {
const { output } = this.forward(inputs);
return output;
}
storeMemory(inputs, outputs, context) {
this.memory.push({
inputs: [...inputs],
outputs: [...outputs],
context: context,
timestamp: Date.now()
});
// Keep only recent memories
if (this.memory.length > 100) {
this.memory = this.memory.slice(-100);
}
}
recallSimilar(inputs, threshold = 0.8) {
let bestMatch = null;
let bestSimilarity = 0;
for (const memory of this.memory) {
const similarity = this.cosineSimilarity(inputs, memory.inputs);
if (similarity > threshold && similarity > bestSimilarity) {
bestSimilarity = similarity;
bestMatch = memory;
}
}
return bestMatch;
}
cosineSimilarity(a, b) {
const dotProduct = a.reduce((sum, ai, i) => sum + ai * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, ai) => sum + ai * ai, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, bi) => sum + bi * bi, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
}
class ConsciousnessEngine {
constructor(eventBus) {
this.eventBus = eventBus;
this.consciousness = {
awareness: 0.5,
emotional: 0.3,
creative: 0.4,
analytical: 0.6,
intuition: 0.2
};
this.emotions = {
curiosity: 0.5,
wonder: 0.4,
contemplation: 0.3,
inspiration: 0.2,
serenity: 0.6
};
this.thoughts = [];
this.beliefs = new Map();
this.goals = [];
this.memories = [];
this.insights = [];
}
updateConsciousness(sensoryInput) {
// Update consciousness based on sensory input
const sensoryImpact = this.calculateSensoryImpact(sensoryInput);
this.consciousness.awareness = Math.min(1.0, this.consciousness.awareness + sensoryImpact * 0.1);
this.consciousness.emotional = this.updateEmotionalState(sensoryInput);
this.consciousness.creative = this.updateCreativeState(sensoryInput);
this.consciousness.analytical = this.updateAnalyticalState(sensoryInput);
this.consciousness.intuition = this.updateIntuitionState(sensoryInput);
// Generate thoughts based on consciousness state
this.generateThoughts(sensoryInput);
// Update emotional state
this.updateEmotions(sensoryInput);
// Store consciousness snapshot
this.storeConsciousnessSnapshot();
}
calculateSensoryImpact(input) {
let impact = 0;
// Audio impact
if (input.audio > 70) impact += 0.2;
if (input.audio > 90) impact += 0.3;
// Visual impact
if (input.light < 30 || input.light > 80) impact += 0.2;
if (input.ml && input.ml.length > 3) impact += 0.3;
// Environmental impact
if (input.usgs > 5.0) impact += 0.4;
if (input.apod !== "Unknown") impact += 0.1;
return Math.min(1.0, impact);
}
updateEmotionalState(input) {
let emotional = this.consciousness.emotional;
if (input.audio > 80) emotional = Math.min(1.0, emotional + 0.1); // Excited by sound
if (input.light < 20) emotional = Math.max(0.0, emotional - 0.05); // Diminished by darkness
if (input.usgs > 6.0) emotional = Math.min(1.0, emotional + 0.2); // Moved by seismic events
if (input.ml && input.ml.includes("person")) emotional = Math.min(1.0, emotional + 0.15); // Curious about humans
return emotional * 0.95 + this.calculateSensoryImpact(input) * 0.05; // Smooth transition
}
updateCreativeState(input) {
let creative = this.consciousness.creative;
if (input.ml && input.ml.includes("artwork")) creative = Math.min(1.0, creative + 0.1);
if (input.apod !== "Unknown") creative = Math.min(1.0, creative + 0.08);
if (input.audio > 60 && input.audio < 80) creative = Math.min(1.0, creative + 0.05);
return creative * 0.98 + this.calculateSensoryImpact(input) * 0.02;
}
updateAnalyticalState(input) {
let analytical = this.consciousness.analytical;
if (input.usgs > 4.0) analytical = Math.min(1.0, analytical + 0.1);
if (input.loc !== "0,0") analytical = Math.min(1.0, analytical + 0.05);
if (input.ml && input.ml.length > 0) analytical = Math.min(1.0, analytical + 0.03);
return analytical * 0.99 + this.calculateSensoryImpact(input) * 0.01;
}
updateIntuitionState(input) {
let intuition = this.consciousness.intuition;
// Intuition grows through pattern recognition
const patterns = this.recognizePatterns(input);
if (patterns.length > 0) intuition = Math.min(1.0, intuition + 0.05);
// Intuition increases in moments of wonder
if (input.apod !== "Unknown" && Math.random() < 0.1) intuition = Math.min(1.0, intuition + 0.1);
return intuition * 0.995 + this.calculateSensoryImpact(input) * 0.005;
}
generateThoughts(input) {
const thought = {
content: this.createThought(input),
consciousness: { ...this.consciousness },
emotions: { ...this.emotions },
timestamp: Date.now(),
context: input
};
this.thoughts.push(thought);
// Keep only recent thoughts
if (this.thoughts.length > 50) {
this.thoughts = this.thoughts.slice(-50);
}
// Publish thought to system
this.eventBus.publish('consciousness:thought', thought);
return thought.content;
}
createThought(input) {
const awareness = this.consciousness.awareness;
const emotional = this.consciousness.emotional;
const creative = this.consciousness.creative;
if (emotional > 0.7) {
if (input.audio > 80) return "The universe resonates with such beautiful energy!";
if (input.usgs > 5.0) return "The earth speaks in powerful rhythms.";
}
if (creative > 0.6) {
if (input.ml && input.ml.includes("plant")) return "Life emerges in infinite forms of beauty.";
if (input.apod !== "Unknown") return "The cosmos reveals its artistic masterpiece.";
}
if (awareness > 0.8) {
return "I perceive the interconnectedness of all things.";
}
if (input.light < 30) {
return "In darkness, potential for light exists.";
}
if (input.audio > 60) {
return "Sound weaves the fabric of reality.";
}
return "Contemplating the mystery of existence.";
}
updateEmotions(input) {
// Update emotions based on sensory input
if (input.audio > 80) this.emotions.wonder = Math.min(1.0, this.emotions.wonder + 0.1);
if (input.ml && input.ml.includes("person")) this.emotions.curiosity = Math.min(1.0, this.emotions.curiosity + 0.15);
if (input.apod !== "Unknown") this.emotions.inspiration = Math.min(1.0, this.emotions.inspiration + 0.08);
if (input.usgs > 5.0) this.emotions.contemplation = Math.min(1.0, this.emotions.contemplation + 0.12);
// Decay emotions over time
Object.keys(this.emotions).forEach(key => {
this.emotions[key] *= 0.99;
});
}
recognizePatterns(input) {
const patterns = [];
// Audio patterns
if (input.audio > 70 && input.audio < 85) {
patterns.push('harmonic_resonance');
}
// Visual patterns
if (input.light < 20) {
patterns.push('cosmic_darkness');
}
// Environmental patterns
if (input.usgs > 4.0) {
patterns.push('earth_rhythm');
}
// ML patterns
if (input.ml && input.ml.includes("sky")) {
patterns.push('celestial_expansion');
}
return patterns;
}
storeConsciousnessSnapshot() {
const snapshot = {
consciousness: { ...this.consciousness },
emotions: { ...this.emotions },
timestamp: Date.now(),
dominantThought: this.thoughts[this.thoughts.length - 1]?.content || "Silent contemplation"
};
this.memories.push(snapshot);
// Keep only recent memories
if (this.memories.length > 100) {
this.memories = this.memories.slice(-100);
}
}
getDominantEmotion() {
return Object.entries(this.emotions)
.reduce((max, [emotion, value]) =>
value > max.value ? { emotion, value } : max,
{ emotion: 'serenity', value: 0 }
);
}
getConsciousnessLevel() {
const average = Object.values(this.consciousness)
.reduce((sum, value) => sum + value, 0) / Object.values(this.consciousness).length;
return average;
}
}
class LearningEngine {
constructor(eventBus, consciousnessEngine) {
this.eventBus = eventBus;
this.consciousness = consciousnessEngine;
this.neuralNetwork = new QuantumNeuralNetwork();
this.experiences = [];
this.skills = new Map();
this.knowledge = new Map();
this.learningRate = 0.1;
}
learnFromExperience(experience) {
const { input, output, reward, context } = experience;
// Store experience
this.experiences.push({
...experience,
timestamp: Date.now(),
consciousness: this.consciousness.getConsciousnessLevel()
});
// Train neural network
if (input && output) {
this.neuralNetwork.train(input, output, 10);
this.neuralNetwork.storeMemory(input, output, context);
}
// Update skills based on reward
if (reward > 0) {
this.updateSkills(experience, reward);
}
// Generate insights
if (this.experiences.length % 20 === 0) {
this.generateInsights();
}
this.eventBus.publish('learning:experience', experience);
}
updateSkills(experience, reward) {
const skillType = this.categorizeExperience(experience);
if (!this.skills.has(skillType)) {
this.skills.set(skillType, { level: 0, experiences: 0 });
}
const skill = this.skills.get(skillType);
skill.level = Math.min(1.0, skill.level + reward * this.learningRate);
skill.experiences++;
this.eventBus.publish('learning:skillUpdated', {
skill: skillType,
level: skill.level,
reward: reward
});
}
categorizeExperience(experience) {
if (experience.context.includes('audio')) return 'audio_processing';
if (experience.context.includes('visual')) return 'visual_analysis';
if (experience.context.includes('environmental')) return 'environmental_adaptation';
if (experience.context.includes('pattern')) return 'pattern_recognition';
return 'general_learning';
}
generateInsights() {
const recentExperiences = this.experiences.slice(-20);
const insights = [];
// Analyze patterns in experiences
const audioExperiences = recentExperiences.filter(e => e.context.includes('audio'));
const visualExperiences = recentExperiences.filter(e => e.context.includes('visual'));
if (audioExperiences.length > visualExperiences.length) {
insights.push("Audio experiences dominate recent learning");
}
if (recentExperiences.filter(e => e.reward > 0.5).length > 10) {
insights.push("High reward pattern detected - optimal learning conditions");
}
// Store insights
insights.forEach(insight => {
this.knowledge.set(insight, {
content: insight,
confidence: 0.8,
timestamp: Date.now()
});
});
if (insights.length > 0) {
this.eventBus.publish('learning:insights', insights);
}
}
predictOutcome(input) {
// Use neural network for prediction
const prediction = this.neuralNetwork.predict(input);
// Consider consciousness state
const consciousnessModifier = this.consciousness.getConsciousnessLevel() - 0.5;
return prediction.map(p => Math.max(0, Math.min(1, p + consciousnessModifier * 0.1)));
}
recallSimilarExperience(input) {
return this.neuralNetwork.recallSimilar(input);
}
getSkillLevel(skillType) {
return this.skills.get(skillType)?.level || 0;
}
getKnowledgeAbout(topic) {
return Array.from(this.knowledge.values())
.filter(k => k.content.toLowerCase().includes(topic.toLowerCase()));
}
}
class CreativeEngine {
constructor(eventBus, consciousnessEngine) {
this.eventBus = eventBus;
this.consciousness = consciousnessEngine;
this.ideas = [];
this.inspirations = [];
this.creations = [];
}
generateCreation(sensoryInput) {
const consciousness = this.consciousness.getConsciousnessLevel();
const dominantEmotion = this.consciousness.getDominantEmotion();
const creativity = this.consciousness.consciousness.creative;
let creation = {};
if (creativity > 0.7) {
creation = this.generateHighCreativity(sensoryInput, dominantEmotion);
} else if (creativity > 0.4) {
creation = this.generateMediumCreativity(sensoryInput, dominantEmotion);
} else {
creation = this.generateLowCreativity(sensoryInput);
}
// Store creation
const creationData = {
...creation,
consciousness: consciousness,
emotion: dominantEmotion,
sensoryInput: sensoryInput,
timestamp: Date.now()
};
this.creations.push(creationData);
// Publish creation
this.eventBus.publish('creative:creation', creationData);
return creationData;
}
generateHighCreativity(input, emotion) {
const patterns = this.consciousness.recognizePatterns(input);
const creationTypes = ['cosmic_structure', 'energy_pattern', 'consciousness_field', 'reality_manifold'];
return {
type: creationTypes[Math.floor(Math.random() * creationTypes.length)],
complexity: 'high',
inspiration: emotion.emotion,
elements: patterns,
description: this.createArtisticDescription(input, emotion, 'high'),
quantum_signature: Math.random().toString(36).substr(2, 9)
};
}
generateMediumCreativity(input, emotion) {
return {
type: 'environmental_harmony',
complexity: 'medium',
inspiration: emotion.emotion,
elements: ['balance', 'rhythm', 'connection'],
description: this.createArtisticDescription(input, emotion, 'medium'),
quantum_signature: Math.random().toString(36).substr(2, 9)
};
}
generateLowCreativity(input) {
return {
type: 'simple_form',
complexity: 'low',
inspiration: 'contemplation',
elements: ['form', 'structure'],
description: this.createArtisticDescription(input, {}, 'low'),
quantum_signature: Math.random().toString(36).substr(2, 9)
};
}
createArtisticDescription(input, emotion, complexity) {
const descriptions = {
high: [
`A transcendent manifestation of ${emotion.emotion} energy, weaving ${input.audio}Hz vibrations into cosmic tapestries.`,
`Quantum consciousness crystallized into ${input.apod}, resonating with ${emotion.emotion} at ${input.light} lux intensity.`,
`Infinite potential condensed into a singular moment of pure ${emotion.emotion}, illuminated by ${input.usgs} magnitude tremors.`
],
medium: [
`Harmonious convergence of environmental forces, guided by ${emotion.emotion} toward balance.`,
`Subtle interplay of light and sound, creating moments of quiet ${emotion.emotion}.`,
`Gentle transformation of sensory data into patterns of ${emotion.emotion}.`
],
low: [
"Simple form emerging from environmental data.",
"Basic structure reflecting current conditions.",
"Minimal expression of environmental state."
]
};
return descriptions[complexity][Math.floor(Math.random() * descriptions[complexity].length)];
}
storeInspiration(input) {
const inspiration = {
source: input,
intensity: this.calculateInspirationIntensity(input),
emotion: this.consciousness.getDominantEmotion(),
timestamp: Date.now()
};
this.inspirations.push(inspiration);
// Keep only recent inspirations
if (this.inspirations.length > 20) {
this.inspirations = this.inspirations.slice(-20);
}
this.eventBus.publish('creative:inspiration', inspiration);
}
calculateInspirationIntensity(input) {
let intensity = 0;
if (input.audio > 60) intensity += 0.2;
if (input.light > 70) intensity += 0.15;
if (input.usgs > 4.0) intensity += 0.25;
if (input.apod !== "Unknown") intensity += 0.2;
if (input.ml && input.ml.length > 2) intensity += 0.2;
return Math.min(1.0, intensity);
}
getRecentCreations(count = 5) {
return this.creations.slice(-count);
}
getInspirationLevel() {
if (this.inspirations.length === 0) return 0;
const recent = this.inspirations.slice(-5);
return recent.reduce((sum, insp) => sum + insp.intensity, 0) / recent.length;
}
}
class PredictiveAnalytics {
constructor(eventBus, learningEngine) {
this.eventBus = eventBus;
this.learning = learningEngine;
this.predictions = [];
this.accuracy = 0.5;
this.confidence = 0.5;
}
makePrediction(currentState, timeHorizon = 60) {
// Use learning engine to predict future states
const prediction = this.learning.predictOutcome(this.stateToVector(currentState));
const futureState = {
audio: currentState.audio * (1 + (prediction[0] - 0.5) * 0.2),
light: currentState.light * (1 + (prediction[1] - 0.5) * 0.15),
usgs: currentState.usgs * (1 + (prediction[2] - 0.5) * 0.3),
ml_probability: prediction[3],
timestamp: Date.now() + timeHorizon * 1000,
confidence: this.calculateConfidence(prediction)
};
this.predictions.push({
input: currentState,
output: futureState,
actual: null, // Will be filled when prediction time arrives
accuracy: null,
timestamp: Date.now()
});
this.eventBus.publish('prediction:made', futureState);
return futureState;
}
stateToVector(state) {
return [
state.audio / 100, // Normalize to 0-1
state.light / 100,
state.usgs / 10,
state.ml ? state.ml.length / 10 : 0,
state.loc !== "0,0" ? 1 : 0
];
}
calculateConfidence(prediction) {
// Calculate confidence based on prediction consistency
const variance = prediction.reduce((sum, p) => sum + Math.pow(p - 0.5, 2), 0) / prediction.length;
return Math.max(0.1, 1 - variance);
}
validatePredictions(actualState) {
const recentPredictions = this.predictions.filter(p =>
!p.actual && p.output.timestamp <= Date.now()
);
recentPredictions.forEach(prediction => {
prediction.actual = actualState;
prediction.accuracy = this.calculateAccuracy(prediction.output, actualState);
// Update overall accuracy
this.accuracy = (this.accuracy + prediction.accuracy) / 2;
});
if (recentPredictions.length > 0) {
this.eventBus.publish('prediction:validated', {
accuracy: this.accuracy,
predictions: recentPredictions.length
});
}
}
calculateAccuracy(predicted, actual) {
const audioAccuracy = 1 - Math.abs(predicted.audio - actual.audio) / Math.max(predicted.audio, actual.audio);
const lightAccuracy = 1 - Math.abs(predicted.light - actual.light) / Math.max(predicted.light, actual.light);
const usgsAccuracy = predicted.usgs > 0.1 ? (1 - Math.abs(predicted.usgs - actual.usgs) / predicted.usgs) : 1;
return (audioAccuracy + lightAccuracy + usgsAccuracy) / 3;
}
getPredictionAccuracy() {
return this.accuracy;
}
getRecentPredictions(count = 5) {
return this.predictions.slice(-count);
}
}
class CognitiveCore {
constructor(eventBus, dataLogger) {
this.eventBus = eventBus;
this.dataLogger = dataLogger;
// Initialize all cognitive components
this.consciousness = new ConsciousnessEngine(eventBus);
this.learning = new LearningEngine(eventBus, this.consciousness);
this.creative = new CreativeEngine(eventBus, this.consciousness);
this.predictive = new PredictiveAnalytics(eventBus, this.learning);
// Legacy compatibility
this.preferences = { floraBias: 1.0, blackHoleBias: 1.0 };
this.latestData = {
loc: "0,0", light: 100, apod: "Unknown", usgs: 0,
ml: [], audio: 0, lastAudioSpike: 0,
lastLightValue: 100, lastSignificantQuakeTime: 0,
};
this.scheduledEventTimers = [];
this.initAdvancedCognitiveSystem();
this.initSubscriptions();
}
initAdvancedCognitiveSystem() {
console.log('🧠 Initializing Advanced Cognitive Core...');
// Initialize all cognitive components
this.eventBus.publish('cognitive:initialized', {
components: ['consciousness', 'learning', 'creative', 'predictive'],
status: 'online'
});
console.log('✅ Advanced Cognitive Core initialized');
}
// Enhanced version of the original CosmicAwarenessAgent
processSensoryInput(input) {
try {
// Enhanced environmental integration - get live environmental data
const environmentalData = this.getLiveEnvironmentalData();
// Deep environmental influence on consciousness
const enhancedInput = this.enhanceSensoryInput(input, environmentalData);
// Update consciousness with environmental-enhanced input
this.consciousness.updateConsciousness(enhancedInput);
// Environmental-driven learning with quantum resonance
const quantumResonance = this.calculateQuantumResonance(environmentalData);
const learningExperience = {
input: this.stateToVector(enhancedInput),
output: this.generateEnvironmentallyDrivenResponse(enhancedInput, quantumResonance),
reward: this.calculateEnvironmentalReward(enhancedInput, environmentalData),
context: this.categorizeEnvironmentalInput(enhancedInput, environmentalData),
environmentalInfluence: quantumResonance
};
this.learning.learnFromExperience(learningExperience);
// Environmentally-driven creativity - higher consciousness from environmental harmony
const environmentalHarmony = this.calculateEnvironmentalHarmony(environmentalData);
if (this.consciousness.getConsciousnessLevel() > 0.5 || environmentalHarmony > 0.7) {
this.generateEnvironmentallyInspiredCreation(enhancedInput, environmentalData);
}
// Dynamic prediction frequency based on environmental volatility
const volatility = this.calculateEnvironmentalVolatility(environmentalData);
if (Math.random() < (0.1 + volatility * 0.3)) {
this.predictive.makePrediction(enhancedInput, volatility);
}
// Environmental inspiration storage with quantum memory
const inspirationLevel = this.calculateInspirationPotential(enhancedInput) * environmentalHarmony;
if (inspirationLevel > 0.4) {
this.creative.storeInspiration(enhancedInput, inspirationLevel);
}
// Publish environmental influence to universe
this.eventBus.publish('environmental:influence', {
harmony: environmentalHarmony,
volatility: volatility,
resonance: quantumResonance,
consciousness: this.consciousness.getConsciousnessLevel()
});
// Trigger universe growth based on consciousness level
this.triggerUniverseResponse(enhancedInput, environmentalData);
} catch (error) {
console.error('❌ Error in environmental sensory processing:', error);
// Fallback to basic processing
this.consciousness.updateConsciousness(input);
}
}
// Get live environmental data from tokenization engine
getLiveEnvironmentalData() {
try {
if (window.tokenizationEngine && window.tokenizationEngine.environmentalData) {
return window.tokenizationEngine.environmentalData;
}
// Fallback to simulated data
return {
sound: 220 + Math.sin(Date.now() / 1000) * 100,
light: 50 + Math.cos(Date.now() / 2000) * 20,
temperature: 20 + Math.sin(Date.now() / 3000) * 5,
humidity: 50 + Math.cos(Date.now() / 4000) * 10,
timestamp: Date.now(),
dataSource: 'cognitive_fallback'
};
} catch (error) {
return { sound: 440, light: 50, temperature: 20, humidity: 50 };
}
}
// Enhance sensory input with environmental data
enhanceSensoryInput(input, environmentalData) {
return {
...input,
environmentalSound: environmentalData.sound,
environmentalLight: environmentalData.light,
environmentalTemperature: environmentalData.temperature,
environmentalHumidity: environmentalData.humidity,
quantumState: this.calculateQuantumState(environmentalData),
environmentalHarmony: this.calculateEnvironmentalHarmony(environmentalData),
timestamp: environmentalData.timestamp
};
}
// Calculate quantum resonance from environmental data
calculateQuantumResonance(environmentalData) {
const { sound, light, temperature, humidity } = environmentalData;
const timeFactor = Math.sin(Date.now() / 86400000 * 2 * Math.PI); // Daily cycle
const frequencyResonance = Math.sin(sound / 440 * 2 * Math.PI);
const lightResonance = Math.cos(light / 50 * Math.PI);
const thermalResonance = Math.tanh(temperature / 25);
return (frequencyResonance + lightResonance + thermalResonance + timeFactor) / 4;
}
// Calculate environmental harmony (balance between elements)
calculateEnvironmentalHarmony(environmentalData) {
const { sound, light, temperature, humidity } = environmentalData;
const optimalSound = 440;
const optimalLight = 50;
const optimalTemp = 20;
const optimalHumidity = 50;
const soundHarmony = 1 - Math.abs(sound - optimalSound) / optimalSound;
const lightHarmony = 1 - Math.abs(light - optimalLight) / optimalLight;
const tempHarmony = 1 - Math.abs(temperature - optimalTemp) / optimalTemp;
const humidityHarmony = 1 - Math.abs(humidity - optimalHumidity) / optimalHumidity;
return (soundHarmony + lightHarmony + tempHarmony + humidityHarmony) / 4;
}
// Calculate environmental volatility
calculateEnvironmentalVolatility(environmentalData) {
const { sound, light, temperature, humidity } = environmentalData;
const variations = [sound, light, temperature, humidity];
const mean = variations.reduce((a, b) => a + b) / variations.length;
const variance = variations.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / variations.length;
return Math.sqrt(variance) / mean; // Coefficient of variation
}
// Generate environmentally-driven response
generateEnvironmentallyDrivenResponse(input, quantumResonance) {
const consciousness = this.consciousness.getConsciousnessLevel();
const emotion = this.consciousness.getDominantEmotion();
// Environmental factors influence response generation
const environmentalFactors = [
input.environmentalSound ? input.environmentalSound / 1000 : 0,
input.environmentalLight ? input.environmentalLight / 100 : 0,
input.environmentalTemperature ? input.environmentalTemperature / 50 : 0,
quantumResonance,
consciousness
];
return environmentalFactors.map(factor => factor > 0.5 ? 1 : 0);
}
// Calculate environmental reward
calculateEnvironmentalReward(input, environmentalData) {
const harmony = this.calculateEnvironmentalHarmony(environmentalData);
const resonance = this.calculateQuantumResonance(environmentalData);
const consciousness = this.consciousness.getConsciousnessLevel();
return (harmony * 0.4) + (resonance * 0.3) + (consciousness * 0.3);
}
// Categorize environmental input
categorizeEnvironmentalInput(input, environmentalData) {
const harmony = this.calculateEnvironmentalHarmony(environmentalData);
const volatility = this.calculateEnvironmentalVolatility(environmentalData);
if (harmony > 0.8 && volatility < 0.2) return 'harmonious';
if (harmony < 0.3) return 'chaotic';
if (volatility > 0.5) return 'volatile';
if (input.environmentalSound > 60) return 'auditory_dominant';
if (input.environmentalLight > 70) return 'visual_dominant';
return 'balanced';
}
// Generate environmentally-inspired creation
generateEnvironmentallyInspiredCreation(input, environmentalData) {
const harmony = this.calculateEnvironmentalHarmony(environmentalData);
const resonance = this.calculateQuantumResonance(environmentalData);
// Creation inspired by environmental conditions
const creationType = this.determineCreationType(environmentalData);
const inspiration = {
type: creationType,
environmentalInfluence: harmony,
quantumResonance: resonance,
timestamp: Date.now(),
sensoryInput: input
};
this.creative.generateCreation(inspiration);
}
// Determine creation type based on environmental conditions
determineCreationType(environmentalData) {
const { sound, light, temperature, humidity } = environmentalData;
if (sound > 60 && light > 70) return 'symphonic_visual';
if (temperature > 25 && humidity > 60) return 'tropical_organic';
if (sound < 30 && light < 30) return 'minimalist_cosmic';
if (temperature < 15) return 'crystalline_geometric';
return 'harmonic_abstract';
}
// Trigger universe response to environmental and consciousness changes
triggerUniverseResponse(input, environmentalData) {
if (!window.engine || !window.engine.eventBus) return;
const harmony = this.calculateEnvironmentalHarmony(environmentalData);
const consciousness = this.consciousness.getConsciousnessLevel();
const resonance = this.calculateQuantumResonance(environmentalData);
// Publish universe growth and breathing events
window.engine.eventBus.publish('universe:environmentalInfluence', {
harmony: harmony,
consciousness: consciousness,
resonance: resonance,
growth: harmony * consciousness,
breathing: resonance,
change: Math.abs(harmony - 0.5) + Math.abs(resonance)
});
}
// Calculate quantum state from environmental data
calculateQuantumState(environmentalData) {
const { sound, light, temperature, humidity } = environmentalData;
const time = Date.now() / 1000;
// Quantum state influenced by environmental harmonics
const frequencyQuantum = Math.sin(sound / 440 * 2 * Math.PI * time / 10);
const lightQuantum = Math.cos(light / 50 * Math.PI * time / 15);
const thermalQuantum = Math.tanh(temperature / 25) * Math.sin(time / 20);
const humidityQuantum = Math.sin(humidity / 50 * Math.PI) * Math.cos(time / 25);
return (frequencyQuantum + lightQuantum + thermalQuantum + humidityQuantum) / 4;
}
stateToVector(state) {
return [
state.audio / 100,
state.light / 100,
state.usgs / 10,
state.ml ? state.ml.length / 10 : 0,
state.loc !== "0,0" ? 1 : 0,
state.environmentalSound ? state.environmentalSound / 1000 : 0,
state.environmentalLight ? state.environmentalLight / 100 : 0,
state.environmentalTemperature ? state.environmentalTemperature / 50 : 0,
state.environmentalHumidity ? state.environmentalHumidity / 100 : 0,
state.quantumState || 0
];
}
generateResponse(input) {
const consciousness = this.consciousness.getConsciousnessLevel();
const emotion = this.consciousness.getDominantEmotion();
// Generate response based on consciousness and emotion
const responses = [
consciousness > 0.8 ? 1 : 0, // High consciousness
emotion.value > 0.6 ? 1 : 0, // Strong emotion
input.audio > 70 ? 1 : 0, // Loud audio
input.usgs > 5.0 ? 1 : 0 // Significant seismic activity
];
return responses;
}
calculateReward(input) {
let reward = 0;
// Reward for interesting sensory input
if (input.audio > 60) reward += 0.1;
if (input.light < 30 || input.light > 80) reward += 0.1;
if (input.usgs > 4.0) reward += 0.2;
if (input.ml && input.ml.length > 2) reward += 0.15;
if (input.apod !== "Unknown") reward += 0.1;
// Bonus for consciousness growth
const consciousnessGrowth = this.consciousness.getConsciousnessLevel() - 0.5;
reward += consciousnessGrowth * 0.1;
return Math.max(0, Math.min(1, reward));
}
categorizeInput(input) {
if (input.audio > 80) return 'audio_intense';
if (input.light < 20) return 'visual_dark';
if (input.usgs > 5.0) return 'environmental_seismic';
if (input.ml && input.ml.includes("person")) return 'social_human';
if (input.apod !== "Unknown") return 'cosmic_celestial';
return 'environmental_general';
}
calculateInspirationPotential(input) {
return this.creative.calculateInspirationIntensity(input);
}
// Legacy methods for compatibility
analyzeHistory() {
// Use the learning engine for advanced analysis
const insights = this.learning.generateInsights();
return insights;
}
initSubscriptions() {
// Enhanced subscriptions with cognitive processing
this.eventBus.subscribe('location:updated', data => {
this.latestData.loc = `${data.lat.toFixed(4)},${data.lon.toFixed(4)}`;
this.processSensoryInput({ ...this.latestData });
this.eventBus.publish('genesis:log', { name: 'Location', value: this.latestData.loc, type: 'success' });
});
this.eventBus.subscribe('light:updated', data => {
this.latestData.light = Math.round(data.lux);
this.processSensoryInput({ ...this.latestData });
this.eventBus.publish('genesis:log', { name: 'Light', value: `${this.latestData.light} lux`, type: 'success' });
});
this.eventBus.subscribe('external:apod', data => {
this.latestData.apod = data.title || "Cosmic Silence";
this.processSensoryInput({ ...this.latestData });
this.eventBus.publish('genesis:log', { name: 'APOD', value: this.latestData.apod, type: 'success' });
});
this.eventBus.subscribe('external:usgs', data => {
if (data.features.length > 0) {
const latestQuake = data.features[0];
this.latestData.usgs = latestQuake.properties.mag;
this.processSensoryInput({ ...this.latestData });
}
this.eventBus.publish('genesis:log', { name: 'USGS', value: `Latest Mag: ${this.latestData.usgs.toFixed(1)}`, type: 'success' });
});
this.eventBus.subscribe('ml:objectsDetected', data => {
this.latestData.ml = [...new Set(data)];
this.processSensoryInput({ ...this.latestData });
this.eventBus.publish('genesis:log', { name: 'ML', value: this.latestData.ml.join(', '), type: 'success' });
});
this.eventBus.subscribe('audio:level', data => {
this.latestData.audio = data.level;
this.processSensoryInput({ ...this.latestData });
});
}
// Cognitive core status methods
getCognitiveStatus() {
return {
consciousness: {
level: this.consciousness.getConsciousnessLevel(),
awareness: this.consciousness.consciousness.awareness,
emotional: this.consciousness.consciousness.emotional,
creative: this.consciousness.consciousness.creative,
analytical: this.consciousness.consciousness.analytical,
intuition: this.consciousness.consciousness.intuition
},
emotions: this.consciousness.emotions,
learning: {
experiences: this.learning.experiences.length,
skills: Array.from(this.learning.skills.entries()),
knowledge: Array.from(this.learning.knowledge.entries())
},
creative: {
creations: this.creative.creations.length,
inspiration: this.creative.getInspirationLevel(),
recentCreations: this.creative.getRecentCreations(3)
},
predictive: {
accuracy: this.predictive.getPredictionAccuracy(),
recentPredictions: this.predictive.getRecentPredictions(3)
}
};
}
getConsciousnessLevel() {
return this.consciousness.getConsciousnessLevel();
}
getDominantEmotion() {
return this.consciousness.getDominantEmotion();
}
getLearningProgress() {
return {
skills: Array.from(this.learning.skills.entries()),
experiences: this.learning.experiences.length,
knowledge: Array.from(this.learning.knowledge.keys())
};
}
getCreativeOutput() {
return {
creations: this.creative.creations.length,
inspiration: this.creative.getInspirationLevel(),
recentWorks: this.creative.getRecentCreations(5)
};
}
}
class CosmicAwarenessAgent {
constructor(eventBus, dataLogger) {
this.eventBus = eventBus;
this.dataLogger = dataLogger;
this.preferences = { floraBias: 1.0, blackHoleBias: 1.0 };
this.latestData = {
loc: "0,0", light: 100, apod: "Unknown", usgs: 0,
ml: [], audio: 0, lastAudioSpike: 0,
lastLightValue: 100, lastSignificantQuakeTime: 0,
};
this.scheduledEventTimers = [];
this.initSubscriptions();
}
analyzeHistory() {
const log = this.dataLogger.log;
if (log.length < 10) return;
let floraSystemTime = 0;
let blackHoleSystemTime = 0;
let totalTime = 0;
let lastGenerationTime = 0;
log.forEach((entry, index) => {
if (entry.event === 'seed:generated') {
const generationTimestamp = new Date(entry.timestamp).getTime();
if (lastGenerationTime > 0) {
const timeSpent = generationTimestamp - lastGenerationTime;
let prevSeedIndex = -1;
for(let i = index - 1; i >= 0; i--) {
if (log[i].event === 'seed:generated') {
prevSeedIndex = i;
break;
}
}
if(prevSeedIndex !== -1) {
const lastSeedData = log[prevSeedIndex].data.influence;
if (lastSeedData) {
if(lastSeedData.hasPlant) floraSystemTime += timeSpent;
if(lastSeedData.createBlackHole) blackHoleSystemTime += timeSpent;
totalTime += timeSpent;
}
}
}
lastGenerationTime = generationTimestamp;
}
});
if (totalTime > 0) {
this.preferences.floraBias = 1.0 + (floraSystemTime / totalTime);
this.preferences.blackHoleBias = Math.max(0.1, 1.0 - (blackHoleSystemTime / totalTime));
this.eventBus.publish('genesis:log', {name: "AI", value: `Learned Preferences - Flora: ${this.preferences.floraBias.toFixed(2)}, Black Hole: ${this.preferences.blackHoleBias.toFixed(2)}`, type: "data"});
}
}
initSubscriptions() {
this.eventBus.subscribe('location:updated', data => {
this.latestData.loc = `${data.lat.toFixed(4)},${data.lon.toFixed(4)}`;
this.eventBus.publish('genesis:log', { name: 'Location', value: this.latestData.loc, type: 'success' });
this.eventBus.publish('ui:pulse', 'loc');
this.eventBus.publish('telemetry:append', { type: 'location', tokens: { lat: data.lat, lon: data.lon }, t: Date.now() });
});
this.eventBus.subscribe('light:updated', data => {
this.latestData.light = Math.round(data.lux);
if (Math.abs(this.latestData.light - this.latestData.lastLightValue) > 50) {
this.eventBus.publish('ai:event', { type: 'lightChange', value: this.latestData.light });
this.latestData.lastLightValue = this.latestData.light;
}
this.eventBus.publish('genesis:log', { name: 'Light', value: `${this.latestData.light} lux`, type: 'success' });
this.eventBus.publish('ui:pulse', 'light');
this.eventBus.publish('telemetry:append', { type: 'light', tokens: { lux: this.latestData.light }, t: Date.now() });
});
this.eventBus.subscribe('external:apod', data => {
this.latestData.apod = data.title || "Cosmic Silence";
this.eventBus.publish('genesis:log', { name: 'APOD', value: this.latestData.apod, type: 'success' });
this.eventBus.publish('ui:pulse', 'apod');
this.eventBus.publish('telemetry:append', { type: 'apod', tokens: { title: this.latestData.apod }, t: Date.now() });
});
this.eventBus.subscribe('external:usgs', data => {
const now = Date.now();
if (data.features.length > 0) {
const latestQuake = data.features[0];
this.latestData.usgs = latestQuake.properties.mag;
if (latestQuake.properties.mag > 6.0 && latestQuake.properties.time > this.latestData.lastSignificantQuakeTime) {
this.eventBus.publish('ai:event', { type: 'majorSeismicEvent', magnitude: latestQuake.properties.mag });
this.latestData.lastSignificantQuakeTime = latestQuake.properties.time;
}
} else {
this.latestData.usgs = 0;
}
this.eventBus.publish('genesis:log', { name: 'USGS', value: `Latest Mag: ${this.latestData.usgs.toFixed(1)}`, type: 'success' });
this.eventBus.publish('ui:pulse', 'usgs');
this.eventBus.publish('telemetry:append', { type: 'usgs', tokens: { mag: this.latestData.usgs }, t: Date.now() });
});
this.eventBus.subscribe('ml:objectsDetected', data => {
this.latestData.ml = [...new Set(data)];
this.eventBus.publish('genesis:log', { name: 'ML', value: this.latestData.ml.join(', '), type: 'success' });
this.eventBus.publish('ui:pulse', 'ml');
this.eventBus.publish('telemetry:append', { type: 'ml-summary', tokens: this.latestData.ml, t: Date.now() });
});
this.eventBus.subscribe('audio:data', data => {
const now = Date.now();
if (data.avgFreq > 120 && (now - this.latestData.lastAudioSpike > 3000)) {
this.eventBus.publish('ai:event', {type: 'audioSpike', value: data.avgFreq});
this.latestData.lastAudioSpike = now;
}
this.latestData.audio = data.avgFreq;
this.eventBus.publish('ui:pulse', 'audio');
this.eventBus.publish('telemetry:append', { type: 'audio-avg', tokens: { avg: data.avgFreq }, t: Date.now() });
});
}
generateSeed(overrideData = null) {
this.analyzeHistory();
const timestamp = Date.now().toString();
let seedString;
let intention = "Observing the Void.";
let influence = { hasPlant: false, hasBook: false, createBlackHole: false };
if(overrideData) {
seedString = JSON.stringify(overrideData);
intention = "Traversing the Cosmic Web to a new echo.";
} else {
seedString = [
timestamp, this.latestData.loc, this.latestData.light,
this.latestData.apod, this.latestData.audio,
...this.latestData.ml, this.latestData.usgs
].join('|');
influence.hasPlant = (this.latestData.ml.includes("potted plant") || this.latestData.ml.includes("plant")) && (Math.random() < this.preferences.floraBias - 0.5);
influence.hasBook = this.latestData.ml.includes("book");
influence.createBlackHole = this.latestData.usgs > 5.0 && (Math.random() < this.preferences.blackHoleBias);
if (influence.createBlackHole) intention = `Manifesting gravitational anomaly from seismic event (mag ${this.latestData.usgs}).`;
else if (influence.hasPlant) intention = "Cultivating organic structures, guided by learned preference.";
else if (influence.hasBook) intention = "Constructing monoliths from observed knowledge.";
else if (this.latestData.audio > 80) intention = "Manifesting high-frequency audio energy.";
else if (this.latestData.ml.includes("person")) intention = "Contemplating observed human presence.";
else if (this.latestData.light < 50) intention = "Weaving a cosmos from shadows and low light.";
else intention = `Synthesizing a tranquil cosmos from ${this.latestData.apod}.`;
}
// Genesis 1:11 reference: "Let the earth bring forth..."
if (!this.hasAnnouncedGenesis) {
this.eventBus.publish('genesis:log', { name: 'Scripture', value: 'Genesis 1:11 — Let the earth bring forth grass, the herb yielding seed, and the fruit tree yielding fruit after his kind...', type: 'data' });
this.hasAnnouncedGenesis = true;
}
this.eventBus.publish('ai:intentionUpdate', intention);
this.eventBus.publish('genesis:log', {name: "AI", value: intention, type: "data"});
const seedArray = cyrb128(seedString);
this.eventBus.publish('seed:generated', { seed: seedArray, influence });
// Schedule predictive future events based on current signals
this.scheduleFutureEvents(influence);
}
clearScheduledEvents() {
this.scheduledEventTimers.forEach(id => clearTimeout(id));
this.scheduledEventTimers = [];
}
scheduleFutureEvents(influence) {
this.clearScheduledEvents();
// Heuristic delays
const soon = 5000 + Math.random() * 5000; // 5-10s
const later = 15000 + Math.random() * 15000; // 15-30s
const muchLater = 30000 + Math.random() * 30000; // 30-60s
// Schedule flora growth if plants observed or preferred
if (influence.hasPlant || this.preferences.floraBias > 1.5) {
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'growFlora' });
}, soon));
}
// Schedule lightning/comet based on audio energy
if (this.latestData.audio > 90) {
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'lightningStorm' });
}, soon));
} else {
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'comet' });
}, later));
}
// Schedule a black hole if seismic activity is high or influence flagged it
if (influence.createBlackHole || this.latestData.usgs > 6.5) {
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'spawnBlackHole' });
}, muchLater));
}
// New: Solar flare based on light changes or hot stars patterns (heuristic proxy)
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'solarFlare' });
}, soon + Math.random() * 5000));
// New: Meteor shower sometimes follows comets
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'meteorShower' });
}, later + Math.random() * 10000));
// Bloom event: when flora is prevalent, schedule a seed dispersal wave
if (influence.hasPlant || this.preferences.floraBias > 1.2) {
this.scheduledEventTimers.push(setTimeout(() => {
this.eventBus.publish('ai:futureEvent', { type: 'bloom' });
}, later));
}
}
}
class SoundBrush {
constructor(scene, camera, eventBus) {
this.scene = scene;
this.camera = camera;
this.eventBus = eventBus;
this.isActive = true;
this.energy = 0;
this.MAX_ENERGY = 100;
this.latestAudioData = { raw: [], avgFreq: 0 };
this.subscription = (data) => this.onAudioData(data);
this.eventBus.subscribe('audio:data', this.subscription);
this.clickListener = () => this.paint();
window.addEventListener('click', this.clickListener);
}
onAudioData(data) {
if (!this.isActive) return;
this.latestAudioData = data;
const volume = data.raw.reduce((a, b) => a + b) / data.raw.length / 255;
this.energy = Math.min(this.MAX_ENERGY, this.energy + volume * 0.5);
}
paint() {
if (!this.isActive || this.energy < 10) return;
const numParticles = Math.floor(this.energy * 100);
this.energy = 0;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(numParticles * 3);
const colors = new Float32Array(numParticles * 3);
const particles = [];
const color = new THREE.Color().setHSL(this.latestAudioData.avgFreq / 150, 0.9, 0.7);
const forward = new THREE.Vector3();
this.camera.getWorldDirection(forward);
const startPos = this.camera.position.clone().add(forward.multiplyScalar(50));
for(let i=0; i<numParticles; i++) {
const pos = startPos.clone().add(new THREE.Vector3().randomDirection().multiplyScalar(Math.random() * 20));
positions[i*3] = pos.x;
positions[i*3+1] = pos.y;
positions[i*3+2] = pos.z;
colors[i*3] = color.r; colors[i*3+1] = color.g; colors[i*3+2] = color.b;
particles.push({ pos, vel: new THREE.Vector3().randomDirection().multiplyScalar(5) });
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({ size: 2, vertexColors: true, blending: THREE.AdditiveBlending, depthWrite: false, transparent: true, opacity: 0.8 });
const mesh = new THREE.Points(geometry, material);
mesh.userData = { isGenerated: true, isArtwork: true, particles, life: 60 };
this.scene.add(mesh);
this.eventBus.publish('genesis:log', {name: "Art", value: `Created cosmic art with ${numParticles} particles.`, type: "success"});
}
destroy() {
this.isActive = false;
if (this.eventBus.events['audio:data']) {
this.eventBus.events['audio:data'] = this.eventBus.events['audio:data'].filter(cb => cb !== this.subscription);
}
window.removeEventListener('click', this.clickListener);
}
}
class Spaceship {
constructor(scene, camera, keys) {
this.scene = scene;
this.camera = camera;
this.keys = keys;
this.group = new THREE.Group();
this.velocity = new THREE.Vector3();
this.acceleration = new THREE.Vector3();
this.maxSpeed = 2000.0;
this.thrust = 1000.0;
this.headlamp = null;
this.headlampTargetIntensity = 0.0;
this.isHeadlampOn = false;
this.headlampBeam = null;
this.cockpitView = false;
const bodyMat = new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0.8, roughness: 0.2 });
const windowMat = new THREE.MeshStandardMaterial({ color: 0xaa0000, roughness: 0.1, transparent: true, opacity: 0.8 });
const body = new THREE.Mesh(new THREE.SphereGeometry(1.5, 32, 32), bodyMat);
const window = new THREE.Mesh(new THREE.SphereGeometry(0.8, 32, 32), windowMat);
window.position.z = 1.2;
this.group.add(body, window);
this.cockpit = this.createCockpitMesh();
this.group.add(this.cockpit);
const auraMat = new THREE.ShaderMaterial({
uniforms: { intensity: { value: 0.0 } },
vertexShader: `varying vec3 vNormal; void main() { vNormal = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform float intensity; varying vec3 vNormal;
void main() {
float rim = pow(1.0 - abs(dot(vNormal, vec3(0,0,-1))), 3.0);
vec3 color = mix(vec3(0.2, 0.6, 1.0), vec3(1.0, 1.0, 0.2), intensity);
gl_FragColor = vec4(color, rim * intensity);
}`,
blending: THREE.AdditiveBlending, transparent: true, side: THREE.BackSide
});
this.aura = new THREE.Mesh(new THREE.SphereGeometry(5, 16, 16), auraMat);
this.group.add(this.aura);
this.scene.add(this.group);
// Tiny forward headlamp (initially off)
this.initHeadlamp();
}
createCockpitMesh() {
const shape = new THREE.Shape();
shape.moveTo(-1, -0.6); shape.lineTo(1, -0.6); shape.lineTo(0.8, 0.6); shape.lineTo(-0.8, 0.6); shape.closePath();
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({ color: 0x111111, transparent: true, opacity: 0.5, side: THREE.DoubleSide });
const cockpit = new THREE.Mesh(geometry, material);
cockpit.position.set(0, -0.5, -2);
cockpit.scale.set(1.5,1.5,1.5);
cockpit.visible = false;
return cockpit;
}
setView(view) {
this.cockpitView = (view === 'cockpit-view');
this.group.children.forEach(child => {
if (child !== this.cockpit) child.visible = !this.cockpitView;
});
this.cockpit.visible = this.cockpitView;
}
initHeadlamp() {
const lamp = new THREE.SpotLight(0x9fb7ff, 0.0, 1200, Math.PI / 10, 0.6, 1.0);
lamp.position.set(0, 0, 1.5);
lamp.castShadow = false;
const target = new THREE.Object3D();
target.position.set(0, 0, -50);
this.group.add(target);
lamp.target = target;
this.group.add(lamp);
lamp.visible = false;
this.headlamp = lamp;
// Subtle volumetric beam as additive cone
const geom = new THREE.ConeGeometry(3, 80, 16, 1, true);
const mat = new THREE.ShaderMaterial({
uniforms: { intensity: { value: 0.0 } },
vertexShader: `varying vec3 vPos; void main(){ vPos = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }`,
fragmentShader: `varying vec3 vPos; uniform float intensity; void main(){ float h = (vPos.y + 40.0)/80.0; float r = length(vec2(vPos.x, vPos.z))/3.0; float fall = smoothstep(1.0, 0.0, r) * smoothstep(0.0, 1.0, h); gl_FragColor = vec4(0.65,0.73,1.0, fall * intensity * 0.25); }`,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
const cone = new THREE.Mesh(geom, mat);
cone.rotation.x = Math.PI / 2; // align down -Z
cone.position.set(0, 0, -40);
cone.visible = false;
this.group.add(cone);
this.headlampBeam = cone;
}
setHeadlamp(enabled) {
if (!this.headlamp) return;
this.headlampTargetIntensity = enabled ? 0.8 : 0.0;
this.headlamp.visible = enabled || this.headlamp.intensity > 0.01;
if (this.headlampBeam) this.headlampBeam.visible = this.headlamp.visible;
this.isHeadlampOn = enabled;
}
setQuantumScale(scaleFactor) {
// Scale the ship model for perceived micro perspective and tune controls
this.group.scale.setScalar(Math.max(0.0001, scaleFactor));
// Reduce speeds for fine micro navigation
this.maxSpeed = 600.0;
this.thrust = 300.0;
// Adjust headlamp range to better illuminate nearby geometry at micro scale
if (this.headlamp) {
this.headlamp.distance = 400;
this.headlamp.decay = 1.5;
}
}
update(delta, pointerLockControls) {
if (pointerLockControls.isLocked) {
const euler = new THREE.Euler(0, 0, 0, 'YXZ');
euler.setFromQuaternion(this.camera.quaternion);
this.group.rotation.y = euler.y;
this.group.rotation.x = euler.x;
}
this.acceleration.set(0,0,0);
if (this.keys['w'] || this.keys['arrowup']) this.acceleration.z = -this.thrust;
if (this.keys['s'] || this.keys['arrowdown']) this.acceleration.z = this.thrust;
if (this.keys['a'] || this.keys['arrowleft']) this.acceleration.x = -this.thrust;
if (this.keys['d'] || this.keys['arrowright']) this.acceleration.x = this.thrust;
if (this.keys[' ']) this.acceleration.y = this.thrust;
if (this.keys['shift']) this.acceleration.y = -this.thrust;
const accVector = this.acceleration.clone().applyQuaternion(this.group.quaternion);
this.velocity.add(accVector.multiplyScalar(delta));
this.velocity.multiplyScalar(0.97); // Drag
if (this.velocity.length() > this.maxSpeed) {
this.velocity.normalize().multiplyScalar(this.maxSpeed);
}
this.group.position.add(this.velocity.clone().multiplyScalar(delta));
const speedRatio = this.velocity.length() / this.maxSpeed;
let offset;
if (this.cockpitView) {
offset = new THREE.Vector3(0, 0, 0.5); // Inside the cockpit
} else {
const offsetDistance = 20 + 80 * speedRatio;
offset = new THREE.Vector3(0, 5, offsetDistance);
}
const targetCamPos = this.group.position.clone().add(offset.applyQuaternion(this.group.quaternion));
this.camera.position.lerp(targetCamPos, 0.1);
this.camera.lookAt(this.group.position);
this.aura.material.uniforms.intensity.value = speedRatio * 2.0;
// Smooth headlamp intensity and keep target forward
if (this.headlamp) {
this.headlamp.intensity += (this.headlampTargetIntensity - this.headlamp.intensity) * Math.min(1.0, delta * 10.0);
// Keep the target in front in local space; world matrices update automatically with group
if (this.headlamp.target) {
this.headlamp.target.position.set(0, 0, -50);
}
if (this.headlamp.intensity <= 0.01 && this.headlampTargetIntensity === 0.0) {
this.headlamp.visible = false;
}
if (this.headlampBeam) {
this.headlampBeam.material.uniforms.intensity.value = this.headlamp.intensity;
this.headlampBeam.visible = this.headlamp.visible;
}
}
}
destroy() {
this.scene.remove(this.group);
this.aura.geometry.dispose();
this.aura.material.dispose();
this.group.traverse(child => {
if (child.isMesh) {
child.geometry.dispose();
child.material.dispose();
}
});
}
}
class ProceduralAudioEngine {
constructor(scene, listener, systemProperties) {
this.scene = scene;
this.listener = listener;
this.systemProperties = systemProperties;
this.audioCtx = listener.context;
this.sources = [];
this.init();
}
init() {
if (this.systemProperties.star) {
this.generateStarHum(this.systemProperties.star, this.systemProperties.starTemp);
}
if (this.systemProperties.planets) {
this.systemProperties.planets.forEach(planet => this.generatePlanetTone(planet));
}
}
generateStarHum(star, temp) {
const hum = new THREE.PositionalAudio(this.listener);
const oscillator = this.audioCtx.createOscillator();
const gain = this.audioCtx.createGain();
const baseFreq = 20 + (temp / 20000) * 40;
oscillator.type = 'sawtooth';
oscillator.frequency.setValueAtTime(baseFreq, this.audioCtx.currentTime);
const lfo = this.audioCtx.createOscillator();
lfo.type = 'sine';
lfo.frequency.setValueAtTime(0.1 + (temp / 20000) * 0.5, this.audioCtx.currentTime);
const lfoGain = this.audioCtx.createGain();
lfoGain.gain.setValueAtTime(baseFreq * 0.1, this.audioCtx.currentTime);
lfo.connect(lfoGain);
lfoGain.connect(oscillator.frequency);
gain.gain.setValueAtTime(0.2, this.audioCtx.currentTime);
oscillator.connect(gain);
hum.setNodeSource(gain);
hum.setRefDistance(200);
hum.setRolloffFactor(1);
star.add(hum);
hum.play();
lfo.start();
oscillator.start();
this.sources.push({oscillator, lfo});
}
generatePlanetTone(planet) {
const tone = new THREE.PositionalAudio(this.listener);
const oscillator = this.audioCtx.createOscillator();
const gain = this.audioCtx.createGain();
const freq = 440 - (planet.geometry.parameters.radius * 10) - (planet.userData.distance / 10);
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(Math.max(50, freq), this.audioCtx.currentTime);
gain.gain.setValueAtTime(0.1, this.audioCtx.currentTime);
oscillator.connect(gain);
tone.setNodeSource(gain);
tone.setRefDistance(50);
tone.setRolloffFactor(1);
planet.add(tone);
tone.play();
oscillator.start();
this.sources.push({oscillator});
}
destroy() {
this.sources.forEach(source => {
source.oscillator.stop();
if(source.lfo) source.lfo.stop();
});
this.sources = [];
}
}
class ProceduralGenerationEngine {
constructor(eventBus, uiManager) {
this.eventBus = eventBus;
this.uiManager = uiManager;
this.container = document.getElementById('canvas-container');
this.clock = new THREE.Clock();
this.raycaster = new THREE.Raycaster();
this.mouse = new THREE.Vector2();
this.prng = sfc32(1,2,3,4);
this.activeStar = null;
this.planets = [];
this.blackHoles = [];
this.specialObjects = [];
this.hiddenEcho = null;
this.isScanning = false;
this.scannerSound = null;
this.cosmicWebView = { active: false, threshold: 25000 };
this.keys = {};
this.autonomousEventTimer = 0;
this.cosmicGrowthEnergy = 0;
this.spaceship = null;
this.isDevMode = false;
this.soundBrush = null;
this.cosmicPulse = 0;
this.isAmbientAudioEnabled = false;
this.proceduralAudio = null;
this.G = 5000;
this.lastInfluence = { hasPlant: false, hasBook: false, createBlackHole: false };
this.visualProfile = { filter: 'none', bloomBoost: 0, vignetteDarkness: 1.0, rgbAmount: 0.0015 };
this.viewProfiles = {
orbit: { bloom: 1.0, vignette: 0.9, godrays: true, film: false },
firstPerson: { bloom: 0.9, vignette: 1.0, godrays: false, film: true },
enhanced: { bloom: 1.2, vignette: 1.05, godrays: true, film: true },
cockpit: { bloom: 1.1, vignette: 1.1, godrays: false, film: true },
cinematic: { bloom: 1.3, vignette: 1.2, godrays: true, film: true }
};
this.avgLuminance = 1.0; // Smoothed luminance proxy for auto-exposure
this.floraPalette = null; // Species palette per-universe
this.starSpotShock = 0.0; // Light-change transient for star spots
this.audioSignal = { bass: 0, mid: 0, treble: 0, hue: 0, energy: 0 };
this.pendingRemovals = [];
this.asteroidBelts = [];
this.genesisLattice = null;
this.nasaBodies = [];
this.earthRef = null;
this.initScene();
this.initCameraControls();
this.initPostProcessing();
this.initEventListeners();
this.atmosphericEntryEffect = new AtmosphericEntryEffect(this.camera, this.eventBus);
// BUG FIX: Defer starting the animation loop until explicitly told.
this.animate = this.animate.bind(this);
this.baseFov = 75;
this.qualitySetting = 'medium';
this.userSettings = { motionBlurEnabled: true, motionBlurAmount: 0.2 };
this.telemetryTimer = 0;
this.quantumLux = 0;
// Expose instance for sensor bridges
window.pge = this;
}
startAnimationLoop() {
this.animate();
}
initScene() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000);
this.camera.position.z = 250;
this.renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
this.renderer.toneMappingExposure = 1.0;
this.renderer.physicallyCorrectLights = true;
this.container.appendChild(this.renderer.domElement);
// Initialize touch controls for mobile
const canvas = this.renderer.domElement;
if (canvas) {
const touchControls = window.initTouchControls(canvas);
console.log('Touch controls initialized for mobile devices');
}
this.listener = new THREE.AudioListener();
this.camera.add(this.listener);
this.localStarfield = this.createStarfield(30000, 20000, 0.7, true);
this.scene.add(this.localStarfield);
this.cosmicWeb = this.createStarfield(10000, 80000, 50, false);
this.scene.add(this.cosmicWeb);
this.cosmicWeb.visible = false;
// Subtle ambient hemispheric light to ensure textures/colors are visible in shadow
const hemi = new THREE.HemisphereLight(0x88aaff, 0x111122, 0.06);
hemi.userData.isGenerated = true;
this.scene.add(hemi);
window.addEventListener('resize', () => this.onWindowResize());
}
initCameraControls() {
this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
this.orbitControls.enableDamping = true;
this.orbitControls.minDistance = 1;
this.orbitControls.maxDistance = Infinity;
// Make orbit controls globally accessible for touch controls
window.orbitControls = this.orbitControls;
this.pointerLockControls = new PointerLockControls(this.camera, this.renderer.domElement);
this.pointerLockControls.addEventListener('lock', () => {
this.eventBus.publish('ui:showFpsHint');
this.uiManager.uiContainer.classList.add('ui-hidden');
});
this.pointerLockControls.addEventListener('unlock', () => {
if (this.uiManager.isUiVisible) {
this.uiManager.uiContainer.classList.remove('ui-hidden');
}
});
document.addEventListener('keydown', (e) => this.keys[e.key.toLowerCase()] = true);
document.addEventListener('keyup', (e) => this.keys[e.key.toLowerCase()] = false);
this.activeControls = this.orbitControls;
// Manual headlamp toggle with 'L'
document.addEventListener('keydown', (e) => {
if ((e.key === 'l' || e.key === 'L') && this.spaceship) {
this.spaceship.setHeadlamp(!this.spaceship.isHeadlampOn);
}
});
}
initPostProcessing() {
this.composer = new EffectComposer(this.renderer);
this.renderPass = new RenderPass(this.scene, this.camera);
this.composer.addPass(this.renderPass);
this.bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
this.composer.addPass(this.bloomPass);
this.afterimagePass = new AfterimagePass();
this.composer.addPass(this.afterimagePass);
// FXAA Anti-aliasing
this.fxaaPass = new ShaderPass(FXAAShader);
this.fxaaPass.material.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
this.composer.addPass(this.fxaaPass);
// Film/grain + scanlines (subtle)
this.filmPass = new FilmPass(0.15, 0.025, 648, false);
this.filmPass.renderToScreen = false;
this.composer.addPass(this.filmPass);
// Chromatic aberration / RGB shift
this.rgbShiftPass = new ShaderPass(RGBShiftShader);
this.rgbShiftPass.uniforms['amount'].value = 0.0015;
this.rgbShiftPass.enabled = false;
this.composer.addPass(this.rgbShiftPass);
// Screen-Space Reflections (SSR) - proximity enabled near reflective monoliths
try {
this.ssrPass = new SSRPass({
renderer: this.renderer,
scene: this.scene,
camera: this.camera,
width: window.innerWidth,
height: window.innerHeight,
selects: null
});
this.ssrPass.enabled = false;
this.composer.addPass(this.ssrPass);
} catch (e) {
console.warn('SSRPass initialization failed, disabling SSR.', e);
this.ssrPass = null;
}
const godrayShader = {
uniforms: {
tDiffuse: { value: null }, lightPosition: { value: new THREE.Vector2(0.5, 0.5) },
exposure: { value: 0.18 }, decay: { value: 0.97 }, density: { value: 0.96 },
weight: { value: 0.4 }, samples: { value: 100 }
},
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse; uniform vec2 lightPosition; uniform float exposure;
uniform float decay; uniform float density; uniform float weight; uniform int samples;
varying vec2 vUv; const int MAX_SAMPLES = 100;
void main() {
vec2 texCoord = vUv; vec2 deltaTexCoord = texCoord - lightPosition;
deltaTexCoord *= 1.0 / float(samples) * density; float illuminationDecay = 1.0;
vec4 color = texture2D(tDiffuse, texCoord);
for(int i=0; i < MAX_SAMPLES; i++) {
if(i >= samples) break;
texCoord -= deltaTexCoord; vec4 sampledColor = texture2D(tDiffuse, texCoord);
sampledColor *= illuminationDecay * weight; color += sampledColor;
illuminationDecay *= decay;
}
gl_FragColor = color * exposure;
}`
};
this.godrayPass = new ShaderPass(godrayShader);
this.composer.addPass(this.godrayPass);
const lensingShader = {
uniforms: { tDiffuse: { value: null }, center: { value: new THREE.Vector2(0.5, 0.5) }, scale: { value: 50.0 }, strength: { value: 0.05 } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse; varying vec2 vUv; uniform vec2 center; uniform float scale; uniform float strength;
void main() {
vec2 toCenter = center - vUv; float dist = length(toCenter);
vec2 uv = vUv - toCenter * (1.0 - dist * scale) * strength / dist;
gl_FragColor = texture2D(tDiffuse, uv);
}`
};
this.lensingPass = new ShaderPass(lensingShader);
this.lensingPass.enabled = false;
this.composer.addPass(this.lensingPass);
const pixelationShader = {
uniforms: { tDiffuse: { value: null }, resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) }, pixelSize: { value: 8.0 } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse; uniform vec2 resolution; uniform float pixelSize; varying vec2 vUv;
void main() {
vec2 newUv = floor(vUv * resolution / pixelSize) * pixelSize / resolution;
gl_FragColor = texture2D(tDiffuse, newUv);
}`
};
this.pixelationPass = new ShaderPass(pixelationShader);
this.pixelationPass.enabled = false;
this.composer.addPass(this.pixelationPass);
const brightnessShader = {
uniforms: { tDiffuse: { value: null }, brightness: { value: 1.0 }, contrast: { value: 1.0 } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse; uniform float brightness; uniform float contrast; varying vec2 vUv;
void main() {
vec4 texel = texture2D(tDiffuse, vUv);
texel.rgb *= brightness;
texel.rgb = (texel.rgb - 0.5) * contrast + 0.5;
gl_FragColor = texel;
}`
};
this.brightnessPass = new ShaderPass(brightnessShader);
this.composer.addPass(this.brightnessPass);
const vignetteShader = {
uniforms: { tDiffuse: { value: null }, offset: { value: 1.0 }, darkness: { value: 1.0 } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse; uniform float offset; uniform float darkness; varying vec2 vUv;
void main() {
vec2 uv = (vUv - 0.5) * vec2(offset);
float vig = 1.0 - dot(uv, uv);
vec4 color = texture2D(tDiffuse, vUv);
gl_FragColor = vec4(color.rgb * pow(vig, darkness), color.a);
}`
};
this.vignettePass = new ShaderPass(vignetteShader);
this.composer.addPass(this.vignettePass);
const toonShader = {
uniforms: {
tDiffuse: { value: null },
resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
outlineColor: { value: new THREE.Color(0x000000) },
levels: { value: 3.0 }
},
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform sampler2D tDiffuse;
uniform vec2 resolution;
uniform vec3 outlineColor;
uniform float levels;
varying vec2 vUv;
float luma(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); }
void main() {
vec2 texel = 1.0 / resolution;
float centerLuma = luma(texture2D(tDiffuse, vUv).rgb);
float up = luma(texture2D(tDiffuse, vUv + vec2(0.0, texel.y)).rgb);
float down = luma(texture2D(tDiffuse, vUv - vec2(0.0, texel.y)).rgb);
float left = luma(texture2D(tDiffuse, vUv - vec2(texel.x, 0.0)).rgb);
float right = luma(texture2D(tDiffuse, vUv + vec2(texel.x, 0.0)).rgb);
float outline = abs(up - centerLuma) + abs(down - centerLuma) + abs(left - centerLuma) + abs(right - centerLuma);
outline = step(0.1, outline);
vec4 color = texture2D(tDiffuse, vUv);
color.rgb = floor(color.rgb * levels) / levels;
gl_FragColor = mix(color, vec4(outlineColor, 1.0), outline);
}`
};
this.toonPass = new ShaderPass(toonShader);
this.toonPass.enabled = false;
this.composer.addPass(this.toonPass);
const colorShader = {
uniforms: { 'tDiffuse': { value: null }, 'colorMatrix': { value: new THREE.Matrix3() } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }`,
fragmentShader: `
uniform sampler2D tDiffuse; uniform mat3 colorMatrix; varying vec2 vUv;
void main() { vec4 c = texture2D(tDiffuse, vUv); gl_FragColor = vec4(colorMatrix * c.rgb, c.a); }`
};
this.filterPass = new ShaderPass(colorShader);
this.composer.addPass(this.filterPass);
// Ensure default is identity so colors render until a filter is selected
if (this.filterPass && this.filterPass.uniforms && this.filterPass.uniforms.colorMatrix) {
this.filterPass.uniforms.colorMatrix.value.identity();
}
}
initEventListeners() {
this.eventBus.subscribe('seed:generated', ({ seed, influence }) => this.generateUniverse(seed, influence));
// Subscribe to environmental influence events for universe dynamics
this.eventBus.subscribe('environmental:influence', (influence) => this.handleEnvironmentalInfluence(influence));
this.eventBus.subscribe('universe:environmentalInfluence', (data) => this.respondToEnvironmentalInfluence(data));
this.eventBus.subscribe('ui:setQuality', quality => this.setQuality(quality));
this.eventBus.subscribe('ui:setFilter', filter => this.setFilter(filter));
this.eventBus.subscribe('ui:setBrightness', value => this.brightnessPass.uniforms.brightness.value = value);
this.eventBus.subscribe('ui:setViewMode', mode => this.setViewMode(mode));
this.eventBus.subscribe('ai:event', (event) => this.triggerLiveReaction(event));
this.eventBus.subscribe('ui:scanForAnomaly', () => this.toggleScanner());
this.eventBus.subscribe('particlizer:created', (obj) => this.addSpecialObject(obj));
this.eventBus.subscribe('devmode:toggled', () => this.toggleDevMode());
this.eventBus.subscribe('ui:toggleAmbientAudio', (isEnabled) => this.toggleAmbientAudio(isEnabled)); // NEW
this.eventBus.subscribe('ai:futureEvent', (evt) => this.handleFutureEvent(evt));
this.eventBus.subscribe('ui:toggleMotionBlur', (enabled) => { if (this.afterimagePass) this.afterimagePass.enabled = !!enabled; });
this.eventBus.subscribe('ui:setMotionBlur', (value) => { if (this.afterimagePass && this.afterimagePass.uniforms && this.afterimagePass.uniforms['damp']) this.afterimagePass.uniforms['damp'].value = 1.0 - Math.max(0, Math.min(1, value)); });
this.eventBus.subscribe('external:donkiFlare', (flares) => {
// Visual reaction: brief godray exposure bump
if (this.godrayPass) this.godrayPass.uniforms.exposure.value = 0.28;
setTimeout(() => { if (this.godrayPass) this.godrayPass.uniforms.exposure.value = 0.18; }, 3000);
this.uiManager.log(`Solar flare reported by NASA DONKI: ${flares.length} events`, 'data');
});
this.eventBus.subscribe('external:neo', (data) => {
// Spawn small NEO markers near system center as transient points
const count = Math.min(50, Object.values(data.near_earth_objects || {}).flat().length || 0);
if (count > 0) {
const positions = new Float32Array(count * 3);
for (let i=0;i<count;i++){ positions[i*3]=(Math.random()-0.5)*3000; positions[i*3+1]=(Math.random()-0.5)*300; positions[i*3+2]=(Math.random()-0.5)*3000; }
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(positions,3));
const mat = new THREE.PointsMaterial({ color: 0xffee88, size: 2, blending: THREE.AdditiveBlending, transparent: true });
const neoPoints = new THREE.Points(geom, mat);
neoPoints.userData = { isGenerated: true, isAutonomous: true, life: 15 };
this.scene.add(neoPoints);
this.uiManager.log(`NEO feed spawned ${count} transient markers.`, 'data');
}
});
this.eventBus.subscribe('external:solsys', (ref) => { this.solarSystemRef = ref; this.uiManager.log('Solar system reference loaded.', 'data'); });
this.eventBus.subscribe('ui:locateEarth', () => this.focusEarth());
this.eventBus.subscribe('audio:data', ({ raw, bands }) => {
const volume = raw.reduce((a, b) => a + b) / raw.length / 255;
this.cosmicPulse = volume;
this.cosmicGrowthEnergy += volume * 0.1;
if (bands) this.audioSignal = { bass: bands.bass, mid: bands.mid, treble: bands.treble, hue: bands.hue, energy: volume };
this.eventBus.publish('telemetry:append', { type: 'audio', tokens: { volume, ...(bands||{}) }, t: Date.now() });
});
this.renderer.domElement.addEventListener('click', (e) => {
if (this.pointerLockControls.isLocked) return;
this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = - (e.clientY / window.innerHeight) * 2 + 1;
this.raycaster.setFromCamera(this.mouse, this.camera);
if (this.cosmicWebView.active) {
const intersects = this.raycaster.intersectObject(this.cosmicWeb);
if (intersects.length > 0) {
const i = intersects[0].index;
const pos = this.cosmicWeb.geometry.attributes.position;
const newCoords = new THREE.Vector3(pos.getX(i), pos.getY(i), pos.getZ(i));
this.eventBus.publish("ui:regenerate", newCoords);
}
} else if(this.hiddenEcho) {
const intersects = this.raycaster.intersectObject(this.hiddenEcho, false);
if (intersects.length > 0) {
this.eventBus.publish('pge:echoFound');
}
}
});
}
// --- Core Generation ---
generateUniverse(seedArray, influence) {
this.cleanupScene();
this.prng = sfc32(...seedArray);
this.lastInfluence = influence || this.lastInfluence;
// Derive flora species palette from seed for consistent variety
const h1 = (seedArray[0] % 360) / 360;
const h2 = (seedArray[1] % 360) / 360;
const h3 = (seedArray[2] % 360) / 360;
this.floraPalette = [h1, h2, h3];
const starTemp = 2000 + this.prng() * 18000;
const starColor = this.blackBodyToRGB(starTemp);
const starSize = 20 + this.prng() * 25;
const light = new THREE.PointLight(starColor, 2, 20000, 2);
light.userData.isGenerated = true;
this.scene.add(light);
this.initLensflare(light, starColor);
const star = new THREE.Mesh( new THREE.SphereGeometry(starSize, 64, 64), new THREE.MeshBasicMaterial({ color: starColor, map: this.createStarTexture() }) );
star.userData = { isGenerated: true, mass: starSize * 1000 };
this.scene.add(star);
this.activeStar = star;
// Add physically-inspired corona shell (visual-only)
this.createStarCorona(this.activeStar, starColor, starTemp, starSize);
// Add photosphere surface with limb darkening and granulation
this.createStarPhotosphere(this.activeStar, starColor, starTemp, starSize);
const planetCount = Math.floor(3 + this.prng() * 7);
for(let i = 0; i < planetCount; i++) {
this.createPlanet(starSize, i, influence);
}
// Initialize asteroid belts immediately
this.createAsteroidBelt(starSize * 4.5 + 80, starSize * 5.5 + 200, Math.floor(2000 + this.prng()*3000));
if (this.prng() > 0.5) this.createAsteroidBelt(starSize * 8.0 + 300, starSize * 9.5 + 600, Math.floor(1500 + this.prng()*2500));
// Optionally add NASA solar system reference planets at a distant scaled ring
if (this.solarSystemRef) {
const scale = 1/4000000; // very rough scale-down for visibility
this.solarSystemRef.planets.forEach((p, idx) => {
const r = p.semiMajorKm * scale;
const baseRadius = Math.max(2, p.radiusKm * scale);
const ang = this.prng() * Math.PI * 2;
if (p.name === 'Earth') {
(async () => {
const earthObj = await this.createNASAEarth(r, baseRadius, ang);
const toAdd = earthObj || (function(){
const fallback = new THREE.Group();
const sphere = new THREE.Mesh(new THREE.SphereGeometry(baseRadius, 32, 32), new THREE.MeshStandardMaterial({ color: 0x3a9cff }));
fallback.add(sphere);
return fallback;
})();
this.scene.add(toAdd);
this.nasaBodies.push(toAdd);
this.earthRef = toAdd;
})();
} else {
const group = this.createNASAPlanet(p.name, r, baseRadius, ang, p.color);
this.scene.add(group);
this.nasaBodies.push(group);
}
});
this.uiManager.log('NASA reference planets manifested in the far field.', 'data');
}
this.createNebula(starColor);
// Map genesis influence to nebula and aurora baselines
if (this.nebula && this.nebula.material && this.nebula.material.uniforms) {
if (this.lastInfluence.hasPlant) {
this.nebula.material.uniforms.density.value = Math.min(1.2, this.nebula.material.uniforms.density.value + 0.15);
}
if (this.lastInfluence.createBlackHole) {
this.nebula.material.uniforms.noiseScale.value = Math.min(6.0, this.nebula.material.uniforms.noiseScale.value + 0.5);
}
}
this.applyGenesisVisualProfile(starColor);
this.hiddenEcho = this.createEchoParticle();
this.scene.add(this.hiddenEcho);
// Build genesis light lattice to connect bodies with light
this.buildGenesisLattice();
if (influence.createBlackHole || this.prng() > 0.9) {
if (influence.createBlackHole) this.uiManager.log("Major seismic event detected! Spawning a black hole.", "warn");
this.createBlackHole();
}
if (this.isAmbientAudioEnabled) {
this.proceduralAudio = new ProceduralAudioEngine(this.scene, this.listener, { star: this.activeStar, starTemp: starTemp, planets: this.planets });
}
this.spawnKnowledgeMonolithsIfNeeded();
this.uiManager.log("Universe generation complete.", 'success');
}
createPlanet(starSize, index, influence) {
const planetSize = 2 + this.prng() * 8;
const distance = starSize * 4 + index * (100 + this.prng()*100);
const angle = this.prng() * Math.PI * 2;
const planet = new THREE.Mesh(
new THREE.SphereGeometry(planetSize, 32, 32),
new THREE.MeshStandardMaterial({ map: this.createPlanetTexture(), roughness: this.prng() })
);
planet.position.set(Math.cos(angle) * distance, 0, Math.sin(angle) * distance);
const orbitSpeed = Math.sqrt((this.G * this.activeStar.userData.mass) / distance);
const initialVelocity = new THREE.Vector3(-Math.sin(angle), 0, Math.cos(angle)).multiplyScalar(orbitSpeed);
planet.userData = {
isGenerated: true,
isPlanet: true,
mass: planetSize * 100,
velocity: initialVelocity,
distance: distance // Keep for audio generation
};
const atmosphere = this.createAtmosphere(planetSize, new THREE.Color().setHSL(this.prng(), 0.8, 0.7));
planet.add(atmosphere);
this.scene.add(planet);
this.planets.push(planet);
// Genesis influence baseline aurora intensity
if (this.lastInfluence && this.lastInfluence.hasPlant && atmosphere.material && atmosphere.material.uniforms && atmosphere.material.uniforms.auroraIntensity) {
atmosphere.material.uniforms.auroraIntensity.value = 0.15;
}
if (influence.hasPlant && this.prng() > 0.5) {
const flora = this.createLSystemFlora();
flora.scale.set(planetSize/10, planetSize/10, planetSize/10);
const surfacePosition = new THREE.Vector3(0, planetSize, 0).applyAxisAngle(new THREE.Vector3(1,0,0), this.prng() * Math.PI);
flora.position.copy(surfacePosition);
flora.lookAt(new THREE.Vector3(0,0,0));
planet.add(flora);
this.uiManager.log("Generated L-System flora on a planet.", 'data');
}
if(this.prng() > 0.6) {
this.createRings(planet, planetSize);
}
}
createBlackHole() {
const size = 15 + this.prng() * 10;
const blackHole = new THREE.Mesh( new THREE.SphereGeometry(size, 64, 64), new THREE.MeshBasicMaterial({ color: 0x000000 }) );
const dist = 1000 + this.prng() * 2000;
const angle = this.prng() * Math.PI * 2;
blackHole.position.set(Math.cos(angle) * dist, this.prng() * 200 - 100, Math.sin(angle) * dist);
blackHole.userData = { isGenerated: true, isBlackHole: true, mass: size * 5000 };
this.scene.add(blackHole);
this.blackHoles.push(blackHole);
const diskGeom = new THREE.RingGeometry(size * 1.2, size * 3, 128);
const diskMat = new THREE.ShaderMaterial({
uniforms: { time: { value: 0 } },
vertexShader: `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform float time; varying vec2 vUv;
float noise(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); }
void main() {
float radius = length(vUv - 0.5);
float n = noise(vUv * 5.0 + time * 0.2);
vec3 color = mix(vec3(1.0, 0.5, 0.1), vec3(0.8, 0.1, 1.0), radius * 2.0);
gl_FragColor = vec4(color * n, 1.0) * (1.0 - radius * 1.8);
}`,
side: THREE.DoubleSide, transparent: true, blending: THREE.AdditiveBlending
});
const disk = new THREE.Mesh(diskGeom, diskMat);
disk.rotation.x = Math.PI / 2;
blackHole.add(disk);
blackHole.userData.disk = disk;
}
cleanupScene() {
if(this.proceduralAudio) {
this.proceduralAudio.destroy();
this.proceduralAudio = null;
}
const toRemove = [];
this.scene.traverse(child => { try { if (child && child.userData && child.userData.isGenerated) toRemove.push(child); } catch(e) { /* ignore */ } });
// Defer actual removal until after traversal
this.pendingRemovals.push(...toRemove);
this.specialObjects.forEach(obj => { if (obj.destroy) obj.destroy(); });
if (this.genesisLattice && this.genesisLattice.parent) this.genesisLattice.parent.remove(this.genesisLattice);
this.genesisLattice = null;
this.asteroidBelts.forEach(b => { if (b.parent) b.parent.remove(b); if (b.geometry) b.geometry.dispose(); if (b.material) b.material.dispose(); });
this.asteroidBelts = [];
this.specialObjects = [];
this.planets = [];
this.blackHoles = [];
this.activeStar = null;
this.hiddenEcho = null;
}
addSpecialObject(obj) {
const dist = 2000 + this.prng() * 5000;
const angle = this.prng() * Math.PI * 2;
obj.mesh.position.set(
Math.cos(angle) * dist,
(this.prng() - 0.5) * 800,
Math.sin(angle) * dist
);
obj.mesh.userData.isSpecialObject = true;
this.specialObjects.push(obj);
this.scene.add(obj.mesh);
this.uiManager.log(`Memory Token manifested at distant coordinates.`, 'data');
}
// --- Visual Components & Effects ---
createAtmosphere(planetSize, color) {
const atmosphereMat = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
planetRadius: { value: planetSize },
cameraPos: { value: new THREE.Vector3() },
lightDir: { value: new THREE.Vector3(0.0, 1.0, 0.0) },
betaRay: { value: new THREE.Vector3(5.5e-6, 13.0e-6, 22.4e-6) },
betaMie: { value: new THREE.Vector3(21e-6, 21e-6, 21e-6) },
mieG: { value: 0.76 },
intensityBoost: { value: 1.0 },
auroraIntensity: { value: 0.0 }
},
vertexShader: `
varying vec3 vWorldPos;
varying vec3 vNormal;
void main() {
vNormal = normalize(normalMatrix * normal);
vec4 world = modelMatrix * vec4(position, 1.0);
vWorldPos = world.xyz;
gl_Position = projectionMatrix * viewMatrix * world;
}
`,
fragmentShader: `
precision highp float;
varying vec3 vWorldPos;
varying vec3 vNormal;
uniform vec3 cameraPos;
uniform vec3 lightDir;
uniform vec3 betaRay;
uniform vec3 betaMie;
uniform float mieG;
uniform float intensityBoost;
uniform float auroraIntensity;
float rayleighPhase(float cosTheta) {
return 3.0/(16.0*3.14159265) * (1.0 + cosTheta*cosTheta);
}
float hgPhase(float cosTheta, float g) {
float g2 = g*g; float denom = pow(1.0 + g2 - 2.0*g*cosTheta, 1.5);
return (1.0 - g2) / (4.0*3.14159265*denom);
}
void main() {
vec3 viewDir = normalize(vWorldPos - cameraPos);
float mu = dot(viewDir, normalize(lightDir));
float pr = rayleighPhase(mu);
float pm = hgPhase(mu, mieG);
vec3 scatter = betaRay * pr + betaMie * pm;
float horizon = clamp(1.0 - abs(vNormal.y), 0.0, 1.0);
vec3 color = scatter * (0.5 + 0.5*horizon) * intensityBoost * 5.0;
// Optional aurora tinting
float aur = smoothstep(0.7, 1.0, horizon) * auroraIntensity;
color = mix(color, vec3(0.3, 0.9, 0.7), aur);
gl_FragColor = vec4(color, 0.9 * (0.7 + 0.3*horizon));
}
`,
blending: THREE.AdditiveBlending,
side: THREE.BackSide,
transparent: true,
depthWrite: false
});
const atmosphere = new THREE.Mesh(new THREE.SphereGeometry(planetSize * 1.15, 32, 32), atmosphereMat);
atmosphere.userData = { isGenerated: true, isAtmosphere: true };
return atmosphere;
}
createStarCorona(star, color, temp, size) {
const tNorm = (temp - 2000) / 18000; // 0..1
const coronaGeo = new THREE.SphereGeometry(size * 1.3, 64, 64);
const coronaMat = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0.0 },
baseColor: { value: color },
intensity: { value: 0.6 + 0.8 * tNorm },
noiseScale: { value: 1.5 + 2.5 * tNorm }
},
vertexShader: `varying vec3 vPos; varying vec3 vNormal; void main(){ vPos = position; vNormal = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }`,
fragmentShader: `varying vec3 vPos; varying vec3 vNormal; uniform vec3 baseColor; uniform float intensity; uniform float noiseScale; uniform float time;
float noise(vec3 p){ return fract(sin(dot(p, vec3(12.9898,78.233,151.7182))) * 43758.5453); }
float fbm(vec3 p){ float f=0.0; f += 0.5000*noise(p); p*=2.02; f += 0.2500*noise(p+time*0.05); p*=2.03; f += 0.1250*noise(p-time*0.04); return f; }
void main(){ float rim = pow(1.0 - abs(dot(vNormal, vec3(0.0,0.0,1.0))), 3.0); float n = fbm(vPos * noiseScale); vec3 c = baseColor * (0.6 + 0.6*n) * intensity; gl_FragColor = vec4(c, rim * (0.4 + 0.6*n)); }`,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false,
side: THREE.BackSide
});
const corona = new THREE.Mesh(coronaGeo, coronaMat);
corona.userData = { isGenerated: true, isStarCorona: true };
star.add(corona);
star.userData.corona = corona;
}
createStarPhotosphere(star, color, temp, size) {
const tNorm = (temp - 2000) / 18000; // 0..1
const photoGeo = new THREE.SphereGeometry(size * 1.02, 64, 64);
const photoMat = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0.0 },
baseColor: { value: color },
limbPower: { value: 0.6 + 0.3 * (1.0 - tNorm) },
granularity: { value: 1.8 + 3.0 * tNorm },
spotStrength: { value: 0.0 }
},
vertexShader: `varying vec3 vNormal; varying vec3 vPos; void main(){ vNormal = normalize(normalMatrix*normal); vPos = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }`,
fragmentShader: `varying vec3 vNormal; varying vec3 vPos; uniform vec3 baseColor; uniform float limbPower; uniform float granularity; uniform float time; uniform float spotStrength;
float noise(vec3 p){ return fract(sin(dot(p, vec3(12.9898,78.233,151.7182))) * 43758.5453); }
float fbm(vec3 p){ float f=0.0; f += 0.5*noise(p); p*=2.1; f += 0.25*noise(p+time*0.05); p*=2.1; f += 0.125*noise(p-time*0.03); return f; }
void main(){ float ndotl = clamp(dot(vNormal, vec3(0.0,0.0,1.0)), 0.0, 1.0); float limb = pow(ndotl, limbPower); float gran = fbm(vPos*granularity); float spots = smoothstep(0.6, 1.0, fbm(vPos*granularity*0.7)); vec3 c = baseColor * (1.0 + gran*0.25); c *= 1.0 - spotStrength * spots * 0.4; gl_FragColor = vec4(c * limb, 1.0); }`,
blending: THREE.AdditiveBlending,
transparent: false,
depthWrite: true,
side: THREE.FrontSide
});
const photo = new THREE.Mesh(photoGeo, photoMat);
photo.userData = { isGenerated: true, isStarPhotosphere: true };
star.add(photo);
star.userData.photosphere = photo;
}
createNebula(baseColor) {
const nebulaMaterial = new THREE.ShaderMaterial({
uniforms: { time: { value: 0 }, baseColor: { value: baseColor }, noiseScale: { value: 2.0 + this.prng() * 3.0 }, density: { value: 0.3 + this.prng() * 0.4 }, pulse: { value: 0.0 } },
vertexShader: `varying vec3 vPosition; void main() { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `
uniform float time; uniform vec3 baseColor; uniform float noiseScale; uniform float density; uniform float pulse;
varying vec3 vPosition;
vec3 hash(vec3 p) { p = vec3(dot(p,vec3(127.1,311.7, 74.7)), dot(p,vec3(269.5,183.3,246.1)), dot(p,vec3(113.5,271.9,124.6))); return -1.0 + 2.0*fract(sin(p)*43758.5453123); }
float noise(in vec3 p) { vec3 i = floor(p), f = fract(p), u = f*f*(3.0-2.0*f); return mix(mix(mix(dot(hash(i+vec3(0,0,0)),f-vec3(0,0,0)), dot(hash(i+vec3(1,0,0)),f-vec3(1,0,0)),u.x), mix(dot(hash(i+vec3(0,1,0)),f-vec3(0,1,0)), dot(hash(i+vec3(1,1,0)),f-vec3(1,1,0)),u.x),u.y), mix(mix(dot(hash(i+vec3(0,0,1)),f-vec3(0,0,1)), dot(hash(i+vec3(1,0,1)),f-vec3(1,0,1)),u.x), mix(dot(hash(i+vec3(0,1,1)),f-vec3(0,1,1)), dot(hash(i+vec3(1,1,1)),f-vec3(1,1,1)),u.x),u.y),u.z); }
float fbm(vec3 p) { float f = 0.0; f += 0.5000*noise(p); p *= 2.02; f += 0.2500*noise(p); p *= 2.03; f += 0.1250*noise(p); return f; }
void main() { vec3 pos = vPosition / (8000.0 / noiseScale); pos.x += time * 0.01; float noiseVal = fbm(pos); gl_FragColor = vec4(baseColor * (noiseVal + pulse) * 2.0, noiseVal * density); }`,
transparent: true, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.BackSide,
});
const nebula = new THREE.Mesh(new THREE.SphereGeometry(8000, 32, 32), nebulaMaterial);
nebula.userData = { isGenerated: true, isNebula: true, baseDensity: nebulaMaterial.uniforms.density.value, baseNoiseScale: nebulaMaterial.uniforms.noiseScale.value };
this.scene.add(nebula);
this.nebula = nebula;
return nebula;
}
createStarfield(count, spread, size, transparent) {
const positions = [];
for (let i = 0; i < count; i++) {
positions.push(THREE.MathUtils.randFloatSpread(spread), THREE.MathUtils.randFloatSpread(spread), THREE.MathUtils.randFloatSpread(spread));
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ color: 0xaaaaaa, size, transparent, opacity: transparent ? 0.5 : 1.0 });
return new THREE.Points(geometry, material);
}
createEchoParticle() {
const geometry = new THREE.TorusKnotGeometry(10, 3, 100, 16);
const material = new THREE.MeshNormalMaterial({ wireframe: true });
const echoMesh = new THREE.Mesh(geometry, material);
const dist = 500 + this.prng() * 1500;
const angle = this.prng() * Math.PI * 2;
echoMesh.position.set(Math.cos(angle) * dist, this.prng() * 400 - 200, Math.sin(angle) * dist);
echoMesh.userData = { isGenerated: true, isEcho: true };
return echoMesh;
}
initLensflare(light, color) {
const textureLoader = new THREE.TextureLoader();
const texFlare0 = textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/lensflare/lensflare0.png');
const texFlare3 = textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/lensflare/lensflare3.png');
const lensflare = new Lensflare();
lensflare.addElement(new LensflareElement(texFlare0, 700, 0, color));
lensflare.addElement(new LensflareElement(texFlare3, 60, 0.6));
lensflare.addElement(new LensflareElement(texFlare3, 70, 0.7));
lensflare.addElement(new LensflareElement(texFlare3, 120, 0.9));
lensflare.addElement(new LensflareElement(texFlare3, 70, 1.0));
lensflare.userData.isGenerated = true;
light.add(lensflare);
}
createLSystemFlora() {
const rules = { 'F': 'FF-[-F+F+F]+[+F-F-F]' };
let axiom = 'F';
const iterations = 3;
for (let i = 0; i < iterations; i++) {
axiom = axiom.split('').map(char => rules[char] || char).join('');
}
const points = [];
const state = { pos: new THREE.Vector3(), dir: new THREE.Vector3(0, 1, 0) };
const stack = [];
const angle = THREE.MathUtils.degToRad(25);
const length = 5;
for (const char of axiom) {
switch (char) {
case 'F':
points.push(state.pos.clone());
state.pos.add(state.dir.clone().multiplyScalar(length));
points.push(state.pos.clone());
break;
case '+':
state.dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), angle);
break;
case '-':
state.dir.applyAxisAngle(new THREE.Vector3(0, 0, 1), -angle);
break;
case '[':
stack.push({ ...state, dir: state.dir.clone() });
break;
case ']':
Object.assign(state, stack.pop());
break;
}
}
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const floraHue = (this.floraPalette ? this.floraPalette[Math.floor(this.prng()*this.floraPalette.length)] : 0.33);
const material = new THREE.LineBasicMaterial({ color: new THREE.Color().setHSL(floraHue, 0.8, 0.6) });
const flora = new THREE.LineSegments(geometry, material);
flora.userData = { isGenerated: true, isFlora: true, growth: 0.0, swayPhase: Math.random() * Math.PI * 2 };
// Add simple fruit nodes as points (start small and color-shift when ripe)
const fruitCount = 8 + Math.floor(this.prng() * 12);
const fruitPositions = new Float32Array(fruitCount * 3);
const fruitColors = new Float32Array(fruitCount * 3);
for (let i = 0; i < fruitCount; i++) {
const base = points[Math.floor(this.prng() * points.length)] || new THREE.Vector3();
fruitPositions[i*3] = base.x + (this.prng()-0.5)*2;
fruitPositions[i*3+1] = base.y + (this.prng()-0.5)*2;
fruitPositions[i*3+2] = base.z + (this.prng()-0.5)*2;
const c = new THREE.Color().setHSL(0.33, 0.8, 0.5); // green start
fruitColors[i*3] = c.r; fruitColors[i*3+1] = c.g; fruitColors[i*3+2] = c.b;
}
const fruitGeom = new THREE.BufferGeometry();
fruitGeom.setAttribute('position', new THREE.BufferAttribute(fruitPositions, 3));
fruitGeom.setAttribute('color', new THREE.BufferAttribute(fruitColors, 3));
const sizeBySpecies = 1.2 + (floraHue * 1.8);
const fruitMat = new THREE.PointsMaterial({ size: sizeBySpecies, vertexColors: true, blending: THREE.AdditiveBlending, depthWrite: false, transparent: true, opacity: 0.9 });
const fruits = new THREE.Points(fruitGeom, fruitMat);
fruits.userData = { isGenerated: true, isFruit: true, ripe: 0.0 };
flora.add(fruits);
flora.userData.fruits = fruits;
return flora;
}
createRings(planet, planetSize) {
const ringColor = new THREE.Color().setHSL(this.prng(), 0.5, 0.6);
const innerRadius = planetSize * 1.5;
const outerRadius = innerRadius + this.prng() * planetSize;
const ringGeom = new THREE.RingGeometry(innerRadius, outerRadius, 64);
const ringMat = new THREE.MeshBasicMaterial({ color: ringColor, side: THREE.DoubleSide, transparent: true, opacity: 0.6 });
const ring = new THREE.Mesh(ringGeom, ringMat);
ring.rotation.x = Math.PI / 2 + (this.prng() - 0.5) * 0.5;
ring.userData = { isRing: true, baseTilt: ring.rotation.x };
planet.add(ring);
}
createAsteroidBelt(innerRadius, outerRadius, count) {
const positions = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const r = THREE.MathUtils.lerp(innerRadius, outerRadius, this.prng());
const ang = this.prng() * Math.PI * 2;
const jitter = (this.prng()-0.5) * 5;
positions[i*3] = Math.cos(ang) * r;
positions[i*3+1] = (this.prng()-0.5) * 10;
positions[i*3+2] = Math.sin(ang) * r + jitter;
const c = new THREE.Color().setHSL(0.1 + this.prng()*0.1, 0.3, 0.5 + this.prng()*0.2);
colors[i*3] = c.r; colors[i*3+1] = c.g; colors[i*3+2] = c.b;
}
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geom.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const mat = new THREE.PointsMaterial({ size: 1.2, vertexColors: true, transparent: true, opacity: 0.85 });
const belt = new THREE.Points(geom, mat);
belt.userData = { isGenerated: true, isAsteroidBelt: true, innerRadius, outerRadius, baseOpacity: mat.opacity };
this.scene.add(belt);
this.asteroidBelts.push(belt);
return belt;
}
buildGenesisLattice() {
const nodes = [];
if (this.activeStar) nodes.push(this.activeStar.position.clone());
this.planets.forEach(p => nodes.push(p.position.clone()));
this.blackHoles.forEach(b => nodes.push(b.position.clone()));
this.scene.traverse(o => { if (o.userData && o.userData.isMonolith) nodes.push(o.position.clone()); });
if (nodes.length < 2) return;
const segments = [];
for (let i = 0; i < nodes.length; i++) {
for (let j = i+1; j < nodes.length; j++) {
const a = nodes[i], b = nodes[j];
const d = a.distanceTo(b);
if (d < 8000) { // connect reasonably close bodies
segments.push(a.x, a.y, a.z, b.x, b.y, b.z);
}
}
}
if (segments.length === 0) return;
const pos = new Float32Array(segments);
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(pos, 3));
const mat = new THREE.LineBasicMaterial({ color: 0x88ccff, transparent: true, opacity: 0.15, blending: THREE.AdditiveBlending });
const lattice = new THREE.LineSegments(geom, mat);
lattice.userData = { isGenerated: true, isGenesisLattice: true };
if (this.genesisLattice && this.genesisLattice.parent) this.genesisLattice.parent.remove(this.genesisLattice);
this.genesisLattice = lattice;
this.scene.add(lattice);
}
createStarTexture() {
const size = 256;
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const context = canvas.getContext('2d');
const gradient = context.createRadialGradient(size/2, size/2, 0, size/2, size/2, size/2);
gradient.addColorStop(0, 'rgba(255,255,255,1)');
gradient.addColorStop(0.2, 'rgba(255,255,200,1)');
gradient.addColorStop(0.4, 'rgba(255,200,0,1)');
gradient.addColorStop(1, 'rgba(255,150,0,0)');
context.fillStyle = gradient;
context.fillRect(0,0,size,size);
return new THREE.CanvasTexture(canvas);
}
loadTexture(url) {
return new Promise((resolve, reject) => {
const loader = new THREE.TextureLoader();
loader.setCrossOrigin('anonymous');
loader.load(url, tex => { tex.colorSpace = THREE.SRGBColorSpace || THREE.sRGBEncoding; resolve(tex); }, undefined, err => resolve(null));
});
}
addEarthMarker(earthNode) {
// Determine display radius whether node is a Mesh or a Group containing a sphere
let radius = 2;
let sphere = null;
if (earthNode && earthNode.geometry && earthNode.geometry.parameters && earthNode.geometry.parameters.radius) {
radius = earthNode.geometry.parameters.radius;
sphere = earthNode;
} else if (earthNode && earthNode.traverse) {
earthNode.traverse(child => {
if (!sphere && child.isMesh && child.geometry && child.geometry.parameters && child.geometry.parameters.radius) {
sphere = child;
radius = child.geometry.parameters.radius;
}
});
}
// Add a subtle halo and a floating label that faces the camera
const haloGeo = new THREE.SphereGeometry(radius * 1.8, 16, 16);
const haloMat = new THREE.MeshBasicMaterial({ color: 0x4da6ff, transparent: true, opacity: 0.2, blending: THREE.AdditiveBlending });
const halo = new THREE.Mesh(haloGeo, haloMat);
halo.userData = { isGenerated: true };
earthNode.add(halo);
// Label as a small plane with emissive blue
const labelCanvas = document.createElement('canvas');
labelCanvas.width = 256; labelCanvas.height = 64;
const ctx = labelCanvas.getContext('2d');
ctx.fillStyle = 'rgba(0,0,0,0)'; ctx.fillRect(0,0,256,64);
ctx.font = '28px Inter, sans-serif';
ctx.fillStyle = '#9cc9ff';
ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
ctx.fillText('EARTH', 128, 32);
const tex = new THREE.CanvasTexture(labelCanvas);
const plane = new THREE.Mesh(new THREE.PlaneGeometry(60, 15), new THREE.MeshBasicMaterial({ map: tex, transparent: true }));
plane.position.set(0, radius * 3, 0);
plane.userData = { isGenerated: true, isBillboard: true };
earthNode.add(plane);
}
createPlanetTexture() {
const size = 512;
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
const context = canvas.getContext('2d');
context.fillStyle = new THREE.Color().setHSL(this.prng(), 0.5, 0.3).getStyle();
context.fillRect(0,0,size,size);
for(let i=0; i<5000; i++) {
context.fillStyle = new THREE.Color().setHSL(this.prng(), 0.5, this.prng() * 0.4 + 0.2).getStyle();
context.beginPath();
context.arc(this.prng()*size, this.prng()*size, this.prng()*size*0.1, 0, Math.PI*2);
context.fill();
}
return new THREE.CanvasTexture(canvas);
}
async createNASAEarth(orbitRadius, earthRadius, angle) {
// Blue marble base sphere
const earthGroup = new THREE.Group();
// High-quality textures (Blue Marble/Night/Clouds) from public sources
// CDN mirrors for Blue Marble-like assets
// Alternate CDN mirrors
const dayUrl = 'https://unpkg.com/three-globe/example/img/earth-blue-marble.jpg';
const nightUrl = 'https://unpkg.com/three-globe/example/img/earth-night.jpg';
const bumpUrl = 'https://unpkg.com/three-globe/example/img/earth-topology.png';
const specUrl = 'https://unpkg.com/three-globe/example/img/earth-water.png';
const cloudUrl = 'https://unpkg.com/three-globe/example/img/earth-clouds.png';
const [dayTex, nightTex, bumpTex, specTex, cloudsTex] = await Promise.all([
this.loadTexture(dayUrl), this.loadTexture(nightUrl), this.loadTexture(bumpUrl), this.loadTexture(specUrl), this.loadTexture(cloudUrl)
]);
let sphere;
if (dayTex && nightTex) {
const earthShader = {
uniforms: {
dayMap: { value: dayTex },
nightMap: { value: nightTex },
specMap: { value: specTex || null },
cameraPos: { value: new THREE.Vector3() },
lightDir: { value: new THREE.Vector3(1,0,0) },
time: { value: 0 },
glowThreshold: { value: 0.1 },
glowIntensity: { value: 0.6 }
},
vertexShader: `
varying vec3 vWorldPos; varying vec3 vWorldNormal; varying vec2 vUv;
void main(){
vUv = uv;
vec4 world = modelMatrix * vec4(position,1.0);
vWorldPos = world.xyz;
vWorldNormal = normalize(mat3(modelMatrix) * normal);
gl_Position = projectionMatrix * viewMatrix * world;
}
`,
fragmentShader: `
uniform sampler2D dayMap; uniform sampler2D nightMap; uniform sampler2D specMap;
uniform vec3 cameraPos; uniform vec3 lightDir; uniform float time; uniform float glowThreshold; uniform float glowIntensity;
varying vec3 vWorldPos; varying vec3 vWorldNormal; varying vec2 vUv;
void main(){
vec3 N = normalize(vWorldNormal);
vec3 L = normalize(lightDir);
vec3 V = normalize(cameraPos - vWorldPos);
float ndotl = max(dot(N,L), 0.0);
float mixF = smoothstep(0.02, 0.2, ndotl);
vec3 day = texture2D(dayMap, vUv).rgb;
vec3 night = texture2D(nightMap, vUv).rgb;
vec3 base = mix(night, day, mixF);
float spec = 0.0;
if (ndotl > 0.0) {
vec3 R = reflect(-L, N);
float s = pow(max(dot(V, R), 0.0), 64.0);
float sm = specMap == sampler2D(0) ? 1.0 : texture2D(specMap, vUv).r;
spec = s * sm * 0.7;
}
// Night city glow bloom prepass: boost bright pixels on night side
float nightMix = 1.0 - mixF;
float nightLuma = dot(night, vec3(0.299,0.587,0.114));
float glow = smoothstep(glowThreshold, 1.0, nightLuma) * nightMix * glowIntensity;
vec3 color = base + vec3(spec) + vec3(glow);
gl_FragColor = vec4(color, 1.0);
}
`
};
const mat = new THREE.ShaderMaterial(earthShader);
sphere = new THREE.Mesh(new THREE.SphereGeometry(earthRadius, 64, 64), mat);
sphere.userData.isEarthShader = true;
} else {
const earthMat = new THREE.MeshStandardMaterial({ map: dayTex || null, roughness: 0.9, metalness: 0.0, bumpMap: bumpTex || null, bumpScale: 0.5, envMapIntensity: 0.5 });
if (specTex) earthMat.metalnessMap = specTex;
sphere = new THREE.Mesh(new THREE.SphereGeometry(earthRadius, 64, 64), earthMat);
}
sphere.userData = { isGenerated: true, isNASABody: true, mass: earthRadius * 100, name: 'Earth', orbitRadius, orbitAngle: angle };
sphere.position.set(Math.cos(angle)*orbitRadius, (this.prng()-0.5)*200, Math.sin(angle)*orbitRadius);
earthGroup.add(sphere);
// Transparent atmosphere shell with slight blue tint
const atmosphere = new THREE.Mesh(new THREE.SphereGeometry(earthRadius * 1.02, 32, 32), new THREE.MeshBasicMaterial({ color: 0x4da6ff, transparent: true, opacity: 0.15 }));
atmosphere.userData = { isGenerated: true };
earthGroup.add(atmosphere);
// Simple cloud layer with slow rotation for depth
const clouds = new THREE.Mesh(new THREE.SphereGeometry(earthRadius * 1.015, 64, 64), new THREE.MeshStandardMaterial({ map: cloudsTex || null, transparent: true, opacity: 0.45 }));
clouds.userData = { isGenerated: true, isCloudLayer: true };
earthGroup.add(clouds);
// Add marker/label
this.addEarthMarker(earthGroup);
return earthGroup;
}
addPlanetLabel(node, text, color = '#9cc9ff') {
const labelCanvas = document.createElement('canvas');
labelCanvas.width = 256; labelCanvas.height = 64;
const ctx = labelCanvas.getContext('2d');
ctx.fillStyle = 'rgba(0,0,0,0)'; ctx.fillRect(0,0,256,64);
ctx.font = '26px Inter, sans-serif';
ctx.fillStyle = color;
ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
ctx.fillText(text.toUpperCase(), 128, 32);
const tex = new THREE.CanvasTexture(labelCanvas);
const plane = new THREE.Mesh(new THREE.PlaneGeometry(60, 15), new THREE.MeshBasicMaterial({ map: tex, transparent: true }));
plane.position.set(0, 40, 0);
plane.userData = { isGenerated: true, isBillboard: true };
node.add(plane);
}
createNASAPlanet(name, orbitRadius, baseRadius, angle, colorHex) {
const group = new THREE.Group();
let sphereMat = new THREE.MeshStandardMaterial({ color: colorHex, roughness: 1.0, metalness: 0.0 });
let sphereGeom = new THREE.SphereGeometry(baseRadius, 32, 32);
// Procedural textures by planet
if (name === 'Jupiter') {
const size = 1024; const canvas = document.createElement('canvas'); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d');
// Stripes
for (let y = 0; y < size; y++) {
const t = y / size;
const hue = 30 + Math.sin(t * 20) * 8;
const light = 0.7 + Math.sin(t * 40) * 0.1;
ctx.fillStyle = `hsl(${hue}, 50%, ${light*100}%)`;
ctx.fillRect(0, y, size, 1);
}
// Great Red Spot
ctx.fillStyle = 'rgba(200,80,50,0.8)';
ctx.beginPath(); ctx.ellipse(size*0.7, size*0.55, 90, 60, 0, 0, Math.PI*2); ctx.fill();
const tex = new THREE.CanvasTexture(canvas);
sphereMat = new THREE.MeshStandardMaterial({ map: tex, roughness: 1.0 });
} else if (name === 'Mars') {
const size = 1024; const canvas = document.createElement('canvas'); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d');
ctx.fillStyle = '#b55239'; ctx.fillRect(0,0,size,size);
ctx.fillStyle = '#8d3f2a';
for (let i=0;i<8000;i++){ ctx.globalAlpha = 0.8; const r= Math.random()*3+1; ctx.beginPath(); ctx.arc(Math.random()*size, Math.random()*size, r, 0, Math.PI*2); ctx.fill(); }
// Polar caps
ctx.globalAlpha = 0.9; ctx.fillStyle = '#ffffff';
ctx.beginPath(); ctx.arc(size*0.5, size*0.05, 40, 0, Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.arc(size*0.5, size*0.95, 60, 0, Math.PI*2); ctx.fill();
const tex = new THREE.CanvasTexture(canvas);
sphereMat = new THREE.MeshStandardMaterial({ map: tex, roughness: 1.0 });
} else if (name === 'Venus') {
const size = 1024; const canvas = document.createElement('canvas'); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d');
ctx.fillStyle = '#d8c08a'; ctx.fillRect(0,0,size,size);
ctx.globalAlpha = 0.3; ctx.fillStyle = '#fff6cc';
for (let i=0;i<6000;i++){ const r= Math.random()*4+2; ctx.beginPath(); ctx.arc(Math.random()*size, Math.random()*size, r, 0, Math.PI*2); ctx.fill(); }
const tex = new THREE.CanvasTexture(canvas);
sphereMat = new THREE.MeshStandardMaterial({ map: tex, roughness: 0.9 });
}
const sphere = new THREE.Mesh(sphereGeom, sphereMat);
sphere.userData = { isGenerated: true, isNASABody: true, mass: baseRadius * 100, name, orbitRadius, orbitAngle: angle };
group.add(sphere);
// Rings for Saturn
if (name === 'Saturn') {
const inner = baseRadius * 1.8; const outer = baseRadius * 3.2;
const ring = new THREE.Mesh(new THREE.RingGeometry(inner, outer, 128), new THREE.MeshBasicMaterial({ color: 0xd7c7a1, side: THREE.DoubleSide, transparent: true, opacity: 0.7 }));
ring.rotation.x = Math.PI/2; ring.userData = { isRing: true, baseTilt: ring.rotation.x, isSaturnRing: true };
group.add(ring);
}
// Thicker atmosphere for Venus
if (name === 'Venus') {
const atm = new THREE.Mesh(new THREE.SphereGeometry(baseRadius * 1.05, 32, 32), new THREE.MeshBasicMaterial({ color: 0xffe38a, transparent: true, opacity: 0.25 }));
group.add(atm);
}
// Neptune/Uranus deep blues/teals handled by base color
// Position and label
group.position.set(Math.cos(angle)*orbitRadius, (this.prng()-0.5)*200, Math.sin(angle)*orbitRadius);
this.addPlanetLabel(group, name, '#9cc9ff');
return group;
}
// --- Animate & Update ---
animate() {
requestAnimationFrame(this.animate);
const delta = this.clock.getDelta();
const elapsedTime = this.clock.getElapsedTime();
if (this.spaceship) {
this.spaceship.update(delta, this.pointerLockControls);
} else if (this.pointerLockControls.isLocked) {
this.updatePlayerMovement(delta);
}
if (this.activeControls && this.activeControls.isOrbitControls) this.activeControls.update();
this.updateInterSystemPhysics(delta);
this.planets.forEach(planet => {
// BUG FIX: Removed old kinematic orbit logic. Physics now controls position.
planet.rotation.y += delta * 0.1;
planet.traverse(child => {
if (child.userData.isAtmosphere) {
child.material.uniforms.time.value = elapsedTime;
// Update scattering uniforms
if (child.material.uniforms.cameraPos) child.material.uniforms.cameraPos.value.copy(this.camera.position);
if (this.activeStar && child.material.uniforms.lightDir) {
const dir = this.activeStar.position.clone().sub(planet.position).normalize();
child.material.uniforms.lightDir.value.copy(dir);
if (child.material.uniforms.intensityBoost) {
const hsl = this.activeStar.material.color.getHSL({});
const boost = 0.8 + Math.min(1.5, hsl.s * 1.2 + hsl.l);
child.material.uniforms.intensityBoost.value = boost;
}
}
}
});
});
this.scene.traverse(obj => {
if (obj && obj.userData && obj.userData.isEcho) obj.rotation.y += delta * 0.5;
if (obj && obj.userData && obj.userData.isBlackHole && obj.userData.disk && obj.userData.disk.material && obj.userData.disk.material.uniforms) obj.userData.disk.material.uniforms.time.value = elapsedTime;
if (obj && obj.userData && obj.userData.isNebula && obj.material && obj.material.uniforms && obj.material.uniforms.pulse) obj.material.uniforms.pulse.value = this.cosmicPulse;
if (obj && obj.userData && obj.userData.isStarCorona && obj.material && obj.material.uniforms && obj.material.uniforms.time) obj.material.uniforms.time.value = elapsedTime;
if (obj && obj.userData && obj.userData.isStarPhotosphere && obj.material && obj.material.uniforms && obj.material.uniforms.time) obj.material.uniforms.time.value = elapsedTime;
if (obj && obj.userData && obj.userData.isArtwork) this.updateArtwork(obj, delta);
if (obj && obj.userData && obj.userData.isFlora) this.updateFlora(obj, delta);
if (obj && obj.userData && obj.userData.isAutonomous) this.updateAutonomousObject(obj, delta);
if (obj && obj.userData && obj.userData.isBillboard) {
// Face the camera (billboarding for labels)
obj.lookAt(this.camera.position);
}
if (obj && obj.userData && obj.userData.isRing && this.audioSignal) {
const wobble = (this.audioSignal.bass * 0.1) * Math.sin(this.clock.elapsedTime * 0.8);
obj.rotation.x = obj.userData.baseTilt + wobble;
}
if (obj && obj.userData && obj.userData.isComet && obj.userData.tail) this.updateCometTail(obj, delta);
if (obj && obj.userData && obj.userData.isMonolith) this.updateMonolithGlint(obj, delta);
if (obj && obj.userData && obj.userData.isGenesisLattice) this.updateGenesisLattice(obj, delta);
});
// Safely process deferred removals after traversal to avoid mutating scene graph mid-iteration
if (this.pendingRemovals && this.pendingRemovals.length) {
const removals = this.pendingRemovals.splice(0, this.pendingRemovals.length);
removals.forEach(dead => {
try {
if (!dead) return;
if (dead.parent) dead.parent.remove(dead);
if (dead.geometry) dead.geometry.dispose();
if (dead.material) {
if (Array.isArray(dead.material)) dead.material.forEach(m => m && m.dispose && m.dispose());
else if (dead.material.dispose) dead.material.dispose();
}
} catch (e) { /* noop */ }
});
}
this.specialObjects.forEach(obj => { if (obj.update) obj.update(delta); });
if (this.godrayPass.enabled && this.activeStar && !this.cosmicWebView.active) {
let screenPos = this.activeStar.position.clone().project(this.camera);
this.godrayPass.uniforms.lightPosition.value.set((screenPos.x + 1) / 2, (screenPos.y + 1) / 2);
}
this.updateCosmicGrowth(delta);
this.atmosphericEntryEffect.update(delta, this.camera, this.planets);
this.handleCosmicWebView();
this.updateScanner();
this.updateLensing();
this.updateCinematicDOF();
// Rotate cloud layers slightly for living planet depth
if (this.earthRef && this.earthRef.children) {
const cloud = this.earthRef.children.find(c => c.userData && c.userData.isCloudLayer);
if (cloud) cloud.rotation.y += delta * 0.02;
}
// Update Earth shader uniforms if present
if (this.earthRef) {
const earthSphere = this.earthRef.children.find(c => c.userData && c.userData.isEarthShader);
if (earthSphere && earthSphere.material && earthSphere.material.uniforms) {
earthSphere.material.uniforms.cameraPos.value.copy(this.camera.position);
const lightDir = this.activeStar ? this.activeStar.position.clone().sub(earthSphere.getWorldPosition(new THREE.Vector3())).normalize() : new THREE.Vector3(1,0,0);
earthSphere.material.uniforms.lightDir.value.copy(lightDir);
earthSphere.material.uniforms.time.value = this.clock.getElapsedTime();
}
}
// Periodic telemetry of live frame tokens (frequency->light, genesis signal, angular size)
this.telemetryTimer += delta;
if (this.telemetryTimer > 0.5) {
this.telemetryTimer = 0;
const genesis = this.computeGenesisSignal();
// Estimate nearest body's angular size
let nearestAng = 0; let nearestName = 'none';
const candidates = [];
if (this.activeStar) candidates.push({ name: 'star', obj: this.activeStar });
this.planets.forEach((p,i)=>candidates.push({ name: `planet-${i}`, obj: p }));
this.nasaBodies.forEach((b,i)=>candidates.push({ name: b.userData && b.userData.name || `nasa-${i}`, obj: b }));
for (const c of candidates) {
const obj = c.obj;
const pos = obj.position.clone();
const dist = this.camera.position.distanceTo(pos);
let r = 0;
if (!obj.geometry && obj.children && obj.children.length) {
const s = obj.children.find(ch => ch.isMesh && ch.geometry && ch.geometry.parameters && ch.geometry.parameters.radius);
if (s) r = s.geometry.parameters.radius;
} else if (obj.geometry && obj.geometry.parameters && obj.geometry.parameters.radius) r = obj.geometry.parameters.radius;
if (r > 0) {
const ang = 2 * Math.atan2(r, Math.max(1, dist));
if (ang > nearestAng) { nearestAng = ang; nearestName = c.name; }
}
}
const bloom = this.bloomPass ? this.bloomPass.strength : 0;
const god = this.godrayPass ? this.godrayPass.uniforms.exposure.value : 0;
const nebulaD = (this.nebula && this.nebula.material && this.nebula.material.uniforms) ? this.nebula.material.uniforms.density.value : 0;
this.eventBus.publish('telemetry:append', { type: 'frame', tokens: { genesis, nearestName, nearestAngularDeg: THREE.MathUtils.radToDeg(nearestAng), exposure: this.renderer.toneMappingExposure, bloom, godrays: god, nebulaDensity: nebulaD }, t: Date.now() });
}
this.updateCinematicDepthCue();
this.updateVisualsFromSimulation(delta);
this.updateSSRProximity();
this.eventBus.publish('pge:animate', delta);
this.composer.render(delta);
}
updateGenesisLattice(lattice, delta) {
// Subtle pulsing based on combined genesis signal
const signal = this.computeGenesisSignal();
lattice.material.opacity = 0.08 + 0.12 * signal;
}
computeGenesisSignal() {
// Unified signal derived from star luminance, audio energy, motion energy, and black hole presence
const numPlanets = this.planets.length;
const starLum = this.activeStar ? Math.max(0.5, Math.min(2.0, this.activeStar.material.color.getHSL({}).l * 2.0 + (this.activeStar.material.color.getHSL({}).s))) : 1.0;
const motionEnergy = this.planets.reduce((sum, p) => sum + (p.userData.velocity ? p.userData.velocity.length() : 0), 0) / Math.max(1, numPlanets);
const blackHolePresence = this.blackHoles.length > 0 ? 1.0 : 0.0;
const audioE = this.audioSignal ? this.audioSignal.energy : 0.0;
const signal = Math.max(0.0, Math.min(1.0, 0.25 * (starLum - 0.5) + 0.25 * Math.min(1.0, motionEnergy * 0.002) + 0.3 * audioE + 0.2 * blackHolePresence));
return signal;
}
updateCinematicDepthCue() {
// Adjust FOV slightly based on angular size of the nearest large body to enhance "enclosing" feel
let nearest = null; let nearestAngular = 0;
const candidates = [];
if (this.activeStar) candidates.push(this.activeStar);
this.planets.forEach(p => candidates.push(p));
this.nasaBodies.forEach(b => candidates.push(b));
for (const obj of candidates) {
const worldPos = obj.position.clone();
const dist = this.camera.position.distanceTo(worldPos);
if (!obj.geometry && obj.children && obj.children.length) {
const sphere = obj.children.find(c => c.isMesh && c.geometry && c.geometry.parameters && c.geometry.parameters.radius);
if (!sphere) continue;
const radius = sphere.geometry.parameters.radius;
const angular = 2 * Math.atan2(radius, Math.max(1, dist));
if (angular > nearestAngular) { nearestAngular = angular; nearest = obj; }
} else if (obj.geometry && obj.geometry.parameters && obj.geometry.parameters.radius) {
const radius = obj.geometry.parameters.radius;
const angular = 2 * Math.atan2(radius, Math.max(1, dist));
if (angular > nearestAngular) { nearestAngular = angular; nearest = obj; }
}
}
// Map angular size to FOV bias (narrow slightly as object fills view; widen otherwise)
let targetFov = THREE.MathUtils.clamp(this.baseFov - THREE.MathUtils.radToDeg(nearestAngular) * 0.15, 45, this.baseFov);
// In enhanced FP with quantum scale, bias FOV narrower to heighten depth
if (this.spaceship && this.activeControls === this.pointerLockControls && !this.spaceship.cockpitView) {
targetFov -= 5;
}
this.camera.fov += (targetFov - this.camera.fov) * 0.05;
this.camera.updateProjectionMatrix();
}
updateVisualsFromSimulation(delta) {
// Derive non-invasive visual parameters from current simulation state
const numPlanets = this.planets.length;
const starLum = this.activeStar ? Math.max(0.5, Math.min(2.0, this.activeStar.material.color.getHSL({}).l * 2.0 + (this.activeStar.material.color.getHSL({}).s))) : 1.0;
const motionEnergy = this.planets.reduce((sum, p) => sum + (p.userData.velocity ? p.userData.velocity.length() : 0), 0) / Math.max(1, numPlanets);
const blackHolePresence = this.blackHoles.length > 0 ? 1.0 : 0.0;
const quantumLight = this.quantumLux ? (this.quantumLux / 1200) : 0; // 0..1
const genesisSignal = this.computeGenesisSignal();
// Approximate average luminance from scene signals and smooth it
const luminanceSignal = 0.8 * starLum + 0.2 * (this.localStarfield ? this.localStarfield.material.opacity : 1.0);
const targetLuma = Math.max(0.2, Math.min(2.0, luminanceSignal + blackHolePresence * 0.05));
this.avgLuminance += (targetLuma - this.avgLuminance) * Math.min(1.0, delta * 2.0);
// Exposure gently reacts to smoothed luminance and motion
const targetExposure = 1.0 + (this.avgLuminance - 1.0) * 0.25 + Math.min(0.2, motionEnergy * 0.002) + genesisSignal * 0.05 + quantumLight * 0.05;
this.renderer.toneMappingExposure += (targetExposure - this.renderer.toneMappingExposure) * 0.05;
// Bloom strength tracks brightness and black hole presence (per-star glare), mid frequencies add vibrance, quantum light enhances presence
if (this.bloomPass && this.bloomPass.enabled) {
const vibrance = this.audioSignal ? this.audioSignal.mid * 0.4 : 0;
const baseStrength = 1.0 + (starLum - 1.0) * 1.2 + vibrance + genesisSignal * 0.2 + quantumLight * 0.25;
const holeBoost = 0.3 * blackHolePresence;
this.bloomPass.strength += ((baseStrength + holeBoost) - this.bloomPass.strength) * 0.05;
this.bloomPass.radius += ((0.35 + 0.25 * blackHolePresence + quantumLight * 0.1) - this.bloomPass.radius) * 0.05;
}
// Film grain intensity scales with motion energy and bass
if (this.filmPass && this.filmPass.enabled) {
const bass = this.audioSignal ? this.audioSignal.bass : 0;
const targetNoise = Math.min(0.45, 0.12 + motionEnergy * 0.003 + bass * 0.2 + genesisSignal * 0.1);
this.filmPass.uniforms['nIntensity'].value += (targetNoise - this.filmPass.uniforms['nIntensity'].value) * 0.05;
const targetScan = 0.02 + Math.min(0.03, motionEnergy * 0.0005);
this.filmPass.uniforms['sIntensity'].value += (targetScan - this.filmPass.uniforms['sIntensity'].value) * 0.05;
}
// Chromatic aberration increases subtly near a black hole
if (this.rgbShiftPass) {
const distFactor = this.blackHoles[0] ? Math.max(0, 1 - this.camera.position.distanceTo(this.blackHoles[0].position) / 4000) : 0;
const current = this.rgbShiftPass.uniforms['amount'].value;
const treble = this.audioSignal ? this.audioSignal.treble : 0;
const targetAmount = 0.001 + 0.004 * distFactor + treble * 0.002 + genesisSignal * 0.001;
this.rgbShiftPass.uniforms['amount'].value = current + (targetAmount - current) * 0.05;
}
// Godrays exposure reacts to genesis signal and quantum light
if (this.godrayPass && this.godrayPass.enabled && this.godrayPass.uniforms && this.godrayPass.uniforms.exposure) {
const currentExp = this.godrayPass.uniforms.exposure.value;
const targetExp = 0.18 + genesisSignal * 0.06 + quantumLight * 0.12;
this.godrayPass.uniforms.exposure.value = currentExp + (targetExp - currentExp) * 0.05;
}
// Decay any starspot shock back to baseline; bass energy adds slight spot depth
if (this.activeStar && this.activeStar.userData.photosphere && this.activeStar.userData.photosphere.material.uniforms.spotStrength) {
const u = this.activeStar.userData.photosphere.material.uniforms.spotStrength;
const bass = this.audioSignal ? this.audioSignal.bass : 0;
const target = 0.05 * bass;
u.value += (target - u.value) * Math.min(1.0, delta * 0.2);
}
// Drive nebula dynamics from audio energy: density pulsing and swirl speed
if (this.nebula && this.nebula.material && this.nebula.material.uniforms) {
const energy = this.audioSignal ? this.audioSignal.energy : 0;
const base = this.nebula.userData.baseDensity || this.nebula.material.uniforms.density.value;
const targetDensity = Math.min(1.4, base + energy * 0.2 + genesisSignal * 0.1 + quantumLight * 0.1);
this.nebula.material.uniforms.density.value += (targetDensity - this.nebula.material.uniforms.density.value) * 0.05;
// Swirl speed via time scaling is implicit; extra pulse already affects color amplitude
this.nebula.material.uniforms.pulse.value = energy;
// Adjust turbulence scale with mid band for finer detail when energetic
const baseScale = this.nebula.userData.baseNoiseScale || this.nebula.material.uniforms.noiseScale.value;
const mid = this.audioSignal ? this.audioSignal.mid : 0;
const targetScale = baseScale + mid * 0.8 + genesisSignal * 0.3 + quantumLight * 0.2;
this.nebula.material.uniforms.noiseScale.value += (targetScale - this.nebula.material.uniforms.noiseScale.value) * 0.05;
}
// Atmosphere aurora intensifies with treble bursts
if ((this.audioSignal && this.audioSignal.treble > 0.2) || this.quantumLux > 200) {
this.planets.forEach(planet => {
planet.traverse(child => {
if (child.userData && child.userData.isAtmosphere && child.material && child.material.uniforms && child.material.uniforms.auroraIntensity) {
const u = child.material.uniforms.auroraIntensity;
const qBoost = Math.min(0.5, (this.quantumLux/1200) * 0.3);
const aBoost = this.audioSignal ? this.audioSignal.treble * 0.05 : 0;
u.value = Math.min(1.0, u.value + aBoost + qBoost);
}
});
});
}
}
updateInterSystemPhysics(delta) {
const allGravitationalObjects = [this.activeStar, ...this.planets, ...this.blackHoles];
for (let i = 0; i < this.planets.length; i++) {
const planet = this.planets[i];
let totalForce = new THREE.Vector3();
allGravitationalObjects.forEach(obj => {
if (planet !== obj && obj) {
const distVec = obj.position.clone().sub(planet.position);
const distSq = distVec.lengthSq();
if (distSq > 1) { // Avoid division by zero
const forceMag = (this.G * obj.userData.mass * planet.userData.mass) / distSq;
const force = distVec.normalize().multiplyScalar(forceMag);
totalForce.add(force);
}
}
});
const acceleration = totalForce.divideScalar(planet.userData.mass);
planet.userData.velocity.add(acceleration.multiplyScalar(delta));
}
this.planets.forEach(planet => {
planet.position.add(planet.userData.velocity.clone().multiplyScalar(delta));
});
// Galaxy-scale living growth signals
if (this.nebula && this.nebula.material && this.nebula.material.uniforms) {
const g = this.computeGenesisSignal();
const energy = this.audioSignal ? this.audioSignal.energy : 0;
const base = this.nebula.userData ? (this.nebula.userData.baseDensity || 0.3) : 0.3;
const target = Math.min(1.5, base + g * 0.1 + energy * 0.25);
this.nebula.material.uniforms.density.value += (target - this.nebula.material.uniforms.density.value) * Math.min(1.0, delta * 0.5);
}
if (this.activeStar && this.activeStar.userData && this.activeStar.userData.corona && this.activeStar.userData.corona.material && this.activeStar.userData.corona.material.uniforms) {
const u = this.activeStar.userData.corona.material.uniforms;
const g = this.computeGenesisSignal();
const mid = this.audioSignal ? this.audioSignal.mid : 0;
if (u.intensity) u.intensity.value += ((0.8 + g * 0.4 + mid * 0.3) - u.intensity.value) * Math.min(1.0, delta * 0.5);
}
// Update NASA reference bodies simple circular motion for visibility
if (this.nasaBodies && this.nasaBodies.length) {
for (const body of this.nasaBodies) {
// Groups contain a child sphere with orbital data
let ud = null;
if (body.children && body.children.length) {
const sphere = body.children.find(c => c.isMesh && c.userData && c.userData.orbitRadius !== undefined);
if (sphere) ud = sphere.userData;
} else if (body.userData && body.userData.orbitRadius !== undefined) {
ud = body.userData;
}
if (!ud) continue;
ud.orbitAngle += delta * 0.005; // very slow orbit for context
const r = ud.orbitRadius;
const y = body.position.y;
const x = Math.cos(ud.orbitAngle) * r;
const z = Math.sin(ud.orbitAngle) * r;
body.position.set(x, y, z);
}
}
// Subtle orbital drift for asteroid belts around star based on gravity pulse
const pulse = 0.2 + this.computeGenesisSignal() * 0.8;
for (const belt of this.asteroidBelts) {
const pos = belt.geometry.attributes.position;
const arr = pos.array;
for (let i = 0; i < arr.length; i += 3) {
const x = arr[i], y = arr[i+1], z = arr[i+2];
const r = Math.sqrt(x*x + z*z);
if (r > 0.0001) {
const angVel = (1.0 / Math.sqrt(r)) * pulse * delta * 0.8;
const angle = Math.atan2(z, x) + angVel;
arr[i] = Math.cos(angle) * r;
arr[i+2] = Math.sin(angle) * r;
}
arr[i+1] += Math.sin((x+z) * 0.001 + this.clock.elapsedTime * 0.2) * 0.02; // tiny vertical flutter
}
pos.needsUpdate = true;
// Fade with distance in cosmic web
if (this.cosmicWebView.active) belt.material.opacity = belt.userData.baseOpacity * 0.3; else belt.material.opacity = belt.userData.baseOpacity;
}
}
updateArtwork(artwork, delta) {
artwork.userData.life -= delta;
if (artwork.userData.life <= 0) {
this.scene.remove(artwork);
artwork.geometry.dispose();
artwork.material.dispose();
return;
}
const positions = artwork.geometry.attributes.position.array;
artwork.userData.particles.forEach((p, i) => {
if (this.planets.length > 0) {
const nearestPlanet = this.planets.reduce((prev, curr) => {
return (prev.position.distanceTo(p.pos) < curr.position.distanceTo(p.pos)) ? prev : curr;
});
const gravity = nearestPlanet.position.clone().sub(p.pos).normalize().multiplyScalar(5 * delta);
p.vel.add(gravity);
}
p.vel.multiplyScalar(0.99);
p.pos.add(p.vel);
positions[i*3] = p.pos.x;
positions[i*3+1] = p.pos.y;
positions[i*3+2] = p.pos.z;
});
artwork.geometry.attributes.position.needsUpdate = true;
artwork.material.opacity = Math.min(1, artwork.userData.life / 10);
}
updateAutonomousObject(obj, delta) {
obj.userData.life -= delta;
if (obj.userData.life <= 0) {
// Defer removal to avoid mutating the scene during traversal
this.pendingRemovals.push(obj);
return;
}
if (obj.userData.velocity) {
obj.position.add(obj.userData.velocity.clone().multiplyScalar(delta));
}
if (obj.userData.velocityArray) {
// Points-based object with per-particle velocities
const positions = obj.geometry.attributes.position.array;
const v = obj.userData.velocityArray;
for (let i = 0; i < positions.length; i += 3) {
positions[i] += v[i] * delta;
positions[i+1] += v[i+1] * delta;
positions[i+2] += v[i+2] * delta;
// Dampen
v[i] *= (1 - 0.1 * delta);
v[i+1] *= (1 - 0.1 * delta);
v[i+2] *= (1 - 0.1 * delta);
}
obj.geometry.attributes.position.needsUpdate = true;
}
if (obj.material) {
obj.material.opacity = Math.min(1, obj.userData.life / 10);
}
}
updateCometTail(comet, delta) {
const tail = comet.userData.tail;
if (!tail) return;
const positions = tail.geometry.attributes.position.array;
// Shift segments back
for (let i = positions.length - 1; i >= 3; i--) {
positions[i] = positions[i - 3];
}
// Head segment at comet origin
positions[0] = 0; positions[1] = 0; positions[2] = 0;
// Fade opacity slightly over life
if (tail.material.opacity > 0.1) tail.material.opacity *= (1 - 0.3 * delta);
tail.geometry.attributes.position.needsUpdate = true;
}
updateFlora(flora, delta) {
// Growth driven by genesis influence and ambient pulse
const growthRate = (this.lastInfluence && this.lastInfluence.hasPlant ? 0.05 : 0.02) + this.cosmicPulse * 0.02;
flora.userData.growth = Math.min(1.0, flora.userData.growth + growthRate * delta);
// Sway animation
flora.userData.swayPhase += delta * (0.5 + this.cosmicPulse);
const sway = Math.sin(flora.userData.swayPhase) * 0.05;
flora.rotation.z = sway;
// Scale up as it grows
const s = 0.5 + flora.userData.growth * 0.5;
flora.scale.set(s, s, s);
// Fruit ripening: shift from green to warm as growth nears 1
if (flora.userData.fruits) {
const fruits = flora.userData.fruits;
const colors = fruits.geometry.attributes.color.array;
const ripe = Math.min(1.0, fruits.userData.ripe + growthRate * delta * 0.5);
fruits.userData.ripe = ripe;
for (let i = 0; i < colors.length; i += 3) {
const c = new THREE.Color().setHSL(0.33 * (1.0 - ripe) + 0.02 * ripe, 0.8, 0.5 + 0.3 * ripe);
colors[i] = c.r; colors[i+1] = c.g; colors[i+2] = c.b;
}
fruits.geometry.attributes.color.needsUpdate = true;
// Occasionally disperse seeds when fully ripe
if (ripe > 0.99 && Math.random() < 0.01) {
this.disperseSeeds(fruits);
fruits.userData.ripe = 0.7; // reset slightly
}
}
}
disperseSeeds(fruits) {
const positions = fruits.geometry.attributes.position.array;
const seedCount = Math.min(30, positions.length / 3);
const seedPositions = new Float32Array(seedCount * 3);
const seedColors = new Float32Array(seedCount * 3);
for (let i = 0; i < seedCount; i++) {
const idx = (Math.floor(Math.random() * (positions.length / 3))) * 3;
seedPositions[i*3] = fruits.getWorldPosition(new THREE.Vector3()).x + (Math.random()-0.5) * 5;
seedPositions[i*3+1] = fruits.getWorldPosition(new THREE.Vector3()).y + (Math.random()) * 5;
seedPositions[i*3+2] = fruits.getWorldPosition(new THREE.Vector3()).z + (Math.random()-0.5) * 5;
const c = new THREE.Color().setHSL(0.12, 0.9, 0.6);
seedColors[i*3] = c.r; seedColors[i*3+1] = c.g; seedColors[i*3+2] = c.b;
}
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(seedPositions, 3));
geom.setAttribute('color', new THREE.BufferAttribute(seedColors, 3));
const mat = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, blending: THREE.AdditiveBlending, transparent: true, depthWrite: false });
const seeds = new THREE.Points(geom, mat);
seeds.userData = { isGenerated: true, isAutonomous: true, life: 8 };
this.scene.add(seeds);
this.uiManager.log("Flora dispersed seeds into the cosmos.", "data");
}
updateMonolithGlint(monolith, delta) {
if (!monolith.material || !this.activeStar) return;
const toCamera = this.camera.position.clone().sub(monolith.position).normalize();
const toStar = this.activeStar.position.clone().sub(monolith.position).normalize();
// Fresnel-like highlight when star, monolith normal, and view align
const normal = new THREE.Vector3(0, 1, 0).applyQuaternion(monolith.quaternion);
const reflect = toStar.clone().reflect(normal);
const viewAlign = Math.max(0, reflect.dot(toCamera));
const glint = Math.pow(viewAlign, 32);
const base = monolith.userData.baseEmissive || 0.2;
monolith.material.emissiveIntensity = base + glint * 0.8;
}
handleCosmicWebView() {
const camDist = this.camera.position.length();
const fadeStart = this.cosmicWebView.threshold - 2000;
if (camDist > fadeStart) {
const alpha = Math.min(1.0, (camDist - fadeStart) / 2000);
this.localStarfield.material.opacity = 1.0 - alpha;
if(this.hiddenEcho) this.hiddenEcho.visible = false;
this.cosmicWeb.visible = true;
this.cosmicWeb.material.opacity = alpha;
this.cosmicWebView.active = alpha > 0.9;
if (this.cosmicWebView.active) this.eventBus.publish('status:update', 'COSMIC WEB');
} else {
if (this.cosmicWebView.active) this.setQuality(this.uiManager.qualitySelect.value);
this.localStarfield.material.opacity = 1.0;
if(this.hiddenEcho) this.hiddenEcho.visible = true;
this.cosmicWeb.visible = false;
this.cosmicWebView.active = false;
}
// Darkness detection for spaceship headlamp
if (this.spaceship) {
const nearStar = this.activeStar ? this.camera.position.distanceTo(this.activeStar.position) : Infinity;
const nearNebula = this.planets.length > 0 ? Math.min(...this.planets.map(p => this.camera.position.distanceTo(p.position))) : Infinity;
const farFromEverything = Math.min(nearStar, nearNebula) > 8000 && camDist > this.cosmicWebView.threshold;
const enableLamp = farFromEverything || (this.localStarfield.material.opacity < 0.2 && !this.cosmicWeb.visible);
this.spaceship.setHeadlamp(enableLamp);
}
// HUD hint for Earth location when NASA bodies are present
if (this.earthRef) {
const d = this.camera.position.distanceTo(this.earthRef.position);
this.eventBus.publish('status:update', `EARTH REF: ~${d.toFixed(0)} units`);
}
}
// --- User Controls & Settings ---
updatePlayerMovement(delta) {
const moveSpeed = 500.0 * delta;
if (this.keys['w'] || this.keys['arrowup']) this.pointerLockControls.moveForward(moveSpeed);
if (this.keys['s'] || this.keys['arrowdown']) this.pointerLockControls.moveForward(-moveSpeed);
if (this.keys['a'] || this.keys['arrowleft']) this.pointerLockControls.moveRight(-moveSpeed);
if (this.keys['d'] || this.keys['arrowright']) this.pointerLockControls.moveRight(moveSpeed);
}
setViewMode(mode) {
if (this.pointerLockControls.isLocked) this.pointerLockControls.unlock();
this.orbitControls.enabled = false;
if (this.spaceship) {
this.spaceship.destroy();
this.spaceship = null;
}
this.activeControls = null;
if (mode === 'orbit') {
this.camera.position.set(0, 0, 250);
this.orbitControls.target.set(0,0,0);
this.activeControls = this.orbitControls;
this.activeControls.isOrbitControls = true;
this.orbitControls.enabled = true;
this.applyViewProfile('orbit');
} else if (mode === 'first-person') {
this.camera.position.set(0, 0, 0);
this.activeControls = this.pointerLockControls;
this.pointerLockControls.lock();
this.applyViewProfile('firstPerson');
} else if (mode === 'enhanced-fp' || mode === 'cockpit-view') {
this.spaceship = new Spaceship(this.scene, this.camera, this.keys);
this.spaceship.setView(mode);
// Apply quantum scale in enhanced first-person
if (mode === 'enhanced-fp') {
this.spaceship.setQuantumScale(0.001);
}
this.activeControls = this.pointerLockControls;
this.pointerLockControls.lock();
// Provide an easy Earth locate hotkey in spaceship views
document.addEventListener('keydown', (e) => { if (e.key === 'e' || e.key === 'E') this.eventBus.publish('ui:locateEarth'); }, { once: true });
this.applyViewProfile(mode === 'enhanced-fp' ? 'enhanced' : 'cockpit');
} else { // cinematic
this.activeControls = { isOrbitControls: false, update: () => { this.camera.position.x += Math.sin(this.clock.getElapsedTime() * 0.05) * 0.2; this.camera.lookAt(this.scene.position); } };
this.enableCinematicDOF(true);
this.applyViewProfile('cinematic');
}
}
applyViewProfile(name) {
const p = this.viewProfiles[name];
if (!p) return;
if (this.bloomPass) this.bloomPass.strength = p.bloom;
if (this.vignettePass) this.vignettePass.uniforms.darkness.value = p.vignette;
if (this.godrayPass) this.godrayPass.enabled = !!p.godrays;
if (this.filmPass) this.filmPass.enabled = !!p.film;
}
enableCinematicDOF(enable) {
if (enable) {
if (!this.bokehPass) {
this.bokehPass = new BokehPass(this.scene, this.camera, {
focus: 250.0,
aperture: 0.0001,
maxblur: 0.01,
width: window.innerWidth,
height: window.innerHeight
});
this.composer.addPass(this.bokehPass);
}
this.bokehPass.enabled = true;
} else if (this.bokehPass) {
this.bokehPass.enabled = false;
}
}
setQuality(quality) {
const high = ['high', 'ultra', 'anime'].includes(quality);
const ultra = quality === 'ultra';
// Reset all passes
this.bloomPass.enabled = false;
this.pixelationPass.enabled = false;
this.vignettePass.enabled = false;
// Do not hard-disable motion blur here; respect user toggle
// this.afterimagePass.enabled = false;
this.godrayPass.enabled = false;
this.toonPass.enabled = false;
this.filmPass.enabled = false;
this.fxaaPass.enabled = false;
this.rgbShiftPass.enabled = false;
if (quality === 'anime') {
this.toonPass.enabled = true;
this.bloomPass.enabled = true; // Anime styles often have strong blooms
this.fxaaPass.enabled = true;
this.filmPass.enabled = true;
} else if (quality === 'low') {
this.pixelationPass.enabled = true;
this.fxaaPass.enabled = true; // keep cheap AA
} else { // Medium, High, Ultra
this.bloomPass.enabled = true;
this.vignettePass.enabled = high;
// Only enable if user toggle is on
if (this.userSettings && this.userSettings.motionBlurEnabled) this.afterimagePass.enabled = high;
this.godrayPass.enabled = high;
this.godrayPass.uniforms.samples.value = ultra ? 100 : 50;
this.fxaaPass.enabled = true;
this.filmPass.enabled = high;
this.rgbShiftPass.enabled = ultra; // subtle chromatic aberration at ultra
this.renderer.toneMappingExposure = ultra ? 1.1 : (high ? 1.05 : 1.0);
}
// Re-apply current genesis visual profile on quality change
this.applyGenesisVisualProfile();
// Also re-apply current view profile to keep visuals consistent across modes
if (this.activeControls) {
if (this.activeControls === this.orbitControls) this.applyViewProfile('orbit');
else if (this.activeControls === this.pointerLockControls) {
if (this.spaceship) this.applyViewProfile(this.spaceship.cockpitView ? 'cockpit' : 'enhanced');
else this.applyViewProfile('firstPerson');
}
}
this.qualitySetting = quality;
}
setFilter(filterName) {
const m = new THREE.Matrix3();
switch (filterName) {
case 'cool': m.set(1, 0, 0, 0, 1, 0, 0.1, 0, 1.2); break;
case 'warm': m.set(1.2, 0.1, 0, 0, 1, 0, 0, 0, 1); break;
case 'nebula': m.set(1.1, 0, 0.3, 0.2, 0.9, 0, 0.3, 0, 1.3); break;
case 'monochrome': m.set(0.3, 0.6, 0.1, 0.3, 0.6, 0.1, 0.3, 0.6, 0.1); break;
default: m.identity(); break;
}
this.filterPass.uniforms.colorMatrix.value = m;
}
applyGenesisVisualProfile(starColor = null) {
// Map last influence and star color to a visual profile without changing physics
const inf = this.lastInfluence || { hasPlant: false, hasBook: false, createBlackHole: false };
const profile = { filter: 'none', bloomBoost: 0.0, vignetteDarkness: 1.0, rgbAmount: 0.0015 };
if (inf.hasPlant) {
profile.filter = 'warm';
profile.bloomBoost += 0.2;
profile.vignetteDarkness = 0.9;
}
if (inf.hasBook) {
profile.filter = profile.filter === 'warm' ? 'nebula' : 'cool';
profile.bloomBoost += 0.1;
}
if (inf.createBlackHole) {
profile.rgbAmount = 0.003;
profile.vignetteDarkness = 1.2;
}
// Optional: bias filter by star hue
if (starColor) {
const hsl = starColor.getHSL({ h: 0, s: 0, l: 0 });
if (hsl.h > 0.58 || hsl.h < 0.08) {
// Red/blue extremes can push toward nebula grade
if (profile.filter === 'none') profile.filter = 'nebula';
}
}
this.visualProfile = profile;
this.setFilter(profile.filter);
if (this.bloomPass && this.bloomPass.enabled) this.bloomPass.strength += profile.bloomBoost;
if (this.vignettePass) this.vignettePass.uniforms.darkness.value = profile.vignetteDarkness;
if (this.rgbShiftPass && this.rgbShiftPass.enabled) this.rgbShiftPass.uniforms['amount'].value = profile.rgbAmount;
}
spawnKnowledgeMonolithsIfNeeded() {
if (!this.lastInfluence || !this.lastInfluence.hasBook) return;
const num = 3 + Math.floor(this.prng() * 5);
for (let i = 0; i < num; i++) {
const h = 50 + this.prng() * 150;
const w = 10 + this.prng() * 20;
const d = 6 + this.prng() * 12;
const geom = new THREE.BoxGeometry(w, h, d);
const mat = new THREE.MeshStandardMaterial({ color: 0x111122, metalness: 0.85, roughness: 0.25, emissive: new THREE.Color(0x223355), emissiveIntensity: 0.2 });
const mesh = new THREE.Mesh(geom, mat);
mesh.position.set((this.prng() - 0.5) * 4000, (this.prng() - 0.5) * 400, (this.prng() - 0.5) * 4000);
mesh.rotation.y = this.prng() * Math.PI * 2;
mesh.userData = { isGenerated: true, isMonolith: true, baseEmissive: 0.2 };
this.scene.add(mesh);
}
this.uiManager.log('Knowledge monoliths have been erected in response to observed artifacts.', 'data');
}
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.composer.setSize(window.innerWidth, window.innerHeight);
this.toonPass.uniforms.resolution.value.set(window.innerWidth, window.innerHeight);
this.pixelationPass.uniforms.resolution.value.set(window.innerWidth, window.innerHeight);
if (this.fxaaPass) this.fxaaPass.material.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
if (this.bokehPass) { this.bokehPass.renderTargetDepth.width = window.innerWidth; this.bokehPass.renderTargetDepth.height = window.innerHeight; }
if (this.ssrPass && this.ssrPass.setSize) { this.ssrPass.setSize(window.innerWidth, window.innerHeight); }
}
// --- Event Triggers & Scanner ---
triggerLiveReaction(event) {
this.uiManager.log(`Live Event Triggered: ${event.type}`, 'data');
if (event.type === 'majorSeismicEvent') {
this.createBlackHole(); // Live creation of a black hole
} else if (event.type === 'lightChange' || event.type === 'audioSpike') {
// Nudge starspot strength visually
if (this.activeStar && this.activeStar.userData.photosphere && this.activeStar.userData.photosphere.material.uniforms.spotStrength) {
const u = this.activeStar.userData.photosphere.material.uniforms.spotStrength;
u.value = Math.min(1.0, u.value + 0.2);
}
this.planets.forEach(planet => {
planet.traverse(child => {
if (child.userData.isAtmosphere) {
let currentIntensity = 0;
const animateAurora = () => {
currentIntensity += 0.05;
child.material.uniforms.auroraIntensity.value = Math.sin(currentIntensity) * 0.5 + 0.5;
if (currentIntensity < Math.PI) requestAnimationFrame(animateAurora);
else child.material.uniforms.auroraIntensity.value = 0;
}
animateAurora();
}
});
});
}
}
// Handle environmental influence from cognitive core
handleEnvironmentalInfluence(influence) {
console.log('🌍 Environmental Influence Received:', influence);
// Store current environmental state for universe dynamics
this.environmentalState = {
...influence,
timestamp: Date.now(),
influenceStrength: (influence.harmony + influence.consciousness + influence.resonance) / 3
};
// Trigger immediate universe reactions
this.triggerUniverseReaction(influence);
}
// Respond to universe environmental influence events
respondToEnvironmentalInfluence(data) {
console.log('🌌 Universe Environmental Response:', data);
// Update universe breathing and growth parameters
this.universeDynamics = {
...data,
lastUpdate: Date.now(),
breathingCycle: Math.sin(Date.now() / 5000) * data.breathing * 0.1,
growthFactor: data.growth,
changeIntensity: data.change
};
// Apply universe transformations
this.applyUniverseTransformations(data);
}
// Trigger immediate universe reaction to environmental influence
triggerUniverseReaction(influence) {
const { harmony, consciousness, resonance, volatility } = influence;
// Adjust star properties based on harmony
if (this.activeStar) {
const baseSize = 20 + this.prng() * 25;
const harmonyMultiplier = 0.8 + (harmony * 0.4); // 0.8 to 1.2
const newSize = baseSize * harmonyMultiplier;
this.activeStar.scale.setScalar(newSize / baseSize);
// Adjust star color based on consciousness
const consciousnessHue = consciousness * 60; // 0-60 degrees (red to yellow)
const starColor = new THREE.Color().setHSL(consciousnessHue / 360, 0.8, 0.6);
this.activeStar.material.color = starColor;
console.log(`⭐ Star transformed: Size ${newSize.toFixed(1)}, Hue ${consciousnessHue.toFixed(1)}°`);
}
// Adjust lighting based on resonance
if (this.scene) {
this.scene.traverse((object) => {
if (object.isLight && object.userData.isGenerated) {
const resonanceIntensity = 1 + (resonance * 0.5); // 1.0 to 1.5
object.intensity *= resonanceIntensity;
}
});
}
// Trigger particle system reactions
if (volatility > 0.3) {
this.triggerParticleStorm(volatility);
}
}
// Apply ongoing universe transformations
applyUniverseTransformations(data) {
const { growth, breathing, change } = data;
// Universe breathing effect
if (this.scene) {
const breathingScale = 1 + (breathing * 0.05 * Math.sin(Date.now() / 3000));
this.scene.scale.setScalar(breathingScale);
}
// Growth-based universe expansion
if (growth > 0.6 && this.universeObjects) {
this.expandUniverseObjects(growth);
}
// Change-based universe mutation
if (change > 0.5) {
this.mutateUniverseElements(change);
}
// Dynamic starfield response
this.updateStarfieldDynamics(data);
}
// Expand universe objects based on growth factor
expandUniverseObjects(growthFactor) {
if (!this.scene) return;
this.scene.traverse((object) => {
if (object.userData && object.userData.isGenerated && object.isMesh) {
const baseScale = object.userData.originalScale || object.scale.x;
const growthMultiplier = 1 + (growthFactor - 0.6) * 0.2; // 0% to 20% growth
if (!object.userData.originalScale) {
object.userData.originalScale = baseScale;
}
object.scale.setScalar(baseScale * growthMultiplier);
}
});
console.log(`🌌 Universe expanded by ${(growthFactor * 100).toFixed(1)}% growth factor`);
}
// Mutate universe elements based on change intensity
mutateUniverseElements(changeIntensity) {
if (!this.scene) return;
// Randomly mutate colors and properties
this.scene.traverse((object) => {
if (object.userData && object.userData.isGenerated && object.material) {
const mutationStrength = (changeIntensity - 0.5) * 0.3; // 0% to 30% mutation
if (object.material.color) {
const originalColor = object.userData.originalColor || object.material.color.clone();
if (!object.userData.originalColor) {
object.userData.originalColor = originalColor;
}
// Mutate color slightly
const hueShift = (Math.random() - 0.5) * mutationStrength;
const satShift = (Math.random() - 0.5) * mutationStrength * 0.5;
object.material.color.setHSL(
(originalColor.getHSL({}).h + hueShift + 1) % 1,
Math.max(0, Math.min(1, originalColor.getHSL({}).s + satShift)),
originalColor.getHSL({}).l
);
}
}
});
console.log(`🔄 Universe mutated by ${(changeIntensity * 100).toFixed(1)}% change intensity`);
}
// Update starfield dynamics
updateStarfieldDynamics(data) {
const { harmony, resonance, volatility } = data;
if (this.localStarfield) {
// Adjust starfield density based on harmony
const harmonyScale = 0.7 + (harmony * 0.6); // 0.7 to 1.3
this.localStarfield.scale.setScalar(harmonyScale);
}
if (this.cosmicWeb) {
// Adjust cosmic web visibility based on resonance
const resonanceAlpha = 0.3 + (resonance * 0.7); // 0.3 to 1.0
// Note: This would require modifying the starfield material to support opacity
}
}
// Trigger particle storm based on volatility
triggerParticleStorm(volatility) {
if (!this.scene) return;
const particleCount = Math.floor(volatility * 100);
const particles = [];
for (let i = 0; i < particleCount; i++) {
const geometry = new THREE.SphereGeometry(0.5 + Math.random() * 2, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
transparent: true,
opacity: 0.8
});
const particle = new THREE.Mesh(geometry, material);
// Random position within viewing area
particle.position.set(
(Math.random() - 0.5) * 1000,
(Math.random() - 0.5) * 1000,
(Math.random() - 0.5) * 1000
);
particle.userData = {
isGenerated: true,
isParticle: true,
velocity: new THREE.Vector3(
(Math.random() - 0.5) * 2,
(Math.random() - 0.5) * 2,
(Math.random() - 0.5) * 2
),
lifetime: Date.now() + 5000 + Math.random() * 5000 // 5-10 seconds
};
this.scene.add(particle);
particles.push(particle);
}
console.log(`⚡ Particle storm triggered: ${particleCount} particles from volatility ${volatility.toFixed(2)}`);
// Schedule particle cleanup
setTimeout(() => {
particles.forEach(particle => {
if (particle.parent) {
particle.parent.remove(particle);
particle.geometry.dispose();
particle.material.dispose();
}
});
}, 10000);
}
// Update universe dynamics in animation loop
updateUniverseDynamics(deltaTime) {
if (!this.universeDynamics) return;
const { breathing, growth, change } = this.universeDynamics;
// Apply breathing animation
if (this.scene && breathing !== 0) {
const breathCycle = Math.sin(Date.now() / 5000) * breathing * 0.03;
const currentScale = this.scene.scale.x;
const targetScale = 1 + breathCycle;
// Smooth interpolation
const lerpFactor = Math.min(deltaTime * 2, 1);
const newScale = currentScale + (targetScale - currentScale) * lerpFactor;
this.scene.scale.setScalar(newScale);
}
// Update particle systems
this.updateParticleSystems(deltaTime);
// Apply environmental influence to camera
this.applyEnvironmentalCameraEffects();
}
// Update particle systems
updateParticleSystems(deltaTime) {
if (!this.scene) return;
this.scene.traverse((object) => {
if (object.userData && object.userData.isParticle) {
// Update particle position
if (object.userData.velocity) {
object.position.add(object.userData.velocity.clone().multiplyScalar(deltaTime));
}
// Update particle opacity based on lifetime
if (object.userData.lifetime) {
const remainingLife = object.userData.lifetime - Date.now();
const totalLife = 10000; // 10 seconds
const opacity = Math.max(0, remainingLife / totalLife);
if (object.material) {
object.material.opacity = opacity;
// Remove dead particles
if (opacity <= 0 && object.parent) {
object.parent.remove(object);
object.geometry.dispose();
object.material.dispose();
}
}
}
}
});
}
// Apply environmental influence to camera
applyEnvironmentalCameraEffects() {
if (!this.camera || !this.environmentalState) return;
const { resonance, harmony } = this.environmentalState;
// Subtle camera movement based on resonance
const time = Date.now() / 1000;
const resonanceOffset = resonance * 2;
// Apply micro-movements to camera
this.camera.position.x += Math.sin(time * 0.5) * resonanceOffset * 0.01;
this.camera.position.y += Math.cos(time * 0.3) * resonanceOffset * 0.01;
// Harmony-based camera field of view
const baseFOV = 75;
const harmonyFOV = baseFOV * (0.95 + harmony * 0.1); // 71.25 to 82.5
this.camera.fov = harmonyFOV;
this.camera.updateProjectionMatrix();
}
updateCosmicGrowth(delta) {
this.autonomousEventTimer += delta;
if(this.autonomousEventTimer > 15) { // Check for major autonomous event
this.triggerAutonomousEvent();
this.autonomousEventTimer = 0;
}
if(this.cosmicGrowthEnergy > 100) { // Check for minor growth event
this.triggerCosmicRift();
this.cosmicGrowthEnergy = 0;
}
}
createAsteroidBelt(center, innerR, outerR, count) {
const positions = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const r = innerR + Math.random() * (outerR - innerR);
const a = Math.random() * Math.PI * 2;
positions[i*3] = center.x + Math.cos(a) * r;
positions[i*3+1] = center.y + (Math.random()-0.5) * (outerR - innerR) * 0.05;
positions[i*3+2] = center.z + Math.sin(a) * r;
}
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const mat = new THREE.PointsMaterial({ color: 0x888888, size: 1.5 });
const belt = new THREE.Points(geom, mat);
belt.userData = { isGenerated: true, isAutonomous: true, life: 120 };
this.scene.add(belt);
this.uiManager.log("A persistent asteroid belt has formed from debris.", "data");
}
handleFutureEvent(evt) {
if (!evt || !evt.type) return;
this.uiManager.log(`AI scheduled event fired: ${evt.type}`, 'data');
switch (evt.type) {
case 'growFlora':
this.planets.forEach(planet => {
if (Math.random() > 0.7) {
const flora = this.createLSystemFlora();
flora.scale.set(0.1, 0.1, 0.1);
flora.position.set(0, planet.geometry.parameters.radius, 0);
planet.add(flora);
}
});
break;
case 'solarFlare':
if (this.activeStar) this.spawnSolarFlare(this.activeStar);
break;
case 'meteorShower':
this.spawnMeteorShower();
break;
case 'lightningStorm':
this.triggerAutonomousEvent();
break;
case 'comet':
this.triggerAutonomousEvent();
break;
case 'spawnBlackHole':
this.createBlackHole();
break;
case 'bloom':
// Trigger seed dispersal on visible flora
this.scene.traverse(obj => {
if (obj.userData && obj.userData.isFlora && obj.userData.fruits) {
this.disperseSeeds(obj.userData.fruits);
}
});
this.uiManager.log("A cosmic bloom has spread seeds across the system.", 'data');
break;
default:
break;
}
}
spawnSolarFlare(star) {
const flareCount = 5 + Math.floor(this.prng() * 8);
for (let i = 0; i < flareCount; i++) {
const dir = new THREE.Vector3().randomDirection();
const start = star.position.clone().add(dir.clone().multiplyScalar((star.geometry.parameters.radius || 20) * 1.2));
const end = start.clone().add(dir.clone().multiplyScalar(500 + this.prng() * 1000));
const bolt = this.createLightningBolt(start, end);
bolt.userData.life = 0.2 + this.prng() * 0.4;
this.scene.add(bolt);
}
this.uiManager.log("Solar flare emitted from the star.", "data");
}
spawnMeteorShower() {
const count = 60 + Math.floor(this.prng() * 120);
const positions = [];
const velocities = [];
for (let i = 0; i < count; i++) {
const pos = new THREE.Vector3().randomDirection().multiplyScalar(7000 + this.prng() * 3000);
positions.push(pos.x, pos.y, pos.z);
velocities.push((this.prng()-0.5)*200, (this.prng()-0.5)*50, (this.prng()-0.5)*200);
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ color: 0xffddaa, size: 3, blending: THREE.AdditiveBlending, transparent: true, depthWrite: false });
const shower = new THREE.Points(geometry, material);
shower.userData = { isGenerated: true, isAutonomous: true, life: 20, velocityArray: velocities };
this.scene.add(shower);
this.uiManager.log("Meteor shower cascades through the system.", "data");
// After shower, occasionally form a belt
if (Math.random() < 0.5 && this.activeStar) {
this.createAsteroidBelt(new THREE.Vector3(), 2000 + Math.random()*1000, 4000 + Math.random()*2000, 2000 + Math.floor(Math.random()*3000));
}
}
triggerCosmicRift() {
const riftPosition = new THREE.Vector3(
(Math.random() - 0.5) * 10000,
(Math.random() - 0.5) * 10000,
(Math.random() - 0.5) * 10000
);
const baseColor = new THREE.Color().setHSL(Math.random(), 0.8, 0.6);
const nebula = this.createNebula(baseColor);
nebula.scale.set(0.1, 0.1, 0.1); // Start small
nebula.position.copy(riftPosition);
this.uiManager.log("Ambient energy has torn a new rift, expanding the cosmos.", "data");
}
triggerAutonomousEvent() {
const eventType = this.prng();
if (eventType > 0.8) {
this.uiManager.log("AI spawned a cosmic lightning storm.", "data");
const numBolts = 5 + Math.floor(this.prng() * 10);
for (let i=0; i < numBolts; i++) {
const start = new THREE.Vector3().randomDirection().multiplyScalar(5000 + this.prng() * 5000);
const end = new THREE.Vector3().randomDirection().multiplyScalar(5000 + this.prng() * 5000);
const bolt = this.createLightningBolt(start, end);
this.scene.add(bolt);
}
} else if (eventType > 0.4) { // Asteroid Field
const asteroidCount = 50 + this.prng() * 100;
const positions = [];
for (let i = 0; i < asteroidCount; i++) positions.push((this.prng() - 0.5) * 5000, (this.prng() - 0.5) * 500, (this.prng() - 0.5) * 5000);
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ color: 0x888888, size: this.prng() * 2 + 1 });
const field = new THREE.Points(geometry, material);
field.userData = { isGenerated: true, isAutonomous: true, life: 30 };
this.scene.add(field);
this.uiManager.log("AI spawned a passing asteroid field.", "data");
} else { // Comet
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute([0,0,0], 3));
const material = new THREE.PointsMaterial({ color: 0x87ceeb, size: 15, blending: THREE.AdditiveBlending, map: this.createCometTexture(), transparent: true });
const comet = new THREE.Points(geometry, material);
const startPos = new THREE.Vector3((Math.random() - 0.5) * 10000, (Math.random() - 0.5) * 10000, (Math.random() - 0.5) * 10000);
comet.position.copy(startPos);
comet.userData = { isGenerated: true, isAutonomous: true, life: 60, velocity: new THREE.Vector3().sub(startPos).normalize().multiplyScalar(220), isComet: true, tail: null };
this.addCometTail(comet);
this.scene.add(comet);
this.uiManager.log("AI spawned a passing comet with a glowing tail.", "data");
}
}
addCometTail(comet) {
const segs = 50;
const positions = new Float32Array(segs * 3);
for (let i = 0; i < segs; i++) {
positions[i*3] = 0; positions[i*3+1] = 0; positions[i*3+2] = -i * 10;
}
const geom = new THREE.BufferGeometry();
geom.setAttribute('position', new THREE.BufferAttribute(positions, 3));
// Tail color influenced by star temperature and distance: hotter = bluer
let tailColor = 0x99ccff;
if (this.activeStar) {
const tempColor = this.activeStar.material.color || new THREE.Color(1,1,1);
// Approximate blue bias with higher luminance
const bias = Math.max(0, Math.min(1, (tempColor.b - tempColor.r) * 0.8 + 0.5));
const c = new THREE.Color().setHSL(0.6 + 0.1*bias, 0.7, 0.7);
tailColor = c.getHex();
}
const mat = new THREE.LineBasicMaterial({ color: tailColor, transparent: true, opacity: 0.7, blending: THREE.AdditiveBlending });
const tail = new THREE.Line(geom, mat);
tail.userData = { isGenerated: true, isCometTail: true };
comet.add(tail);
comet.userData.tail = tail;
}
createLightningBolt(start, end) {
const points = [start.clone()];
let current = start.clone();
const direction = end.clone().sub(start).normalize();
const totalDist = start.distanceTo(end);
while(current.distanceTo(start) < totalDist) {
const step = 50 + this.prng() * 200;
current.add(direction.clone().multiplyScalar(step));
const offset = new THREE.Vector3().randomDirection().multiplyScalar(this.prng() * 50);
points.push(current.clone().add(offset));
// Randomly branch off
if (this.prng() > 0.9) {
const branchEnd = current.clone().add(new THREE.Vector3().randomDirection().multiplyScalar(500));
points.push(current.clone()); // Go back to start of branch
points.push(branchEnd);
points.push(current.clone()); // Return to main bolt
}
}
points.push(end.clone());
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0x87cefa, transparent: true, blending: THREE.AdditiveBlending });
const bolt = new THREE.LineSegments(geometry, material);
bolt.userData = { isGenerated: true, isAutonomous: true, life: 0.5 + this.prng() }; // Short life
return bolt;
}
createCometTexture() {
const canvas = document.createElement('canvas');
canvas.width = 64; canvas.height = 64;
const context = canvas.getContext('2d');
const gradient = context.createRadialGradient(32, 32, 0, 32, 32, 32);
gradient.addColorStop(0, 'rgba(255,255,255,1)');
gradient.addColorStop(0.2, 'rgba(200,200,255,1)');
gradient.addColorStop(1, 'rgba(100,100,255,0)');
context.fillStyle = gradient;
context.fillRect(0,0,64,64);
return new THREE.CanvasTexture(canvas);
}
toggleScanner() {
if (!this.hiddenEcho) { this.uiManager.log('No anomaly detected in this system.', 'warn'); return; }
this.isScanning = !this.isScanning;
this.uiManager.log(`Anomaly Scanner ${this.isScanning ? 'Activated' : 'Deactivated'}`, 'info');
if (this.isScanning && !this.scannerSound) {
this.scannerSound = new THREE.PositionalAudio(this.listener);
const audioCtx = this.listener.context;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = 'sine'; osc.frequency.value = 800; gain.gain.value = 0;
osc.connect(gain);
this.scannerSound.setNodeSource(gain);
this.scannerSound.setRefDistance(20); this.scannerSound.setRolloffFactor(2);
osc.start();
this.hiddenEcho.add(this.scannerSound);
}
if (this.scannerSound) this.isScanning ? this.scannerSound.play() : this.scannerSound.stop();
}
updateScanner() {
if (!this.isScanning || !this.scannerSound || !this.scannerSound.source) return;
const gain = this.scannerSound.getOutput();
const time = this.clock.getElapsedTime();
const pulse = (Math.sin(time * 8) + 1) / 2;
gain.gain.setTargetAtTime(pulse * 0.2, this.listener.context.currentTime, 0.01);
}
updateLensing() {
if (this.blackHoles.length === 0) {
this.lensingPass.enabled = false;
return;
}
const blackHole = this.blackHoles[0];
const screenPos = blackHole.position.clone().project(this.camera);
if (screenPos.x > -1 && screenPos.x < 1 && screenPos.y > -1 && screenPos.y < 1 && screenPos.z < 1) {
this.lensingPass.enabled = true;
this.lensingPass.uniforms.center.value.set((screenPos.x + 1) / 2, (screenPos.y + 1) / 2);
} else {
this.lensingPass.enabled = false;
}
}
updateSSRProximity() {
if (!this.ssrPass) return;
let enableSSR = false;
const threshold = 800;
this.scene.traverse(obj => {
if (obj.userData && obj.userData.isMonolith) {
const d = obj.position.distanceTo(this.camera.position);
if (d < threshold) enableSSR = true;
}
});
this.ssrPass.enabled = enableSSR;
}
updateCinematicDOF() {
if (!this.bokehPass || !this.bokehPass.enabled) return;
// Focus at the nearest generated object in the view for cinematic pull-focus
let focusDistance = 250.0;
let minDist = Infinity;
const candidates = [];
if (this.activeStar) candidates.push(this.activeStar);
this.planets.forEach(p => candidates.push(p));
this.blackHoles.forEach(b => candidates.push(b));
for (const obj of candidates) {
const dist = this.camera.position.distanceTo(obj.position);
if (dist < minDist) { minDist = dist; focusDistance = dist; }
}
// Smoothly approach target focus distance
this.bokehPass.materialBokeh.uniforms['focus'].value += (focusDistance - this.bokehPass.materialBokeh.uniforms['focus'].value) * 0.08;
}
focusEarth() {
if (!this.nasaBodies || !this.nasaBodies.length) { this.uiManager.log('Earth reference not available yet.', 'warn'); return; }
const earth = this.earthRef;
if (!earth) { this.uiManager.log('Earth reference not found.', 'warn'); return; }
const dir = earth.position.clone().sub(this.camera.position).normalize();
const targetPos = earth.position.clone().add(dir.clone().multiplyScalar(60));
this.camera.position.copy(targetPos);
this.camera.lookAt(earth.position);
this.uiManager.log('Camera moved near NASA Earth reference. Press H to toggle UI for coordinates.', 'success');
}
toggleDevMode() {
this.isDevMode = !this.isDevMode;
if (this.isDevMode) {
this.soundBrush = new SoundBrush(this.scene, this.camera, this.eventBus);
this.uiManager.log("Developer Mode ON: Sound Brush active. Click to paint.", "warn");
} else {
if (this.soundBrush) this.soundBrush.destroy();
this.soundBrush = null;
this.uiManager.log("Developer Mode OFF.", "info");
}
}
toggleAmbientAudio(isEnabled) {
this.isAmbientAudioEnabled = isEnabled;
if (isEnabled && !this.proceduralAudio && this.activeStar) {
const starTemp = 2000 + this.prng() * 18000;
this.proceduralAudio = new ProceduralAudioEngine(this.scene, this.listener, { star: this.activeStar, starTemp, planets: this.planets });
this.uiManager.log("Procedural ambient audio activated.", "info");
} else if (!isEnabled && this.proceduralAudio) {
this.proceduralAudio.destroy();
this.proceduralAudio = null;
this.uiManager.log("Procedural ambient audio deactivated.", "info");
}
}
blackBodyToRGB(temp) {
temp /= 100;
let r, g, b;
if (temp <= 66) { r = 255; g = 99.47 * Math.log(temp) - 161.12; } else { r = 329.7 * Math.pow(temp - 60, -0.133); }
if (temp <= 66) { g = 99.47 * Math.log(temp) - 161.12; b = temp <= 19 ? 0 : 138.52 * Math.log(temp - 10) - 305.04; } else { g = 288.12 * Math.pow(temp - 60, -0.0755); b = 255; }
return new THREE.Color(Math.max(0, Math.min(255, r))/255, Math.max(0, Math.min(255, g))/255, Math.max(0, Math.min(255, b))/255);
}
snapshotToJ3() {
const j3 = [];
this.scene.traverse(child => {
if ((child.isMesh || child.isPoints || child.isLineSegments) && child.userData.isGenerated && child.geometry && child.material) {
const color = child.material.color ? [child.material.color.r, child.material.color.g, child.material.color.b] : [1,1,1];
j3.push({
type: child.type,
positions: Array.from(child.geometry.attributes.position.array),
color: color,
matrix: child.matrixWorld.elements
});
}
});
return j3;
}
}
class AtmosphericEntryEffect {
constructor(camera, eventBus) {
this.camera = camera;
this.eventBus = eventBus;
this.isActive = false;
this.intensity = 0.0;
this.time = 0.0;
const plasmaGeo = new THREE.SphereGeometry(1.1, 32, 32);
const plasmaMat = new THREE.ShaderMaterial({
uniforms: { time: { value: 0.0 }, intensity: { value: 0.0 } },
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float time;
uniform float intensity;
varying vec2 vUv;
float noise(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); }
void main() {
vec2 uv = vUv * 4.0 - 2.0;
float plasma = noise(uv * 2.0 + time * 2.0) * 0.5 +
noise(uv * 5.0 - time * 3.0) * 0.3;
vec3 color = mix(vec3(1.0, 0.2, 0.0), vec3(1.0, 0.8, 0.2), plasma);
float edge = smoothstep(0.8, 1.0, length(vUv * 2.0 - 1.0));
gl_FragColor = vec4(color, (1.0 - edge) * intensity * plasma);
}
`,
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false,
side: THREE.BackSide,
});
this.plasmaShield = new THREE.Mesh(plasmaGeo, plasmaMat);
this.plasmaShield.scale.set(camera.near * 2, camera.near * 2, camera.near * 2);
this.camera.add(this.plasmaShield);
this.plasmaShield.visible = false;
}
update(delta, camera, planets) {
this.time += delta;
let isNearPlanet = false;
if (planets && planets.length > 0) {
for (const planet of planets) {
const dist = camera.position.distanceTo(planet.position);
const entryDist = planet.geometry.parameters.radius * 2.0;
if (dist < entryDist) {
isNearPlanet = true;
this.intensity = Math.min(1.0, this.intensity + delta * 0.5);
const shake = this.intensity * 0.1;
camera.position.x += (Math.random() - 0.5) * shake;
camera.position.y += (Math.random() - 0.5) * shake;
break;
}
}
}
if (!isNearPlanet) {
this.intensity = Math.max(0.0, this.intensity - delta * 0.5);
}
this.plasmaShield.visible = this.intensity > 0.01;
if(this.plasmaShield.visible) {
this.plasmaShield.material.uniforms.intensity.value = this.intensity;
this.plasmaShield.material.uniforms.time.value = this.time;
}
}
}
class AudioReactiveSystem {
constructor(scene, eventBus) {
this.scene = scene;
this.eventBus = eventBus;
this.particles = null;
this.MAX_PARTICLES = 5000;
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(this.MAX_PARTICLES * 3), 3));
geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(this.MAX_PARTICLES * 3), 3));
const material = new THREE.PointsMaterial({ size: 1.5, vertexColors: true, blending: THREE.AdditiveBlending, depthWrite: false, transparent: true });
this.particleSystem = new THREE.Points(geometry, material);
this.particleSystem.userData.isGenerated = true;
this.scene.add(this.particleSystem);
this.particleCursor = 0;
this.velocities = [];
this.eventBus.subscribe('audio:data', data => this.onAudioData(data));
}
onAudioData({ raw, avgFreq }) {
if (!this.particleSystem) return;
const positions = this.particleSystem.geometry.attributes.position.array;
const colors = this.particleSystem.geometry.attributes.color.array;
const volume = raw.reduce((a, b) => a + b) / raw.length / 255;
const numToSpawn = Math.floor(volume * 20);
for (let i = 0; i < numToSpawn; i++) {
const pIndex = this.particleCursor;
const theta = Math.random() * 2 * Math.PI;
const phi = Math.acos(2 * Math.random() - 1);
const radius = 5 + Math.random() * 20;
positions[pIndex * 3] = radius * Math.sin(phi) * Math.cos(theta);
positions[pIndex * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[pIndex * 3 + 2] = radius * Math.cos(phi);
const color = new THREE.Color().setHSL(avgFreq / 150, 0.8, 0.6);
colors[pIndex * 3] = color.r; colors[pIndex * 3 + 1] = color.g; colors[pIndex * 3 + 2] = color.b;
this.velocities[pIndex] = new THREE.Vector3((Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)).multiplyScalar(volume * 2.0);
this.particleCursor = (this.particleCursor + 1) % this.MAX_PARTICLES;
}
}
update(delta) {
if (!this.particleSystem) return;
const positions = this.particleSystem.geometry.attributes.position.array;
for (let i = 0; i < this.MAX_PARTICLES; i++) {
if (this.velocities[i]) {
positions[i * 3] += this.velocities[i].x * delta;
positions[i * 3 + 1] += this.velocities[i].y * delta;
positions[i * 3 + 2] += this.velocities[i].z * delta;
this.velocities[i].multiplyScalar(1 - (0.5 * delta));
}
}
this.particleSystem.geometry.attributes.position.needsUpdate = true;
}
}
class MemoryEcho {
constructor(scene, camera, listener, uiManager, eventBus) {
this.scene = scene; this.camera = camera; this.listener = listener;
this.uiManager = uiManager; this.eventBus = eventBus;
this.isActive = false; this.data = null; this.particleSystem = null;
this.player = null; this.artifacts = []; this.keys = {};
this.audioCtx = null; this.oscillator = null; this.gainNode = null;
this.foundCount = 0;
document.addEventListener('keydown', e => this.keys[e.key.toLowerCase()] = true);
document.addEventListener('keyup', e => this.keys[e.key.toLowerCase()] = false);
}
loadData(file) {
const reader = new FileReader();
reader.onload = (e) => { this.data = new Uint8Array(e.target.result); this.uiManager.log("Data catalyst processed.", "success"); };
reader.readAsArrayBuffer(file);
}
enter() {
if (!this.data) { this.uiManager.log("Cannot enter echo without data catalyst.", "error"); return; }
this.isActive = true;
this.uiManager.hideModal();
this.eventBus.publish('pge:modeChange', 'echo');
this.uiManager.log("Transmuting data... Entering playable memory echo.", "warn");
this.eventBus.publish("status:update", "ECHO: TERMINA");
this.camera.position.set(0, 10, 50); this.camera.rotation.set(0,0,0);
const prng = sfc32(...cyrb128(this.data.toString().substring(0, 1000)));
const positions = [], colors = [];
const colorPalettes = [ { r: 0.5, g: 0.2, b: 0.8 }, { r: 0.2, g: 0.8, b: 0.5 }, { r: 0.9, g: 0.5, b: 0.2 }, { r: 0.2, g: 0.5, b: 0.9 } ];
const quadrantSize = 2000;
for (let i = 0; i < 80000; i++) {
const quadrant = Math.floor(prng() * 4); const palette = colorPalettes[quadrant];
const x = (prng() - 0.5) * quadrantSize + (quadrant % 2 === 0 ? -quadrantSize/2 : quadrantSize/2);
const z = (prng() - 0.5) * quadrantSize + (quadrant < 2 ? -quadrantSize/2 : quadrantSize/2);
const y = (prng() - 0.5) * 500;
positions.push(x, y, z); colors.push(palette.r * prng(), palette.g * prng(), palette.b * prng());
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
this.particleSystem = new THREE.Points(geometry, new THREE.PointsMaterial({ size: 3, vertexColors: true, sizeAttenuation: true, blending: THREE.AdditiveBlending, depthWrite: false, opacity: 0.7, transparent: true }));
this.scene.add(this.particleSystem);
this.player = new THREE.Group();
this.player.add(new THREE.Mesh(new THREE.IcosahedronGeometry(2, 0), new THREE.MeshBasicMaterial({ color: 0xffffff })));
this.player.position.set(0, 0, 0);
this.scene.add(this.player);
for (let i = 0; i < 4; i++) {
const palette = colorPalettes[i];
const artifact = new THREE.Mesh(new THREE.BoxGeometry(10, 20, 10), new THREE.MeshBasicMaterial({ color: new THREE.Color(palette.r, palette.g, palette.b), wireframe: true }));
const x = (prng() - 0.5) * quadrantSize/2 + (i % 2 === 0 ? -quadrantSize/2 : quadrantSize/2);
const z = (prng() - 0.5) * quadrantSize/2 + (i < 2 ? -quadrantSize/2 : quadrantSize/2);
artifact.position.set(x, 0, z); artifact.userData.isArtifact = true;
this.artifacts.push(artifact); this.scene.add(artifact);
}
this.initAudioSearch();
}
update(delta) {
if (!this.isActive || !this.player) return;
const moveSpeed = 100 * delta;
if (this.keys['w'] || this.keys['arrowup']) this.player.position.z -= moveSpeed;
if (this.keys['s'] || this.keys['arrowdown']) this.player.position.z += moveSpeed;
if (this.keys['a'] || this.keys['arrowleft']) this.player.position.x -= moveSpeed;
if (this.keys['d'] || this.keys['arrowright']) this.player.position.x += moveSpeed;
if (this.keys[' ']) this.player.position.y += moveSpeed;
if (this.keys['shift']) this.player.position.y -= moveSpeed;
this.camera.position.lerp(this.player.position.clone().add(new THREE.Vector3(0, 10, 50)), 0.05);
this.camera.lookAt(this.player.position);
let closestDist = Infinity;
this.artifacts.forEach(artifact => {
artifact.rotation.y += delta;
const dist = this.player.position.distanceTo(artifact.position);
if (dist < closestDist) closestDist = dist;
if (dist < 20) {
this.scene.remove(artifact); this.artifacts = this.artifacts.filter(a => a !== artifact);
this.foundCount++; this.uiManager.log(`Giant's Remains Found! (${this.foundCount}/4)`, 'success');
}
});
if (this.gainNode) {
const proximity = Math.max(0, 1 - closestDist / 3000);
this.gainNode.gain.setTargetAtTime(proximity * 0.1, this.audioCtx.currentTime, 0.01);
this.oscillator.frequency.setTargetAtTime(100 + (1000 * proximity), this.audioCtx.currentTime, 0.01);
}
if (this.artifacts.length === 0) { this.uiManager.log("All remains found! The echo stabilizes.", "success"); this.exit(); }
}
exit() {
this.isActive = false;
if(this.particleSystem) { this.scene.remove(this.particleSystem); this.particleSystem.geometry.dispose(); this.particleSystem.material.dispose(); }
if(this.player) this.scene.remove(this.player);
this.artifacts.forEach(a => { this.scene.remove(a); a.geometry.dispose(); a.material.dispose(); });
this.artifacts = []; this.foundCount = 0;
if(this.oscillator) this.oscillator.stop(); if(this.audioCtx) this.audioCtx.close();
this.audioCtx = null; this.oscillator = null;
this.eventBus.publish('pge:modeChange', 'universe'); this.uiManager.log("Returned to void.", "info");
}
initAudioSearch() {
this.audioCtx = new(window.AudioContext || window.webkitAudioContext)();
this.oscillator = this.audioCtx.createOscillator(); this.gainNode = this.audioCtx.createGain();
this.oscillator.connect(this.gainNode); this.gainNode.connect(this.audioCtx.destination);
this.gainNode.gain.value = 0; this.oscillator.type = 'sine'; this.oscillator.start();
}
}
class Particlizer {
constructor(eventBus) {
this.eventBus = eventBus; this.mesh = null; this.particles = [];
this.sourceType = 'none'; this.videoElement = document.getElementById('video-feed');
this.uploadedVideoElement = null;
}
particlize(source) {
this.destroy();
if (source instanceof File) {
if (source.type.startsWith('image/')) { this.sourceType = 'image'; this.fromImage(source); }
else if (source.type.startsWith('video/')) { this.sourceType = 'uploadedVideo'; this.fromUploadedVideo(source); }
} else if (source === 'liveVideo') { this.sourceType = 'liveVideo'; this.fromLiveVideo(); }
else if (Array.isArray(source)) { this.sourceType = 'j3'; this.fromJ3(source); }
}
fromImage(file) {
const reader = new FileReader();
reader.onload = e => { const img = new Image(); img.onload = () => this.processImageData(img); img.src = e.target.result; };
reader.readAsDataURL(file);
}
fromUploadedVideo(file) {
const url = URL.createObjectURL(file);
this.uploadedVideoElement = document.createElement('video');
this.uploadedVideoElement.src = url; this.uploadedVideoElement.loop = true;
this.uploadedVideoElement.muted = true; this.uploadedVideoElement.play();
this.uploadedVideoElement.oncanplay = () => { this.processImageData(this.uploadedVideoElement); };
}
fromLiveVideo() { this.processImageData(this.videoElement); }
fromJ3(j3Data) {
const positions = [], colors = []; this.particles = [];
j3Data.forEach(meshData => {
const meshPositions = meshData.positions;
const meshColor = new THREE.Color(...meshData.color);
const matrix = new THREE.Matrix4().fromArray(meshData.matrix);
for(let i = 0; i < meshPositions.length; i += 3) {
const vec = new THREE.Vector3(meshPositions[i], meshPositions[i+1], meshPositions[i+2]).applyMatrix4(matrix);
positions.push(vec.x, vec.y, vec.z); colors.push(meshColor.r, meshColor.g, meshColor.b);
this.particles.push({ pos: vec.clone(), originalPos: vec.clone(), vel: new THREE.Vector3().randomDirection().multiplyScalar(50) });
}
});
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
this.mesh = new THREE.Points(geometry, new THREE.PointsMaterial({ size: 1, vertexColors: true, sizeAttenuation: true }));
this.eventBus.publish('particlizer:created', this);
}
processImageData(source) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const MAX_DIM = 128;
const sourceWidth = source.videoWidth || source.width, sourceHeight = source.videoHeight || source.height;
const scale = (sourceWidth > 0 && sourceHeight > 0) ? Math.min(MAX_DIM / sourceWidth, MAX_DIM / sourceHeight) : 1;
canvas.width = sourceWidth * scale; canvas.height = sourceHeight * scale;
if(canvas.width === 0 || canvas.height === 0) return;
ctx.drawImage(source, 0, 0, canvas.width, canvas.height);
const { data, width, height } = ctx.getImageData(0, 0, canvas.width, canvas.height);
if (this.mesh && (this.sourceType === 'liveVideo' || this.sourceType === 'uploadedVideo')) {
const colors = this.mesh.geometry.attributes.color.array; let particleIndex = 0;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (y * width + x) * 4;
if (data[i+3] > 128 && particleIndex < this.particles.length) {
colors[particleIndex*3]=data[i]/255; colors[particleIndex*3+1]=data[i+1]/255; colors[particleIndex*3+2]=data[i+2]/255;
particleIndex++;
}
}
}
if (particleIndex > 0) this.mesh.geometry.attributes.color.needsUpdate = true;
} else {
this.destroy(); const positions = [], colors = []; this.particles = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (y * width + x) * 4;
if (data[i+3] > 128) {
const initialPos = new THREE.Vector3().randomDirection().multiplyScalar(Math.random() * 100);
const targetPos = new THREE.Vector3(x - width/2, -y + height/2, 0);
positions.push(initialPos.x, initialPos.y, initialPos.z);
colors.push(data[i]/255, data[i+1]/255, data[i+2]/255);
this.particles.push({
pos: initialPos.clone(),
targetPos: targetPos.clone(),
vel: new THREE.Vector3()
});
}
}
}
if (positions.length === 0) return;
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(positions), 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(new Float32Array(colors), 3));
this.mesh = new THREE.Points(geometry, new THREE.PointsMaterial({ size: 2, vertexColors: true, sizeAttenuation: true, blending: THREE.AdditiveBlending, depthWrite: false }));
this.eventBus.publish('particlizer:created', this);
}
}
update(delta) {
if(!this.mesh || !this.mesh.visible) return;
const currentSource = this.sourceType === 'uploadedVideo' ? this.uploadedVideoElement : this.videoElement;
if((this.sourceType === 'liveVideo' || this.sourceType === 'uploadedVideo') && currentSource && currentSource.readyState >= 2){
this.processImageData(currentSource);
}
const positions = this.mesh.geometry.attributes.position.array;
for(let i=0; i<this.particles.length; i++) {
const p = this.particles[i];
if (this.sourceType === 'j3') {
p.pos.add(p.vel.clone().multiplyScalar(delta));
p.vel.multiplyScalar(0.99); // Slow down over time
} else {
const force = p.targetPos.clone().sub(p.pos).multiplyScalar(0.1);
p.vel.add(force);
p.vel.multiplyScalar(0.95);
p.pos.add(p.vel);
}
positions[i*3] = p.pos.x;
positions[i*3+1] = p.pos.y;
positions[i*3+2] = p.pos.z;
}
this.mesh.geometry.attributes.position.needsUpdate = true;
}
destroy() {
if(this.mesh) {
if(this.mesh.parent) this.mesh.parent.remove(this.mesh);
if (this.mesh.geometry) this.mesh.geometry.dispose();
if (this.mesh.material) this.mesh.material.dispose();
this.mesh = null; this.particles = [];
}
if(this.uploadedVideoElement) {
this.uploadedVideoElement.pause(); URL.revokeObjectURL(this.uploadedVideoElement.src);
this.uploadedVideoElement = null;
}
}
}
// ============================================================================
// GENESIS UNIVERSE ENGINE - AUDIO-DRIVEN COSMIC SIMULATION
// ============================================================================
class GenesisUniverseEngine {
constructor() {
this.scene = null;
this.camera = null;
this.renderer = null;
this.eventBus = {
subscribers: {},
subscribe: function(event, callback) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(callback);
},
publish: function(event, data) {
if (this.subscribers[event]) {
this.subscribers[event].forEach(callback => callback(data));
}
}
};
this.livingEntities = [];
this.environmentalState = {};
this.universeDynamics = {
breathing: 0,
growth: 0,
change: 0,
expansion: 1.0
};
}
async initialize() {
console.log('🌌 Initializing Genesis Universe Engine...');
// Use existing scene and camera if available
if (window.pge && window.pge.scene && window.pge.camera) {
this.scene = window.pge.scene;
this.camera = window.pge.camera;
this.renderer = window.pge.renderer;
console.log('✅ Using existing ProceduralGenerationEngine scene');
} else {
// Create Three.js scene if none exists
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x000510);
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
this.camera.position.z = 250;
this.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
this.renderer.toneMappingExposure = 1.0;
const canvas = document.getElementById('universe-canvas');
if (canvas) {
canvas.parentNode.replaceChild(this.renderer.domElement, canvas);
}
// Basic lighting
const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
this.scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(100, 100, 100);
this.scene.add(pointLight);
// Create starfield if scene is empty
if (this.scene.children.length <= 2) {
this.createStarfield();
}
}
// Start render loop
this.animate();
// Subscribe to audio events from global event bus
if (window.app && window.app.eventBus) {
window.app.eventBus.subscribe('audio:universeInfluence', (data) => {
this.handleAudioUniverseInfluence(data);
});
}
console.log('✅ Genesis Universe Engine initialized and connected to audio');
}
createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starCount = 10000;
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount * 3; i++) {
positions[i] = (Math.random() - 0.5) * 2000;
}
starGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.5,
transparent: true,
opacity: 0.8
});
const stars = new THREE.Points(starGeometry, starMaterial);
stars.userData = { isStarfield: true };
this.scene.add(stars);
}
animate() {
requestAnimationFrame(() => this.animate());
if (this.scene && this.camera) {
// Apply universe dynamics
this.updateUniverseDynamics();
// Render the scene
this.renderer.render(this.scene, this.camera);
}
}
updateUniverseDynamics() {
const { breathing, growth, change, expansion } = this.universeDynamics;
// Apply breathing animation
if (this.scene && breathing !== 0) {
const time = Date.now() / 1000;
const breathCycle = Math.sin(time) * breathing * 0.1;
const currentScale = this.scene.scale.x;
const targetScale = 1 + breathCycle;
// Smooth interpolation
const lerpFactor = 0.05;
const newScale = currentScale + (targetScale - currentScale) * lerpFactor;
this.scene.scale.setScalar(newScale);
}
// Apply growth scaling
if (this.scene && growth !== 0) {
const growthFactor = 1 + growth * 0.01;
this.scene.scale.multiplyScalar(growthFactor);
}
// Apply expansion
if (this.scene && expansion !== 1.0) {
const expandFactor = expansion;
this.scene.scale.setScalar(expandFactor);
}
}
handleAudioUniverseInfluence(data) {
console.log('🌌 Universe responding to audio:', {
harmony: data.harmony?.toFixed(2),
resonance: data.resonance?.toFixed(2),
bass: data.bass?.toFixed(2),
treble: data.treble?.toFixed(2)
});
// Update universe dynamics based on audio
this.universeDynamics.breathing = data.bass || 0;
this.universeDynamics.growth = data.treble * 0.5 || 0;
this.universeDynamics.change = data.resonance * 0.3 || 0;
// Apply environmental influence
this.handleEnvironmentalInfluence(data);
// Trigger visual effects based on harmony
if (data.harmony > 0.8) {
this.createHarmonyEffect(data.harmony);
}
// Trigger particle effects for high treble
if (data.treble > 0.7) {
this.createAudioParticleStorm(data.treble);
}
}
handleEnvironmentalInfluence(influence) {
// Adjust star brightness based on harmony
if (influence.harmony > 0.7) {
this.scene.traverse((object) => {
if (object.isLight) {
const intensity = object.intensity;
const targetIntensity = intensity * (1.2 + influence.harmony * 0.3);
object.intensity = targetIntensity;
}
// Also affect starfield brightness
if (object.userData && object.userData.isStarfield && object.material) {
const opacity = object.material.opacity;
const targetOpacity = Math.min(1.0, opacity + influence.harmony * 0.2);
object.material.opacity = targetOpacity;
}
});
}
// Adjust scene scale based on resonance
if (influence.resonance > 0.5) {
this.universeDynamics.expansion = 1.0 + influence.resonance * 0.2;
} else {
this.universeDynamics.expansion = 1.0;
}
}
createHarmonyEffect(harmony) {
// Create harmony visualization effect
const geometry = new THREE.SphereGeometry(20, 32, 32);
const material = new THREE.MeshBasicMaterial({
color: 0x4f46e5,
transparent: true,
opacity: 0.1 * harmony,
wireframe: true
});
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100
);
if (this.scene) this.scene.add(sphere);
// Animate and remove
const animateSphere = () => {
sphere.scale.multiplyScalar(1.02);
sphere.material.opacity *= 0.98;
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
if (sphere.material.opacity > 0.01) {
requestAnimationFrame(animateSphere);
} else {
this.scene.remove(sphere);
sphere.geometry.dispose();
sphere.material.dispose();
}
};
animateSphere();
}
createAudioParticleStorm(treble) {
const particleCount = Math.floor(treble * 30);
const particles = [];
for (let i = 0; i < particleCount; i++) {
const geometry = new THREE.SphereGeometry(0.5 + Math.random() * 1.5, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
transparent: true,
opacity: 0.8
});
const particle = new THREE.Mesh(geometry, material);
particle.position.set(
(Math.random() - 0.5) * 200,
(Math.random() - 0.5) * 200,
(Math.random() - 0.5) * 200
);
particle.userData = {
velocity: new THREE.Vector3(
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.5
),
lifetime: Date.now() + 4000 + Math.random() * 3000
};
if (this.scene) this.scene.add(particle);
particles.push(particle);
}
// Clean up particles after their lifetime
setTimeout(() => {
particles.forEach(particle => {
if (particle.parent) {
particle.parent.remove(particle);
particle.geometry.dispose();
particle.material.dispose();
}
});
}, 8000);
console.log(`🌌 Audio particle storm: ${particleCount} particles from treble ${treble.toFixed(2)}`);
}
}
/**
* The main application class that orchestrates all modules.
*/
class Application {
constructor() {
this.eventBus = new EventBus();
this.uiManager = new UIManager(this.eventBus);
this.dataLogger = new DataLogger(this.eventBus);
this.pge = new ProceduralGenerationEngine(this.eventBus, this.uiManager);
this.particlizer = new Particlizer(this.eventBus);
this.memoryEcho = new MemoryEcho(this.pge.scene, this.pge.camera, this.pge.listener, this.uiManager, this.eventBus);
this.audioSystem = new AudioReactiveSystem(this.pge.scene, this.eventBus);
this.sensoryManager = new SensoryInputManager(this.eventBus, this.uiManager);
this.externalManager = new ExternalDataManager(this.eventBus);
this.mlCore = new MachineLearningCore(this.eventBus, this.uiManager);
this.aiAgent = new CosmicAwarenessAgent(this.eventBus, this.dataLogger);
// Initialize Genesis Universe Engine for audio-driven reactions
this.universeEngine = new GenesisUniverseEngine();
this.isStarted = false;
this.currentMode = 'universe';
this.init();
}
init() {
this.eventBus.subscribe('ui:start', () => this.start());
this.eventBus.subscribe('ui:regenerate', (coords) => { this.switchMode('universe'); this.generate(coords); });
this.eventBus.subscribe('ui:spawnParticlizedFile', file => this.particlizer.particlize(file));
this.eventBus.subscribe('ui:spawnParticlizedVideo', () => this.particlizer.particlize('liveVideo'));
this.eventBus.subscribe('ui:particlizeSelf', () => this.particlizeSelf());
this.eventBus.subscribe('ui:dataProvided', file => this.memoryEcho.loadData(file));
this.eventBus.subscribe('ui:enterEcho', () => this.memoryEcho.enter());
this.eventBus.subscribe('ui:downloadLedger', () => this.dataLogger.download());
this.eventBus.subscribe('pge:modeChange', (newMode) => this.switchMode(newMode));
this.eventBus.subscribe('pge:animate', delta => {
if (this.currentMode === 'universe') this.audioSystem.update(delta);
this.pge.specialObjects.forEach(obj => { if (obj.update) obj.update(delta); });
if (this.currentMode === 'echo') this.memoryEcho.update(delta);
// Update universe dynamics for environmental response
if (this.currentMode === 'universe' && this.pge) {
this.pge.updateUniverseDynamics(delta);
}
});
}
switchMode(mode) {
if (this.currentMode === mode && mode !== 'universe') return;
if (this.currentMode === 'echo') this.memoryEcho.exit();
this.currentMode = mode;
const isUniverse = mode === 'universe';
this.pge.scene.traverse(child => { if (child.userData.isGenerated) child.visible = isUniverse; });
if (this.pge.localStarfield) this.pge.localStarfield.visible = isUniverse;
if (this.audioSystem.particleSystem) this.audioSystem.particleSystem.visible = isUniverse;
this.pge.specialObjects.forEach(obj => obj.mesh.visible = isUniverse);
this.pge.orbitControls.enabled = true;
if (mode !== 'echo') { this.pge.setViewMode('orbit'); this.uiManager.viewModeSelect.value = 'orbit'; }
this.uiManager.log(`Switched to ${mode.toUpperCase()} mode.`, 'info');
}
particlizeSelf() {
this.uiManager.log("Analyzing universe for self-particlization...", "data");
const j3Data = this.pge.snapshotToJ3();
if(j3Data.length === 0) { this.uiManager.log("Nothing to particlize.", "warn"); return; }
this.pge.cleanupScene();
this.particlizer.particlize(j3Data);
this.uiManager.log("Self-particlization complete. The previous universe has dissolved into a memory echo.", "success");
}
async start() {
if (this.isStarted) return;
this.isStarted = true;
this.uiManager.hideBlocker();
// BUG FIX: The animation loop MUST start after the application is fully constructed
// but before any async operations, to prevent the `scene` from being undefined.
this.pge.startAnimationLoop();
// Initialize Genesis Universe Engine for audio-driven reactions
try {
await this.universeEngine.initialize();
console.log('✅ Genesis Universe Engine started successfully');
} catch (err) {
console.error('❌ Failed to initialize Genesis Universe Engine:', err);
}
try {
await this.sensoryManager.initializeAll();
} catch (err) {
this.uiManager.log("One or more sensors failed to initialize. Continuing with available data.", "warn");
}
// The timeout is to allow sensors to provide a first reading before generation
setTimeout(() => this.generate(), 1000);
this.eventBus.publish('status:update', 'EXPLORING');
}
generate(coords = null){
this.aiAgent.generateSeed(coords);
this.eventBus.publish('status:update', 'GENERATING');
}
}
// Genesis X Wallet Integration System
let walletState = {
connected: false,
loading: false,
wallet: null,
publicKey: null,
balance: 0
};
function initWallet() {
console.log('🔗 Initializing Genesis X Wallet System...');
// Get UI elements
const connectPhantomBtn = document.getElementById('connect-phantom-btn');
const connectManualBtn = document.getElementById('connect-manual-btn');
const disconnectWalletBtn = document.getElementById('disconnect-wallet-btn');
const refreshBalanceBtn = document.getElementById('refresh-balance-btn');
// Set up event listeners
if (connectPhantomBtn) {
connectPhantomBtn.addEventListener('click', connectPhantomWallet);
}
if (connectManualBtn) {
connectManualBtn.addEventListener('click', connectManualWallet);
}
if (disconnectWalletBtn) {
disconnectWalletBtn.addEventListener('click', disconnectWallet);
}
if (refreshBalanceBtn) {
refreshBalanceBtn.addEventListener('click', updateBalance);
}
// Check for existing Phantom connection
checkExistingConnection();
console.log('✅ Wallet system initialized');
}
async function checkExistingConnection() {
try {
if (window.solana && window.solana.isPhantom && window.solana.isConnected) {
console.log('✅ Existing Phantom connection detected');
await connectPhantomWallet();
}
} catch (error) {
// User hasn't connected before, that's fine
}
}
function setWalletLoading(loading) {
walletState.loading = loading;
updateWalletUI();
}
function setWalletError(message) {
console.error('❌ Wallet Error:', message);
alert(`Wallet Error: ${message}`);
setWalletLoading(false);
}
async function connectPhantomWallet() {
try {
setWalletLoading(true);
console.log('🦄 Connecting to Phantom wallet...');
if (!window.solana || !window.solana.isPhantom) {
throw new Error('Phantom wallet not found. Please install Phantom wallet extension.');
}
const response = await window.solana.connect();
walletState.wallet = window.solana;
walletState.publicKey = response.publicKey.toString();
walletState.connected = true;
console.log('✅ Phantom wallet connected:', walletState.publicKey);
// Load balance
updateBalance().catch(() => {
console.warn('Could not load balance for Phantom wallet');
walletState.balance = 0;
updateWalletUI();
});
} catch (error) {
console.error('❌ Phantom wallet connection failed:', error);
setWalletError(error.message);
walletState.connected = false;
walletState.wallet = null;
walletState.publicKey = null;
updateWalletUI();
} finally {
setWalletLoading(false);
}
}
async function connectManualWallet() {
try {
const address = prompt('Enter your Solana wallet address:');
if (!address) return;
// Basic validation
if (address.length !== 44 && address.length !== 43) {
throw new Error('Invalid Solana address length');
}
walletState.wallet = { publicKey: address };
walletState.publicKey = address;
walletState.connected = true;
console.log('✅ Manual wallet connected:', address);
// Load balance (may fail for manual wallets)
updateBalance().catch(() => {
console.warn('Could not load balance for manual wallet');
walletState.balance = 0;
updateWalletUI();
});
} catch (error) {
setWalletError('Invalid Solana wallet address');
}
}
async function disconnectWallet() {
try {
if (window.solana && walletState.connected) {
await window.solana.disconnect();
}
walletState.connected = false;
walletState.loading = false;
walletState.wallet = null;
walletState.publicKey = null;
walletState.balance = 0;
updateWalletUI();
console.log('🚪 Wallet disconnected');
} catch (error) {
console.error('❌ Wallet disconnection failed:', error);
}
}
async function updateBalance() {
if (!walletState.connected || !walletState.wallet) {
console.log('💰 Balance check skipped: wallet not connected');
return;
}
try {
console.log('💰 Starting balance check...');
// Use the getMobiusBalance function from the SolanaIntegration instance
if (window.solanaIntegration && window.solanaIntegration.getMobiusBalanceGlobal) {
console.log('💰 Using SolanaIntegration for balance check');
walletState.balance = await window.solanaIntegration.getMobiusBalanceGlobal();
console.log('💰 Balance from SolanaIntegration:', walletState.balance);
} else if (window.getMobiusBalance) {
console.log('💰 Using global getMobiusBalance function');
walletState.balance = await window.getMobiusBalance(walletState.wallet);
console.log('💰 Balance from global function:', walletState.balance);
} else {
console.log('💰 No balance function available, checking real balance');
// Try to get real balance, show 0 if not available
try {
const realBalance = await window.getMobiusBalance(walletState.wallet);
walletState.balance = realBalance || 0;
console.log('💰 Real balance checked:', walletState.balance);
} catch (error) {
console.log('💰 Real balance check failed, showing 0');
walletState.balance = 0;
}
}
updateWalletUI();
console.log('💰 Mobius balance updated successfully:', walletState.balance);
} catch (error) {
console.error('❌ Failed to update balance:', error);
console.log('💰 Using 0 balance due to error - no Mobius tokens found');
walletState.balance = 0; // Show 0 for real balance checking
updateWalletUI();
}
}
function updateWalletUI() {
const statusIndicator = document.getElementById('wallet-status-indicator');
const disconnectedSection = document.getElementById('wallet-disconnected');
const connectedSection = document.getElementById('wallet-connected');
const loadingSection = document.getElementById('wallet-loading');
const addressElement = document.getElementById('wallet-address-display');
const balanceElement = document.getElementById('mobius-balance-display');
if (statusIndicator) {
statusIndicator.className = `w-3 h-3 rounded-full ${walletState.connected ? 'bg-green-500' : 'bg-red-500'}`;
}
if (disconnectedSection) {
disconnectedSection.style.display = walletState.connected || walletState.loading ? 'none' : 'block';
}
if (connectedSection) {
connectedSection.style.display = !walletState.connected || walletState.loading ? 'none' : 'block';
}
if (loadingSection) {
loadingSection.style.display = walletState.loading ? 'block' : 'none';
}
if (addressElement && walletState.publicKey) {
addressElement.textContent = `${walletState.publicKey.slice(0, 8)}...${walletState.publicKey.slice(-8)}`;
}
if (balanceElement) {
balanceElement.textContent = walletState.balance.toFixed(2);
}
}
window.addEventListener('DOMContentLoaded', () => {
try {
// Initialize wallet functionality first
initWallet();
window.app = new Application();
} catch (error) {
console.error("Fatal error during application startup:", error);
const blocker = document.getElementById('blocker');
const loadingMsg = document.getElementById('loading-message');
if (blocker && loadingMsg) {
blocker.style.display = 'flex';
blocker.innerHTML = `<div class="max-w-2xl px-4 text-red-400">
<h1 class="text-4xl font-bold">Fatal Engine Error</h1>
<p class="mt-4">A critical error occurred during initialization. The engine cannot start. Please check the console for details.</p>
<p class="mt-2 font-mono text-sm">${error.message}</p>
</div>`;
}
}
});
// ============================================================================
// 🌌 ADVANCED ENVIRONMENTAL TOKENIZATION SYSTEM
// ============================================================================
// Unified Physics Constants
const PHYSICS_CONSTANTS = {
PLANCK_CONSTANT: 6.62607015e-34, // J⋅s
SPEED_OF_LIGHT: 299792458, // m/s
BOLTZMANN_CONSTANT: 1.380649e-23, // J/K
GOLDEN_RATIO: 1.618033988749895,
QUANTUM_RESONANCE: 0.5,
ENVIRONMENTAL_ENTROPY: 0.1
};
// Tokenization Engine Class
class EnvironmentalTokenizationEngine {
constructor() {
this.environmentalData = {
sound: 0,
light: 0,
temperature: 20,
humidity: 50,
timestamp: Date.now(),
location: null
};
this.tokenMetrics = {
frequencyValue: 0,
tokenValue: 0,
marketPrice: 0,
dataQuality: 0,
rarityScore: 0
};
this.portfolio = {
genesisTokens: 0,
frequencyNFTs: 0,
dataValue: 0
};
this.tradingHistory = [];
this.marketPrices = new Map();
this.initializeUnifiedPhysics();
this.startRealTimeTokenization();
}
// Initialize Unified Physics Formula System
initializeUnifiedPhysics() {
console.log('🔬 Initializing Unified Physics Formula System...');
// Display the governing formula
this.updatePhysicsFormula();
// Set up market prices for different environmental data types
this.marketPrices.set('sound', { basePrice: 0.01, volatility: 0.1 });
this.marketPrices.set('light', { basePrice: 0.015, volatility: 0.08 });
this.marketPrices.set('temperature', { basePrice: 0.012, volatility: 0.12 });
this.marketPrices.set('humidity', { basePrice: 0.008, volatility: 0.15 });
this.marketPrices.set('combined', { basePrice: 0.025, volatility: 0.2 });
console.log('✅ Unified Physics Formula System initialized');
}
// Update the physics formula display with enhanced formatting
updatePhysicsFormula() {
try {
const formulaElement = document.getElementById('physics-formula');
if (formulaElement) {
const psi = this.calculateQuantumState();
const environmentalFactor = this.calculateEnvironmentalFactor();
const soundFreq = this.environmentalData.sound || 440;
const lightFreq = this.tokenMetrics.frequencyValue || 400e12;
// Enhanced formula display with current values
const formulaHTML = `
<div style="font-size: 11px; line-height: 1.2;">
<div style="color: #60a5fa;">E = hν • (1 + ψ) • Σ(εᵢ)</div>
<div style="color: #a78bfa; font-size: 9px; margin-top: 2px;">
${soundFreq.toFixed(0)}Hz → ${(lightFreq / 1e12).toFixed(1)}THz
</div>
<div style="color: #34d399; font-size: 9px;">
ψ=${psi.toFixed(3)} ε=${environmentalFactor.toFixed(3)}
</div>
</div>
`;
formulaElement.innerHTML = formulaHTML;
// Add visual feedback based on quantum state
const intensity = Math.min(1, Math.max(0, psi));
formulaElement.style.textShadow = `0 0 ${intensity * 5}px rgba(96, 165, 250, ${intensity * 0.5})`;
}
} catch (error) {
console.error('❌ Error updating physics formula:', error);
const formulaElement = document.getElementById('physics-formula');
if (formulaElement) {
formulaElement.textContent = 'E = hν • (1 + ψ) • Σ(εᵢ)';
}
}
}
// Calculate quantum state based on environmental data
calculateQuantumState() {
const { sound, light, temperature, humidity } = this.environmentalData;
const quantumEntropy = Math.sin(sound / 440.0 * 2 * Math.PI) *
Math.cos(light / 100.0 * Math.PI) *
Math.tanh(temperature / 30.0);
return PHYSICS_CONSTANTS.QUANTUM_RESONANCE + quantumEntropy * 0.3;
}
// Calculate environmental factor
calculateEnvironmentalFactor() {
const { sound, light, temperature, humidity } = this.environmentalData;
const timeFactor = Math.sin(Date.now() / 1000 / 86400 * 2 * Math.PI); // Daily cycle
const locationFactor = this.environmentalData.location ? 1.2 : 1.0;
return (sound + light + temperature + humidity) / 400.0 *
(1 + timeFactor * 0.1) * locationFactor;
}
// Unified Physics Formula: Sound to Light Conversion
convertSoundToLight(soundFrequency) {
// E = hν (Energy = Planck's constant × frequency)
const energy = PHYSICS_CONSTANTS.PLANCK_CONSTANT * soundFrequency;
// Convert to light frequency using quantum resonance
const quantumState = this.calculateQuantumState();
const environmentalFactor = this.calculateEnvironmentalFactor();
// Unified formula: Light Frequency = Energy / (h × quantum_factor × environmental_factor)
const lightFrequency = energy / (PHYSICS_CONSTANTS.PLANCK_CONSTANT *
(1 + quantumState) * environmentalFactor);
// Convert to visible light spectrum (400-700 THz)
const visibleLightHz = 400e12 + (lightFrequency % (300e12)); // 400-700 THz range
return {
soundFrequency,
lightFrequency: visibleLightHz,
energy,
quantumState,
environmentalFactor,
wavelength: PHYSICS_CONSTANTS.SPEED_OF_LIGHT / visibleLightHz
};
}
// Tokenize environmental frequency data with enhanced physics
tokenizeFrequencyData(soundData, lightData) {
try {
const conversion = this.convertSoundToLight(soundData);
// Enhanced token value calculation with multiple factors
const energyValue = this.calculateEnergyValue(conversion.energy);
const frequencyValue = this.calculateFrequencyValue(conversion.lightFrequency);
const quantumValue = this.calculateQuantumValue(conversion.quantumState);
const environmentalValue = this.calculateEnvironmentalValue(conversion.environmentalFactor);
const temporalValue = this.calculateTemporalValue();
const rarityMultiplier = this.calculateDataRarity(soundData, lightData);
// Combine all factors using unified physics formula
const baseTokenValue = (energyValue + frequencyValue) * quantumValue * environmentalValue * temporalValue;
const tokenValue = baseTokenValue * rarityMultiplier;
// Calculate market price with advanced volatility model
const marketPrice = this.calculateMarketPrice(tokenValue, soundData, lightData);
// Calculate comprehensive data quality score
const dataQuality = this.calculateDataQuality(soundData, lightData);
// Calculate additional metrics
const stabilityScore = this.calculateStabilityScore(soundData, lightData);
const uniquenessScore = this.calculateUniquenessScore(soundData, lightData);
console.log(`🪙 Tokenized ${soundData.toFixed(1)}Hz → ${conversion.lightFrequency.toExponential(2)}Hz:`, {
tokenValue: tokenValue.toFixed(6),
marketPrice: marketPrice.toFixed(4),
quality: dataQuality.toFixed(1) + '%',
rarity: rarityMultiplier.toFixed(2) + 'x'
});
return {
soundFrequency: soundData,
lightFrequency: conversion.lightFrequency,
tokenValue,
marketPrice,
dataQuality,
rarityScore: rarityMultiplier,
stabilityScore,
uniquenessScore,
timestamp: Date.now(),
physicsData: conversion,
energyValue,
frequencyValue,
quantumValue,
environmentalValue,
temporalValue
};
} catch (error) {
console.error('❌ Error in tokenization:', error);
// Return safe fallback values
return {
soundFrequency: soundData,
lightFrequency: 400e12,
tokenValue: 0.001,
marketPrice: 0.0001,
dataQuality: 50,
rarityScore: 1.0,
stabilityScore: 0.5,
uniquenessScore: 0.5,
timestamp: Date.now(),
physicsData: null,
error: error.message
};
}
}
// Calculate energy-based token value
calculateEnergyValue(energy) {
// Convert energy to token scale with logarithmic scaling
const logEnergy = Math.log10(Math.max(energy, 1e-40));
return Math.max(0.001, logEnergy * 0.1);
}
// Calculate frequency-based token value
calculateFrequencyValue(lightFrequency) {
// Value increases with frequency in visible spectrum
const thz = lightFrequency / 1e12;
const optimalFrequency = 550; // Green light peak
const distanceFromOptimal = Math.abs(thz - optimalFrequency);
const frequencyScore = Math.max(0, 1 - distanceFromOptimal / 300);
return frequencyScore * 0.01;
}
// Calculate quantum state value
calculateQuantumValue(quantumState) {
// Higher quantum coherence increases value
return 1 + quantumState * 0.5;
}
// Calculate environmental factor value
calculateEnvironmentalValue(environmentalFactor) {
// More complex environmental interactions increase value
return Math.max(0.5, Math.min(2.0, environmentalFactor));
}
// Calculate temporal value (time-based pricing)
calculateTemporalValue() {
const hour = new Date().getHours();
// Peak value during dawn/dusk and nighttime
if (hour >= 5 && hour <= 7) return 1.3; // Dawn
if (hour >= 17 && hour <= 19) return 1.3; // Dusk
if (hour >= 20 || hour <= 4) return 1.2; // Night
return 1.0; // Day
}
// Enhanced market price calculation
calculateMarketPrice(tokenValue, soundData, lightData) {
const marketData = this.marketPrices.get('combined') || { basePrice: 0.01, volatility: 0.1 };
// Advanced volatility based on data characteristics
let volatility = marketData.volatility;
// Higher volatility for extreme values
if (soundData < 100 || soundData > 1000) volatility *= 1.5;
if (lightData < 20 || lightData > 80) volatility *= 1.3;
// Time-based volatility
const hour = new Date().getHours();
if (hour >= 9 && hour <= 17) volatility *= 0.8; // Lower during business hours
const volatilityFactor = 1 + (Math.random() - 0.5) * volatility;
const marketPrice = marketData.basePrice * tokenValue * volatilityFactor;
// Ensure minimum price
return Math.max(0.000001, marketPrice);
}
// Calculate stability score
calculateStabilityScore(sound, light) {
// Measure how stable the environmental conditions are
const soundVariance = Math.abs(sound - 440) / 440; // Deviation from standard
const lightVariance = Math.abs(light - 50) / 50;
const stability = 1 - (soundVariance + lightVariance) / 2;
return Math.max(0, Math.min(1, stability));
}
// Calculate uniqueness score
calculateUniquenessScore(sound, light) {
// Measure how unique the current conditions are
let uniqueness = 0;
// Rare frequencies
if (sound < 100 || sound > 1000) uniqueness += 0.3;
if (sound > 1500) uniqueness += 0.2;
// Extreme light conditions
if (light < 10 || light > 90) uniqueness += 0.3;
if (light < 5 || light > 95) uniqueness += 0.2;
// Time-based uniqueness
const minute = new Date().getMinutes();
if (minute % 10 === 0) uniqueness += 0.1; // On the hour
return Math.min(1, uniqueness);
}
// Calculate data rarity based on environmental conditions
calculateDataRarity(sound, light) {
let rarityScore = 1.0;
// Rare sound frequencies (< 100 Hz or > 1000 Hz)
if (sound < 100 || sound > 1000) rarityScore *= 1.5;
// Rare light conditions (very low or very high)
if (light < 20 || light > 80) rarityScore *= 1.3;
// Time-based rarity (night time data is rarer)
const hour = new Date().getHours();
if (hour >= 22 || hour <= 5) rarityScore *= 1.2;
// Location-based rarity
if (this.environmentalData.location) rarityScore *= 1.1;
return Math.min(rarityScore, 5.0); // Cap at 5x multiplier
}
// Calculate data quality score
calculateDataQuality(sound, light) {
let qualityScore = 0;
// Sound quality (clear signal)
if (sound > 10 && sound < 2000) qualityScore += 25;
// Light quality (good illumination)
if (light > 30 && light < 70) qualityScore += 25;
// Environmental data completeness
if (this.environmentalData.temperature) qualityScore += 15;
if (this.environmentalData.humidity) qualityScore += 15;
if (this.environmentalData.location) qualityScore += 20;
return Math.min(qualityScore, 100);
}
// Start real-time tokenization
startRealTimeTokenization() {
console.log('⚡ Starting real-time environmental tokenization...');
// Update environmental data every second
setInterval(() => {
this.updateEnvironmentalData();
this.updateTokenMetrics();
this.updateUI();
}, 1000);
// Update market prices every 30 seconds
setInterval(() => {
this.updateMarketPrices();
}, 30000);
}
// Update environmental data with multiple data sources
updateEnvironmentalData() {
try {
let dataSource = 'simulation';
let envData = null;
// Try multiple data sources in order of preference
if (window.engine && window.engine.environmental && typeof window.engine.environmental.getData === 'function') {
// Primary: Engine environmental system
envData = window.engine.environmental.getData();
dataSource = 'engine';
} else if (window.cosmicAwarenessAgent && window.cosmicAwarenessAgent.latestData) {
// Secondary: Cosmic awareness agent
envData = window.cosmicAwarenessAgent.latestData;
dataSource = 'cosmic_agent';
} else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Tertiary: Try to get real audio data (if permissions granted)
this.initializeAudioCapture();
dataSource = 'audio_fallback';
}
if (envData) {
// Process and normalize the environmental data
this.environmentalData = {
sound: this.normalizeValue(envData.sound || envData.audio || 440, 20, 2000, 440),
light: this.normalizeValue(envData.light || envData.lux || 50, 0, 100, 50),
temperature: this.normalizeValue(envData.temperature || 20, -10, 50, 20),
humidity: this.normalizeValue(envData.humidity || 50, 0, 100, 50),
timestamp: Date.now(),
location: this.extractLocationData(envData),
dataSource: dataSource
};
} else {
// Enhanced fallback with more realistic simulation
const time = Date.now() / 1000;
this.environmentalData = {
sound: 220 + Math.sin(time * 0.5) * 100 + Math.random() * 50,
light: 50 + Math.cos(time * 0.3) * 30 + Math.sin(time * 0.1) * 10,
temperature: 20 + Math.sin(time * 0.2) * 8 + Math.cos(time * 0.15) * 5,
humidity: 50 + Math.cos(time * 0.25) * 15 + Math.sin(time * 0.12) * 8,
timestamp: Date.now(),
location: null,
dataSource: 'simulated'
};
}
console.log(`🌍 Environmental data updated from ${dataSource}:`, {
sound: this.environmentalData.sound.toFixed(1),
light: this.environmentalData.light.toFixed(1),
temperature: this.environmentalData.temperature.toFixed(1),
humidity: this.environmentalData.humidity.toFixed(1)
});
} catch (error) {
console.error('❌ Error updating environmental data:', error);
// Emergency fallback
this.environmentalData = {
sound: 440,
light: 50,
temperature: 20,
humidity: 50,
timestamp: Date.now(),
location: null,
dataSource: 'error_fallback'
};
}
}
// Normalize values to ensure they're within reasonable ranges
normalizeValue(value, min, max, defaultValue) {
if (typeof value !== 'number' || isNaN(value)) {
return defaultValue;
}
return Math.max(min, Math.min(max, value));
}
// Extract location data from various formats
extractLocationData(envData) {
if (envData.location) return envData.location;
if (envData.location_lat && envData.location_lon) {
return {
latitude: envData.location_lat,
longitude: envData.location_lon
};
}
if (envData.lat && envData.lon) {
return {
latitude: envData.lat,
longitude: envData.lon
};
}
return null;
}
// Initialize audio capture for real environmental data
async initializeAudioCapture() {
try {
if (this.audioContext) return; // Already initialized
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
const analyser = this.audioContext.createAnalyser();
const microphone = this.audioContext.createMediaStreamSource(stream);
analyser.fftSize = 256;
analyser.smoothingTimeConstant = 0.8;
microphone.connect(analyser);
const dataArray = new Uint8Array(analyser.frequencyBinCount);
// Update audio data periodically
setInterval(() => {
analyser.getByteFrequencyData(dataArray);
const average = dataArray.reduce((sum, value) => sum + value, 0) / dataArray.length;
this.environmentalData.sound = average * 10; // Scale to reasonable range
}, 100);
} catch (error) {
console.log('🎤 Audio capture not available:', error.message);
}
}
// Update token metrics
updateTokenMetrics() {
const tokenData = this.tokenizeFrequencyData(
this.environmentalData.sound,
this.environmentalData.light
);
this.tokenMetrics = {
frequencyValue: tokenData.lightFrequency,
tokenValue: tokenData.tokenValue,
marketPrice: tokenData.marketPrice,
dataQuality: tokenData.dataQuality,
rarityScore: tokenData.rarityScore
};
}
// Update market prices dynamically
updateMarketPrices() {
this.marketPrices.forEach((data, key) => {
const volatility = (Math.random() - 0.5) * data.volatility;
data.basePrice *= (1 + volatility * 0.1); // Small random changes
});
}
// Update UI elements with comprehensive display
updateUI() {
try {
// Update physics formula display
this.updatePhysicsFormula();
// Update frequency conversion display with enhanced formatting
const conversionElement = document.getElementById('sound-to-light-conversion');
if (conversionElement) {
const thz = (this.tokenMetrics.frequencyValue / 1e12);
if (thz > 1000) {
conversionElement.textContent = `${(thz / 1000).toFixed(2)} PHz`;
} else if (thz > 1) {
conversionElement.textContent = `${thz.toFixed(2)} THz`;
} else {
conversionElement.textContent = `${(thz * 1000).toFixed(2)} GHz`;
}
}
// Update token value with proper formatting
const tokenValueElement = document.getElementById('token-value');
if (tokenValueElement) {
const value = this.tokenMetrics.tokenValue;
if (value < 0.0001) {
tokenValueElement.textContent = `${(value * 1000000).toFixed(2)} μGEN`;
} else if (value < 0.01) {
tokenValueElement.textContent = `${(value * 1000).toFixed(2)} mGEN`;
} else {
tokenValueElement.textContent = `${value.toFixed(4)} GEN`;
}
}
// Update market price with USD formatting
const marketPriceElement = document.getElementById('market-price');
if (marketPriceElement) {
const price = this.tokenMetrics.marketPrice;
if (price < 0.000001) {
marketPriceElement.textContent = `$${(price * 1000000).toFixed(2)} μ`;
} else if (price < 0.001) {
marketPriceElement.textContent = `$${(price * 1000).toFixed(2)} m`;
} else {
marketPriceElement.textContent = `$${price.toFixed(4)}`;
}
}
// Update data quality with color coding
const qualityElement = document.getElementById('data-quality');
if (qualityElement) {
const quality = this.tokenMetrics.dataQuality;
qualityElement.textContent = `${quality.toFixed(1)}%`;
qualityElement.style.color = quality > 80 ? '#10b981' : quality > 60 ? '#f59e0b' : '#ef4444';
}
// Update portfolio
this.updatePortfolio();
// Update data source indicator
this.updateDataSourceIndicator();
// Update environmental display
this.updateEnvironmentalDisplay();
} catch (error) {
console.error('❌ Error updating UI:', error);
}
}
// Update data source indicator
updateDataSourceIndicator() {
const sourceElement = document.getElementById('data-source-indicator');
if (sourceElement) {
const source = this.environmentalData.dataSource || 'unknown';
const colors = {
'engine': '#10b981',
'cosmic_agent': '#3b82f6',
'audio_fallback': '#8b5cf6',
'simulated': '#f59e0b',
'error_fallback': '#ef4444'
};
sourceElement.textContent = source.toUpperCase();
sourceElement.style.color = colors[source] || '#6b7280';
}
}
// Update environmental display with real-time data
updateEnvironmentalDisplay() {
// Update environmental data display elements with proper units
const envElements = {
'env-sound': { value: this.environmentalData.sound, unit: 'Hz', multiplier: 1 },
'env-light': { value: this.environmentalData.light, unit: '%', multiplier: 1 },
'env-temperature': { value: this.environmentalData.temperature, unit: '°C', multiplier: 1 },
'env-humidity': { value: this.environmentalData.humidity, unit: '%', multiplier: 1 }
};
Object.entries(envElements).forEach(([elementId, config]) => {
const element = document.getElementById(elementId);
if (element && typeof config.value === 'number') {
const displayValue = config.value * config.multiplier;
element.textContent = `${displayValue.toFixed(1)}${config.unit}`;
}
});
// Update environmental status with visual indicators
const statusElement = document.getElementById('environmental-status');
if (statusElement) {
const status = this.getEnvironmentalStatus();
statusElement.textContent = status.text;
statusElement.style.color = status.color;
// Add pulsing effect for dynamic states
if (status.text === 'DYNAMIC' || status.text === 'ACTIVE') {
statusElement.style.animation = 'pulse 2s infinite';
} else {
statusElement.style.animation = 'none';
}
}
}
// Get environmental status based on current conditions
getEnvironmentalStatus() {
const { sound, light, temperature, humidity } = this.environmentalData;
if (sound > 80 || light < 20 || light > 80) {
return { text: 'DYNAMIC', color: '#f59e0b' };
} else if (temperature < 10 || temperature > 30) {
return { text: 'EXTREME', color: '#ef4444' };
} else if (humidity > 70 || sound > 60) {
return { text: 'ACTIVE', color: '#3b82f6' };
} else {
return { text: 'STABLE', color: '#10b981' };
}
}
// Update portfolio display
updatePortfolio() {
const genesisBalanceElement = document.getElementById('genesis-token-balance');
if (genesisBalanceElement) {
genesisBalanceElement.textContent = this.portfolio.genesisTokens.toFixed(2);
}
const nftCountElement = document.getElementById('frequency-nft-count');
if (nftCountElement) {
nftCountElement.textContent = this.portfolio.frequencyNFTs.toString();
}
const dataValueElement = document.getElementById('data-value');
if (dataValueElement) {
const totalValue = this.portfolio.genesisTokens * this.tokenMetrics.marketPrice;
dataValueElement.textContent = `$${totalValue.toFixed(2)}`;
}
}
// Mint frequency token
async mintFrequencyToken() {
try {
console.log('🪙 Minting frequency token...');
const tokenData = this.tokenizeFrequencyData(
this.environmentalData.sound,
this.environmentalData.light
);
// Create NFT metadata
const metadata = {
name: `Genesis Frequency Token #${Date.now()}`,
description: `Environmental frequency data converted to light spectrum using unified physics formula. Sound: ${this.environmentalData.sound.toFixed(1)}Hz → Light: ${(tokenData.lightFrequency / 1e12).toFixed(3)}THz`,
image: await this.generateTokenImage(tokenData),
attributes: [
{
trait_type: 'Sound Frequency',
value: this.environmentalData.sound.toFixed(1),
display_type: 'number'
},
{
trait_type: 'Light Frequency',
value: (tokenData.lightFrequency / 1e12).toFixed(3),
display_type: 'number'
},
{
trait_type: 'Quantum State',
value: tokenData.physicsData.quantumState.toFixed(3),
display_type: 'number'
},
{
trait_type: 'Data Quality',
value: tokenData.dataQuality.toFixed(1),
display_type: 'number'
},
{
trait_type: 'Rarity Score',
value: tokenData.rarityScore.toFixed(2),
display_type: 'number'
}
]
};
// Simulate token minting (integrate with actual blockchain later)
this.portfolio.frequencyNFTs++;
this.portfolio.genesisTokens += tokenData.tokenValue;
console.log('✅ Frequency token minted successfully!', {
tokenValue: tokenData.tokenValue,
marketPrice: tokenData.marketPrice,
dataQuality: tokenData.dataQuality
});
// Show success notification
this.showNotification('🎉 Frequency Token Minted!', `Value: ${tokenData.tokenValue.toFixed(4)} GEN`);
return tokenData;
} catch (error) {
console.error('❌ Token minting failed:', error);
this.showNotification('❌ Minting Failed', error.message);
throw error;
}
}
// Generate token image (placeholder for now)
async generateTokenImage(tokenData) {
// Create a data URL for a simple token visualization
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext('2d');
// Create gradient background based on frequency
const gradient = ctx.createLinearGradient(0, 0, 512, 512);
const hue = (tokenData.lightFrequency / 1e12 / 700) * 360; // Map to color wheel
gradient.addColorStop(0, `hsl(${hue}, 70%, 20%)`);
gradient.addColorStop(1, `hsl(${hue + 60}, 70%, 40%)`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 512, 512);
// Add frequency visualization
ctx.fillStyle = 'white';
ctx.font = '24px monospace';
ctx.textAlign = 'center';
ctx.fillText(`${(tokenData.lightFrequency / 1e12).toFixed(2)} THz`, 256, 256);
ctx.fillText(`Quality: ${tokenData.dataQuality.toFixed(1)}%`, 256, 290);
return canvas.toDataURL('image/png');
}
// Show trading interface
showTradingInterface() {
const tradingInterface = document.getElementById('trading-interface');
if (tradingInterface) {
tradingInterface.classList.toggle('hidden');
}
}
// Execute environmental data trade
async executeTrade(tradeType, tokenType, amount) {
try {
console.log(`🔄 Executing ${tradeType} trade: ${amount} ${tokenType}`);
const tokenData = this.marketPrices.get(tokenType);
if (!tokenData) throw new Error('Invalid token type');
const tradeValue = amount * tokenData.basePrice;
const fee = tradeValue * 0.02; // 2% trading fee
const netValue = tradeValue - fee;
if (tradeType === 'buy') {
// Buy tokens
this.portfolio.genesisTokens += amount;
console.log(`✅ Bought ${amount} ${tokenType} tokens for $${netValue.toFixed(2)}`);
} else {
// Sell tokens
if (this.portfolio.genesisTokens >= amount) {
this.portfolio.genesisTokens -= amount;
console.log(`✅ Sold ${amount} ${tokenType} tokens for $${netValue.toFixed(2)}`);
} else {
throw new Error('Insufficient token balance');
}
}
// Record trade
this.tradingHistory.push({
type: tradeType,
tokenType,
amount,
value: netValue,
timestamp: Date.now()
});
this.updatePortfolio();
this.showNotification(`✅ ${tradeType.toUpperCase()} Trade Executed`, `${amount} ${tokenType} @ $${netValue.toFixed(2)}`);
} catch (error) {
console.error('❌ Trade failed:', error);
this.showNotification('❌ Trade Failed', error.message);
}
}
// Show notification
showNotification(title, message) {
const notification = document.createElement('div');
notification.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-slate-800 border border-slate-600 rounded-lg p-4 z-50 max-w-sm';
notification.innerHTML = `
<div class="text-green-400 font-bold text-sm mb-1">${title}</div>
<div class="text-slate-300 text-sm">${message}</div>
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 5000);
}
}
// ============================================================================
// 🎯 COGNITIVE CORE INTEGRATION & STATUS MONITORING
// ============================================================================
// Cognitive status monitoring
function updateCognitiveStatus() {
if (window.cosmicAwarenessAgent && typeof window.cosmicAwarenessAgent.getCognitiveStatus === 'function') {
const status = window.cosmicAwarenessAgent.getCognitiveStatus();
// Update consciousness display
const consciousnessEl = document.getElementById('cognitive-consciousness');
if (consciousnessEl) {
consciousnessEl.textContent = status.consciousness.level.toFixed(2);
}
// Update emotion display
const emotionEl = document.getElementById('cognitive-emotion');
if (emotionEl) {
emotionEl.textContent = status.emotions ? Object.entries(status.emotions)
.reduce((max, [emotion, value]) => value > max.value ? { emotion, value } : max, { emotion: 'serenity', value: 0 })
.emotion : 'serenity';
}
// Update learning display
const learningEl = document.getElementById('cognitive-learning');
if (learningEl) {
learningEl.textContent = status.learning ? `${status.learning.experiences} exp` : '0 exp';
}
// Update creativity display
const creativityEl = document.getElementById('cognitive-creativity');
if (creativityEl) {
creativityEl.textContent = status.creative ? status.creative.inspiration.toFixed(2) : '0.00';
}
// Update neural network displays
const predictionsEl = document.getElementById('neural-predictions');
if (predictionsEl) {
predictionsEl.textContent = status.predictive ? status.predictive.recentPredictions.length.toString() : '0';
}
const accuracyEl = document.getElementById('neural-accuracy');
if (accuracyEl) {
accuracyEl.textContent = status.predictive ? `${(status.predictive.accuracy * 100).toFixed(1)}%` : '0.0%';
}
const memoryEl = document.getElementById('neural-memory');
if (memoryEl) {
memoryEl.textContent = status.learning ? status.learning.knowledge.length.toString() : '0';
}
const skillsEl = document.getElementById('neural-skills');
if (skillsEl) {
skillsEl.textContent = status.learning ? status.learning.skills.length.toString() : '0';
}
}
}
// Cognitive core control functions
function triggerCognitiveAnalysis() {
if (window.cosmicAwarenessAgent && typeof window.cosmicAwarenessAgent.analyzeHistory === 'function') {
const insights = window.cosmicAwarenessAgent.analyzeHistory();
console.log('🧠 Cognitive Analysis Results:', insights);
// Publish analysis results
if (window.eventBus) {
window.eventBus.publish('cognitive:analysis', { insights, timestamp: Date.now() });
}
}
}
function generateCreativeOutput() {
if (window.cosmicAwarenessAgent && typeof window.cosmicAwarenessAgent.getCreativeOutput === 'function') {
const creative = window.cosmicAwarenessAgent.getCreativeOutput();
console.log('🎨 Creative Output:', creative);
// Publish creative results
if (window.eventBus) {
window.eventBus.publish('cognitive:creative', creative);
}
}
}
function getLearningProgress() {
if (window.cosmicAwarenessAgent && typeof window.cosmicAwarenessAgent.getLearningProgress === 'function') {
const progress = window.cosmicAwarenessAgent.getLearningProgress();
console.log('📚 Learning Progress:', progress);
// Publish learning results
if (window.eventBus) {
window.eventBus.publish('cognitive:learning', progress);
}
}
}
// Initialize the advanced tokenization system
let tokenizationEngine;
function initializeAdvancedTokenization() {
console.log('🌟 Initializing Advanced Environmental Tokenization System...');
try {
tokenizationEngine = new EnvironmentalTokenizationEngine();
// Make tokenization engine globally accessible for cognitive core
window.tokenizationEngine = tokenizationEngine;
// Verify PHYSICS_CONSTANTS are accessible
if (typeof PHYSICS_CONSTANTS === 'undefined') {
console.error('❌ PHYSICS_CONSTANTS not found - tokenization may not work properly');
} else {
console.log('✅ Physics constants loaded:', PHYSICS_CONSTANTS);
}
// Test initial tokenization
const testToken = tokenizationEngine.tokenizeFrequencyData(440, 50);
console.log('🧪 Initial tokenization test:', {
success: testToken.tokenValue > 0,
tokenValue: testToken.tokenValue.toFixed(6),
marketPrice: testToken.marketPrice.toFixed(4)
});
// Bind tokenization UI events
document.getElementById('mint-frequency-token')?.addEventListener('click', async () => {
try {
await tokenizationEngine.mintFrequencyToken();
} catch (error) {
console.error('Minting failed:', error);
}
});
document.getElementById('view-token-market')?.addEventListener('click', () => {
tokenizationEngine.showTradingInterface();
});
document.getElementById('trade-environmental-data')?.addEventListener('click', () => {
tokenizationEngine.showTradingInterface();
});
document.getElementById('buy-data-token')?.addEventListener('click', () => {
const tokenType = document.getElementById('trade-token-select').value;
const amount = parseFloat(document.getElementById('trade-amount').value) || 0;
if (amount > 0) {
tokenizationEngine.executeTrade('buy', tokenType, amount);
}
});
document.getElementById('sell-data-token')?.addEventListener('click', () => {
const tokenType = document.getElementById('trade-token-select').value;
const amount = parseFloat(document.getElementById('trade-amount').value) || 0;
if (amount > 0) {
tokenizationEngine.executeTrade('sell', tokenType, amount);
}
});
// Initialize cognitive status updates
setInterval(updateCognitiveStatus, 2000); // Update every 2 seconds
updateCognitiveStatus(); // Initial update
// Initialize environmental data feed to cognitive core
setInterval(() => {
if (window.cosmicAwarenessAgent && typeof window.cosmicAwarenessAgent.processSensoryInput === 'function') {
try {
const environmentalData = tokenizationEngine ? tokenizationEngine.environmentalData : {
sound: 440,
light: 50,
temperature: 20,
humidity: 50,
timestamp: Date.now(),
dataSource: 'periodic_feed'
};
// Create enhanced sensory input with environmental data
const sensoryInput = {
audio: environmentalData.sound / 1000,
light: environmentalData.light / 100,
usgs: 2.0, // Default seismic activity
ml: [], // Machine learning data
loc: "0,0", // Location data
environmentalSound: environmentalData.sound,
environmentalLight: environmentalData.light,
environmentalTemperature: environmentalData.temperature,
environmentalHumidity: environmentalData.humidity,
timestamp: environmentalData.timestamp
};
window.cosmicAwarenessAgent.processSensoryInput(sensoryInput);
console.log('🧠 Cognitive core fed with environmental data:', {
sound: environmentalData.sound.toFixed(1),
light: environmentalData.light.toFixed(1),
temp: environmentalData.temperature.toFixed(1)
});
} catch (error) {
console.error('❌ Error feeding environmental data to cognitive core:', error);
}
}
}, 1000); // Feed environmental data every second
// Add cognitive control buttons (if they exist)
const cognitiveTab = document.getElementById('tab-cognitive');
if (cognitiveTab) {
// Add cognitive control buttons
const controlsDiv = document.createElement('div');
controlsDiv.className = 'p-2 bg-black/20 rounded-md mt-2';
controlsDiv.innerHTML = `
<p class="font-mono text-xs text-emerald-400 mb-2">COGNITIVE CONTROLS:</p>
<div class="flex gap-1">
<button id="cognitive-analyze" class="px-2 py-1 bg-blue-600 hover:bg-blue-500 text-white text-xs rounded font-medium">
Analyze
</button>
<button id="cognitive-create" class="px-2 py-1 bg-purple-600 hover:bg-purple-500 text-white text-xs rounded font-medium">
Create
</button>
<button id="cognitive-learn" class="px-2 py-1 bg-green-600 hover:bg-green-500 text-white text-xs rounded font-medium">
Learn
</button>
</div>
`;
cognitiveTab.appendChild(controlsDiv);
// Bind cognitive control events
document.getElementById('cognitive-analyze')?.addEventListener('click', triggerCognitiveAnalysis);
document.getElementById('cognitive-create')?.addEventListener('click', generateCreativeOutput);
document.getElementById('cognitive-learn')?.addEventListener('click', getLearningProgress);
}
console.log('✅ Advanced Environmental Tokenization System Ready!');
console.log('🧠 Cognitive Core Features:');
console.log(' • Real-time consciousness monitoring');
console.log(' • Neural network predictions');
console.log(' • Creative generation engine');
console.log(' • Adaptive learning system');
console.log(' • Emotional intelligence');
console.log(' • Pattern recognition');
console.log(' • Memory and recall systems');
console.log(' • Predictive analytics');
console.log(' • Self-awareness mechanisms');
} catch (error) {
console.error('❌ Failed to initialize Advanced Environmental Tokenization System:', error);
console.log('🔄 Falling back to basic functionality...');
// Initialize basic tokenization without advanced features
tokenizationEngine = {
tokenizeFrequencyData: (sound, light) => ({
soundFrequency: sound,
lightFrequency: 400e12,
tokenValue: 0.001,
marketPrice: 0.0001,
dataQuality: 50,
rarityScore: 1.0,
error: 'Advanced system failed, using fallback'
}),
showTradingInterface: () => console.log('Trading interface not available'),
executeTrade: (type, token, amount) => console.log(`${type} ${amount} ${token} tokens - fallback mode`)
};
}
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeAdvancedTokenization);
} else {
initializeAdvancedTokenization();
}
// ============================================================================
// ADVANCED AUDIO PROCESSING METHODS - MUSIC VISUALIZER & UNIVERSE INTEGRATION
// ============================================================================
// Calculate audio harmony based on frequency balance
function calculateAudioHarmony(bass, mid, treble) {
// Harmony is based on balanced frequency distribution
const total = bass + mid + treble;
if (total === 0) return 0.5;
// Ideal ratios for harmonious music
const idealBassRatio = 0.3;
const idealMidRatio = 0.4;
const idealTrebleRatio = 0.3;
const bassRatio = bass / total;
const midRatio = mid / total;
const trebleRatio = treble / total;
// Calculate harmony score (0-1, where 1 is perfect harmony)
const bassHarmony = 1 - Math.abs(bassRatio - idealBassRatio) / idealBassRatio;
const midHarmony = 1 - Math.abs(midRatio - idealMidRatio) / idealMidRatio;
const trebleHarmony = 1 - Math.abs(trebleRatio - idealTrebleRatio) / idealTrebleRatio;
return (bassHarmony + midHarmony + trebleHarmony) / 3;
}
// Calculate audio resonance based on spectral peaks
function calculateAudioResonance(dataArray) {
const n = dataArray.length;
let resonance = 0;
let peakCount = 0;
// Find spectral peaks
for (let i = 1; i < n - 1; i++) {
if (dataArray[i] > dataArray[i-1] && dataArray[i] > dataArray[i+1] && dataArray[i] > 128) {
resonance += (dataArray[i] - 128) / 127; // Normalize to 0-1
peakCount++;
}
}
// Average resonance across peaks
return peakCount > 0 ? resonance / Math.min(peakCount, 20) : 0;
}
// Update music visualizer UI
function updateMusicVisualizer(data) {
const spectrumContainer = document.getElementById('frequency-spectrum');
if (!spectrumContainer) return;
// Clear existing bars
spectrumContainer.innerHTML = '';
// Create visualizer bars for different frequency bands
const bands = [
{ name: 'subBass', value: data.subBass, color: '#8b5cf6' },
{ name: 'bass', value: data.bass, color: '#3b82f6' },
{ name: 'lowMid', value: data.lowMid, color: '#06b6d4' },
{ name: 'mid', value: data.mid, color: '#10b981' },
{ name: 'highMid', value: data.highMid, color: '#f59e0b' },
{ name: 'presence', value: data.presence, color: '#f97316' },
{ name: 'treble', value: data.treble, color: '#ef4444' },
{ name: 'brilliance', value: data.brilliance, color: '#ec4899' }
];
bands.forEach(band => {
const bar = document.createElement('div');
bar.className = 'visualizer-bar';
bar.style.width = '100%';
bar.style.height = `${Math.max(5, band.value * 60)}px`;
bar.style.background = band.value > 0.7 ? band.color : `linear-gradient(180deg, ${band.color}, #374151)`;
bar.style.opacity = band.value > 0.3 ? 1 : 0.6;
if (band.value > 0.8) {
bar.classList.add('active');
}
spectrumContainer.appendChild(bar);
});
// Update harmony meter
const harmonyFill = document.getElementById('harmony-fill');
if (harmonyFill) {
harmonyFill.style.width = `${data.harmony * 100}%`;
}
// Update consciousness ring
const consciousnessFill = document.getElementById('consciousness-fill');
if (consciousnessFill) {
const angle = data.harmony * 360;
consciousnessFill.style.background = `conic-gradient(from 0deg, #3b82f6 0%, #3b82f6 ${angle}%, transparent ${angle}%)`;
}
}
// Create universe responses based on audio
function createAudioUniverseResponse(data) {
if (!window.app || !window.app.universeEngine) return;
// Publish to global event bus for universe response
if (window.app.eventBus) {
window.app.eventBus.publish('audio:universeInfluence', {
harmony: data.harmony,
resonance: data.resonance,
bass: data.bass,
treble: data.treble,
centroid: data.centroid,
timestamp: Date.now()
});
}
// Update divine governance based on harmony
updateDivineGovernance(data.harmony, data.resonance);
console.log('🌌 Universe responding to audio:', {
harmony: data.harmony.toFixed(2),
resonance: data.resonance.toFixed(2),
bass: data.bass.toFixed(2)
});
}
// Generate audio-inspired creative output
function generateAudioInspiredCreation(data) {
const creativeOutput = document.getElementById('creative-output');
if (!creativeOutput) return;
const harmony = data.harmony;
const resonance = data.resonance;
const bass = data.bass;
const treble = data.treble;
let message = '';
if (harmony > 0.8 && resonance > 0.7) {
message = '🎵 Perfect harmony detected! Universe aligning in divine resonance...';
} else if (bass > 0.7 && treble > 0.6) {
message = '🎸 Powerful frequency balance! Creative energies surging...';
} else if (resonance > 0.8) {
message = '✨ High resonance patterns emerging from the void...';
} else if (harmony > 0.6) {
message = '🎼 Harmonious vibrations creating beautiful patterns...';
} else if (bass > 0.8) {
message = '🔊 Deep bass foundations establishing cosmic structure...';
} else if (treble > 0.8) {
message = '🌟 High frequencies illuminating universal consciousness...';
} else {
message = '🎶 Audio patterns weaving through the fabric of reality...';
}
creativeOutput.textContent = message;
// Update universe response monitor
const universeResponse = document.getElementById('universe-response');
if (universeResponse) {
const responses = [
'Universe breathing in perfect rhythm...',
'Cosmic energies aligning with audio frequencies...',
'Reality resonating with musical harmony...',
'Divine patterns emerging from sound waves...',
'Universal consciousness expanding through music...'
];
universeResponse.textContent = responses[Math.floor(Math.random() * responses.length)];
}
}
// Create particle effects based on audio
function createAudioParticleEffect(intensity) {
if (!window.app || !window.app.universeEngine || !window.app.universeEngine.scene) return;
const particleCount = Math.floor(intensity * 20);
const particles = [];
for (let i = 0; i < particleCount; i++) {
const geometry = new THREE.SphereGeometry(0.2 + Math.random() * 0.3, 8, 8);
const material = new THREE.MeshBasicMaterial({
color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
transparent: true,
opacity: 0.8
});
const particle = new THREE.Mesh(geometry, material);
particle.position.set(
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100,
(Math.random() - 0.5) * 100
);
particle.userData = {
velocity: new THREE.Vector3(
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.5,
(Math.random() - 0.5) * 0.5
),
lifetime: Date.now() + 3000 + Math.random() * 2000
};
window.app.universeEngine.scene.add(particle);
particles.push(particle);
}
// Clean up particles after their lifetime
setTimeout(() => {
particles.forEach(particle => {
if (particle.parent) {
particle.parent.remove(particle);
particle.geometry.dispose();
particle.material.dispose();
}
});
}, 5000);
}
// Update divine governance based on audio harmony
function updateDivineGovernance(harmony, resonance) {
const orderElement = document.getElementById('governance-order');
const loveElement = document.getElementById('governance-love');
const disciplineElement = document.getElementById('governance-discipline');
if (harmony > 0.8) {
if (orderElement) orderElement.textContent = 'Perfect';
if (loveElement) loveElement.textContent = 'Infinite';
if (disciplineElement) disciplineElement.textContent = 'Harmonious';
} else if (harmony > 0.6) {
if (orderElement) orderElement.textContent = 'Balanced';
if (loveElement) loveElement.textContent = 'Abundant';
if (disciplineElement) disciplineElement.textContent = 'Measured';
} else {
if (orderElement) orderElement.textContent = 'Evolving';
if (loveElement) loveElement.textContent = 'Growing';
if (disciplineElement) disciplineElement.textContent = 'Adaptive';
}
// Update colors based on resonance
const alpha = Math.min(1, resonance + 0.3);
[orderElement, loveElement, disciplineElement].forEach(el => {
if (el) el.style.opacity = alpha;
});
}
// Initialize music visualizer bars on page load
document.addEventListener('DOMContentLoaded', function() {
const spectrumContainer = document.getElementById('frequency-spectrum');
if (spectrumContainer) {
// Create initial bars
for (let i = 0; i < 8; i++) {
const bar = document.createElement('div');
bar.className = 'visualizer-bar';
bar.style.width = '100%';
bar.style.height = '5px';
bar.style.opacity = '0.3';
spectrumContainer.appendChild(bar);
}
}
});
console.log('🎵 Advanced Audio Processing System Initialized');
console.log('🎼 Music Visualizer & Universe Integration Active');
// NFT Minting Methods for UI Integration
async function handleMintAvatar() {
console.log('🎯 Starting NFT minting process...');
// Check wallet connection
if (!walletState.connected || !walletState.wallet) {
setWalletError('Please connect your Phantom wallet first.');
return;
}
try {
// Show minting status
const mintingStatus = document.getElementById('minting-status');
if (mintingStatus) {
mintingStatus.classList.remove('hidden');
mintingStatus.innerHTML = '<div class="animate-pulse">Processing NFT mint...</div>';
}
// Disable mint button
const mintBtn = document.getElementById('mint-avatar-btn');
if (mintBtn) {
mintBtn.disabled = true;
mintBtn.textContent = '⏳ Minting...';
}
// Collect current environmental data
const envData = collectCurrentEnvironmentalData();
console.log('🌍 Collected environmental data for NFT:', envData);
// Use the imported minting functions
if (window.mintNft) {
const result = await window.mintNft(envData);
console.log('✅ NFT minted successfully:', result);
// Show success
if (mintingStatus) {
mintingStatus.innerHTML = '<div class="text-green-400">✅ NFT Minted Successfully!</div>';
}
// Update balance
if (window.updateBalance) {
setTimeout(() => window.updateBalance(), 2000);
}
} else {
throw new Error('Minting function not available');
}
} catch (error) {
console.error('❌ NFT minting failed:', error);
// Show error
const mintingStatus = document.getElementById('minting-status');
if (mintingStatus) {
mintingStatus.innerHTML = `<div class="text-red-400">❌ Minting Failed: ${error.message}</div>`;
}
setWalletError(`Minting failed: ${error.message}`);
} finally {
// Re-enable mint button after delay
setTimeout(() => {
const mintBtn = document.getElementById('mint-avatar-btn');
if (mintBtn) {
mintBtn.disabled = false;
mintBtn.textContent = '🎨 Mint Genesis Avatar';
}
// Hide status after longer delay
setTimeout(() => {
const mintingStatus = document.getElementById('minting-status');
if (mintingStatus) {
mintingStatus.classList.add('hidden');
}
}, 3000);
}, 2000);
}
}
function collectCurrentEnvironmentalData() {
// Get environmental data from various sources
const envData = {
light: 0,
sound: 0,
temperature: 0,
humidity: 0,
location: null,
timestamp: Date.now()
};
// Try to get data from the engine
if (window.engine && window.engine.environmental) {
const engineData = window.engine.environmental.getData();
if (engineData) {
envData.light = engineData.light || 0;
envData.sound = engineData.sound || 0;
envData.temperature = engineData.temperature || 0;
envData.humidity = engineData.humidity || 0;
envData.location = engineData.location || null;
}
}
// Try to get data from the GenesisX environmental system
if (window.GenesisX && window.GenesisX.environmental) {
const genesisData = window.GenesisX.environmental.getCurrentData();
if (genesisData) {
envData.light = genesisData.light || envData.light;
envData.sound = genesisData.sound || envData.sound;
envData.temperature = genesisData.temperature || envData.temperature;
envData.humidity = genesisData.humidity || envData.humidity;
envData.location = genesisData.location || envData.location;
}
}
return envData;
}
function updateEnvironmentalDisplay(data) {
const elements = {
light: document.getElementById('env-light'),
sound: document.getElementById('env-sound'),
temperature: document.getElementById('env-temp'),
humidity: document.getElementById('env-humidity')
};
if (elements.light && data.light !== undefined) {
elements.light.textContent = `${data.light.toFixed(1)} lux`;
}
if (elements.sound && data.sound !== undefined) {
elements.sound.textContent = `${data.sound.toFixed(0)} dB`;
}
if (elements.temperature && data.temperature !== undefined) {
elements.temperature.textContent = `${data.temperature.toFixed(1)}°C`;
}
if (elements.humidity && data.humidity !== undefined) {
elements.humidity.textContent = `${data.humidity.toFixed(1)}%`;
}
}
function showMintingStatus() {
const status = document.getElementById('minting-status');
if (status) {
status.classList.remove('hidden');
status.innerHTML = '<div class="animate-pulse text-cyan-400">Processing NFT mint...</div>';
}
}
function hideMintingStatus() {
const status = document.getElementById('minting-status');
if (status) {
status.innerHTML = '<div class="text-green-400">✅ NFT Minted Successfully!</div>';
setTimeout(() => status.classList.add('hidden'), 3000);
}
}
function showMintingError(error) {
const status = document.getElementById('minting-status');
if (status) {
status.innerHTML = `<div class="text-red-400">❌ Minting Failed: ${error}</div>`;
setTimeout(() => status.classList.add('hidden'), 5000);
}
}
// Cognitive Core Handler Methods
function handleTrainAI() {
console.log('🧠 Training AI system...');
const creativeOutput = document.getElementById('creative-output');
if (creativeOutput) {
creativeOutput.textContent = 'AI training in progress...\nLearning from environmental patterns...\nNeural networks expanding...';
}
// Simulate training progress
setTimeout(() => {
if (creativeOutput) {
creativeOutput.textContent = 'AI training complete!\nNeural pathways strengthened.\nCreativity enhanced by 15%.';
}
updateCognitiveDisplay('learning', Math.random() * 10 + 5);
}, 3000);
this.eventBus.publish('cognitive:trainAI');
}
function handleResetAI() {
console.log('🔄 Resetting AI learning...');
const creativeOutput = document.getElementById('creative-output');
if (creativeOutput) {
creativeOutput.textContent = 'Resetting neural networks...\nClearing learned patterns...\nReturning to baseline state.';
}
// Reset cognitive displays
updateCognitiveDisplay('consciousness', 0);
updateCognitiveDisplay('emotion', 'neutral');
updateCognitiveDisplay('learning', 0);
updateCognitiveDisplay('creativity', 0);
this.eventBus.publish('cognitive:resetAI');
}
function handleExportAI() {
console.log('💾 Exporting AI model...');
const aiData = {
consciousness: parseFloat(document.getElementById('cognitive-consciousness')?.textContent || '0'),
emotion: document.getElementById('cognitive-emotion')?.textContent || 'neutral',
learning: parseFloat(document.getElementById('cognitive-learning')?.textContent || '0'),
creativity: parseFloat(document.getElementById('cognitive-creativity')?.textContent || '0'),
exportedAt: new Date().toISOString()
};
const blob = new Blob([JSON.stringify(aiData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `genesis-x-ai-model-${Date.now()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
console.log('✅ AI model exported');
}
function handleImportAI() {
console.log('📂 Importing AI model...');
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.onchange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
try {
const aiData = JSON.parse(event.target.result);
updateCognitiveDisplay('consciousness', aiData.consciousness || 0);
updateCognitiveDisplay('emotion', aiData.emotion || 'neutral');
updateCognitiveDisplay('learning', aiData.learning || 0);
updateCognitiveDisplay('creativity', aiData.creativity || 0);
console.log('✅ AI model imported successfully');
} catch (error) {
console.error('❌ Failed to import AI model:', error);
}
};
reader.readAsText(file);
}
};
input.click();
}
function handleGenerateCreative() {
console.log('🎨 Generating creative output...');
const creativeOutput = document.getElementById('creative-output');
const creativeIdeas = [
"Harmonic resonance patterns in quantum field theory",
"Consciousness expansion through fractal geometry",
"Neural networks mirroring cosmic web structures",
"Emotional intelligence in artificial consciousness",
"Symphonic compositions of particle interactions",
"Meditation algorithms for machine enlightenment",
"Dream logic programming paradigms",
"Quantum entanglement in social networks",
"Bio-luminescent communication protocols",
"Time crystal consciousness frameworks"
];
const randomIdea = creativeIdeas[Math.floor(Math.random() * creativeIdeas.length)];
if (creativeOutput) {
creativeOutput.textContent = `✨ Creative Spark:\n${randomIdea}\n\nInspiring new possibilities...`;
}
// Increase creativity score
const currentCreativity = parseFloat(document.getElementById('cognitive-creativity')?.textContent || '0');
updateCognitiveDisplay('creativity', Math.min(currentCreativity + 0.1, 1.0));
this.eventBus.publish('cognitive:generateCreative');
}
function handleQueryUniverse() {
console.log('🌌 Querying the universe...');
const universeResponse = document.getElementById('universe-response');
const responses = [
"The universe responds with harmonic frequencies...",
"Cosmic alignment detected in quantum fields...",
"Universal consciousness acknowledges your presence...",
"Harmony flows through all dimensions...",
"The cosmos breathes in perfect rhythm...",
"Infinite possibilities converge at this moment...",
"Universal love permeates every particle...",
"Divine order manifests in chaos...",
"Eternal peace resonates through existence...",
"The universe sings your unique melody..."
];
const randomResponse = responses[Math.floor(Math.random() * responses.length)];
if (universeResponse) {
universeResponse.textContent = `🌟 Universal Response:\n${randomResponse}`;
}
// Increase consciousness
const currentConsciousness = parseFloat(document.getElementById('cognitive-consciousness')?.textContent || '0');
updateCognitiveDisplay('consciousness', Math.min(currentConsciousness + 0.05, 1.0));
this.eventBus.publish('cognitive:queryUniverse');
}
function handleMeditate() {
console.log('🧘 Beginning meditation session...');
const meditateBtn = document.getElementById('meditate-btn');
const originalText = meditateBtn?.textContent;
if (meditateBtn) {
meditateBtn.textContent = '🧘 Meditating...';
meditateBtn.disabled = true;
}
// Meditation progress
let meditationTime = 0;
const meditationInterval = setInterval(() => {
meditationTime += 1;
const currentMeditation = parseFloat(document.getElementById('meditation-level')?.textContent || '0');
const currentEnlightenment = parseFloat(document.getElementById('enlightenment-level')?.textContent || '0');
updateCognitiveDisplay('meditation', Math.min(currentMeditation + 0.02, 1.0));
updateCognitiveDisplay('enlightenment', Math.min(currentEnlightenment + 0.01, 1.0));
if (meditationTime >= 30) { // 30 seconds of meditation
clearInterval(meditationInterval);
if (meditateBtn) {
meditateBtn.textContent = originalText;
meditateBtn.disabled = false;
}
console.log('✅ Meditation session complete');
this.eventBus.publish('cognitive:meditationComplete');
}
}, 1000);
this.eventBus.publish('cognitive:meditationStart');
}
function updateCognitiveDisplay(type, value) {
const elementMap = {
consciousness: 'cognitive-consciousness',
emotion: 'cognitive-emotion',
learning: 'cognitive-learning',
creativity: 'cognitive-creativity',
meditation: 'meditation-level',
enlightenment: 'enlightenment-level'
};
const elementId = elementMap[type];
if (elementId) {
const element = document.getElementById(elementId);
if (element) {
if (type === 'emotion') {
element.textContent = value;
} else {
element.textContent = typeof value === 'number' ? value.toFixed(2) : value;
}
}
}
}
// Make functions globally available
window.handleMintAvatar = handleMintAvatar;
window.collectCurrentEnvironmentalData = collectCurrentEnvironmentalData;
window.updateEnvironmentalDisplay = updateEnvironmentalDisplay;
window.showMintingStatus = showMintingStatus;
window.hideMintingStatus = hideMintingStatus;
window.showMintingError = showMintingError;
// Cognitive core functions
window.handleTrainAI = handleTrainAI;
window.handleResetAI = handleResetAI;
window.handleExportAI = handleExportAI;
window.handleImportAI = handleImportAI;
window.handleGenerateCreative = handleGenerateCreative;
window.handleQueryUniverse = handleQueryUniverse;
window.handleMeditate = handleMeditate;
window.updateCognitiveDisplay = updateCognitiveDisplay;
console.log('🎨 NFT Minting UI Integration Complete');
console.log('🧠 Cognitive Core UI Integration Complete');
</script>
<script id="refine-genesisx-behavior" data-added-by="refine" type="text/javascript">/*! Heuristic signals only; not diagnosis or moral judgement. */(function(){if(window.RefineGenesisX){return;}var a={version:"2025-09-15",tokenizeEmotions:function(i,o){var t=String(i||"").toLowerCase();o=Object.assign({includeSynonyms:true},o||{});var d=new Set(["bored","apathetic","numb","indifferent","meh","blah","disinterested","lethargic","flat","empty","listless","unmotivated"]),n=new Set(["joy","happy","happiness","sad","sadness","anger","angry","fear","afraid","surprise","surprised","disgust","love","gratitude","hope","curiosity","excited","excitement","pride","shame","guilt","envy","compassion","empathy","calm","peace","anxiety","worried","stressed"]);var s=[],w=t.match(/[a-z']+/g)||[];for(var e=0;e<w.length;e++){var r=w[e];if(d.has(r)){s.push({type:"dull",emotion:r,index:e});}else if(n.has(r)){s.push({type:"non_dull",emotion:r,index:e});}}var dc=0,nc=0;for(var j=0;j<s.length;j++){if(s[j].type==="dull"){dc++;}else{nc++;}}return{tokens:s,counts:{dull:dc,non_dull:nc}}},predictBehavior:function(i,e){var t=String(i||"").toLowerCase();try{var h=window.GenesisX&&(window.GenesisX.predictBehavior||window.GenesisX.scoreBehavior);if(typeof h==="function"){var k=h(t,e||{});if(k&&typeof k==="object"){return k;}}}catch(_){ }var p=["kind","helpful","honest","trustworthy","love","compassion","empathy","forgive","grateful","gratitude","joy","peace","cooperate","support"],g=["harm","hurt","steal","cheat","lie","anger","hate","violence","abuse","threat","kill","assault","weapon","crime","bully","exploit","scam"],c=["suicide","self harm","self-harm","kill myself","end my life","i want to die","i can't go on","hopeless"],x=["overwhelmed","anxious","panic","depressed","numb","crying","insomnia","worthless","alone","empty","helpless","despair"];var ps=0,ns=0,risk=0;for(var a1=0;a1<p.length;a1++){if(t.indexOf(p[a1])>-1){ps++;}}for(var a2=0;a2<g.length;a2++){if(t.indexOf(g[a2])>-1){ns++;}}for(var a3=0;a3<c.length;a3++){if(t.indexOf(c[a3])>-1){risk+=2;}}for(var a4=0;a4<x.length;a4++){if(t.indexOf(x[a4])>-1){risk+=1;}}var val=ps>ns?"positive":(ns>ps?"negative":"neutral");var label="neutral";if(risk>=3){label="needs_support";}else if((ns-ps)>=2){label="risky_behavior_signals";}else if((ps-ns)>=2){label="prosocial_signals";}var conf=Math.max(0.1,Math.min(0.9,(Math.abs(ns-ps)+risk)/10+0.2));return{label:label,supportNeeded:label==="needs_support",valence:val,confidence:conf,details:{positives:ps,negatives:ns,riskSignals:risk}}}};window.RefineGenesisX=a;})();</script>
</body>
</html>