import React, { useRef, useEffect, useState, useCallback } from 'react' import { AudioEngine } from '../engine/AudioEngine' import { ParticleSystemParams, ParticleSphere, DEFAULT_FREQUENCY_RANGES, DEFAULT_SPHERE_PARAMS, FogParams } from '../types/visualization' import { NoiseGenerator, BeatManager, generateNewNoiseScale } from '../utils/noise' import configLoader from '../utils/configLoader' interface WorldTreeVisualizerProps { audioEngine: AudioEngine | null } // ENTRONAUT INTEGRATION: Symbolic Emergence Field Analysis interface EntronautState { sefaScore: Float32Array emergenceField: Float32Array adaptiveParams: { damping: Float32Array diffusion: Float32Array coupling: Float32Array } informationMetrics: { complexity: number emergence: number coherence: number } } // Advanced 3D Particle System Visualizer - Enhanced with Entronaut SEFA export const WorldTreeVisualizer: React.FC = ({ audioEngine }) => { const canvasRef = useRef(null) const animationRef = useRef() const lastTimeRef = useRef(0) // Three.js core objects const sceneRef = useRef() const rendererRef = useRef() const cameraRef = useRef() const controlsRef = useRef() // Advanced visualization state const spheresRef = useRef([]) const noiseGeneratorRef = useRef() const beatManagerRef = useRef() const tendrilSystemRef = useRef() const dysonSphereRef = useRef() // ENTRONAUT: Symbolic emergence tracking const entronautStateRef = useRef() // State for UI controls const [isVisualizationReady, setIsVisualizationReady] = useState(false) const [activeSpheresCount, setActiveSpheresCount] = useState(5) // All spheres active by default const [cymateGeometry, setCymateGeometry] = useState(true) const [entronautEnabled, setEntronautEnabled] = useState(true) const [adaptiveCoupling, setAdaptiveCoupling] = useState(true) const [performanceMode, setPerformanceMode] = useState(false) const [controlsCollapsed, setControlsCollapsed] = useState(true) const [cameraControlsEnabled, setCameraControlsEnabled] = useState(true) const [autoRotate, setAutoRotate] = useState(false) const [aboutCollapsed, setAboutCollapsed] = useState(true) const [tendrilsEnabled, setTendrilsEnabled] = useState(true) const [tendrilDensity, setTendrilDensity] = useState(0.3) const [dysonSphereEnabled, setDysonSphereEnabled] = useState(true) const [vineGrowthRate, setVineGrowthRate] = useState(0.02) const [vineComplexity, setVineComplexity] = useState(24) const [showStartupInfo, setShowStartupInfo] = useState(true) const [fogParams, setFogParams] = useState({ enabled: true, color: '#000000', near: 2.7, far: 3.7 }) // Store state (currently minimal, expanded as needed) // const { playback } = useNexusStore() // Simplified performance monitoring - no complex optimizer const [performanceStats, setPerformanceStats] = useState({ fps: 60, particleCount: 0, lastFpsUpdate: 0, frameCount: 0 }) // Hidden Auto-Refresh System const autoRefreshRef = useRef({ lastRefresh: 0, refreshInterval: 120000, // 2 minutes base interval performanceDegradationCount: 0, particleHealthChecks: 0, emergencyResetCount: 0, isRefreshing: false }) // Monitor particle system health const checkParticleHealth = useCallback(() => { if (!spheresRef.current) return true let healthyParticles = 0 let totalParticles = 0 spheresRef.current.forEach(sphere => { if (!sphere.params.enabled) return const { positions, velocities } = sphere const particleCount = sphere.params.particleCount totalParticles += particleCount for (let i = 0; i < particleCount; i++) { const i3 = i * 3 const x = positions[i3] const y = positions[i3 + 1] const z = positions[i3 + 2] const vx = velocities[i3] const vy = velocities[i3 + 1] const vz = velocities[i3 + 2] // Check if particle is healthy (finite values, reasonable position/velocity) if (isFinite(x) && isFinite(y) && isFinite(z) && isFinite(vx) && isFinite(vy) && isFinite(vz)) { const dist = Math.sqrt(x*x + y*y + z*z) const vel = Math.sqrt(vx*vx + vy*vy + vz*vz) if (dist < 10 && vel < 1) { // Reasonable bounds healthyParticles++ } } } }) const healthRatio = totalParticles > 0 ? healthyParticles / totalParticles : 1 return healthRatio > 0.85 // 85% healthy particles threshold }, []) // Perform hidden refresh of particle systems const performHiddenRefresh = useCallback(async (force = false) => { if (autoRefreshRef.current.isRefreshing && !force) return autoRefreshRef.current.isRefreshing = true console.log('๐Ÿ”„ Performing hidden system refresh...') try { // Gradual refresh to avoid frame drops for (let sphereIndex = 0; sphereIndex < spheresRef.current.length; sphereIndex++) { const sphere = spheresRef.current[sphereIndex] if (!sphere.params.enabled) continue // Refresh 20% of particles at a time over 5 frames const particleCount = sphere.params.particleCount const batchSize = Math.floor(particleCount * 0.2) for (let batch = 0; batch < 5; batch++) { const startIdx = batch * batchSize const endIdx = Math.min(startIdx + batchSize, particleCount) // Reset particles in this batch for (let i = startIdx; i < endIdx; i++) { const i3 = i * 3 const radius = sphere.params.sphereRadius * sphere.params.innerSphereRadius const theta = Math.random() * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const r = Math.cbrt(Math.random()) * radius sphere.positions[i3] = r * Math.sin(phi) * Math.cos(theta) sphere.positions[i3 + 1] = r * Math.sin(phi) * Math.sin(theta) sphere.positions[i3 + 2] = r * Math.cos(phi) sphere.velocities[i3] = 0 sphere.velocities[i3 + 1] = 0 sphere.velocities[i3 + 2] = 0 sphere.lifetimes[i] = Math.random() * sphere.params.particleLifetime sphere.beatEffects[i] = 0 } // Wait one frame between batches to maintain smooth animation if (batch < 4) { await new Promise(resolve => requestAnimationFrame(() => resolve(undefined))) } } // Note: Geometry updates are handled by the main animation loop } // Reset counters autoRefreshRef.current.performanceDegradationCount = 0 autoRefreshRef.current.emergencyResetCount = 0 autoRefreshRef.current.lastRefresh = Date.now() console.log('โœ… Hidden refresh completed successfully') } catch (error) { console.warn('โš ๏ธ Hidden refresh error:', error) } finally { autoRefreshRef.current.isRefreshing = false } }, []) // ENTRONAUT: Initialize emergence field analysis - SIMPLIFIED for performance const initializeEntronaut = useCallback(() => { // Simplified - basic structure for UI display only console.log('๐Ÿง  Entronaut SEFA system simplified for performance') entronautStateRef.current = { sefaScore: new Float32Array(0), emergenceField: new Float32Array(0), adaptiveParams: { damping: new Float32Array(0), diffusion: new Float32Array(0), coupling: new Float32Array(0) }, informationMetrics: { complexity: 0, emergence: 0, coherence: 0 } } }, []) // ENTRONAUT: Analyze audio - SIMPLIFIED const analyzeSymbolicEmergence = useCallback((audioData: any, _currentTime: number) => { // Simplified - only basic metrics without complex calculations if (!entronautStateRef.current || !entronautEnabled) return // Just update basic metrics without heavy computation const { informationMetrics } = entronautStateRef.current informationMetrics.complexity = audioData.overallAmplitude || 0 informationMetrics.emergence = audioData.beatDetected ? 1.0 : 0.1 informationMetrics.coherence = (audioData.deepEnergy + audioData.midEnergy + audioData.highEnergy) / 3.0 }, [entronautEnabled]) // ENTRONAUT: Apply adaptive coupling - SIMPLIFIED const applyEntronautCoupling = useCallback((_sphere: ParticleSphere, _particleIndex: number) => { // Return simple defaults - no complex field calculations return { damping: 0.95, diffusion: 0.008, coupling: 0.02 } }, []) // Initialize Three.js scene and particle systems const initializeVisualization = useCallback(async () => { if (!canvasRef.current) return console.log('๐ŸŽจ Initializing advanced particle visualization with Entronaut SEFA...') try { // Dynamically import Three.js const THREE = await import('three') // Create scene const scene = new THREE.Scene() scene.background = new THREE.Color(0x000000) sceneRef.current = scene // Create camera const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) camera.position.set(0, 0, 2.5) cameraRef.current = camera // Create renderer const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.current!, antialias: true }) renderer.setSize(window.innerWidth, window.innerHeight) rendererRef.current = renderer // Initialize camera controls const { OrbitControls } = await import('three/examples/jsm/controls/OrbitControls.js') const controls = new OrbitControls(camera, renderer.domElement) // Configure controls controls.enableDamping = true controls.dampingFactor = 0.05 controls.enableZoom = true controls.enablePan = true controls.enableRotate = true // Set limits controls.maxDistance = 50 controls.minDistance = 0.1 controls.maxPolarAngle = Math.PI // Allow full rotation // Auto-rotate settings controls.autoRotate = autoRotate controls.autoRotateSpeed = 0.5 // Prevent controls from interfering with UI elements controls.addEventListener('change', () => { // Only update if camera controls are enabled if (!cameraControlsEnabled) { controls.enabled = false } }) controlsRef.current = controls // Initialize noise generator and beat manager noiseGeneratorRef.current = new NoiseGenerator() beatManagerRef.current = new BeatManager() // Initialize Entronaut initializeEntronaut() // Create particle spheres await createParticleSpheres(THREE, scene) // Create dynamic tendril system if (tendrilsEnabled) { await createTendrilSystem(THREE, scene) } // Create Dyson sphere/growing vines system if (dysonSphereEnabled) { await createDysonSphere(THREE, scene) } // Setup fog updateFog(THREE) setIsVisualizationReady(true) console.log('โœ… Advanced particle visualization with Entronaut initialized') } catch (error) { console.error('โŒ Failed to initialize visualization:', error) } }, [initializeEntronaut]) // Create multiple particle sphere systems const createParticleSpheres = useCallback(async (THREE: any, scene: any) => { const spheres: ParticleSphere[] = [] // Load organic color schemes from config const config = configLoader.getConfig() const configColorSchemes = (config as any)?.colors?.sphereColorSchemes // Enhanced organic color schemes for each sphere const colorSchemes = configColorSchemes || [ { start: '#2d5016', end: '#7d4f39' }, // Deep forest to iron oxide (sub-bass) { start: '#8b5a2b', end: '#4a6741' }, // Earth brown to vine green (bass) { start: '#cd853f', end: '#556b2f' }, // Sandy brown to moss green (mid) { start: '#daa520', end: '#2e8b57' }, // Gold leaf to sea green (high-mid) { start: '#b8860b', end: '#20b2aa' } // Burnished gold to teal depth (high) ] for (let i = 0; i < 5; i++) { const sphereParams: ParticleSystemParams = { ...DEFAULT_SPHERE_PARAMS, enabled: true, // All spheres enabled by default ...DEFAULT_FREQUENCY_RANGES[i] || DEFAULT_FREQUENCY_RANGES[0], colorStart: colorSchemes[i].start, colorEnd: colorSchemes[i].end, // Enhanced settings for organic, rich visuals particleCount: 15000, // Increased for more density turbulenceStrength: 0.006, // Reduced for more organic movement beatStrength: 0.015, // Gentler beat response for organic feel noiseScale: 2.5 + i * 0.3, // Smoother noise variation sphereRadius: 1.0 + i * 0.06, // More subtle spatial variation rotationSpeedMax: 0.04 + i * 0.006, // Slower, more organic rotation particleLifetime: 12.0 + i * 2.0 // Longer lifetimes for stability } const sphere = await createParticleSphere(THREE, scene, i, sphereParams) spheres.push(sphere) } spheresRef.current = spheres console.log(`๐Ÿ”ฎ Created ${spheres.length} particle sphere systems`) }, []) // Create dynamic tendril system that connects particles const createTendrilSystem = useCallback(async (THREE: any, scene: any) => { if (!tendrilsEnabled) return console.log('๐ŸŒฟ Creating dynamic tendril system...') // Create tendril network between particles const maxTendrils = 2000 // Maximum number of tendrils const maxTendrilLength = 0.8 // Maximum distance for tendril connections const tendrilSegments = 8 // Segments per tendril for smooth curves // Create tendril geometry const tendrilGeometry = new THREE.BufferGeometry() const tendrilPositions = new Float32Array(maxTendrils * tendrilSegments * 6) // 2 points per segment const tendrilColors = new Float32Array(maxTendrils * tendrilSegments * 6) // RGB for each point const tendrilOpacities = new Float32Array(maxTendrils * tendrilSegments * 2) // Alpha for each point // Initialize with empty data tendrilPositions.fill(0) tendrilColors.fill(0.3) // Dim gold base tendrilOpacities.fill(0) tendrilGeometry.setAttribute('position', new THREE.BufferAttribute(tendrilPositions, 3)) tendrilGeometry.setAttribute('color', new THREE.BufferAttribute(tendrilColors, 3)) tendrilGeometry.setAttribute('alpha', new THREE.BufferAttribute(tendrilOpacities, 1)) // Create custom shader material for tendrils const tendrilMaterial = new THREE.ShaderMaterial({ uniforms: { time: { value: 0.0 }, sefaField: { value: 0.0 }, audioEnergy: { value: 0.0 } }, vertexShader: ` attribute float alpha; varying float vAlpha; varying vec3 vColor; uniform float time; uniform float sefaField; uniform float audioEnergy; void main() { vAlpha = alpha * (0.3 + 0.7 * sin(time * 2.0 + position.x * 10.0)); vColor = color * (0.5 + 0.5 * audioEnergy); vec3 pos = position; // Add SEFA-driven undulation pos += 0.02 * sefaField * sin(time * 3.0 + position.y * 15.0) * normal; gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); } `, fragmentShader: ` varying float vAlpha; varying vec3 vColor; void main() { // Create glowing tendril effect float glow = 1.0 - length(gl_PointCoord - vec2(0.5)); glow = pow(glow, 2.0); gl_FragColor = vec4(vColor, vAlpha * glow); } `, transparent: true, blending: THREE.AdditiveBlending, side: THREE.DoubleSide }) // Create tendril line system const tendrilLines = new THREE.LineSegments(tendrilGeometry, tendrilMaterial) tendrilLines.userData = { type: 'tendrils' } scene.add(tendrilLines) tendrilSystemRef.current = { geometry: tendrilGeometry, material: tendrilMaterial, lines: tendrilLines, positions: tendrilPositions, colors: tendrilColors, opacities: tendrilOpacities, maxTendrils, maxTendrilLength, tendrilSegments, lastUpdate: 0 } console.log('โœ… Dynamic tendril system created') }, [tendrilsEnabled]) // Create Dyson sphere/growing vines system const createDysonSphere = useCallback(async (THREE: any, scene: any) => { if (!dysonSphereEnabled) return console.log('๐ŸŒฟ Creating Dyson sphere growing vines system...') const config = configLoader.getConfig() const dysonConfig = (config as any)?.dysonSphere const colors = (config as any)?.colors?.dysonVines if (!dysonConfig || !colors) { console.warn('Dyson sphere configuration missing') return } // Initialize vine system const maxVines = vineComplexity const maxSegments = dysonConfig.vines.maxSegmentsPerVine const sphereRadius = dysonConfig.vines.sphereRadius // Create vine geometry const vineGeometry = new THREE.BufferGeometry() const vinePositions = new Float32Array(maxVines * maxSegments * 6) // Line segments const vineColors = new Float32Array(maxVines * maxSegments * 6) const vineOpacities = new Float32Array(maxVines * maxSegments * 2) // Initialize with empty data vinePositions.fill(0) vineColors.fill(0) vineOpacities.fill(0) vineGeometry.setAttribute('position', new THREE.BufferAttribute(vinePositions, 3)) vineGeometry.setAttribute('color', new THREE.BufferAttribute(vineColors, 3)) vineGeometry.setAttribute('alpha', new THREE.BufferAttribute(vineOpacities, 1)) // Create node geometry for connection points const nodeGeometry = new THREE.SphereGeometry(dysonConfig.nodes.nodeSize, 8, 6) const nodeMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color(colors.nodeColor), transparent: true, opacity: 0.8 }) // Create vine shader material const vineMaterial = new THREE.ShaderMaterial({ uniforms: { time: { value: 0.0 }, growthProgress: { value: 0.0 }, audioEnergy: { value: 0.0 }, emergenceField: { value: 0.0 }, vineGlow: { value: dysonConfig.visual.vineGlow }, primaryColor: { value: new THREE.Color(colors.primaryVine) }, secondaryColor: { value: new THREE.Color(colors.secondaryVine) }, highlightColor: { value: new THREE.Color(colors.vineHighlight) } }, vertexShader: ` attribute float alpha; varying float vAlpha; varying vec3 vColor; varying vec3 vPosition; uniform float time; uniform float growthProgress; uniform float audioEnergy; uniform vec3 primaryColor; uniform vec3 secondaryColor; uniform vec3 highlightColor; void main() { vAlpha = alpha * (0.4 + 0.6 * sin(time * 2.0 + position.x * 8.0)); vPosition = position; // Organic color blending float colorMix = sin(time * 1.5 + position.y * 6.0) * 0.5 + 0.5; vColor = mix(primaryColor, secondaryColor, colorMix); vColor = mix(vColor, highlightColor, audioEnergy * 0.3); vec3 pos = position; // Add organic growth undulation float growth = min(1.0, growthProgress + sin(time * 0.5) * 0.1); pos *= growth; // Audio-reactive pulsing pos += 0.01 * audioEnergy * sin(time * 4.0 + length(position) * 12.0) * normalize(position); gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); } `, fragmentShader: ` varying float vAlpha; varying vec3 vColor; varying vec3 vPosition; uniform float vineGlow; void main() { // Distance-based glow effect float dist = length(vPosition); float glow = 1.0 / (1.0 + dist * 2.0); glow = pow(glow, vineGlow); // Organic pulsing opacity float pulse = sin(dist * 8.0 - time * 3.0) * 0.3 + 0.7; gl_FragColor = vec4(vColor * glow, vAlpha * pulse); } `, transparent: true, blending: THREE.AdditiveBlending, side: THREE.DoubleSide }) // Create vine line system const vineLines = new THREE.LineSegments(vineGeometry, vineMaterial) vineLines.userData = { type: 'dysonVines' } scene.add(vineLines) // Create node instances const nodeInstances = [] for (let i = 0; i < dysonConfig.nodes.nodeCount; i++) { const node = new THREE.Mesh(nodeGeometry, nodeMaterial.clone()) node.userData = { type: 'dysonNode', index: i } scene.add(node) nodeInstances.push(node) } // Initialize vine growth data const vineData = { vines: [] as any[], growthProgress: 0, lastUpdate: 0 } // Create initial vine seeds for (let i = 0; i < dysonConfig.growth.seedPoints; i++) { const theta = (i / dysonConfig.growth.seedPoints) * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const startPos = { x: sphereRadius * Math.sin(phi) * Math.cos(theta), y: sphereRadius * Math.sin(phi) * Math.sin(theta), z: sphereRadius * Math.cos(phi) } vineData.vines.push({ segments: [startPos], growth: 0, direction: { x: Math.random() - 0.5, y: Math.random() - 0.5, z: Math.random() - 0.5 }, branches: [], maturity: 0, energy: Math.random() }) } dysonSphereRef.current = { vineGeometry, vineMaterial, vineLines, nodeGeometry, nodeInstances, vinePositions, vineColors, vineOpacities, vineData, maxVines, maxSegments, sphereRadius, lastUpdate: 0, config: dysonConfig, colors } console.log('โœ… Dyson sphere growing vines system created') }, [dysonSphereEnabled, vineComplexity]) // Create individual particle sphere const createParticleSphere = async ( THREE: any, scene: any, index: number, params: ParticleSystemParams ): Promise => { // Create geometry and buffers const geometry = new THREE.BufferGeometry() const positions = new Float32Array(params.particleCount * 3) const colors = new Float32Array(params.particleCount * 3) const velocities = new Float32Array(params.particleCount * 3) const basePositions = new Float32Array(params.particleCount * 3) const lifetimes = new Float32Array(params.particleCount) const maxLifetimes = new Float32Array(params.particleCount) const beatEffects = new Float32Array(params.particleCount) // Initialize particles for (let i = 0; i < params.particleCount; i++) { const i3 = i * 3 const radius = THREE.MathUtils.lerp(0, params.sphereRadius, params.innerSphereRadius) const theta = Math.random() * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const r = Math.cbrt(Math.random()) * radius const x = r * Math.sin(phi) * Math.cos(theta) const y = r * Math.sin(phi) * Math.sin(theta) const z = r * Math.cos(phi) positions[i3] = x positions[i3 + 1] = y positions[i3 + 2] = z basePositions[i3] = x basePositions[i3 + 1] = y basePositions[i3 + 2] = z velocities[i3] = 0 velocities[i3 + 1] = 0 velocities[i3 + 2] = 0 const lt = Math.random() * params.particleLifetime lifetimes[i] = lt maxLifetimes[i] = lt beatEffects[i] = 0 } geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)) geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)) // Create material with organic styling const material = new THREE.PointsMaterial({ size: params.particleSize * (0.8 + index * 0.05), // Subtle size variation per sphere vertexColors: true, transparent: true, opacity: 0.85 - index * 0.05, // Decreasing opacity for depth blending: THREE.AdditiveBlending, fog: true, sizeAttenuation: true // Natural size falloff with distance }) // Create particle system const particleSystem = new THREE.Points(geometry, material) particleSystem.visible = params.enabled particleSystem.userData = { sphereIndex: index } // Critical: Link to sphere scene.add(particleSystem) // Create sphere object const sphere: ParticleSphere = { index, params, positions, velocities, basePositions, lifetimes, maxLifetimes, beatEffects, colors, lastNoiseScale: params.noiseScale, lastValidVolume: 0, lastRotationSpeed: 0, peakDetection: { energyHistory: [], historyLength: 30, lastPeakTime: 0, minTimeBetweenPeaks: 200 } } // Update colors updateSphereColors(THREE, sphere) return sphere } // Update sphere colors with organic palette blending const updateSphereColors = (THREE: any, sphere: ParticleSphere) => { const color1 = new THREE.Color(sphere.params.colorStart) const color2 = new THREE.Color(sphere.params.colorEnd) // Load organic palette for enhanced blending const config = configLoader.getConfig() const organicPalette = (config as any)?.colors?.organicPalette for (let i = 0; i < sphere.params.particleCount; i++) { const t = i / sphere.params.particleCount // Base color interpolation let r = color1.r * (1 - t) + color2.r * t let g = color1.g * (1 - t) + color2.g * t let b = color1.b * (1 - t) + color2.b * t // Apply organic palette enhancement if available if (organicPalette && entronautEnabled) { const emergence = entronautStateRef.current?.informationMetrics?.emergence || 0 // Blend with organic colors based on SEFA emergence const organicInfluence = emergence * 0.3 // Choose organic color based on frequency range let organicColor if (sphere.index === 0) { // Sub-bass -> deep forest/bronze organicColor = hexToRgb(organicPalette.deepForest) || { r: 0.18, g: 0.31, b: 0.09 } } else if (sphere.index === 1) { // Bass -> earth brown/copper organicColor = hexToRgb(organicPalette.earthBrown) || { r: 0.54, g: 0.27, b: 0.07 } } else if (sphere.index === 2) { // Mid -> copper glow/gold organicColor = hexToRgb(organicPalette.copperGlow) || { r: 0.72, g: 0.45, b: 0.20 } } else if (sphere.index === 3) { // High-mid -> gold leaf/moss organicColor = hexToRgb(organicPalette.goldLeaf) || { r: 0.85, g: 0.65, b: 0.13 } } else { // High -> teal depth/amber organicColor = hexToRgb(organicPalette.tealDepth) || { r: 0.13, g: 0.70, b: 0.67 } } // Blend with organic color r = r * (1 - organicInfluence) + organicColor.r * organicInfluence g = g * (1 - organicInfluence) + organicColor.g * organicInfluence b = b * (1 - organicInfluence) + organicColor.b * organicInfluence } sphere.colors[i * 3] = r sphere.colors[i * 3 + 1] = g sphere.colors[i * 3 + 2] = b } } // Update fog const updateFog = (THREE: any) => { if (!sceneRef.current) return if (!fogParams.enabled) { sceneRef.current.fog = null } else { const color = new THREE.Color(fogParams.color) sceneRef.current.fog = new THREE.Fog(color, fogParams.near, fogParams.far) } } // Main animation loop const animate = useCallback((currentTime: number) => { if (!isVisualizationReady || !rendererRef.current || !sceneRef.current || !cameraRef.current) { animationRef.current = requestAnimationFrame(animate) return } const deltaTime = lastTimeRef.current ? (currentTime - lastTimeRef.current) / 1000 : 0 lastTimeRef.current = currentTime // Check if audio is playing and hide startup info if (showStartupInfo && audioEngine) { const audioData = audioEngine.getAudioData() if (audioData.overallAmplitude > 0.01) { setShowStartupInfo(false) } } // Enhanced FPS monitoring with auto-refresh triggers setPerformanceStats(prev => { const frameCount = prev.frameCount + 1 const timeSinceLastUpdate = currentTime - prev.lastFpsUpdate if (timeSinceLastUpdate > 1000) { // Update FPS every second const fps = Math.round(frameCount * 1000 / timeSinceLastUpdate) const totalParticles = spheresRef.current.reduce((sum, sphere) => sum + (sphere.params.enabled ? sphere.params.particleCount : 0), 0) // Hidden Auto-Refresh Logic const autoRefresh = autoRefreshRef.current const now = Date.now() // Check for performance degradation if (fps < 30) { autoRefresh.performanceDegradationCount++ } else { autoRefresh.performanceDegradationCount = Math.max(0, autoRefresh.performanceDegradationCount - 1) } // Check particle health every 5 seconds if (frameCount % 5 === 0) { autoRefresh.particleHealthChecks++ const isHealthy = checkParticleHealth() if (!isHealthy) { autoRefresh.emergencyResetCount++ } } // Trigger hidden refresh if conditions are met const timeSinceLastRefresh = now - autoRefresh.lastRefresh const shouldRefresh = ( // Periodic refresh (every 2 minutes base) timeSinceLastRefresh > autoRefresh.refreshInterval || // Performance degradation (3 consecutive low FPS readings) autoRefresh.performanceDegradationCount >= 3 || // Particle health issues (2 consecutive unhealthy checks) autoRefresh.emergencyResetCount >= 2 ) if (shouldRefresh && !autoRefresh.isRefreshing) { // Adjust refresh interval based on performance if (autoRefresh.performanceDegradationCount >= 3) { autoRefresh.refreshInterval = 60000 // 1 minute for poor performance } else if (fps > 45) { autoRefresh.refreshInterval = 180000 // 3 minutes for good performance } else { autoRefresh.refreshInterval = 120000 // 2 minutes default } // Perform refresh without blocking the main thread setTimeout(() => performHiddenRefresh(), 100) } return { fps, particleCount: totalParticles, lastFpsUpdate: currentTime, frameCount: 0 } } return { ...prev, frameCount } }) // Update camera controls if (controlsRef.current) { controlsRef.current.enabled = cameraControlsEnabled controlsRef.current.autoRotate = autoRotate && cameraControlsEnabled if (cameraControlsEnabled) { controlsRef.current.update() } } // Update beat manager beatManagerRef.current?.update(deltaTime) // ENTRONAUT: Analyze emergence patterns in audio data (reduced frequency for performance) if (audioEngine && entronautEnabled && (Math.floor(currentTime * 0.01) % 3 === 0)) { // Run every 3rd frame const audioData = audioEngine.getAudioData() if (Math.random() < 0.005) { // Reduced logging frequency console.log('๐Ÿง  SEFA Analysis - Audio Data:', { deepEnergy: audioData.deepEnergy, midEnergy: audioData.midEnergy, highEnergy: audioData.highEnergy, overallAmplitude: audioData.overallAmplitude, beatDetected: audioData.beatDetected }) } analyzeSymbolicEmergence(audioData, currentTime) } // Update particle spheres updateParticleSpheres(currentTime, deltaTime) // Update dynamic tendrils updateTendrilSystem(currentTime, deltaTime) // Update Dyson sphere/growing vines updateDysonSphere(currentTime, deltaTime) // Render scene rendererRef.current.render(sceneRef.current, cameraRef.current) animationRef.current = requestAnimationFrame(animate) }, [isVisualizationReady, audioEngine, entronautEnabled, analyzeSymbolicEmergence]) // Update all particle spheres with inter-sphere communication const updateParticleSpheres = (currentTime: number, deltaTime: number) => { if (!audioEngine || !noiseGeneratorRef.current || !beatManagerRef.current) return // Calculate global emergence state for inter-sphere communication const globalEmergence = entronautStateRef.current ? entronautStateRef.current.informationMetrics.emergence : 0 const globalComplexity = entronautStateRef.current ? entronautStateRef.current.informationMetrics.complexity : 0 spheresRef.current.forEach((sphere, sphereIndex) => { if (!sphere.params.enabled) return // Get audio data for this sphere const audioData = audioEngine.getAdvancedAudioData(sphere) // Add debug logging for the first sphere if (sphere.index === 0 && Math.random() < 0.01) { // 1% chance to log console.log('๐ŸŽฏ Audio data for sphere 0:', { rangeEnergy: audioData.rangeEnergy, rangeEnergyBeat: audioData.rangeEnergyBeat, peakDetected: audioData.peakDetected, beatThreshold: sphere.params.beatThreshold }) } // OPTIMIZED INTER-SPHERE COMMUNICATION (run less frequently) if (entronautEnabled && adaptiveCoupling && (sphereIndex === 0 || Math.random() < 0.1)) { // Simplified sphere influence with reduced frequency let avgNoiseScale = 0 let activeNeighbors = 0 spheresRef.current.forEach((otherSphere, otherIndex) => { if (otherIndex !== sphereIndex && otherSphere.params.enabled) { avgNoiseScale += otherSphere.params.noiseScale activeNeighbors++ } }) if (activeNeighbors > 0) { avgNoiseScale /= activeNeighbors const networkInfluence = globalEmergence * 0.1 // Reduced influence sphere.params.noiseScale = sphere.params.noiseScale * (1 - networkInfluence) + avgNoiseScale * networkInfluence } // Simplified synchronization const syncPulse = globalComplexity * 0.2 sphere.params.turbulenceStrength *= (1 + syncPulse) } // Handle peak detection and dynamic noise scaling if (audioData.peakDetected && sphere.params.dynamicNoiseScale) { sphere.params.noiseScale = generateNewNoiseScale(sphere.params, sphere.lastNoiseScale) sphere.lastNoiseScale = sphere.params.noiseScale } // Beat detection and wave triggering const beatDetected = audioData.rangeEnergyBeat > sphere.params.beatThreshold if (beatDetected && !beatManagerRef.current!.isWaveActive && sphere.params.beatStrength > 0) { beatManagerRef.current!.triggerWave(audioData.rangeEnergyBeat) } // Update particles updateSphereParticles(sphere, currentTime, deltaTime, beatDetected) // Update rotation based on audio updateSphereRotation(sphere, audioData) }) } // Update dynamic tendril system with performance optimization const updateTendrilSystem = (currentTime: number, _deltaTime: number) => { if (!tendrilsEnabled || !tendrilSystemRef.current || !audioEngine || !entronautStateRef.current) return // Performance optimization for tendril system const adaptiveLevel = 1.0 // Simplified - no performance monitoring const tendrilSystem = tendrilSystemRef.current const { positions, colors, opacities, maxTendrils, maxTendrilLength, tendrilSegments } = tendrilSystem // Update shader uniforms const audioData = audioEngine.getAudioData() const sefaMetrics = entronautStateRef.current.informationMetrics tendrilSystem.material.uniforms.time.value = currentTime * 0.001 tendrilSystem.material.uniforms.sefaField.value = sefaMetrics.emergence tendrilSystem.material.uniforms.audioEnergy.value = audioData.overallAmplitude || 0 // Only update connections periodically for performance if (currentTime - tendrilSystem.lastUpdate < 100) return // Update every 100ms tendrilSystem.lastUpdate = currentTime let tendrilIndex = 0 const performanceMultiplier = Math.max(0.2, adaptiveLevel) // Minimum 20% tendrils even at low performance const activeTendrils = Math.floor(maxTendrils * tendrilDensity * performanceMultiplier * (0.5 + 0.5 * audioData.overallAmplitude)) // Reset all positions positions.fill(0) opacities.fill(0) // Create connections between particles from different spheres for (let sphereA = 0; sphereA < spheresRef.current.length && tendrilIndex < activeTendrils; sphereA++) { const sphere1 = spheresRef.current[sphereA] if (!sphere1.params.enabled) continue for (let sphereB = sphereA + 1; sphereB < spheresRef.current.length && tendrilIndex < activeTendrils; sphereB++) { const sphere2 = spheresRef.current[sphereB] if (!sphere2.params.enabled) continue // Sample particles from each sphere const sampleCount = Math.min(10, Math.floor(sphere1.params.particleCount / 1000)) for (let i = 0; i < sampleCount && tendrilIndex < activeTendrils; i++) { const p1Index = Math.floor(Math.random() * sphere1.params.particleCount) const p2Index = Math.floor(Math.random() * sphere2.params.particleCount) const p1x = sphere1.positions[p1Index * 3] const p1y = sphere1.positions[p1Index * 3 + 1] const p1z = sphere1.positions[p1Index * 3 + 2] const p2x = sphere2.positions[p2Index * 3] const p2y = sphere2.positions[p2Index * 3 + 1] const p2z = sphere2.positions[p2Index * 3 + 2] const distance = Math.sqrt( (p2x - p1x) ** 2 + (p2y - p1y) ** 2 + (p2z - p1z) ** 2 ) // Only create tendril if particles are within range if (distance < maxTendrilLength) { // Calculate SEFA influence on tendril strength const fieldWidth = 32 const fieldX = Math.floor(((p1x + p2x) * 0.5 + 1) * 0.5 * fieldWidth) const fieldY = Math.floor(((p1y + p2y) * 0.5 + 1) * 0.5 * fieldWidth) const sefaIndex = Math.max(0, Math.min( entronautStateRef.current.sefaScore.length - 1, fieldY * fieldWidth + fieldX )) const sefaStrength = entronautStateRef.current.sefaScore[sefaIndex] // Create curved tendril with multiple segments for (let segment = 0; segment < tendrilSegments - 1; segment++) { const t1 = segment / (tendrilSegments - 1) const t2 = (segment + 1) / (tendrilSegments - 1) // Calculate curved path with SEFA-driven undulation const curve1 = getCurvedTendrilPoint(p1x, p1y, p1z, p2x, p2y, p2z, t1, currentTime, sefaStrength) const curve2 = getCurvedTendrilPoint(p1x, p1y, p1z, p2x, p2y, p2z, t2, currentTime, sefaStrength) const baseIndex = tendrilIndex * tendrilSegments * 6 + segment * 6 // Set positions for line segment positions[baseIndex] = curve1.x positions[baseIndex + 1] = curve1.y positions[baseIndex + 2] = curve1.z positions[baseIndex + 3] = curve2.x positions[baseIndex + 4] = curve2.y positions[baseIndex + 5] = curve2.z // Set colors based on frequency and SEFA with organic palette blending const colorIntensity = 0.4 + 0.6 * sefaStrength // More subtle intensity range const freq1Color = getFrequencyColor(sphere1.params.minFrequency, colorIntensity) const freq2Color = getFrequencyColor(sphere2.params.minFrequency, colorIntensity) // Blend colors organically const blendFactor = Math.sin(currentTime * 0.0008 + distance * 5) * 0.5 + 0.5 colors[baseIndex] = freq1Color.r * (1 - blendFactor) + freq2Color.r * blendFactor colors[baseIndex + 1] = freq1Color.g * (1 - blendFactor) + freq2Color.g * blendFactor colors[baseIndex + 2] = freq1Color.b * (1 - blendFactor) + freq2Color.b * blendFactor colors[baseIndex + 3] = freq2Color.r * (1 - blendFactor) + freq1Color.r * blendFactor colors[baseIndex + 4] = freq2Color.g * (1 - blendFactor) + freq1Color.g * blendFactor colors[baseIndex + 5] = freq2Color.b * (1 - blendFactor) + freq1Color.b * blendFactor // Set opacity based on audio energy and distance const opacity = (1 - distance / maxTendrilLength) * sefaStrength * audioData.overallAmplitude const opacityIndex = tendrilIndex * tendrilSegments * 2 + segment * 2 opacities[opacityIndex] = opacity opacities[opacityIndex + 1] = opacity } tendrilIndex++ } } } } // Mark geometry for update tendrilSystem.geometry.attributes.position.needsUpdate = true tendrilSystem.geometry.attributes.color.needsUpdate = true tendrilSystem.geometry.attributes.alpha.needsUpdate = true } // Update Dyson sphere/growing vines system with performance optimization const updateDysonSphere = (currentTime: number, deltaTime: number) => { if (!dysonSphereEnabled || !dysonSphereRef.current || !audioEngine) return // Performance optimization for Dyson sphere // Simplified - no dynamic update frequency const dysonSystem = dysonSphereRef.current const { vineMaterial, vinePositions, vineColors, vineOpacities, vineData, config, colors } = dysonSystem // Update shader uniforms const audioData = audioEngine.getAudioData() const sefaMetrics = entronautStateRef.current?.informationMetrics || { emergence: 0, complexity: 0 } vineMaterial.uniforms.time.value = currentTime * 0.001 vineMaterial.uniforms.audioEnergy.value = audioData.overallAmplitude || 0 vineMaterial.uniforms.emergenceField.value = sefaMetrics.emergence vineMaterial.uniforms.growthProgress.value = vineData.growthProgress // Only update vine growth periodically for performance if (currentTime - dysonSystem.lastUpdate < 50) return // Update every 50ms dysonSystem.lastUpdate = currentTime // Update vine growth vineData.growthProgress = Math.min(1.0, vineData.growthProgress + vineGrowthRate * deltaTime) let vineIndex = 0 // Reset all positions vinePositions.fill(0) vineOpacities.fill(0) // Update each vine vineData.vines.forEach((vine: any, vIndex: number) => { if (vineIndex >= dysonSystem.maxVines) return // Grow vine segments based on audio energy and SEFA const audioInfluence = (audioData.overallAmplitude || 0) * config.vines.audioReactivity const growthRate = config.vines.growthSpeed * (1 + audioInfluence) * vineData.growthProgress vine.growth += growthRate * deltaTime vine.maturity = Math.min(1.0, vine.maturity + deltaTime / config.growth.maturityTime) // Add new segments as vine grows if (vine.growth > 1.0 && vine.segments.length < config.vines.maxSegmentsPerVine) { vine.growth = 0 const lastSegment = vine.segments[vine.segments.length - 1] // Calculate organic growth direction const centerForce = { x: -lastSegment.x * 0.1, y: -lastSegment.y * 0.1, z: -lastSegment.z * 0.1 } // Add curvature and organic variation vine.direction.x += (Math.random() - 0.5) * config.vines.organicVariation + centerForce.x vine.direction.y += (Math.random() - 0.5) * config.vines.organicVariation + centerForce.y vine.direction.z += (Math.random() - 0.5) * config.vines.organicVariation + centerForce.z // Normalize direction const dirLength = Math.sqrt(vine.direction.x ** 2 + vine.direction.y ** 2 + vine.direction.z ** 2) if (dirLength > 0) { vine.direction.x /= dirLength vine.direction.y /= dirLength vine.direction.z /= dirLength } // Create new segment const segmentLength = 0.1 + sefaMetrics.emergence * 0.05 const newSegment = { x: lastSegment.x + vine.direction.x * segmentLength, y: lastSegment.y + vine.direction.y * segmentLength, z: lastSegment.z + vine.direction.z * segmentLength } vine.segments.push(newSegment) // Update node positions if (dysonSystem.nodeInstances[vIndex]) { dysonSystem.nodeInstances[vIndex].position.set(newSegment.x, newSegment.y, newSegment.z) // Update node material based on audio const nodeMat = dysonSystem.nodeInstances[vIndex].material as any nodeMat.opacity = 0.5 + 0.5 * audioData.overallAmplitude nodeMat.color.setHex(parseInt(colors.nodeColor.replace('#', ''), 16)) } } // Render vine segments for (let i = 0; i < vine.segments.length - 1 && vineIndex < dysonSystem.maxVines; i++) { const segment1 = vine.segments[i] const segment2 = vine.segments[i + 1] const baseIndex = vineIndex * 6 // Set positions for line segment vinePositions[baseIndex] = segment1.x vinePositions[baseIndex + 1] = segment1.y vinePositions[baseIndex + 2] = segment1.z vinePositions[baseIndex + 3] = segment2.x vinePositions[baseIndex + 4] = segment2.y vinePositions[baseIndex + 5] = segment2.z // Set colors based on maturity and audio const maturityColor = vine.maturity const audioColor = audioData.overallAmplitude || 0 const primaryColor = hexToRgb(colors.primaryVine) const secondaryColor = hexToRgb(colors.secondaryVine) const highlightColor = hexToRgb(colors.vineHighlight) if (primaryColor && secondaryColor && highlightColor) { const blendedColor = { r: primaryColor.r * (1 - maturityColor) + secondaryColor.r * maturityColor, g: primaryColor.g * (1 - maturityColor) + secondaryColor.g * maturityColor, b: primaryColor.b * (1 - maturityColor) + secondaryColor.b * maturityColor } // Apply audio highlight blendedColor.r = Math.min(1, blendedColor.r + highlightColor.r * audioColor * 0.3) blendedColor.g = Math.min(1, blendedColor.g + highlightColor.g * audioColor * 0.3) blendedColor.b = Math.min(1, blendedColor.b + highlightColor.b * audioColor * 0.3) vineColors[baseIndex] = blendedColor.r vineColors[baseIndex + 1] = blendedColor.g vineColors[baseIndex + 2] = blendedColor.b vineColors[baseIndex + 3] = blendedColor.r vineColors[baseIndex + 4] = blendedColor.g vineColors[baseIndex + 5] = blendedColor.b } // Set opacity based on growth and audio const opacity = vine.maturity * (0.6 + 0.4 * audioData.overallAmplitude) const opacityIndex = vineIndex * 2 vineOpacities[opacityIndex] = opacity vineOpacities[opacityIndex + 1] = opacity vineIndex++ } }) // Mark geometry for update dysonSystem.vineGeometry.attributes.position.needsUpdate = true dysonSystem.vineGeometry.attributes.color.needsUpdate = true dysonSystem.vineGeometry.attributes.alpha.needsUpdate = true } // Helper function to convert hex color to RGB const hexToRgb = (hex: string) => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) return result ? { r: parseInt(result[1], 16) / 255, g: parseInt(result[2], 16) / 255, b: parseInt(result[3], 16) / 255 } : null } // Helper function to create curved tendril points const getCurvedTendrilPoint = (x1: number, y1: number, z1: number, x2: number, y2: number, z2: number, t: number, time: number, sefaStrength: number) => { // Linear interpolation const x = x1 + (x2 - x1) * t const y = y1 + (y2 - y1) * t const z = z1 + (z2 - z1) * t // Add curvature and SEFA-driven undulation const midPoint = t * (1 - t) * 4 // Peaks at t=0.5 const curve = midPoint * 0.2 * sefaStrength const undulation = 0.05 * sefaStrength * Math.sin(time * 0.002 + t * 10) return { x: x + curve * Math.sin(time * 0.001 + t * 5) + undulation, y: y + curve * Math.cos(time * 0.001 + t * 5) + undulation * 0.5, z: z + curve * Math.sin(time * 0.0015 + t * 3) + undulation * 0.3 } } // Helper function to get frequency-based color with organic palette const getFrequencyColor = (frequency: number, intensity: number) => { const config = configLoader.getConfig() const organicBlend = (config as any)?.colors?.tendrilColors?.organicBlend if (organicBlend) { const normalizedFreq = Math.min(1, frequency / 10000) // Use organic color blending let color if (normalizedFreq < 0.2) { color = organicBlend.forest // Deep greens for low frequencies } else if (normalizedFreq < 0.4) { color = organicBlend.bronze // Bronze for low-mid frequencies } else if (normalizedFreq < 0.6) { color = organicBlend.copper // Copper for mid frequencies } else if (normalizedFreq < 0.8) { color = organicBlend.gold // Gold for high-mid frequencies } else { color = organicBlend.teal // Teal for high frequencies } return { r: color[0] * intensity, g: color[1] * intensity, b: color[2] * intensity } } // Fallback to original calculation const normalizedFreq = Math.min(1, frequency / 10000) return { r: (0.8 + 0.2 * normalizedFreq) * intensity, g: (0.6 + 0.4 * Math.sin(normalizedFreq * Math.PI)) * intensity, b: (0.2 + 0.8 * (1 - normalizedFreq)) * intensity } } // Organic cymatic pattern generator - creates natural, sound-driven formations const getCymatePattern = useCallback((x: number, y: number, z: number, frequency: number, time: number) => { // Create organic patterns inspired by natural growth and cymatics const r = Math.sqrt(x*x + y*y + z*z) const theta = Math.atan2(y, x) const phi = Math.acos(z / (r || 1)) // Frequency-based pattern selection with organic variation const freqFactor = frequency / 1000 const pattern = Math.floor(freqFactor) % 5 // Added 5th pattern let patternX = 0, patternY = 0, patternZ = 0 // Load config for cymatic pattern settings const config = configLoader.getConfig() const cymateConfig = (config as any)?.cymatics?.patterns switch (pattern) { case 0: // Organic radial waves (tree rings, water ripples) const radialFreq = cymateConfig?.radialWaves?.frequencyFactor || 0.08 const radialPetals = cymateConfig?.radialWaves?.petalCount || 6 const radialPattern = Math.sin(r * radialFreq + time * 0.8) * Math.cos(theta * radialPetals + time * 0.3) patternX = radialPattern * Math.cos(theta) * 0.7 patternY = radialPattern * Math.sin(theta) * 0.7 patternZ = Math.sin(phi * 3 + time * 0.4) * (cymateConfig?.radialWaves?.amplitudeZ || 0.4) break case 1: // Natural spiral harmonics (nautilus, plant growth) const l = Math.max(1, Math.floor(freqFactor * 0.4) + 1) const m = Math.floor(freqFactor * 0.25) const spiralFactor = 1 + 0.3 * Math.sin(time * 0.6) patternX = Math.sin(l * phi * spiralFactor) * Math.cos(m * theta + time * 0.7) patternY = Math.sin(l * phi * spiralFactor) * Math.sin(m * theta + time * 0.7) patternZ = Math.cos(l * phi) * Math.sin(time * 1.2) * 0.6 break case 2: // Organic lattice (honeycomb, crystal growth) const latticeFreq = cymateConfig?.geometricLattice?.frequencyFactor || 0.15 const organic = 0.8 + 0.2 * Math.sin(time * 0.5) patternX = (Math.sin(x * latticeFreq + time * 0.6) + Math.sin(y * latticeFreq * 1.1)) * organic patternY = (Math.sin(y * latticeFreq + time * 0.8) + Math.sin(z * latticeFreq * 0.9)) * organic patternZ = (Math.sin(z * latticeFreq + time * 0.7) + Math.sin(x * latticeFreq * 1.05)) * organic break case 3: // Enhanced flower of life (sacred geometry) const flowerFreq = cymateConfig?.flowerOfLife?.frequencyFactor || 0.12 const basePetals = cymateConfig?.flowerOfLife?.basePetals || 6 const petalVariation = cymateConfig?.flowerOfLife?.petalVariation || 0.1 const flowerPetals = basePetals + Math.floor(freqFactor * petalVariation * 10) const bloom = 0.7 + 0.3 * Math.sin(time * 0.4) patternX = Math.sin(theta * flowerPetals + time * 0.5) * Math.sin(r * flowerFreq) * bloom patternY = Math.cos(theta * flowerPetals + time * 0.5) * Math.sin(r * flowerFreq) * bloom patternZ = Math.sin(phi * flowerPetals * 0.7 + time * 0.6) * (cymateConfig?.flowerOfLife?.amplitudeZ || 0.25) break case 4: // New: Organic vine growth pattern const vineFreq = freqFactor * 0.1 const vineSpiral = theta + r * 0.5 + time * 0.3 const growth = 0.6 + 0.4 * Math.sin(time * 0.35) patternX = Math.sin(vineSpiral) * Math.exp(-r * 0.2) * growth patternY = Math.cos(vineSpiral) * Math.exp(-r * 0.2) * growth patternZ = Math.sin(r * vineFreq + time * 0.5) * 0.4 * growth break } // Organic breathing effect with natural variation const breathing = cymateConfig?.breathing const breathingSpeed = breathing?.speed || 0.4 const intensityBase = breathing?.intensityBase || 0.25 const intensityVariation = breathing?.intensityVariation || 0.6 const intensity = intensityBase + intensityVariation * Math.sin(time * breathingSpeed) * (0.8 + 0.2 * Math.sin(time * breathingSpeed * 0.7)) // Natural variation return { x: patternX * intensity, y: patternY * intensity, z: patternZ * intensity } }, [cymateGeometry]) // Update individual sphere particles with performance optimization const updateSphereParticles = ( sphere: ParticleSphere, currentTime: number, deltaTime: number, beatDetected: boolean ) => { const { params, positions, velocities, lifetimes, beatEffects } = sphere const noise = noiseGeneratorRef.current! const beatManager = beatManagerRef.current! // Performance optimization: Skip heavy calculations if needed const adaptiveLevel = 1.0 // Simplified - no performance monitoring // Frame skipping for low performance - simplified // STABILITY: Clamp deltaTime to prevent integration instability const clampedDeltaTime = Math.min(deltaTime, 1/30) // Max 30 FPS equivalent timestep const config = configLoader.getConfig() const maxVelocity = config?.visualization?.physics?.maxVelocity || 0.1 const stabilityThreshold = config?.visualization?.physics?.stabilityThreshold || 10.0 // Adaptive particle count based on performance const adaptiveParticleCount = Math.min(params.particleCount, adaptiveLevel * 15000) // Simplified - no dynamic particle count // Level of detail calculation const particleUpdateStep = Math.max(1, Math.floor(1 / adaptiveLevel)) for (let i = 0; i < adaptiveParticleCount; i += particleUpdateStep) { const i3 = i * 3 let x = positions[i3] let y = positions[i3 + 1] let z = positions[i3 + 2] let vx = velocities[i3] let vy = velocities[i3 + 1] let vz = velocities[i3 + 2] let lt = lifetimes[i] let be = beatEffects[i] // STABILITY: Check for NaN or infinite values if (!isFinite(x) || !isFinite(y) || !isFinite(z) || !isFinite(vx) || !isFinite(vy) || !isFinite(vz)) { // Reset particle to safe position const theta = Math.random() * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const r = Math.cbrt(Math.random()) * params.sphereRadius * 0.5 x = r * Math.sin(phi) * Math.cos(theta) y = r * Math.sin(phi) * Math.sin(theta) z = r * Math.cos(phi) vx = vy = vz = 0 console.warn(`๐Ÿšจ Particle ${i} reset due to invalid values`) } // STABILITY: Check distance from origin - emergency containment const distFromOrigin = Math.sqrt(x*x + y*y + z*z) if (distFromOrigin > stabilityThreshold) { // Pull particle back to safe zone const pullFactor = 0.1 x *= pullFactor y *= pullFactor z *= pullFactor vx *= 0.1 // Severe velocity damping vy *= 0.1 vz *= 0.1 console.warn(`๐Ÿšจ Particle ${i} emergency reset - distance: ${distFromOrigin.toFixed(2)}`) } // Update lifetime lt -= clampedDeltaTime // Calculate distance and sphere radius early for use in forces const dist = Math.sqrt(x*x + y*y + z*z) const sphereRadius = params.sphereRadius // Define containment zones for use throughout particle update const coreZone = sphereRadius * 0.4 // Core zone - natural movement const innerZone = sphereRadius * 0.65 // Inner zone - gentle forces const boundaryZone = sphereRadius * 0.8 // Warning zone - medium forces const dangerZone = sphereRadius * 0.92 // Danger zone - strong forces const emergencyZone = sphereRadius * 0.98 // Emergency zone - very strong forces const hardBoundary = sphereRadius * 1.02 // Hard boundary - immediate reset // Apply noise-based turbulence with distance-based scaling const ns = params.noiseScale * adaptiveLevel // Scale noise with performance const speed = params.noiseSpeed const timeFactor = currentTime * 0.001 // Calculate noise values directly - no caching overhead const noiseValues = { x: noise.noise3D(x * ns + timeFactor * speed, y * ns, z * ns), y: noise.noise3D(x * ns, y * ns + timeFactor * speed, z * ns), z: noise.noise3D(x * ns, y * ns, z * ns + timeFactor * speed) } const noiseX = noiseValues.x const noiseY = noiseValues.y const noiseZ = noiseValues.z // STABILITY: Scale turbulence by performance, distance, and containment zones const performanceScale = Math.min(1.0, 60 * clampedDeltaTime) // Scale down for low FPS // Scale turbulence to maintain audio reactivity while preventing boundary escape const distanceScale = Math.max(0.3, 1 - (dist / sphereRadius) * 0.6) // Less aggressive reduction const turbulenceScale = params.turbulenceStrength * performanceScale * distanceScale * 0.9 // Preserve more turbulence vx += noiseX * turbulenceScale vy += noiseY * turbulenceScale vz += noiseZ * turbulenceScale // Apply beat effects if (beatDetected) { be = 1.0 } be *= 0.95 if (be > 0.01) { const dist = Math.sqrt(x*x + y*y + z*z) if (dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Modified beat force to prevent dispersion with stronger containment awareness const baseBeatForce = be * params.beatStrength * 0.8 // Increased to preserve audio reactivity // Use containment zones already defined above if (dist < coreZone) { // Normal outward beat force in core zone only const beatForce = baseBeatForce vx += dx * beatForce vy += dy * beatForce vz += dz * beatForce } else if (dist < innerZone) { // Reduced outward beat force in inner zone const beatForce = baseBeatForce * 0.6 vx += dx * beatForce vy += dy * beatForce vz += dz * beatForce } else if (dist < boundaryZone) { // Tangential beat force in boundary zone to add movement without outward push const tangentX = -dy const tangentY = dx const tangentZ = dz * 0.1 // Minimal Z movement const beatForce = baseBeatForce * 0.4 vx += tangentX * beatForce vy += tangentY * beatForce vz += tangentZ * beatForce } else if (dist < dangerZone) { // Inward beat force in danger zone to pull particles back const beatForce = baseBeatForce * 0.6 vx -= dx * beatForce vy -= dy * beatForce vz -= dz * beatForce } else { // Strong inward beat force beyond danger zone const beatForce = baseBeatForce * 1.2 vx -= dx * beatForce vy -= dy * beatForce vz -= dz * beatForce } } } // Apply wave forces with strong containment awareness const waveForce = beatManager.getWaveForce({ x, y, z }) if (waveForce > 0 && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Balance wave force intensity to preserve audio reactivity while maintaining containment const baseWaveIntensity = 0.0006 // Increased to preserve audio reactivity // Use containment zones already defined above for wave behavior let waveIntensity = baseWaveIntensity let waveDirection = 1 // 1 = outward, -1 = inward, 0 = tangential if (dist < coreZone) { // Normal outward waves in core waveIntensity = baseWaveIntensity waveDirection = 1 } else if (dist < innerZone) { // Reduced outward waves in inner zone waveIntensity = baseWaveIntensity * 0.6 waveDirection = 1 } else if (dist < boundaryZone) { // Tangential waves in boundary zone waveIntensity = baseWaveIntensity * 0.3 // Create tangential force instead of radial const tangentX = -dy const tangentY = dx const tangentZ = 0 vx += tangentX * waveForce * waveIntensity vy += tangentY * waveForce * waveIntensity vz += tangentZ * waveForce * waveIntensity waveDirection = 0 // Skip radial application below } else { // Inward waves beyond boundary zone waveIntensity = baseWaveIntensity * 0.8 waveDirection = -1 } // Apply radial wave force if not tangential if (waveDirection !== 0) { vx += dx * waveForce * waveIntensity * waveDirection vy += dy * waveForce * waveIntensity * waveDirection vz += dz * waveForce * waveIntensity * waveDirection } } // Cymatic geometry patterns - sound-driven geometric formations with containment awareness if (cymateGeometry && audioEngine) { const freq = sphere.params.minFrequency + (sphere.params.maxFrequency - sphere.params.minFrequency) * 0.5 // Create geometric patterns based on frequency const geometricPattern = getCymatePattern(x, y, z, freq, currentTime * 0.001) // Scale cymatic intensity to balance audio reactivity with containment let cymateScale = 1.0 if (dist > boundaryZone) { // Moderate reduction near boundaries while preserving some reactivity cymateScale = 0.4 } else if (dist > coreZone) { // Gentle reduction outside core cymateScale = 1.0 - ((dist - coreZone) / (boundaryZone - coreZone)) * 0.4 } // Maintain stronger cymatic intensity for audio reactivity const organicIntensity = 0.0012 * cymateScale * (0.8 + 0.2 * Math.sin(currentTime * 0.0005)) vx += geometricPattern.x * organicIntensity vy += geometricPattern.y * organicIntensity vz += geometricPattern.z * organicIntensity } // Update positions x += vx y += vy z += vz // ENTRONAUT: Apply enhanced biomimetic coupling parameters const entronautParams = applyEntronautCoupling(sphere, i) // Optimized living entity behavior: adaptive computational load const entronautStep = Math.max(10, Math.floor(30 / adaptiveLevel)) // More aggressive stepping at low performance if (entronautEnabled && adaptiveCoupling && (i % entronautStep === 0)) { // Adaptive step size // Simplified flocking behavior with fewer neighbor checks let avgVx = 0, avgVy = 0, avgVz = 0 let neighborCount = 0 const flockRadius = 0.25 // Check only a few nearby particles for performance for (let j = Math.max(0, i - 20); j < Math.min(params.particleCount, i + 20); j += 5) { if (j === i) continue const j3 = j * 3 const dx = positions[j3] - x const dy = positions[j3 + 1] - y const dz = positions[j3 + 2] - z const distSq = dx*dx + dy*dy + dz*dz // Use squared distance to avoid sqrt if (distSq < flockRadius * flockRadius && distSq > 0) { avgVx += velocities[j3] avgVy += velocities[j3 + 1] avgVz += velocities[j3 + 2] neighborCount++ } } if (neighborCount > 0) { avgVx /= neighborCount avgVy /= neighborCount avgVz /= neighborCount // Reduce flocking influence to prevent convergence and preserve individuality const flockInfluence = entronautParams.coupling * 0.08 // Reduced from 0.2 // Add some randomness to promote emergence rather than convergence const emergenceRandomness = (Math.random() - 0.5) * 0.001 vx += (avgVx - vx) * flockInfluence + emergenceRandomness vy += (avgVy - vy) * flockInfluence + emergenceRandomness vz += (avgVz - vz) * flockInfluence + emergenceRandomness } } // Light metabolic pulsing to add organic variation without dampening if (entronautEnabled && adaptiveCoupling) { const metabolicPulse = entronautParams.diffusion * 0.3 // Reduced from 0.5 const timeVariation = currentTime * 0.0001 // Add time-based variation vx += metabolicPulse * Math.cos(i * 0.01 + timeVariation) vy += metabolicPulse * Math.sin(i * 0.01 + timeVariation) vz += metabolicPulse * Math.sin(i * 0.007 + timeVariation) * 0.5 // Add Z variation } // STABILITY: Velocity clamping to prevent runaway particles const velocity = Math.sqrt(vx*vx + vy*vy + vz*vz) if (velocity > maxVelocity) { const scale = maxVelocity / velocity vx *= scale vy *= scale vz *= scale } // Apply adaptive drag/damping with preservation of audio reactivity let dampingFactor = entronautParams.damping // Only apply extra damping in extreme zones to preserve energy if (dist > emergencyZone) { dampingFactor *= 0.9 // Light extra damping only near hard boundary } // Use less aggressive velocity decay to maintain particle liveliness const velocityDecay = config?.visualization?.physics?.velocityDecay || 0.998 // Increased from 0.995 dampingFactor = Math.max(dampingFactor, velocityDecay) // Use max to preserve energy vx *= dampingFactor vy *= dampingFactor vz *= dampingFactor // ENHANCED MULTI-LAYER CONTAINMENT SYSTEM // (dist, sphereRadius, and containment zones already calculated above) // HARD BOUNDARY - Immediate containment for escaped particles if (dist > hardBoundary) { // Immediately pull particle back to safe zone const pullbackFactor = 0.7 // Pull back to 70% of sphere radius const safeRadius = sphereRadius * pullbackFactor const safeX = (x / dist) * safeRadius const safeY = (y / dist) * safeRadius const safeZ = (z / dist) * safeRadius x = safeX y = safeY z = safeZ // Zero velocities for escaped particles vx *= 0.1 vy *= 0.1 vz *= 0.1 console.warn(`๐Ÿšจ Particle ${i} hard reset - distance: ${dist.toFixed(2)}`) } // EMERGENCY ZONE - Very strong containment else if (dist > emergencyZone && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Very strong inward force const emergencyForce = (dist - emergencyZone) / (hardBoundary - emergencyZone) * 0.025 vx -= dx * emergencyForce vy -= dy * emergencyForce vz -= dz * emergencyForce // Strong velocity damping const dampingFactor = 0.7 vx *= dampingFactor vy *= dampingFactor vz *= dampingFactor } // DANGER ZONE - Strong containment else if (dist > dangerZone && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Strong inward force const dangerForce = (dist - dangerZone) / (emergencyZone - dangerZone) * 0.015 vx -= dx * dangerForce vy -= dy * dangerForce vz -= dz * dangerForce // Medium velocity damping const dampingFactor = 0.85 vx *= dampingFactor vy *= dampingFactor vz *= dampingFactor } // BOUNDARY ZONE - Medium containment else if (dist > boundaryZone && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Medium inward force const boundaryForce = (dist - boundaryZone) / (dangerZone - boundaryZone) * 0.008 vx -= dx * boundaryForce vy -= dy * boundaryForce vz -= dz * boundaryForce // Light velocity damping const dampingFactor = 0.92 vx *= dampingFactor vy *= dampingFactor vz *= dampingFactor } // INNER ZONE - Gentle containment else if (dist > innerZone && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Gentle inward force const innerForce = (dist - innerZone) / (boundaryZone - innerZone) * 0.003 vx -= dx * innerForce vy -= dy * innerForce vz -= dz * innerForce } // GENTLE CENTER BIAS - Only for particles very far from center if (dist > sphereRadius * 0.9 && dist > 0) { const dx = x / dist const dy = y / dist const dz = z / dist // Very gentle pull only when approaching boundaries const centerBias = (dist - sphereRadius * 0.9) / (sphereRadius * 0.1) * 0.0008 vx -= dx * centerBias vy -= dy * centerBias vz -= dz * centerBias } // VELOCITY CLAMPING - Less restrictive to preserve audio reactivity let maxVel = config?.visualization?.physics?.maxVelocity || 0.025 // Increased base velocity if (dist > emergencyZone) { maxVel *= 0.6 // Moderate limit only in emergency zone } else if (dist > dangerZone) { maxVel *= 0.8 // Light limit in danger zone } const velMag = Math.sqrt(vx*vx + vy*vy + vz*vz) if (velMag > maxVel) { const scale = maxVel / velMag vx *= scale vy *= scale vz *= scale } // Respawn dead particles if (lt <= 0) { const radius = params.sphereRadius * params.innerSphereRadius const theta = Math.random() * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const r = Math.cbrt(Math.random()) * radius x = r * Math.sin(phi) * Math.cos(theta) y = r * Math.sin(phi) * Math.sin(theta) z = r * Math.cos(phi) vx = 0 vy = 0 vz = 0 lt = Math.random() * params.particleLifetime be = 0 } // Final stability check before updating arrays const finalDist = Math.sqrt(x*x + y*y + z*z) const finalVel = Math.sqrt(vx*vx + vy*vy + vz*vz) // Emergency stability check if (finalDist > sphereRadius * 1.5 || finalVel > 0.1 || !isFinite(finalDist) || !isFinite(finalVel)) { // Emergency reset - place particle safely in core zone const safeRadius = sphereRadius * 0.3 const theta = Math.random() * Math.PI * 2 const phi = Math.acos(2 * Math.random() - 1) const r = Math.cbrt(Math.random()) * safeRadius x = r * Math.sin(phi) * Math.cos(theta) y = r * Math.sin(phi) * Math.sin(theta) z = r * Math.cos(phi) vx = 0 vy = 0 vz = 0 console.warn(`๐Ÿšจ Emergency stability reset for particle ${i} - dist: ${finalDist.toFixed(2)}, vel: ${finalVel.toFixed(3)}`) } // Update arrays positions[i3] = x positions[i3 + 1] = y positions[i3 + 2] = z velocities[i3] = vx velocities[i3 + 1] = vy velocities[i3 + 2] = vz lifetimes[i] = lt beatEffects[i] = be } // Mark geometry for update if (sceneRef.current) { const particleSystem = sceneRef.current.children.find((child: any) => child.userData?.sphereIndex === sphere.index ) as any if (particleSystem?.geometry) { particleSystem.geometry.attributes.position.needsUpdate = true } } } // Update sphere rotation based on audio const updateSphereRotation = (sphere: ParticleSphere, _audioData: any) => { if (!audioEngine) return const volumeData = audioEngine.getSmoothVolume( sphere.lastValidVolume, sphere.params.volumeChangeThreshold ) if (volumeData.shouldUpdate) { const targetRotationSpeed = sphere.params.rotationSpeedMin + (sphere.params.rotationSpeedMax - sphere.params.rotationSpeedMin) * volumeData.volume sphere.lastRotationSpeed = sphere.params.rotationSpeed + (targetRotationSpeed - sphere.params.rotationSpeed) * sphere.params.rotationSmoothness sphere.lastValidVolume = volumeData.volume } // Apply rotation if (sceneRef.current) { const particleSystem = sceneRef.current.children.find((child: any) => child.userData?.sphereIndex === sphere.index ) as any if (particleSystem) { particleSystem.rotation.y += sphere.lastRotationSpeed } } } // Camera control functions const resetCameraPosition = useCallback(() => { if (!cameraRef.current || !controlsRef.current) return cameraRef.current.position.set(0, 0, 2.5) controlsRef.current.target.set(0, 0, 0) controlsRef.current.update() }, []) const setCameraPreset = useCallback((preset: 'default' | 'inside' | 'far' | 'top' | 'side') => { if (!cameraRef.current || !controlsRef.current) return switch (preset) { case 'default': cameraRef.current.position.set(0, 0, 2.5) break case 'inside': cameraRef.current.position.set(0, 0, 0.5) break case 'far': cameraRef.current.position.set(0, 0, 8) break case 'top': cameraRef.current.position.set(0, 5, 0) break case 'side': cameraRef.current.position.set(5, 0, 0) break } controlsRef.current.target.set(0, 0, 0) controlsRef.current.update() }, []) // Handle window resize const handleResize = useCallback(() => { if (!cameraRef.current || !rendererRef.current) return cameraRef.current.aspect = window.innerWidth / window.innerHeight cameraRef.current.updateProjectionMatrix() rendererRef.current.setSize(window.innerWidth, window.innerHeight) // Update controls on resize if (controlsRef.current) { controlsRef.current.handleResize?.() } }, []) // Initialize on mount useEffect(() => { initializeVisualization() window.addEventListener('resize', handleResize) // Listen for camera control disable events from audio dock const handleCameraControlToggle = (event: CustomEvent) => { if (controlsRef.current) { controlsRef.current.enabled = !event.detail && cameraControlsEnabled } } window.addEventListener('disableCameraControls', handleCameraControlToggle as EventListener) return () => { window.removeEventListener('resize', handleResize) window.removeEventListener('disableCameraControls', handleCameraControlToggle as EventListener) if (animationRef.current) { cancelAnimationFrame(animationRef.current) } if (controlsRef.current) { controlsRef.current.dispose() } } }, [initializeVisualization, handleResize, cameraControlsEnabled]) // Start animation when ready useEffect(() => { if (isVisualizationReady) { animationRef.current = requestAnimationFrame(animate) } return () => { if (animationRef.current) { cancelAnimationFrame(animationRef.current) } } }, [isVisualizationReady, animate]) return (
{ // Enable camera controls when mouse enters visualization area if (controlsRef.current && cameraControlsEnabled) { controlsRef.current.enabled = true } }} /> {/* Compact Controls Panel */}
{ // Disable camera controls when mouse enters controls panel const event = new CustomEvent('disableCameraControls', { detail: true }) window.dispatchEvent(event) }} onMouseLeave={() => { // Re-enable camera controls when mouse leaves controls panel const event = new CustomEvent('disableCameraControls', { detail: false }) window.dispatchEvent(event) }} > {/* Collapse/Expand Toggle */} {/* Collapsed State Indicator */} {controlsCollapsed && (
โŸ
entity
interface
)} {/* Full Controls Panel */}

