Spaces:
Sleeping
Sleeping
Update src/components/WorldTreeVisualizer.tsx
Browse files
src/components/WorldTreeVisualizer.tsx
CHANGED
|
@@ -86,6 +86,119 @@ export const WorldTreeVisualizer: React.FC<WorldTreeVisualizerProps> = ({ audioE
|
|
| 86 |
frameCount: 0
|
| 87 |
})
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
// ENTRONAUT: Initialize emergence field analysis - SIMPLIFIED for performance
|
| 90 |
const initializeEntronaut = useCallback(() => {
|
| 91 |
// Simplified - basic structure for UI display only
|
|
@@ -692,7 +805,7 @@ export const WorldTreeVisualizer: React.FC<WorldTreeVisualizerProps> = ({ audioE
|
|
| 692 |
const deltaTime = lastTimeRef.current ? (currentTime - lastTimeRef.current) / 1000 : 0
|
| 693 |
lastTimeRef.current = currentTime
|
| 694 |
|
| 695 |
-
//
|
| 696 |
setPerformanceStats(prev => {
|
| 697 |
const frameCount = prev.frameCount + 1
|
| 698 |
const timeSinceLastUpdate = currentTime - prev.lastFpsUpdate
|
|
@@ -702,6 +815,52 @@ export const WorldTreeVisualizer: React.FC<WorldTreeVisualizerProps> = ({ audioE
|
|
| 702 |
const totalParticles = spheresRef.current.reduce((sum, sphere) =>
|
| 703 |
sum + (sphere.params.enabled ? sphere.params.particleCount : 0), 0)
|
| 704 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
return {
|
| 706 |
fps,
|
| 707 |
particleCount: totalParticles,
|
|
@@ -2333,14 +2492,36 @@ export const WorldTreeVisualizer: React.FC<WorldTreeVisualizerProps> = ({ audioE
|
|
| 2333 |
{!aboutCollapsed && (
|
| 2334 |
<div style={{
|
| 2335 |
padding: '20px',
|
| 2336 |
-
transition: 'all 0.3s ease-in-out'
|
|
|
|
| 2337 |
}}>
|
|
|
|
| 2338 |
<div style={{
|
| 2339 |
-
|
| 2340 |
-
|
| 2341 |
-
|
| 2342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2343 |
}}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2344 |
<h3 className="ancient-title" style={{
|
| 2345 |
margin: 0,
|
| 2346 |
fontSize: '15px',
|
|
@@ -2385,6 +2566,7 @@ export const WorldTreeVisualizer: React.FC<WorldTreeVisualizerProps> = ({ audioE
|
|
| 2385 |
<div><span className="rune">◯</span> audio-visual emergence field</div>
|
| 2386 |
<div><span className="rune">≋</span> real-time particle dynamics</div>
|
| 2387 |
</div>
|
|
|
|
| 2388 |
</div>
|
| 2389 |
)}
|
| 2390 |
</div>
|
|
|
|
| 86 |
frameCount: 0
|
| 87 |
})
|
| 88 |
|
| 89 |
+
// Hidden Auto-Refresh System
|
| 90 |
+
const autoRefreshRef = useRef({
|
| 91 |
+
lastRefresh: 0,
|
| 92 |
+
refreshInterval: 120000, // 2 minutes base interval
|
| 93 |
+
performanceDegradationCount: 0,
|
| 94 |
+
particleHealthChecks: 0,
|
| 95 |
+
emergencyResetCount: 0,
|
| 96 |
+
isRefreshing: false
|
| 97 |
+
})
|
| 98 |
+
|
| 99 |
+
// Monitor particle system health
|
| 100 |
+
const checkParticleHealth = useCallback(() => {
|
| 101 |
+
if (!spheresRef.current) return true
|
| 102 |
+
|
| 103 |
+
let healthyParticles = 0
|
| 104 |
+
let totalParticles = 0
|
| 105 |
+
|
| 106 |
+
spheresRef.current.forEach(sphere => {
|
| 107 |
+
if (!sphere.params.enabled) return
|
| 108 |
+
|
| 109 |
+
const { positions, velocities } = sphere
|
| 110 |
+
const particleCount = sphere.params.particleCount
|
| 111 |
+
totalParticles += particleCount
|
| 112 |
+
|
| 113 |
+
for (let i = 0; i < particleCount; i++) {
|
| 114 |
+
const i3 = i * 3
|
| 115 |
+
const x = positions[i3]
|
| 116 |
+
const y = positions[i3 + 1]
|
| 117 |
+
const z = positions[i3 + 2]
|
| 118 |
+
const vx = velocities[i3]
|
| 119 |
+
const vy = velocities[i3 + 1]
|
| 120 |
+
const vz = velocities[i3 + 2]
|
| 121 |
+
|
| 122 |
+
// Check if particle is healthy (finite values, reasonable position/velocity)
|
| 123 |
+
if (isFinite(x) && isFinite(y) && isFinite(z) &&
|
| 124 |
+
isFinite(vx) && isFinite(vy) && isFinite(vz)) {
|
| 125 |
+
const dist = Math.sqrt(x*x + y*y + z*z)
|
| 126 |
+
const vel = Math.sqrt(vx*vx + vy*vy + vz*vz)
|
| 127 |
+
|
| 128 |
+
if (dist < 10 && vel < 1) { // Reasonable bounds
|
| 129 |
+
healthyParticles++
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
})
|
| 134 |
+
|
| 135 |
+
const healthRatio = totalParticles > 0 ? healthyParticles / totalParticles : 1
|
| 136 |
+
return healthRatio > 0.85 // 85% healthy particles threshold
|
| 137 |
+
}, [])
|
| 138 |
+
|
| 139 |
+
// Perform hidden refresh of particle systems
|
| 140 |
+
const performHiddenRefresh = useCallback(async (force = false) => {
|
| 141 |
+
if (autoRefreshRef.current.isRefreshing && !force) return
|
| 142 |
+
|
| 143 |
+
autoRefreshRef.current.isRefreshing = true
|
| 144 |
+
console.log('🔄 Performing hidden system refresh...')
|
| 145 |
+
|
| 146 |
+
try {
|
| 147 |
+
// Gradual refresh to avoid frame drops
|
| 148 |
+
for (let sphereIndex = 0; sphereIndex < spheresRef.current.length; sphereIndex++) {
|
| 149 |
+
const sphere = spheresRef.current[sphereIndex]
|
| 150 |
+
if (!sphere.params.enabled) continue
|
| 151 |
+
|
| 152 |
+
// Refresh 20% of particles at a time over 5 frames
|
| 153 |
+
const particleCount = sphere.params.particleCount
|
| 154 |
+
const batchSize = Math.floor(particleCount * 0.2)
|
| 155 |
+
|
| 156 |
+
for (let batch = 0; batch < 5; batch++) {
|
| 157 |
+
const startIdx = batch * batchSize
|
| 158 |
+
const endIdx = Math.min(startIdx + batchSize, particleCount)
|
| 159 |
+
|
| 160 |
+
// Reset particles in this batch
|
| 161 |
+
for (let i = startIdx; i < endIdx; i++) {
|
| 162 |
+
const i3 = i * 3
|
| 163 |
+
const radius = sphere.params.sphereRadius * sphere.params.innerSphereRadius
|
| 164 |
+
const theta = Math.random() * Math.PI * 2
|
| 165 |
+
const phi = Math.acos(2 * Math.random() - 1)
|
| 166 |
+
const r = Math.cbrt(Math.random()) * radius
|
| 167 |
+
|
| 168 |
+
sphere.positions[i3] = r * Math.sin(phi) * Math.cos(theta)
|
| 169 |
+
sphere.positions[i3 + 1] = r * Math.sin(phi) * Math.sin(theta)
|
| 170 |
+
sphere.positions[i3 + 2] = r * Math.cos(phi)
|
| 171 |
+
|
| 172 |
+
sphere.velocities[i3] = 0
|
| 173 |
+
sphere.velocities[i3 + 1] = 0
|
| 174 |
+
sphere.velocities[i3 + 2] = 0
|
| 175 |
+
|
| 176 |
+
sphere.lifetimes[i] = Math.random() * sphere.params.particleLifetime
|
| 177 |
+
sphere.beatEffects[i] = 0
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
// Wait one frame between batches to maintain smooth animation
|
| 181 |
+
if (batch < 4) {
|
| 182 |
+
await new Promise(resolve => requestAnimationFrame(() => resolve(undefined)))
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
// Note: Geometry updates are handled by the main animation loop
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
// Reset counters
|
| 190 |
+
autoRefreshRef.current.performanceDegradationCount = 0
|
| 191 |
+
autoRefreshRef.current.emergencyResetCount = 0
|
| 192 |
+
autoRefreshRef.current.lastRefresh = Date.now()
|
| 193 |
+
|
| 194 |
+
console.log('✅ Hidden refresh completed successfully')
|
| 195 |
+
} catch (error) {
|
| 196 |
+
console.warn('⚠️ Hidden refresh error:', error)
|
| 197 |
+
} finally {
|
| 198 |
+
autoRefreshRef.current.isRefreshing = false
|
| 199 |
+
}
|
| 200 |
+
}, [])
|
| 201 |
+
|
| 202 |
// ENTRONAUT: Initialize emergence field analysis - SIMPLIFIED for performance
|
| 203 |
const initializeEntronaut = useCallback(() => {
|
| 204 |
// Simplified - basic structure for UI display only
|
|
|
|
| 805 |
const deltaTime = lastTimeRef.current ? (currentTime - lastTimeRef.current) / 1000 : 0
|
| 806 |
lastTimeRef.current = currentTime
|
| 807 |
|
| 808 |
+
// Enhanced FPS monitoring with auto-refresh triggers
|
| 809 |
setPerformanceStats(prev => {
|
| 810 |
const frameCount = prev.frameCount + 1
|
| 811 |
const timeSinceLastUpdate = currentTime - prev.lastFpsUpdate
|
|
|
|
| 815 |
const totalParticles = spheresRef.current.reduce((sum, sphere) =>
|
| 816 |
sum + (sphere.params.enabled ? sphere.params.particleCount : 0), 0)
|
| 817 |
|
| 818 |
+
// Hidden Auto-Refresh Logic
|
| 819 |
+
const autoRefresh = autoRefreshRef.current
|
| 820 |
+
const now = Date.now()
|
| 821 |
+
|
| 822 |
+
// Check for performance degradation
|
| 823 |
+
if (fps < 30) {
|
| 824 |
+
autoRefresh.performanceDegradationCount++
|
| 825 |
+
} else {
|
| 826 |
+
autoRefresh.performanceDegradationCount = Math.max(0, autoRefresh.performanceDegradationCount - 1)
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
// Check particle health every 5 seconds
|
| 830 |
+
if (frameCount % 5 === 0) {
|
| 831 |
+
autoRefresh.particleHealthChecks++
|
| 832 |
+
const isHealthy = checkParticleHealth()
|
| 833 |
+
|
| 834 |
+
if (!isHealthy) {
|
| 835 |
+
autoRefresh.emergencyResetCount++
|
| 836 |
+
}
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
+
// Trigger hidden refresh if conditions are met
|
| 840 |
+
const timeSinceLastRefresh = now - autoRefresh.lastRefresh
|
| 841 |
+
const shouldRefresh = (
|
| 842 |
+
// Periodic refresh (every 2 minutes base)
|
| 843 |
+
timeSinceLastRefresh > autoRefresh.refreshInterval ||
|
| 844 |
+
// Performance degradation (3 consecutive low FPS readings)
|
| 845 |
+
autoRefresh.performanceDegradationCount >= 3 ||
|
| 846 |
+
// Particle health issues (2 consecutive unhealthy checks)
|
| 847 |
+
autoRefresh.emergencyResetCount >= 2
|
| 848 |
+
)
|
| 849 |
+
|
| 850 |
+
if (shouldRefresh && !autoRefresh.isRefreshing) {
|
| 851 |
+
// Adjust refresh interval based on performance
|
| 852 |
+
if (autoRefresh.performanceDegradationCount >= 3) {
|
| 853 |
+
autoRefresh.refreshInterval = 60000 // 1 minute for poor performance
|
| 854 |
+
} else if (fps > 45) {
|
| 855 |
+
autoRefresh.refreshInterval = 180000 // 3 minutes for good performance
|
| 856 |
+
} else {
|
| 857 |
+
autoRefresh.refreshInterval = 120000 // 2 minutes default
|
| 858 |
+
}
|
| 859 |
+
|
| 860 |
+
// Perform refresh without blocking the main thread
|
| 861 |
+
setTimeout(() => performHiddenRefresh(), 100)
|
| 862 |
+
}
|
| 863 |
+
|
| 864 |
return {
|
| 865 |
fps,
|
| 866 |
particleCount: totalParticles,
|
|
|
|
| 2492 |
{!aboutCollapsed && (
|
| 2493 |
<div style={{
|
| 2494 |
padding: '20px',
|
| 2495 |
+
transition: 'all 0.3s ease-in-out',
|
| 2496 |
+
position: 'relative'
|
| 2497 |
}}>
|
| 2498 |
+
{/* Subtle Logo Background */}
|
| 2499 |
<div style={{
|
| 2500 |
+
position: 'absolute',
|
| 2501 |
+
top: 0,
|
| 2502 |
+
left: 0,
|
| 2503 |
+
right: 0,
|
| 2504 |
+
bottom: 0,
|
| 2505 |
+
backgroundImage: 'url(/images/logo.webp)',
|
| 2506 |
+
backgroundSize: 'contain',
|
| 2507 |
+
backgroundRepeat: 'no-repeat',
|
| 2508 |
+
backgroundPosition: 'center center',
|
| 2509 |
+
opacity: 0.18,
|
| 2510 |
+
borderRadius: '10px',
|
| 2511 |
+
pointerEvents: 'none'
|
| 2512 |
+
}} />
|
| 2513 |
+
|
| 2514 |
+
{/* Content Overlay */}
|
| 2515 |
+
<div style={{
|
| 2516 |
+
position: 'relative',
|
| 2517 |
+
zIndex: 2
|
| 2518 |
}}>
|
| 2519 |
+
<div style={{
|
| 2520 |
+
display: 'flex',
|
| 2521 |
+
alignItems: 'center',
|
| 2522 |
+
justifyContent: 'space-between',
|
| 2523 |
+
marginBottom: '15px'
|
| 2524 |
+
}}>
|
| 2525 |
<h3 className="ancient-title" style={{
|
| 2526 |
margin: 0,
|
| 2527 |
fontSize: '15px',
|
|
|
|
| 2566 |
<div><span className="rune">◯</span> audio-visual emergence field</div>
|
| 2567 |
<div><span className="rune">≋</span> real-time particle dynamics</div>
|
| 2568 |
</div>
|
| 2569 |
+
</div>
|
| 2570 |
</div>
|
| 2571 |
)}
|
| 2572 |
</div>
|