Severian commited on
Commit
827acdb
·
verified ·
1 Parent(s): 079307d

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
- // Simple FPS monitoring - no complex optimization
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
- display: 'flex',
2340
- alignItems: 'center',
2341
- justifyContent: 'space-between',
2342
- marginBottom: '15px'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>