โŸ Liminal Sessions โŸ

โ‰ˆ intercepted transmission โ‰ˆ
โ—ฆ audio-reactive entity โ—ฆ
{/* Scrollable Content Area */}
{ e.currentTarget.style.setProperty('--webkit-scrollbar-width', '6px') e.currentTarget.style.setProperty('--webkit-scrollbar-track-background', 'transparent') e.currentTarget.style.setProperty('--webkit-scrollbar-thumb-background', 'var(--copper-medium)') e.currentTarget.style.setProperty('--webkit-scrollbar-thumb-border-radius', '3px') }} >
{ const count = parseInt(e.target.value) setActiveSpheresCount(count) spheresRef.current.forEach((sphere, index) => { sphere.params.enabled = index < count if (sceneRef.current) { const particleSystem = sceneRef.current.children.find((child: any) => child.userData?.sphereIndex === sphere.index ) as any if (particleSystem) { particleSystem.visible = sphere.params.enabled } } }) }} style={{ width: '100%' }} />
setTendrilDensity(parseFloat(e.target.value))} disabled={!tendrilsEnabled} style={{ width: '100%' }} />
setVineComplexity(parseInt(e.target.value))} disabled={!dysonSphereEnabled} style={{ width: '100%' }} />
setVineGrowthRate(parseFloat(e.target.value))} disabled={!dysonSphereEnabled} style={{ width: '100%' }} />
{/* Performance Stats Display */}
โšก quality: 100%
๐Ÿ–ฅ๏ธ particles: {performanceStats.particleCount.toLocaleString()}
๐Ÿ“Š performance: {performanceStats.fps >= 45 ? 'optimal' : performanceStats.fps >= 30 ? 'good' : 'stressed'}
{/* Manual Refresh Button */}
{/* Camera Preset Buttons */} {cameraControlsEnabled && (
Camera Presets:
)}
โ—ฆ audio-reactive โ—ฆ | โ‰‹ beat-detection โ‰‹ | โŸ dynamic-noise โŸ
โ—ฏ {spheresRef.current.filter(s => s.params.enabled).length} entities | โœฆ {performanceStats.particleCount.toLocaleString()} particles
โงจ {performanceStats.fps} fps | transmission {performanceStats.fps >= 45 ? 'stable' : performanceStats.fps >= 30 ? 'fluctuating' : 'unstable'}
{cymateGeometry &&
โ—ˆ cymatic patterns active
} {tendrilsEnabled &&
โŸจโŸฉ neural tendrils ({Math.round(tendrilDensity * 100)}% density)
} {dysonSphereEnabled &&
๐ŸŒฟ growing vines ({vineComplexity} complexity, {Math.round(vineGrowthRate * 1000)}% growth)
} {cameraControlsEnabled && (
โŸ observer: orbit | zoom | pan
)} {entronautEnabled && (
โŸ sefa analysis: {entronautStateRef.current ? 'active' : 'initializing'}
{entronautStateRef.current && ( <>
complexity: {(entronautStateRef.current.informationMetrics.complexity * 100).toFixed(1)}%
emergence: {(entronautStateRef.current.informationMetrics.emergence * 100).toFixed(1)}%
coherence: {(entronautStateRef.current.informationMetrics.coherence * 100).toFixed(1)}%
{adaptiveCoupling && (
โงจ biomimetic coupling active
)} )}
)}
sub-bass (20-80hz) | bass (120-250hz) | mid (250-800hz)
high-mid (1k-4khz) | high (5k-10khz)
{/* About Section - Expanded Clickable Widget */}
setAboutCollapsed(!aboutCollapsed)} style={{ position: 'fixed', bottom: aboutCollapsed ? '20px' : '5%', left: aboutCollapsed ? '50%' : '50%', transform: aboutCollapsed ? 'translateX(-50%) translateY(calc(100% - 75px))' : 'translateX(-50%) translateY(0)', zIndex: 1000, background: 'linear-gradient(135deg, var(--marble-dark), var(--teal-dark))', borderRadius: aboutCollapsed ? '10px' : '15px', color: 'var(--copper-light)', fontFamily: 'Metamorphous, serif', width: aboutCollapsed ? '420px' : '90vw', minWidth: aboutCollapsed ? '420px' : '800px', maxWidth: aboutCollapsed ? '420px' : '1200px', height: aboutCollapsed ? 'auto' : '80vh', maxHeight: aboutCollapsed ? 'none' : '80vh', transition: 'all 0.5s ease-in-out', backdropFilter: 'blur(20px)', border: '2px solid var(--copper-medium)', pointerEvents: 'auto', boxShadow: aboutCollapsed ? '0 4px 20px var(--copper-dark), inset 0 0 15px var(--teal-dark)' : '0 10px 40px rgba(0, 0, 0, 0.7), inset 0 0 25px var(--teal-dark)', cursor: 'pointer', overflow: aboutCollapsed ? 'visible' : 'hidden' }} onMouseEnter={(e) => { // Disable camera controls when mouse enters about section const event = new CustomEvent('disableCameraControls', { detail: true }) window.dispatchEvent(event) // Add hover effect e.currentTarget.style.borderColor = 'var(--transmission-glow)' e.currentTarget.style.boxShadow = '0 6px 25px var(--transmission-glow)' }} onMouseLeave={(e) => { // Re-enable camera controls when mouse leaves about section const event = new CustomEvent('disableCameraControls', { detail: false }) window.dispatchEvent(event) // Remove hover effect e.currentTarget.style.borderColor = 'var(--copper-medium)' e.currentTarget.style.boxShadow = '0 4px 20px var(--copper-dark)' }} > {/* Collapsed State - Clickable Widget */} {aboutCollapsed && (
โŸ
- liminal sessions -
โ—ฆ click to access entity data โ—ฆ
โŸจ
)} {/* Expanded State - Full About Panel */} {!aboutCollapsed && (
{/* Subtle Logo Background */}
{/* Content Overlay */}

โŸ Liminal Sessions โŸ

{ e.currentTarget.style.opacity = '1' e.currentTarget.style.transform = 'scale(1.1)' }} onMouseLeave={(e) => { e.currentTarget.style.opacity = '0.7' e.currentTarget.style.transform = 'scale(1)' }} >โŸฉ

Liminal Sessions emerges from the spaces between heartbeats, where ancient algorithms carved themselves into stone before mathematics had names.

Their sound excavates frequencies buried beneath millennia of sediment, translating the geometric hymns that echo in empty cathedrals and forgotten temples. Through acoustic brutality and primordial precision, they channel the conversations between wood and metal, breath and bone, time and its shadows.

The music arrives as if summoned from depths where djent mathematics merge with earth's oldest songs. Each composition becomes an archaeological expedition into the strata of sound, where rhythm serves as both excavation tool and ancient map.

They are archaeologists of sound, unearthing the sacred geometry that binds chaos to rhythm in the liminal space where all echoes converge.

โ—ˆ Transmission Properties

โ™ช ambient electronic resonance
โ—ฏ audio-visual emergence field
โ‰‹ real-time particle dynamics
โŸ symbolic emergence field analysis
โงจ biomimetic coupling systems
โ—ˆ cymatic pattern generation
โ—ฆ click anywhere to close and return to visualization โ—ฆ
)}
{/* Startup Info Message */} {showStartupInfo && (
โŸ

Visualization Awaiting Signal

The particle field remains dormant until audio transmission begins.

Press the play button or select a track from the audio interface to activate the visualization.

โ—ฆ this message will disappear once audio begins โ—ฆ
)} {/* Floating Refresh Button - Top Right */}
{/* Add CSS animation for spinning */}
) }