awacke1 commited on
Commit
072b941
·
verified ·
1 Parent(s): 1bc509f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +459 -1283
index.html CHANGED
@@ -3,1340 +3,516 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AI Agentic Demo - Dynamic Fractals & 3D Control</title>
7
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
8
  <style>
9
- body {
10
- margin: 0;
11
- padding: 0;
12
- background: linear-gradient(135deg, #0c0c0c 0%, #1a1a2e 50%, #16213e 100%);
13
- font-family: 'Courier New', monospace;
14
- color: #00ff88;
15
- overflow: hidden;
16
- }
17
-
18
- .dashboard {
19
  position: absolute;
20
- top: 0;
21
- left: 0;
22
- width: 100%;
23
- height: 100%;
24
- display: grid;
25
- grid-template-columns: 300px 1fr 300px;
26
- grid-template-rows: 60px 1fr 200px;
27
- gap: 10px;
28
- padding: 10px;
29
- box-sizing: border-box;
30
- }
31
-
32
- .header {
33
- grid-column: 1 / -1;
34
- background: rgba(0, 255, 136, 0.1);
35
- border: 1px solid #00ff88;
36
- border-radius: 8px;
37
- display: flex;
38
- align-items: center;
39
- justify-content: space-between;
40
- padding: 0 20px;
41
- backdrop-filter: blur(10px);
42
- }
43
-
44
- .ai-panel {
45
- background: rgba(0, 255, 136, 0.05);
46
- border: 1px solid #00ff88;
47
- border-radius: 8px;
48
  padding: 15px;
49
- backdrop-filter: blur(10px);
50
- overflow-y: auto;
51
- }
52
-
53
- .viz-container {
54
- position: relative;
55
- border: 1px solid #00ff88;
56
- border-radius: 8px;
57
- overflow: hidden;
58
- background: rgba(0, 0, 0, 0.3);
59
- }
60
-
61
- .control-panel {
62
- grid-column: 1 / -1;
63
- background: rgba(0, 255, 136, 0.05);
64
- border: 1px solid #00ff88;
65
  border-radius: 8px;
66
- padding: 15px;
67
- backdrop-filter: blur(10px);
68
- display: grid;
69
- grid-template-columns: repeat(4, 1fr);
70
- gap: 15px;
 
71
  }
72
-
73
- .agent-card {
74
- background: rgba(0, 255, 136, 0.1);
75
- border: 1px solid #00ff88;
76
- border-radius: 4px;
77
- padding: 10px;
78
  margin-bottom: 10px;
79
- transition: all 0.3s ease;
80
- }
81
-
82
- .agent-card:hover {
83
- background: rgba(0, 255, 136, 0.2);
84
- transform: translateX(5px);
85
- }
86
-
87
- .agent-status {
88
- display: inline-block;
89
- width: 8px;
90
- height: 8px;
91
- border-radius: 50%;
92
- margin-right: 8px;
93
  }
94
-
95
- .active { background: #00ff88; }
96
- .idle { background: #ffaa00; }
97
- .error { background: #ff4444; }
98
-
99
- button {
100
- background: linear-gradient(45deg, #00ff88, #00cc66);
101
- border: none;
102
- border-radius: 4px;
103
- color: #000;
104
- padding: 8px 16px;
105
- font-weight: bold;
106
- cursor: pointer;
107
- transition: all 0.3s ease;
108
- font-family: inherit;
109
  }
110
-
111
- button:hover {
112
- transform: translateY(-2px);
113
- box-shadow: 0 4px 12px rgba(0, 255, 136, 0.3);
114
  }
115
-
116
- .code-block {
117
- background: rgba(0, 0, 0, 0.6);
118
- border: 1px solid #333;
119
- border-radius: 4px;
120
- padding: 10px;
121
- font-family: 'Courier New', monospace;
122
- font-size: 12px;
123
- margin: 10px 0;
124
- overflow-x: auto;
125
- }
126
-
127
- .log-entry {
128
- background: rgba(0, 255, 136, 0.1);
129
- border-left: 3px solid #00ff88;
130
- padding: 8px;
131
- margin: 5px 0;
132
- border-radius: 0 4px 4px 0;
133
- font-size: 12px;
134
- }
135
-
136
- input[type="range"] {
137
  width: 100%;
138
- margin: 10px 0;
139
- }
140
-
141
- .fractal-params {
142
- display: grid;
143
- grid-template-columns: 1fr 1fr;
144
- gap: 10px;
145
- margin-top: 10px;
146
- }
147
-
148
- .param-group {
149
  display: flex;
150
  flex-direction: column;
151
- gap: 5px;
 
 
 
 
152
  }
153
-
154
- label {
155
- font-size: 12px;
156
- color: #00ff88;
 
 
 
 
 
 
 
 
157
  }
158
  </style>
 
159
  </head>
160
  <body>
161
- <div class="dashboard">
162
- <div class="header">
163
- <h1>🤖 AI Agentic Control System</h1>
164
- <div>
165
- <span id="status">🟢 System Active</span>
166
- <span style="margin-left: 20px;">FPS: <span id="fps">60</span></span>
167
- </div>
168
- </div>
169
-
170
- <div class="ai-panel">
171
- <h3>🧠 AI Agents</h3>
172
- <div id="agents-container">
173
- <!-- Agents will be populated here -->
174
- </div>
175
-
176
- <h4>📊 System Logs</h4>
177
- <div id="logs-container">
178
- <!-- Logs will appear here -->
179
- </div>
180
- </div>
181
-
182
- <div class="viz-container">
183
- <canvas id="three-canvas"></canvas>
184
- </div>
185
-
186
- <div class="ai-panel">
187
- <h3>🔧 Dynamic Code Engine</h3>
188
- <button onclick="updateFractalCode()">🔄 Evolve Fractal</button>
189
- <button onclick="generateNewSurface()">🌊 New Surface</button>
190
-
191
- <div class="code-block" id="current-code">
192
- // Current fractal function
193
- z = z² + c
194
- </div>
195
-
196
- <h4>🎯 Active Targets</h4>
197
- <div id="targets-list">
198
- <div class="log-entry">Target: Web App Control</div>
199
- <div class="log-entry">Target: Fractal Evolution</div>
200
- <div class="log-entry">Target: 3D Animation</div>
201
- </div>
202
- </div>
203
-
204
- <div class="control-panel">
205
- <div>
206
- <h4>🌀 Fractal Controls</h4>
207
- <div class="fractal-params">
208
- <div class="param-group">
209
- <label>Iterations:</label>
210
- <input type="range" id="iterations" min="10" max="200" value="50">
211
- </div>
212
- <div class="param-group">
213
- <label>Zoom:</label>
214
- <input type="range" id="zoom" min="0.1" max="5" step="0.1" value="1">
215
- </div>
216
- <div class="param-group">
217
- <label>C Real:</label>
218
- <input type="range" id="c-real" min="-2" max="2" step="0.01" value="-0.7">
219
- </div>
220
- <div class="param-group">
221
- <label>C Imag:</label>
222
- <input type="range" id="c-imag" min="-2" max="2" step="0.01" value="0.27">
223
- </div>
224
- </div>
225
- </div>
226
-
227
- <div>
228
- <h4>🏙️ City Controls</h4>
229
- <button onclick="addPerson()">🚶 Add Person</button>
230
- <button onclick="addVehicle()">🚗 Add Vehicle</button>
231
- <button onclick="addAnimal()">🐕 Add Animal</button>
232
- <button onclick="toggleTimeSpeed()">⏰ Time Speed</button>
233
- </div>
234
-
235
- <div>
236
- <h4>☀️ Day/Night</h4>
237
- <button onclick="forceDayTime()">☀️ Force Day</button>
238
- <button onclick="forceNightTime()">🌙 Force Night</button>
239
- <button onclick="randomizeColors()">🎨 Colors</button>
240
- <button onclick="addControlPoint()">✨ Add Orb</button>
241
- </div>
242
-
243
- <div>
244
- <h4>🚀 Agent Actions</h4>
245
- <button onclick="deployAgent('fractal')">🌀 Fractal Agent</button>
246
- <button onclick="deployAgent('visual')">👁️ Visual Agent</button>
247
- <button onclick="deployAgent('control')">🎮 Control Agent</button>
248
- <button onclick="deployAgent('browser')">🌐 Browser Agent</button>
249
- </div>
250
-
251
- <div>
252
- <h4>📡 System Status</h4>
253
- <div style="font-size: 12px;">
254
- <div>People: <span id="people-count">8</span></div>
255
- <div>Vehicles: <span id="vehicle-count">9</span></div>
256
- <div>Animals: <span id="animal-count">11</span></div>
257
- <div>Time: <span id="time-cycle">Day</span></div>
258
- </div>
259
- </div>
260
- </div>
261
  </div>
 
262
 
263
- <script>
264
- // AI Agent System
265
- class AIAgent {
266
- constructor(name, type, color) {
267
- this.name = name;
268
- this.type = type;
269
- this.color = color;
270
- this.status = 'idle';
271
- this.tasks = [];
272
- this.lastUpdate = Date.now();
273
- }
274
-
275
- execute(task) {
276
- this.status = 'active';
277
- this.tasks.push(task);
278
- addLog(`${this.name}: Executing ${task}`);
279
-
280
- // Simulate agent work
281
- setTimeout(() => {
282
- this.status = 'idle';
283
- addLog(`${this.name}: Completed ${task}`);
284
- }, Math.random() * 2000 + 1000);
285
  }
286
  }
287
-
288
- // Initialize AI Agents
289
- const agents = [
290
- new AIAgent('Fractal-AI', 'computation', '#00ff88'),
291
- new AIAgent('Visual-AI', 'graphics', '#ff6b6b'),
292
- new AIAgent('Control-AI', 'interface', '#4ecdc4'),
293
- new AIAgent('Browser-AI', 'automation', '#45b7d1')
294
- ];
295
-
296
- // Three.js Setup
297
- let scene, camera, renderer, fractalMesh, controlPoints = [];
298
- let animationId;
299
- let isAnimating = true;
300
-
301
- // City elements
302
- let buildings = [];
303
- let people = [];
304
- let vehicles = [];
305
- let animals = [];
306
- let dayNightCycle = { time: 0, sunLight: null, moonLight: null, ambientLight: null };
307
-
308
- function initThreeJS() {
309
- const container = document.getElementById('three-canvas');
310
- const rect = container.parentElement.getBoundingClientRect();
311
-
312
- scene = new THREE.Scene();
313
- camera = new THREE.PerspectiveCamera(75, rect.width / rect.height, 0.1, 1000);
314
- renderer = new THREE.WebGLRenderer({ canvas: container, alpha: true });
315
- renderer.setSize(rect.width, rect.height);
316
- renderer.setClearColor(0x87CEEB, 1.0); // Sky blue
 
 
317
  renderer.shadowMap.enabled = true;
318
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
319
-
320
- // Setup lighting system
321
- setupLighting();
322
-
323
- // Create city environment
324
- createCity();
325
- createPeople();
326
- createVehicles();
327
- createAnimals();
328
-
329
- // Create dynamic fractal surface (smaller, positioned as part of city)
330
- createFractalSurface();
331
-
332
- camera.position.set(0, 8, 12);
333
- camera.lookAt(0, 0, 0);
334
-
335
- animate();
336
- }
337
-
338
- function setupLighting() {
339
- // Ambient light
340
- dayNightCycle.ambientLight = new THREE.AmbientLight(0x404040, 0.3);
341
- scene.add(dayNightCycle.ambientLight);
342
-
343
- // Sun light
344
- dayNightCycle.sunLight = new THREE.DirectionalLight(0xffffff, 1.0);
345
- dayNightCycle.sunLight.position.set(10, 10, 5);
346
- dayNightCycle.sunLight.castShadow = true;
347
- dayNightCycle.sunLight.shadow.mapSize.width = 2048;
348
- dayNightCycle.sunLight.shadow.mapSize.height = 2048;
349
- scene.add(dayNightCycle.sunLight);
350
-
351
- // Moon light
352
- dayNightCycle.moonLight = new THREE.DirectionalLight(0x6666ff, 0.3);
353
- dayNightCycle.moonLight.position.set(-10, 8, -5);
354
- dayNightCycle.moonLight.castShadow = true;
355
- dayNightCycle.moonLight.visible = false;
356
- scene.add(dayNightCycle.moonLight);
357
- }
358
-
359
- function createCity() {
360
- // Ground
361
- const groundGeometry = new THREE.PlaneGeometry(20, 20);
362
- const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x444444 });
 
 
 
 
 
 
 
 
 
 
363
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
364
  ground.rotation.x = -Math.PI / 2;
365
  ground.receiveShadow = true;
366
  scene.add(ground);
367
-
368
- // Create buildings with animated windows
369
- for (let i = 0; i < 12; i++) {
370
- createBuilding(
371
- (Math.random() - 0.5) * 15,
372
- 0,
373
- (Math.random() - 0.5) * 15
374
- );
375
- }
376
-
377
- // Streets
378
- createStreets();
379
  }
380
-
381
- function createBuilding(x, y, z) {
382
- const height = Math.random() * 4 + 2;
383
- const width = Math.random() * 1.5 + 1;
384
- const depth = Math.random() * 1.5 + 1;
385
-
386
- // Building structure
387
- const buildingGeometry = new THREE.BoxGeometry(width, height, depth);
388
- const buildingMaterial = new THREE.MeshLambertMaterial({
389
- color: new THREE.Color().setHSL(Math.random() * 0.1 + 0.15, 0.3, 0.4)
390
- });
391
- const building = new THREE.Mesh(buildingGeometry, buildingMaterial);
392
- building.position.set(x, height / 2, z);
393
- building.castShadow = true;
394
- building.receiveShadow = true;
395
- scene.add(building);
396
-
397
- // Create windows
398
- const windows = [];
399
- const windowsX = Math.floor(width * 4);
400
- const windowsY = Math.floor(height * 3);
401
-
402
- for (let wx = 0; wx < windowsX; wx++) {
403
- for (let wy = 0; wy < windowsY; wy++) {
404
- const windowGeometry = new THREE.PlaneGeometry(0.15, 0.15);
405
- const windowMaterial = new THREE.MeshBasicMaterial({
406
- color: 0x444444,
407
- transparent: true,
408
- opacity: 0.8
409
- });
410
- const window = new THREE.Mesh(windowGeometry, windowMaterial);
411
-
412
- window.position.set(
413
- x + (wx - windowsX/2) * 0.2,
414
- y + (wy - windowsY/2) * 0.3 + height/2,
415
- z + width/2 + 0.01
416
- );
417
-
418
- window.userData = {
419
- isOn: Math.random() > 0.5,
420
- flickerTimer: Math.random() * 1000
421
- };
422
-
423
- windows.push(window);
424
- scene.add(window);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  }
426
  }
427
-
428
- buildings.push({ structure: building, windows: windows });
429
- }
430
-
431
- function createStreets() {
432
- // Main streets
433
- const streetMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 });
434
-
435
- // Horizontal street
436
- const hStreetGeometry = new THREE.PlaneGeometry(20, 1);
437
- const hStreet = new THREE.Mesh(hStreetGeometry, streetMaterial);
438
- hStreet.rotation.x = -Math.PI / 2;
439
- hStreet.position.y = 0.01;
440
- scene.add(hStreet);
441
-
442
- // Vertical street
443
- const vStreetGeometry = new THREE.PlaneGeometry(1, 20);
444
- const vStreet = new THREE.Mesh(vStreetGeometry, streetMaterial);
445
- vStreet.rotation.x = -Math.PI / 2;
446
- vStreet.position.y = 0.01;
447
- scene.add(vStreet);
448
- }
449
-
450
- function createPeople() {
451
- for (let i = 0; i < 8; i++) {
452
- const person = createPerson();
453
- people.push(person);
454
- scene.add(person.group);
455
- }
456
- }
457
-
458
- function createPerson() {
459
- const group = new THREE.Group();
460
-
461
- // Body
462
- const bodyGeometry = new THREE.CylinderGeometry(0.1, 0.15, 0.4);
463
- const bodyMaterial = new THREE.MeshLambertMaterial({
464
- color: new THREE.Color().setHSL(Math.random(), 0.6, 0.5)
465
- });
466
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
467
- body.position.y = 0.4;
468
- group.add(body);
469
-
470
- // Head
471
- const headGeometry = new THREE.SphereGeometry(0.08);
472
- const headMaterial = new THREE.MeshLambertMaterial({ color: 0xffdbac });
473
- const head = new THREE.Mesh(headGeometry, headMaterial);
474
- head.position.y = 0.7;
475
- group.add(head);
476
-
477
- // Position and movement
478
- const path = createRandomPath();
479
- group.position.copy(path[0]);
480
- group.castShadow = true;
481
-
482
- return {
483
- group: group,
484
- path: path,
485
- pathIndex: 0,
486
- speed: Math.random() * 0.02 + 0.01,
487
- walkCycle: 0
488
- };
489
  }
490
-
491
- function createVehicles() {
492
- // Cars
493
- for (let i = 0; i < 4; i++) {
494
- const car = createCar();
495
- vehicles.push(car);
496
- scene.add(car.group);
497
- }
498
-
499
- // Trucks
500
- for (let i = 0; i < 2; i++) {
501
- const truck = createTruck();
502
- vehicles.push(truck);
503
- scene.add(truck.group);
504
- }
505
-
506
- // Bicycles
507
- for (let i = 0; i < 3; i++) {
508
- const bicycle = createBicycle();
509
- vehicles.push(bicycle);
510
- scene.add(bicycle.group);
511
- }
512
- }
513
-
514
- function createCar() {
515
- const group = new THREE.Group();
516
-
517
- // Car body
518
- const bodyGeometry = new THREE.BoxGeometry(0.8, 0.3, 0.4);
519
- const bodyMaterial = new THREE.MeshLambertMaterial({
520
- color: new THREE.Color().setHSL(Math.random(), 0.8, 0.5)
521
- });
522
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
523
- body.position.y = 0.2;
524
- group.add(body);
525
-
526
- // Wheels
527
- const wheelGeometry = new THREE.CylinderGeometry(0.08, 0.08, 0.05);
528
- const wheelMaterial = new THREE.MeshLambertMaterial({ color: 0x222222 });
529
-
530
- const wheels = [];
531
- const wheelPositions = [
532
- [-0.3, 0.08, -0.15], [0.3, 0.08, -0.15],
533
- [-0.3, 0.08, 0.15], [0.3, 0.08, 0.15]
534
- ];
535
-
536
- wheelPositions.forEach(pos => {
537
- const wheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
538
- wheel.position.set(...pos);
539
- wheel.rotation.z = Math.PI / 2;
540
- wheels.push(wheel);
541
- group.add(wheel);
542
- });
543
-
544
- const path = createVehiclePath();
545
- group.position.copy(path[0]);
546
- group.castShadow = true;
547
-
548
- return {
549
- group: group,
550
- wheels: wheels,
551
- path: path,
552
- pathIndex: 0,
553
- speed: Math.random() * 0.05 + 0.03,
554
- type: 'car'
555
- };
556
- }
557
-
558
- function createTruck() {
559
- const group = new THREE.Group();
560
-
561
- // Truck body
562
- const bodyGeometry = new THREE.BoxGeometry(1.2, 0.5, 0.6);
563
- const bodyMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
564
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
565
- body.position.y = 0.3;
566
- group.add(body);
567
-
568
- // Cab
569
- const cabGeometry = new THREE.BoxGeometry(0.4, 0.4, 0.6);
570
- const cabMaterial = new THREE.MeshLambertMaterial({ color: 0x654321 });
571
- const cab = new THREE.Mesh(cabGeometry, cabMaterial);
572
- cab.position.set(-0.5, 0.4, 0);
573
- group.add(cab);
574
-
575
- const path = createVehiclePath();
576
- group.position.copy(path[0]);
577
- group.castShadow = true;
578
-
579
- return {
580
- group: group,
581
- path: path,
582
- pathIndex: 0,
583
- speed: Math.random() * 0.03 + 0.02,
584
- type: 'truck'
585
- };
586
- }
587
-
588
- function createBicycle() {
589
- const group = new THREE.Group();
590
-
591
- // Frame
592
- const frameGeometry = new THREE.CylinderGeometry(0.02, 0.02, 0.6);
593
- const frameMaterial = new THREE.MeshLambertMaterial({ color: 0x0066cc });
594
- const frame = new THREE.Mesh(frameGeometry, frameMaterial);
595
- frame.position.y = 0.15;
596
- frame.rotation.z = Math.PI / 6;
597
- group.add(frame);
598
-
599
- // Wheels
600
- const wheelGeometry = new THREE.TorusGeometry(0.12, 0.02, 8, 16);
601
- const wheelMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 });
602
-
603
- const frontWheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
604
- frontWheel.position.set(0.3, 0.12, 0);
605
- group.add(frontWheel);
606
-
607
- const backWheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
608
- backWheel.position.set(-0.3, 0.12, 0);
609
- group.add(backWheel);
610
-
611
- const path = createRandomPath();
612
- group.position.copy(path[0]);
613
- group.castShadow = true;
614
-
615
- return {
616
- group: group,
617
- wheels: [frontWheel, backWheel],
618
- path: path,
619
- pathIndex: 0,
620
- speed: Math.random() * 0.04 + 0.02,
621
- type: 'bicycle'
622
- };
623
- }
624
-
625
- function createAnimals() {
626
- // Dogs
627
- for (let i = 0; i < 3; i++) {
628
- const dog = createDog();
629
- animals.push(dog);
630
- scene.add(dog.group);
631
- }
632
-
633
- // Cats
634
- for (let i = 0; i < 2; i++) {
635
- const cat = createCat();
636
- animals.push(cat);
637
- scene.add(cat.group);
638
- }
639
-
640
- // Birds
641
- for (let i = 0; i < 6; i++) {
642
- const bird = createBird();
643
- animals.push(bird);
644
- scene.add(bird.group);
645
  }
646
  }
647
-
648
- function createDog() {
649
- const group = new THREE.Group();
650
-
651
- // Body
652
- const bodyGeometry = new THREE.BoxGeometry(0.3, 0.15, 0.15);
653
- const bodyMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
654
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
655
- body.position.y = 0.1;
656
- group.add(body);
657
-
658
- // Head
659
- const headGeometry = new THREE.BoxGeometry(0.12, 0.1, 0.1);
660
- const head = new THREE.Mesh(headGeometry, bodyMaterial);
661
- head.position.set(0.2, 0.12, 0);
662
- group.add(head);
663
-
664
- // Tail
665
- const tailGeometry = new THREE.CylinderGeometry(0.02, 0.02, 0.1);
666
- const tail = new THREE.Mesh(tailGeometry, bodyMaterial);
667
- tail.position.set(-0.15, 0.15, 0);
668
- tail.rotation.z = Math.PI / 4;
669
- group.add(tail);
670
-
671
- const path = createRandomPath();
672
- group.position.copy(path[0]);
673
- group.castShadow = true;
674
-
675
- return {
676
- group: group,
677
- tail: tail,
678
- path: path,
679
- pathIndex: 0,
680
- speed: Math.random() * 0.03 + 0.02,
681
- type: 'dog',
682
- tailWag: 0
683
- };
684
- }
685
-
686
- function createCat() {
687
- const group = new THREE.Group();
688
-
689
- // Body
690
- const bodyGeometry = new THREE.BoxGeometry(0.25, 0.1, 0.1);
691
- const bodyMaterial = new THREE.MeshLambertMaterial({ color: 0x696969 });
692
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
693
- body.position.y = 0.08;
694
- group.add(body);
695
-
696
- // Head
697
- const headGeometry = new THREE.SphereGeometry(0.05);
698
- const head = new THREE.Mesh(headGeometry, bodyMaterial);
699
- head.position.set(0.15, 0.1, 0);
700
- group.add(head);
701
-
702
- const path = createRandomPath();
703
- group.position.copy(path[0]);
704
- group.castShadow = true;
705
-
706
- return {
707
- group: group,
708
- path: path,
709
- pathIndex: 0,
710
- speed: Math.random() * 0.025 + 0.015,
711
- type: 'cat'
712
- };
713
- }
714
-
715
- function createBird() {
716
- const group = new THREE.Group();
717
-
718
- // Body
719
- const bodyGeometry = new THREE.SphereGeometry(0.04);
720
- const bodyMaterial = new THREE.MeshLambertMaterial({
721
- color: new THREE.Color().setHSL(Math.random(), 0.7, 0.6)
722
- });
723
- const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
724
- group.add(body);
725
-
726
- // Wings
727
- const wingGeometry = new THREE.PlaneGeometry(0.08, 0.03);
728
- const wingMaterial = new THREE.MeshLambertMaterial({
729
- color: bodyMaterial.color,
730
- transparent: true,
731
- opacity: 0.8
732
- });
733
-
734
- const leftWing = new THREE.Mesh(wingGeometry, wingMaterial);
735
- leftWing.position.set(-0.05, 0, 0);
736
- leftWing.rotation.z = Math.PI / 6;
737
- group.add(leftWing);
738
-
739
- const rightWing = new THREE.Mesh(wingGeometry, wingMaterial);
740
- rightWing.position.set(0.05, 0, 0);
741
- rightWing.rotation.z = -Math.PI / 6;
742
- group.add(rightWing);
743
-
744
- group.position.set(
745
- (Math.random() - 0.5) * 15,
746
- Math.random() * 3 + 2,
747
- (Math.random() - 0.5) * 15
748
- );
749
-
750
- return {
751
- group: group,
752
- wings: [leftWing, rightWing],
753
- flightPath: Math.random() * Math.PI * 2,
754
- flightRadius: Math.random() * 5 + 2,
755
- height: group.position.y,
756
- speed: Math.random() * 0.02 + 0.01,
757
- wingFlap: 0,
758
- type: 'bird'
759
- };
760
- }
761
-
762
- function createRandomPath() {
763
- const path = [];
764
- for (let i = 0; i < 6; i++) {
765
- path.push(new THREE.Vector3(
766
- (Math.random() - 0.5) * 15,
767
- 0,
768
- (Math.random() - 0.5) * 15
769
- ));
770
  }
771
- return path;
772
- }
773
-
774
- function createVehiclePath() {
775
- // Create paths along streets
776
- const paths = [
777
- // Horizontal street
778
- [
779
- new THREE.Vector3(-10, 0, 0),
780
- new THREE.Vector3(10, 0, 0)
781
- ],
782
- // Vertical street
783
- [
784
- new THREE.Vector3(0, 0, -10),
785
- new THREE.Vector3(0, 0, 10)
786
- ]
787
- ];
788
- return paths[Math.floor(Math.random() * paths.length)];
789
  }
790
 
791
- function createFractalSurface() {
792
- const geometry = new THREE.PlaneGeometry(2, 2, 32, 32);
793
- const vertices = geometry.attributes.position.array;
794
-
795
- // Generate fractal heightmap
796
- for (let i = 0; i < vertices.length; i += 3) {
797
- const x = vertices[i];
798
- const y = vertices[i + 1];
799
-
800
- // Mandelbrot-inspired surface
801
- const c_real = parseFloat(document.getElementById('c-real')?.value || -0.7);
802
- const c_imag = parseFloat(document.getElementById('c-imag')?.value || 0.27);
803
- const zoom = parseFloat(document.getElementById('zoom')?.value || 1);
804
-
805
- let z_real = x * zoom;
806
- let z_imag = y * zoom;
807
- let iterations = 0;
808
- const maxIter = parseInt(document.getElementById('iterations')?.value || 50);
809
-
810
- while (z_real * z_real + z_imag * z_imag < 4 && iterations < maxIter) {
811
- const temp = z_real * z_real - z_imag * z_imag + c_real;
812
- z_imag = 2 * z_real * z_imag + c_imag;
813
- z_real = temp;
814
- iterations++;
815
- }
816
-
817
- vertices[i + 2] = (iterations / maxIter) * 0.3 * Math.sin(Date.now() * 0.001 + x + y);
818
- }
819
-
820
- geometry.attributes.position.needsUpdate = true;
821
- geometry.computeVertexNormals();
822
-
823
- // Dynamic material with time-based colors
824
- const material = new THREE.MeshPhongMaterial({
825
- color: new THREE.Color().setHSL((Date.now() * 0.0001) % 1, 0.7, 0.6),
826
- wireframe: false,
827
- transparent: true,
828
- opacity: 0.6
829
- });
830
-
831
- if (fractalMesh) {
832
- scene.remove(fractalMesh);
833
  }
834
-
835
- fractalMesh = new THREE.Mesh(geometry, material);
836
- fractalMesh.position.set(5, 0.5, 5); // Position in city as art installation
837
- fractalMesh.rotation.x = -Math.PI / 2;
838
- scene.add(fractalMesh);
839
  }
840
-
841
- function updateDayNightCycle() {
842
- dayNightCycle.time += 0.001;
843
- const cycle = (Math.sin(dayNightCycle.time) + 1) / 2; // 0 to 1
844
-
845
- // Sun position (spherical path)
846
- const sunAngle = dayNightCycle.time;
847
- const sunRadius = 15;
848
- dayNightCycle.sunLight.position.set(
849
- Math.cos(sunAngle) * sunRadius,
850
- Math.sin(sunAngle) * sunRadius,
851
- 5
 
 
 
 
 
 
 
 
852
  );
853
-
854
- // Moon position (opposite to sun)
 
 
 
855
  const moonAngle = sunAngle + Math.PI;
856
- dayNightCycle.moonLight.position.set(
857
- Math.cos(moonAngle) * sunRadius,
858
- Math.sin(moonAngle) * sunRadius,
859
- -5
860
  );
861
-
862
- // Day/night lighting
863
- if (cycle > 0.5) {
864
- // Day time
865
- dayNightCycle.sunLight.visible = true;
866
- dayNightCycle.moonLight.visible = false;
867
- dayNightCycle.sunLight.intensity = cycle;
868
- dayNightCycle.ambientLight.intensity = cycle * 0.5;
869
-
870
- // Sky color transition
871
- const skyHue = 0.55; // Blue
872
- const skySaturation = 0.6;
873
- const skyLightness = 0.4 + cycle * 0.4;
874
- renderer.setClearColor(new THREE.Color().setHSL(skyHue, skySaturation, skyLightness));
875
- } else {
876
- // Night time
877
- dayNightCycle.sunLight.visible = false;
878
- dayNightCycle.moonLight.visible = true;
879
- dayNightCycle.moonLight.intensity = (1 - cycle) * 0.3;
880
- dayNightCycle.ambientLight.intensity = (1 - cycle) * 0.2;
881
-
882
- // Night sky
883
- const skyHue = 0.65; // Dark blue
884
- const skySaturation = 0.8;
885
- const skyLightness = 0.1 + (1 - cycle) * 0.1;
886
- renderer.setClearColor(new THREE.Color().setHSL(skyHue, skySaturation, skyLightness));
887
  }
888
- }
889
-
890
- function updateBuildingWindows() {
891
- const isNight = (Math.sin(dayNightCycle.time) + 1) / 2 < 0.5;
892
-
893
- buildings.forEach(building => {
894
- building.windows.forEach(window => {
895
- window.userData.flickerTimer += 16; // ~60fps
896
-
897
- // More lights on at night
898
- const lightProbability = isNight ? 0.7 : 0.2;
899
-
900
- if (window.userData.flickerTimer > 1000 + Math.random() * 2000) {
901
- window.userData.isOn = Math.random() < lightProbability;
902
- window.userData.flickerTimer = 0;
903
- }
904
-
905
- if (window.userData.isOn) {
906
- const warmth = Math.random() * 0.1 + 0.1;
907
- window.material.color.setHSL(warmth, 0.8, 0.6);
908
- window.material.opacity = 0.9;
909
- } else {
910
- window.material.color.setRGB(0.2, 0.2, 0.3);
911
- window.material.opacity = 0.3;
912
- }
913
- });
914
- });
915
- }
916
-
917
- function updatePeople() {
918
- people.forEach(person => {
919
- const path = person.path;
920
- const currentPos = path[person.pathIndex];
921
- const nextPos = path[(person.pathIndex + 1) % path.length];
922
-
923
- // Move towards next position
924
- const direction = new THREE.Vector3().subVectors(nextPos, currentPos).normalize();
925
- person.group.position.add(direction.multiplyScalar(person.speed));
926
-
927
- // Rotation to face movement direction
928
- person.group.lookAt(person.group.position.clone().add(direction));
929
-
930
- // Walking animation
931
- person.walkCycle += 0.3;
932
- person.group.children[0].rotation.z = Math.sin(person.walkCycle) * 0.1;
933
-
934
- // Check if reached next waypoint
935
- if (person.group.position.distanceTo(nextPos) < 0.2) {
936
- person.pathIndex = (person.pathIndex + 1) % path.length;
937
- }
938
- });
939
- }
940
-
941
- function updateVehicles() {
942
- vehicles.forEach(vehicle => {
943
- const path = vehicle.path;
944
- const currentPos = path[vehicle.pathIndex];
945
- const nextPos = path[(vehicle.pathIndex + 1) % path.length];
946
-
947
- // Move towards next position
948
- const direction = new THREE.Vector3().subVectors(nextPos, currentPos).normalize();
949
- vehicle.group.position.add(direction.multiplyScalar(vehicle.speed));
950
-
951
- // Rotation to face movement direction
952
- vehicle.group.lookAt(vehicle.group.position.clone().add(direction));
953
-
954
- // Wheel rotation for cars and bicycles
955
- if (vehicle.wheels) {
956
- vehicle.wheels.forEach(wheel => {
957
- wheel.rotation.x += vehicle.speed * 2;
958
  });
959
- }
960
-
961
- // Check if reached next waypoint
962
- if (vehicle.group.position.distanceTo(nextPos) < 0.2) {
963
- vehicle.pathIndex = (vehicle.pathIndex + 1) % path.length;
964
- }
965
- });
966
- }
967
-
968
- function updateAnimals() {
969
- animals.forEach(animal => {
970
- if (animal.type === 'bird') {
971
- // Circular flight pattern
972
- animal.flightPath += animal.speed;
973
- animal.group.position.x = Math.cos(animal.flightPath) * animal.flightRadius;
974
- animal.group.position.z = Math.sin(animal.flightPath) * animal.flightRadius;
975
- animal.group.position.y = animal.height + Math.sin(animal.flightPath * 3) * 0.5;
976
-
977
- // Wing flapping
978
- animal.wingFlap += 0.5;
979
- const flapAngle = Math.sin(animal.wingFlap) * 0.5;
980
- animal.wings[0].rotation.z = Math.PI / 6 + flapAngle;
981
- animal.wings[1].rotation.z = -Math.PI / 6 - flapAngle;
982
-
983
- // Face flight direction
984
- const flightDirection = new THREE.Vector3(
985
- -Math.sin(animal.flightPath),
986
- 0,
987
- Math.cos(animal.flightPath)
988
- );
989
- animal.group.lookAt(animal.group.position.clone().add(flightDirection));
990
-
991
  } else {
992
- // Ground animals (dogs, cats)
993
- const path = animal.path;
994
- const currentPos = path[animal.pathIndex];
995
- const nextPos = path[(animal.pathIndex + 1) % path.length];
996
-
997
- const direction = new THREE.Vector3().subVectors(nextPos, currentPos).normalize();
998
- animal.group.position.add(direction.multiplyScalar(animal.speed));
999
- animal.group.lookAt(animal.group.position.clone().add(direction));
1000
-
1001
- // Special animations
1002
- if (animal.type === 'dog' && animal.tail) {
1003
- animal.tailWag += 0.4;
1004
- animal.tail.rotation.y = Math.sin(animal.tailWag) * 0.5;
1005
- }
1006
-
1007
- if (animal.group.position.distanceTo(nextPos) < 0.1) {
1008
- animal.pathIndex = (animal.pathIndex + 1) % path.length;
1009
- }
1010
  }
1011
  });
1012
- }
1013
-
1014
- function addControlPoint() {
1015
- const geometry = new THREE.SphereGeometry(0.1, 16, 16);
1016
- const material = new THREE.MeshPhongMaterial({
1017
- color: new THREE.Color().setHSL(Math.random(), 0.8, 0.6),
1018
- emissive: new THREE.Color().setHSL(Math.random(), 0.3, 0.1)
 
 
 
1019
  });
1020
-
1021
- const sphere = new THREE.Mesh(geometry, material);
1022
- sphere.position.set(
1023
- (Math.random() - 0.5) * 16,
1024
- Math.random() * 4 + 2,
1025
- (Math.random() - 0.5) * 16
1026
- );
1027
-
1028
- sphere.userData = {
1029
- velocity: new THREE.Vector3(
1030
- (Math.random() - 0.5) * 0.03,
1031
- (Math.random() - 0.5) * 0.02,
1032
- (Math.random() - 0.5) * 0.03
1033
- )
1034
- };
1035
-
1036
- sphere.castShadow = true;
1037
- controlPoints.push(sphere);
1038
- scene.add(sphere);
1039
-
1040
- addLog(`Control point added at (${sphere.position.x.toFixed(2)}, ${sphere.position.y.toFixed(2)})`);
1041
- }
1042
-
1043
- function addPerson() {
1044
- const person = createPerson();
1045
- people.push(person);
1046
- scene.add(person.group);
1047
- addLog(`New person added to city`);
1048
- }
1049
-
1050
- function addVehicle() {
1051
- const vehicleType = ['car', 'truck', 'bicycle'][Math.floor(Math.random() * 3)];
1052
- let vehicle;
1053
-
1054
- if (vehicleType === 'car') vehicle = createCar();
1055
- else if (vehicleType === 'truck') vehicle = createTruck();
1056
- else vehicle = createBicycle();
1057
-
1058
- vehicles.push(vehicle);
1059
- scene.add(vehicle.group);
1060
- addLog(`New ${vehicleType} added to streets`);
1061
- }
1062
-
1063
- function addAnimal() {
1064
- const animalType = ['dog', 'cat', 'bird'][Math.floor(Math.random() * 3)];
1065
- let animal;
1066
-
1067
- if (animalType === 'dog') animal = createDog();
1068
- else if (animalType === 'cat') animal = createCat();
1069
- else animal = createBird();
1070
-
1071
- animals.push(animal);
1072
- scene.add(animal.group);
1073
- addLog(`New ${animalType} spotted in city`);
1074
- }
1075
-
1076
- function toggleTimeSpeed() {
1077
- const currentSpeed = 0.001;
1078
- dayNightCycle.timeSpeed = dayNightCycle.timeSpeed === currentSpeed ? currentSpeed * 5 : currentSpeed;
1079
- addLog(`Time speed: ${dayNightCycle.timeSpeed === currentSpeed ? 'Normal' : '5x Fast'}`);
1080
- }
1081
-
1082
- function forceDayTime() {
1083
- dayNightCycle.time = Math.PI / 2; // Noon
1084
- addLog('Forced to day time');
1085
- }
1086
-
1087
- function forceNightTime() {
1088
- dayNightCycle.time = -Math.PI / 2; // Midnight
1089
- addLog('Forced to night time');
1090
- }
1091
-
1092
- function clearControlPoints() {
1093
- controlPoints.forEach(point => scene.remove(point));
1094
- controlPoints = [];
1095
- addLog('All control points cleared');
1096
- }
1097
-
1098
- function animate() {
1099
- if (!isAnimating) return;
1100
-
1101
- animationId = requestAnimationFrame(animate);
1102
-
1103
- // Update day/night cycle
1104
- updateDayNightCycle();
1105
-
1106
- // Update building windows
1107
- updateBuildingWindows();
1108
-
1109
- // Update all moving entities
1110
- updatePeople();
1111
- updateVehicles();
1112
- updateAnimals();
1113
-
1114
- // Update fractal surface
1115
- if (fractalMesh) {
1116
- fractalMesh.rotation.z += 0.002;
1117
- fractalMesh.material.color.setHSL((Date.now() * 0.0001) % 1, 0.7, 0.6);
1118
- }
1119
-
1120
- // Animate control points
1121
- controlPoints.forEach(point => {
1122
- point.position.add(point.userData.velocity);
1123
-
1124
- // Bounce off boundaries
1125
- if (Math.abs(point.position.x) > 8) point.userData.velocity.x *= -1;
1126
- if (Math.abs(point.position.y - 2) > 4) point.userData.velocity.y *= -1;
1127
- if (Math.abs(point.position.z) > 8) point.userData.velocity.z *= -1;
1128
-
1129
- // Add some orbital motion
1130
- point.rotation.x += 0.02;
1131
- point.rotation.y += 0.03;
1132
  });
1133
-
 
 
1134
  renderer.render(scene, camera);
1135
-
1136
- // Update FPS
1137
- updateFPS();
1138
- }
1139
-
1140
- let lastTime = Date.now();
1141
- let frameCount = 0;
1142
-
1143
- function updateFPS() {
1144
- frameCount++;
1145
- const now = Date.now();
1146
- if (now - lastTime >= 1000) {
1147
- document.getElementById('fps').textContent = frameCount;
1148
- frameCount = 0;
1149
- lastTime = now;
1150
- }
1151
- }
1152
-
1153
- // Dynamic Code Engine
1154
- const fractalFunctions = [
1155
- "z = z² + c",
1156
- "z = z³ + c",
1157
- "z = sin(z) + c",
1158
- "z = |z|² + c",
1159
- "z = z² + c + sin(t)",
1160
- "z = z*cos(z) + c",
1161
- "z = exp(z) + c"
1162
- ];
1163
-
1164
- function updateFractalCode() {
1165
- const newFunction = fractalFunctions[Math.floor(Math.random() * fractalFunctions.length)];
1166
- document.getElementById('current-code').innerHTML = `// Current fractal function<br/>${newFunction}`;
1167
-
1168
- createFractalSurface();
1169
- agents[0].execute('fractal code evolution');
1170
- addLog(`Fractal function updated: ${newFunction}`);
1171
- }
1172
-
1173
- function generateNewSurface() {
1174
- // Randomize parameters
1175
- document.getElementById('c-real').value = (Math.random() - 0.5) * 4;
1176
- document.getElementById('c-imag').value = (Math.random() - 0.5) * 4;
1177
- document.getElementById('zoom').value = Math.random() * 3 + 0.5;
1178
-
1179
- createFractalSurface();
1180
- agents[1].execute('surface generation');
1181
  }
1182
-
1183
- function toggleAnimation() {
1184
- isAnimating = !isAnimating;
1185
- if (isAnimating) {
1186
- animate();
1187
- addLog('Animation resumed');
1188
- } else {
1189
- cancelAnimationFrame(animationId);
1190
- addLog('Animation paused');
1191
- }
1192
- }
1193
-
1194
- function randomizeColors() {
1195
- if (fractalMesh) {
1196
- fractalMesh.material.color.setHSL(Math.random(), 0.7, 0.6);
1197
- }
1198
- controlPoints.forEach(point => {
1199
- point.material.color.setHSL(Math.random(), 0.8, 0.6);
1200
- point.material.emissive.setHSL(Math.random(), 0.3, 0.1);
1201
- });
1202
- agents[1].execute('color randomization');
1203
- }
1204
-
1205
- function deployAgent(type) {
1206
- const agent = agents.find(a => a.type === type || a.name.toLowerCase().includes(type));
1207
- if (agent) {
1208
- const tasks = {
1209
- fractal: 'fractal computation optimization',
1210
- visual: 'visual enhancement protocol',
1211
- control: 'interface adaptation',
1212
- browser: 'web application orchestration'
1213
- };
1214
- agent.execute(tasks[type] || 'general task execution');
1215
- }
1216
- }
1217
-
1218
- // UI Functions
1219
- function renderAgents() {
1220
- const container = document.getElementById('agents-container');
1221
- container.innerHTML = '';
1222
-
1223
- agents.forEach(agent => {
1224
- const card = document.createElement('div');
1225
- card.className = 'agent-card';
1226
- card.innerHTML = `
1227
- <div>
1228
- <span class="agent-status ${agent.status}"></span>
1229
- <strong>${agent.name}</strong>
1230
- </div>
1231
- <div style="font-size: 12px; color: ${agent.color};">
1232
- ${agent.type.toUpperCase()} • ${agent.tasks.length} tasks
1233
- </div>
1234
- `;
1235
- container.appendChild(card);
1236
- });
1237
- }
1238
-
1239
- function addLog(message) {
1240
- const container = document.getElementById('logs-container');
1241
- const entry = document.createElement('div');
1242
- entry.className = 'log-entry';
1243
- entry.innerHTML = `<small>${new Date().toLocaleTimeString()}</small><br/>${message}`;
1244
- container.appendChild(entry);
1245
-
1246
- // Keep only last 10 logs
1247
- while (container.children.length > 10) {
1248
- container.removeChild(container.firstChild);
1249
- }
1250
-
1251
- container.scrollTop = container.scrollHeight;
1252
- }
1253
-
1254
- function updateSystemStats() {
1255
- document.getElementById('memory-usage').textContent = `${Math.floor(Math.random() * 30 + 40)}%`;
1256
- document.getElementById('cpu-usage').textContent = `${Math.floor(Math.random() * 40 + 20)}%`;
1257
- document.getElementById('agent-count').textContent = agents.length;
1258
- document.getElementById('target-count').textContent = document.querySelectorAll('#targets-list .log-entry').length;
1259
- }
1260
-
1261
- // Event Listeners
1262
- document.getElementById('iterations')?.addEventListener('input', createFractalSurface);
1263
- document.getElementById('zoom')?.addEventListener('input', createFractalSurface);
1264
- document.getElementById('c-real')?.addEventListener('input', createFractalSurface);
1265
- document.getElementById('c-imag')?.addEventListener('input', createFractalSurface);
1266
-
1267
- // Initialize System
1268
- window.addEventListener('load', () => {
1269
- initThreeJS();
1270
- renderAgents();
1271
-
1272
- // Add initial control points
1273
- for (let i = 0; i < 3; i++) {
1274
- setTimeout(() => addControlPoint(), i * 500);
1275
- }
1276
-
1277
- // System status updates
1278
- setInterval(updateSystemStats, 2000);
1279
- setInterval(renderAgents, 1000);
1280
-
1281
- // Auto-evolution
1282
- setInterval(() => {
1283
- if (Math.random() < 0.1) {
1284
- updateFractalCode();
1285
- }
1286
- }, 5000);
1287
-
1288
- addLog('AI Agentic System initialized');
1289
- addLog('3D visualization engine active');
1290
- addLog('Dynamic fractal computation online');
1291
- addLog('Browser automation ready');
1292
- });
1293
-
1294
- // Handle window resize
1295
- window.addEventListener('resize', () => {
1296
- const container = document.getElementById('three-canvas');
1297
- const rect = container.parentElement.getBoundingClientRect();
1298
- camera.aspect = rect.width / rect.height;
1299
  camera.updateProjectionMatrix();
1300
- renderer.setSize(rect.width, rect.height);
1301
- });
1302
-
1303
- // Simulate browser automation capabilities
1304
- function simulateBrowserAutomation() {
1305
- const actions = [
1306
- 'Opening new browser window',
1307
- 'Navigating to target application',
1308
- 'Injecting control scripts',
1309
- 'Establishing WebSocket connection',
1310
- 'Monitoring DOM changes',
1311
- 'Executing automated interactions'
1312
- ];
1313
-
1314
- let index = 0;
1315
- const interval = setInterval(() => {
1316
- if (index < actions.length) {
1317
- addLog(`Browser Agent: ${actions[index]}`);
1318
- index++;
1319
- } else {
1320
- clearInterval(interval);
1321
- addLog('Browser automation sequence complete');
1322
- }
1323
- }, 1500);
1324
  }
1325
-
1326
- // Simulate AI model inference
1327
- function simulateAIInference() {
1328
- const models = ['text-classification', 'object-detection', 'sentiment-analysis', 'code-generation'];
1329
- const model = models[Math.floor(Math.random() * models.length)];
1330
-
1331
- addLog(`Running ${model} inference...`);
1332
- setTimeout(() => {
1333
- addLog(`${model} inference complete: confidence 0.${Math.floor(Math.random() * 30 + 70)}`);
1334
- }, Math.random() * 2000 + 500);
1335
- }
1336
-
1337
- // Periodic AI activities
1338
- setInterval(simulateAIInference, 8000);
1339
- setTimeout(simulateBrowserAutomation, 3000);
1340
  </script>
1341
  </body>
1342
- </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Three.js Dynamic Simulated City</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
  <style>
9
+ body { margin: 0; overflow: hidden; background-color: #000000; color: #e2e8f0; font-family: 'Inter', sans-serif; }
10
+ canvas { display: block; }
11
+ #infoPanel {
 
 
 
 
 
 
 
12
  position: absolute;
13
+ top: 20px;
14
+ left: 20px;
15
+ background-color: rgba(0,0,0,0.75);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  padding: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  border-radius: 8px;
18
+ color: white;
19
+ font-size: 0.85em;
20
+ max-width: 320px;
21
+ box-shadow: 0 4px 12px rgba(0,0,0,0.5);
22
+ max-height: 90vh;
23
+ overflow-y: auto;
24
  }
25
+ #infoPanel h2 {
26
+ margin-top: 0;
27
+ font-size: 1.1em;
28
+ border-bottom: 1px solid #4a5568;
29
+ padding-bottom: 5px;
 
30
  margin-bottom: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
+ #infoPanel p, #infoPanel ul {
33
+ margin-bottom: 8px;
34
+ line-height: 1.5;
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
+ #infoPanel ul {
37
+ list-style: disc;
38
+ padding-left: 20px;
 
39
  }
40
+ #loadingScreen {
41
+ position: fixed;
42
+ top: 0;
43
+ left: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  width: 100%;
45
+ height: 100%;
46
+ background-color: #111827; /* Darker initial loading */
 
 
 
 
 
 
 
 
 
47
  display: flex;
48
  flex-direction: column;
49
+ justify-content: center;
50
+ align-items: center;
51
+ z-index: 9999;
52
+ color: white;
53
+ font-size: 1.5em;
54
  }
55
+ .spinner {
56
+ border: 4px solid rgba(255, 255, 255, 0.3);
57
+ border-radius: 50%;
58
+ border-top: 4px solid #fff;
59
+ width: 40px;
60
+ height: 40px;
61
+ animation: spin 1s linear infinite;
62
+ margin-bottom: 20px;
63
+ }
64
+ @keyframes spin {
65
+ 0% { transform: rotate(0deg); }
66
+ 100% { transform: rotate(360deg); }
67
  }
68
  </style>
69
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
70
  </head>
71
  <body>
72
+ <div id="loadingScreen">
73
+ <div class="spinner"></div>
74
+ Loading Dynamic City...
75
+ </div>
76
+ <div id="infoPanel">
77
+ <h2>Dynamic Simulated City</h2>
78
+ <p>Observe the day/night cycle, moving entities, and dynamic building windows. This visualization demonstrates how a more complex simulation could be represented.</p>
79
+ <p><strong>Features Added:</strong></p>
80
+ <ul>
81
+ <li>Moving cars and people (simple paths).</li>
82
+ <li>Birds flying in the sky.</li>
83
+ <li>Building windows with lights turning on/off.</li>
84
+ <li>Sun and Moon with day/night cycle affecting lighting and sky.</li>
85
+ </ul>
86
+ <p><strong>Conceptual Integration Points:</strong> (As before, imagine these influencing the dynamics)</p>
87
+ <ul>
88
+ <li><strong>AI Agents:</strong> Could control traffic flow, pedestrian density, "power grid" for window lights, or trigger city-wide events based on (simulated) external data.</li>
89
+ <li><strong>Wasm/Fractals:</strong> Could define more organic city growth, traffic patterns, or even complex behaviors for the simulated entities.</li>
90
+ </ul>
91
+ <p><em>Use mouse to orbit, scroll to zoom, right-click to pan.</em></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  </div>
93
+ <canvas id="cityCanvas"></canvas>
94
 
95
+ <script type="importmap">
96
+ {
97
+ "imports": {
98
+ "three": "https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js",
99
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
  }
102
+ </script>
103
+
104
+ <script type="module">
105
+ import * as THREE from 'three';
106
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
107
+
108
+ let scene, camera, renderer, controls;
109
+ const buildings = [];
110
+ const vehicles = [];
111
+ const pedestrians = [];
112
+ const birds = [];
113
+
114
+ const citySize = 20; // Grid size for the city
115
+ const buildingSpacing = 2.0; // Increased spacing for roads
116
+ const roadWidth = 0.5;
117
+ const buildingMaxHeight = 8;
118
+ const buildingMinHeight = 1;
119
+
120
+ let sunLight, moonLight, ambientLight;
121
+ const skyRadius = citySize * buildingSpacing * 1.5; // Radius for sun/moon path
122
+
123
+ const dayClearColor = new THREE.Color(0x87CEEB); // Sky blue
124
+ const nightClearColor = new THREE.Color(0x000020); // Deep navy
125
+ const dayFogColor = new THREE.Color(0x87CEEB);
126
+ const nightFogColor = new THREE.Color(0x000010);
127
+
128
+ // --- Core Three.js Setup ---
129
+ function init() {
130
+ const canvas = document.getElementById('cityCanvas');
131
+ renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
132
+ renderer.setSize(window.innerWidth, window.innerHeight);
133
+ renderer.setPixelRatio(window.devicePixelRatio);
134
  renderer.shadowMap.enabled = true;
135
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
136
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
137
+ renderer.toneMappingExposure = 0.8;
138
+
139
+
140
+ scene = new THREE.Scene();
141
+ // scene.background will be set dynamically
142
+
143
+ camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, skyRadius * 2.5);
144
+ camera.position.set(citySize * 0.7, citySize * 0.6, citySize * 0.7);
145
+
146
+ controls = new OrbitControls(camera, renderer.domElement);
147
+ controls.enableDamping = true;
148
+ controls.dampingFactor = 0.05;
149
+ controls.screenSpacePanning = false;
150
+ controls.minDistance = 3;
151
+ controls.maxDistance = citySize * 2.5;
152
+ controls.maxPolarAngle = Math.PI / 2 - 0.01; // Prevent going too low
153
+
154
+ // --- Lighting ---
155
+ ambientLight = new THREE.AmbientLight(0xffffff, 0.1); // Start dim
156
+ scene.add(ambientLight);
157
+
158
+ sunLight = new THREE.DirectionalLight(0xffffee, 0); // Start with 0 intensity
159
+ sunLight.castShadow = true;
160
+ sunLight.shadow.mapSize.width = 2048;
161
+ sunLight.shadow.mapSize.height = 2048;
162
+ sunLight.shadow.camera.near = 0.5;
163
+ sunLight.shadow.camera.far = skyRadius * 0.8;
164
+ sunLight.shadow.camera.left = -citySize * 1.5;
165
+ sunLight.shadow.camera.right = citySize * 1.5;
166
+ sunLight.shadow.camera.top = citySize * 1.5;
167
+ sunLight.shadow.camera.bottom = -citySize * 1.5;
168
+ sunLight.shadow.bias = -0.0005; // Helps with shadow acne
169
+ scene.add(sunLight);
170
+ // const sunShadowHelper = new THREE.CameraHelper(sunLight.shadow.camera); // For debugging
171
+ // scene.add(sunShadowHelper);
172
+
173
+
174
+ moonLight = new THREE.DirectionalLight(0x7788cc, 0); // Start with 0 intensity
175
+ moonLight.castShadow = true; // Moon can cast shadows, but might be subtle/expensive
176
+ moonLight.shadow.mapSize.width = 1024; // Lower res for moon
177
+ moonLight.shadow.mapSize.height = 1024;
178
+ moonLight.shadow.camera.near = 0.5;
179
+ moonLight.shadow.camera.far = skyRadius * 0.8;
180
+ moonLight.shadow.bias = -0.0005;
181
+ scene.add(moonLight);
182
+
183
+ // --- Ground ---
184
+ const groundGeometry = new THREE.PlaneGeometry(citySize * buildingSpacing * 1.2, citySize * buildingSpacing * 1.2);
185
+ const groundMaterial = new THREE.MeshStandardMaterial({
186
+ color: 0x445544, // Earthy green/grey
187
+ roughness: 0.9,
188
+ metalness: 0.1
189
+ });
190
  const ground = new THREE.Mesh(groundGeometry, groundMaterial);
191
  ground.rotation.x = -Math.PI / 2;
192
  ground.receiveShadow = true;
193
  scene.add(ground);
194
+
195
+ // --- City, Entities ---
196
+ generateCity();
197
+ createVehicles(30); // Create some cars
198
+ createPedestrians(50); // Create some people
199
+ createBirds(20); // Create some birds
200
+
201
+ document.getElementById('loadingScreen').style.display = 'none';
202
+ window.addEventListener('resize', onWindowResize, false);
203
+ animate();
 
 
204
  }
205
+
206
+ // --- Procedural City Generation with Windows ---
207
+ function generateCity() {
208
+ const buildingBaseGeometry = new THREE.BoxGeometry(1, 1, 1);
209
+
210
+ for (let i = 0; i < citySize; i++) {
211
+ for (let j = 0; j < citySize; j++) {
212
+ if (Math.random() > 0.25) { // 75% chance of building
213
+ const buildingHeight = THREE.MathUtils.randFloat(buildingMinHeight, buildingMaxHeight);
214
+ const buildingWidth = THREE.MathUtils.randFloat(0.7, buildingSpacing - roadWidth * 0.8);
215
+ const buildingDepth = THREE.MathUtils.randFloat(0.7, buildingSpacing - roadWidth * 0.8);
216
+
217
+ const buildingMaterial = new THREE.MeshStandardMaterial({
218
+ color: new THREE.Color().setHSL(Math.random() * 0.1 + 0.55, 0.1, Math.random() * 0.2 + 0.3), // Greys, browns, dark blues
219
+ roughness: THREE.MathUtils.randFloat(0.6, 0.9),
220
+ metalness: THREE.MathUtils.randFloat(0.0, 0.2),
221
+ });
222
+
223
+ const building = new THREE.Mesh(buildingBaseGeometry, buildingMaterial);
224
+ building.scale.set(buildingWidth, buildingHeight, buildingDepth);
225
+ building.position.set(
226
+ (i - citySize / 2 + 0.5) * buildingSpacing,
227
+ buildingHeight / 2,
228
+ (j - citySize / 2 + 0.5) * buildingSpacing
229
+ );
230
+ building.castShadow = true;
231
+ building.receiveShadow = true;
232
+ scene.add(building);
233
+ building.userData.windows = [];
234
+
235
+ // Add Windows
236
+ const windowSize = 0.15;
237
+ const windowSpacing = 0.25;
238
+ const windowDepthOffset = 0.01; // Slightly in front of facade
239
+
240
+ // Facade X ( iterating Z for height, X for width on this face)
241
+ for (let bh = windowSpacing; bh < buildingHeight - windowSpacing; bh += windowSpacing * 2) {
242
+ for (let bw = -buildingWidth / 2 + windowSpacing; bw < buildingWidth / 2 - windowSpacing / 2; bw += windowSpacing * 1.5) {
243
+ if (Math.random() < 0.8) { // Chance to have a window
244
+ const windowMat = new THREE.MeshStandardMaterial({
245
+ color: 0x111122, // Dark window
246
+ emissive: 0x000000,
247
+ emissiveIntensity: 0,
248
+ transparent: true,
249
+ opacity: 0.7
250
+ });
251
+ const windowGeo = new THREE.PlaneGeometry(windowSize, windowSize);
252
+ const win = new THREE.Mesh(windowGeo, windowMat);
253
+ win.position.set(bw / buildingWidth, (bh - buildingHeight/2) / buildingHeight , 0.5 + windowDepthOffset/buildingDepth); // Normalized local coords
254
+ building.add(win); // Add to building so it scales/moves with it
255
+ building.userData.windows.push(win);
256
+ }
257
+ }
258
+ }
259
+ // Facade Z (iterating Z for height, Z for width on this face)
260
+ for (let bh = windowSpacing; bh < buildingHeight - windowSpacing; bh += windowSpacing * 2) {
261
+ for (let bd = -buildingDepth / 2 + windowSpacing; bd < buildingDepth / 2 - windowSpacing / 2; bd += windowSpacing * 1.5) {
262
+ if (Math.random() < 0.8) {
263
+ const windowMat = new THREE.MeshStandardMaterial({
264
+ color: 0x111122, emissive: 0x000000, emissiveIntensity: 0, transparent: true, opacity: 0.7
265
+ });
266
+ const windowGeo = new THREE.PlaneGeometry(windowSize, windowSize);
267
+ const win = new THREE.Mesh(windowGeo, windowMat);
268
+ win.position.set(0.5 + windowDepthOffset/buildingWidth, (bh - buildingHeight/2) / buildingHeight, bd / buildingDepth);
269
+ win.rotation.y = Math.PI / 2;
270
+ building.add(win);
271
+ building.userData.windows.push(win);
272
+ }
273
+ }
274
+ }
275
+ // Opposite facades (could be more efficient, but ok for demo)
276
+ for (let bh = windowSpacing; bh < buildingHeight - windowSpacing; bh += windowSpacing * 2) {
277
+ for (let bw = -buildingWidth / 2 + windowSpacing; bw < buildingWidth / 2 - windowSpacing / 2; bw += windowSpacing * 1.5) {
278
+ if (Math.random() < 0.8) {
279
+ const windowMat = new THREE.MeshStandardMaterial({
280
+ color: 0x111122, emissive: 0x000000, emissiveIntensity: 0, transparent: true, opacity: 0.7
281
+ });
282
+ const windowGeo = new THREE.PlaneGeometry(windowSize, windowSize);
283
+ const win = new THREE.Mesh(windowGeo, windowMat);
284
+ win.position.set(bw / buildingWidth, (bh - buildingHeight/2) / buildingHeight , -0.5 - windowDepthOffset/buildingDepth);
285
+ win.rotation.y = Math.PI;
286
+ building.add(win);
287
+ building.userData.windows.push(win);
288
+ }
289
+ }
290
+ }
291
+ for (let bh = windowSpacing; bh < buildingHeight - windowSpacing; bh += windowSpacing * 2) {
292
+ for (let bd = -buildingDepth / 2 + windowSpacing; bd < buildingDepth / 2 - windowSpacing / 2; bd += windowSpacing * 1.5) {
293
+ if (Math.random() < 0.8) {
294
+ const windowMat = new THREE.MeshStandardMaterial({
295
+ color: 0x111122, emissive: 0x000000, emissiveIntensity: 0, transparent: true, opacity: 0.7
296
+ });
297
+ const windowGeo = new THREE.PlaneGeometry(windowSize, windowSize);
298
+ const win = new THREE.Mesh(windowGeo, windowMat);
299
+ win.position.set(-0.5 - windowDepthOffset/buildingWidth, (bh - buildingHeight/2) / buildingHeight, bd / buildingDepth);
300
+ win.rotation.y = -Math.PI / 2;
301
+ building.add(win);
302
+ building.userData.windows.push(win);
303
+ }
304
+ }
305
+ }
306
+
307
+
308
+ buildings.push(building);
309
+ }
310
  }
311
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  }
313
+
314
+ // --- Create Moving Entities ---
315
+ function createVehicles(count) {
316
+ const carGeo = new THREE.BoxGeometry(0.6, 0.25, 0.3);
317
+ const carMat = new THREE.MeshStandardMaterial({ color: 0xaa0000, roughness: 0.3, metalness: 0.5 });
318
+ for (let i = 0; i < count; i++) {
319
+ const vehicle = new THREE.Mesh(carGeo, carMat.clone());
320
+ vehicle.material.color.setHSL(Math.random(), 0.7, 0.5); // Random car colors
321
+ vehicle.castShadow = true;
322
+ // Position on a "road"
323
+ const onXAxis = Math.random() > 0.5;
324
+ const roadLine = Math.floor(Math.random() * citySize) - citySize / 2 + 0.5;
325
+ vehicle.position.set(
326
+ onXAxis ? (Math.random() - 0.5) * citySize * buildingSpacing : roadLine * buildingSpacing + (Math.random() > 0.5 ? roadWidth : -roadWidth),
327
+ 0.125,
328
+ onXAxis ? roadLine * buildingSpacing + (Math.random() > 0.5 ? roadWidth : -roadWidth) : (Math.random() - 0.5) * citySize * buildingSpacing
329
+ );
330
+ vehicle.userData.speed = THREE.MathUtils.randFloat(0.02, 0.05) * (Math.random() > 0.5 ? 1 : -1);
331
+ vehicle.userData.axis = onXAxis ? 'x' : 'z';
332
+ if ((vehicle.userData.axis === 'x' && vehicle.userData.speed < 0) || (vehicle.userData.axis === 'z' && vehicle.userData.speed > 0)) {
333
+ vehicle.rotation.y = Math.PI / 2;
334
+ }
335
+
336
+
337
+ scene.add(vehicle);
338
+ vehicles.push(vehicle);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  }
340
  }
341
+
342
+ function createPedestrians(count) {
343
+ const pedGeo = new THREE.CylinderGeometry(0.05, 0.05, 0.3, 8);
344
+ const pedMat = new THREE.MeshStandardMaterial({ color: 0x00aa00, roughness: 0.8, metalness: 0.1 });
345
+ for (let i = 0; i < count; i++) {
346
+ const pedestrian = new THREE.Mesh(pedGeo, pedMat.clone());
347
+ pedestrian.material.color.setHSL(Math.random(), 0.6, 0.6);
348
+ pedestrian.castShadow = true;
349
+ // Position on a "sidewalk"
350
+ const buildingIndex = Math.floor(Math.random() * buildings.length);
351
+ const targetBuilding = buildings[buildingIndex];
352
+ if (!targetBuilding) continue;
353
+
354
+ const side = Math.floor(Math.random() * 4);
355
+ let offsetX = 0, offsetZ = 0;
356
+ const sidewalkOffset = targetBuilding.scale.x / 2 + 0.15; // Assuming square base for simplicity
357
+
358
+ if (side === 0) { offsetZ = sidewalkOffset; offsetX = (Math.random()-0.5) * targetBuilding.scale.x; } // Front
359
+ else if (side === 1) { offsetZ = -sidewalkOffset; offsetX = (Math.random()-0.5) * targetBuilding.scale.x; } // Back
360
+ else if (side === 2) { offsetX = sidewalkOffset; offsetZ = (Math.random()-0.5) * targetBuilding.scale.z; } // Right
361
+ else { offsetX = -sidewalkOffset; offsetZ = (Math.random()-0.5) * targetBuilding.scale.z; } // Left
362
+
363
+ pedestrian.position.set(
364
+ targetBuilding.position.x + offsetX,
365
+ 0.15,
366
+ targetBuilding.position.z + offsetZ
367
+ );
368
+ pedestrian.userData.speed = THREE.MathUtils.randFloat(0.005, 0.01);
369
+ pedestrian.userData.direction = new THREE.Vector3(Math.random()-0.5, 0, Math.random()-0.5).normalize();
370
+ scene.add(pedestrian);
371
+ pedestrians.push(pedestrian);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
  }
374
 
375
+ function createBirds(count) {
376
+ const birdGeo = new THREE.SphereGeometry(0.1, 8, 6); // Simpler bird
377
+ const birdMat = new THREE.MeshStandardMaterial({ color: 0x555555, roughness: 0.5 });
378
+ for (let i = 0; i < count; i++) {
379
+ const bird = new THREE.Mesh(birdGeo, birdMat.clone());
380
+ bird.material.color.setHex(Math.random() * 0xffffff);
381
+ bird.position.set(
382
+ (Math.random() - 0.5) * citySize * buildingSpacing * 0.8,
383
+ THREE.MathUtils.randFloat(buildingMaxHeight + 2, buildingMaxHeight + 10),
384
+ (Math.random() - 0.5) * citySize * buildingSpacing * 0.8
385
+ );
386
+ bird.userData.speed = THREE.MathUtils.randFloat(0.02, 0.06);
387
+ bird.userData.phase = Math.random() * Math.PI * 2; // For circular/wave motion
388
+ bird.userData.amplitudeY = THREE.MathUtils.randFloat(0.5, 2);
389
+ bird.userData.radius = THREE.MathUtils.randFloat(citySize * 0.2, citySize * 0.5);
390
+ bird.userData.angle = Math.random() * Math.PI * 2;
391
+ bird.userData.angleSpeed = THREE.MathUtils.randFloat(0.001, 0.005) * (Math.random() > 0.5 ? 1: -1);
392
+
393
+ scene.add(bird);
394
+ birds.push(bird);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  }
 
 
 
 
 
396
  }
397
+
398
+
399
+ // --- Animation Loop ---
400
+ let lastWindowUpdateTime = 0;
401
+ const windowUpdateInterval = 200; // milliseconds
402
+
403
+ function animate(time) { // time is passed by requestAnimationFrame
404
+ requestAnimationFrame(animate);
405
+ const currentTime = time || 0; // Ensure time is defined
406
+ const delta = currentTime - (lastWindowUpdateTime || 0);
407
+
408
+
409
+ const timeOfDay = (currentTime * 0.00002) % 1; // 0 to 1, representing 24 hours
410
+ const sunAngle = timeOfDay * Math.PI * 2; // Full circle
411
+
412
+ // Update Sun
413
+ sunLight.position.set(
414
+ Math.cos(sunAngle) * skyRadius,
415
+ Math.sin(sunAngle) * skyRadius * 0.7, // Lower peak for more visible arc
416
+ Math.sin(sunAngle - Math.PI / 4) * skyRadius // Offset Z for non-linear path
417
  );
418
+ sunLight.intensity = Math.max(0, Math.sin(sunAngle)) * 1.8; // Brighter sun
419
+ sunLight.visible = sunLight.intensity > 0.01;
420
+
421
+
422
+ // Update Moon (opposite side of sun)
423
  const moonAngle = sunAngle + Math.PI;
424
+ moonLight.position.set(
425
+ Math.cos(moonAngle) * skyRadius * 0.9, // Slightly different orbit
426
+ Math.sin(moonAngle) * skyRadius * 0.6,
427
+ Math.sin(moonAngle - Math.PI / 4) * skyRadius * 0.9
428
  );
429
+ moonLight.intensity = Math.max(0, Math.sin(moonAngle)) * 0.4;
430
+ moonLight.visible = moonLight.intensity > 0.01;
431
+
432
+ // Update Ambient Light & Fog & Background
433
+ const dayFactor = Math.pow(Math.max(0, Math.sin(sunAngle)), 0.7); // Emphasize day/night difference
434
+ ambientLight.intensity = dayFactor * 0.5 + 0.1; // Brighter during day, min at night
435
+
436
+ scene.background = nightClearColor.clone().lerp(dayClearColor, dayFactor);
437
+ if (scene.fog) {
438
+ scene.fog.color = nightFogColor.clone().lerp(dayFogColor, dayFactor);
439
+ scene.fog.near = skyRadius * 0.2 * (1 - dayFactor * 0.5); // Fog closer at night
440
+ scene.fog.far = skyRadius * (1 - dayFactor * 0.3);
441
+ } else { // Initialize fog if not present
442
+ scene.fog = new THREE.Fog(scene.background, skyRadius * 0.2, skyRadius);
 
 
 
 
 
 
 
 
 
 
 
 
443
  }
444
+
445
+
446
+ // Animate Windows (less frequent updates)
447
+ if (delta > windowUpdateInterval) {
448
+ lastWindowUpdateTime = currentTime;
449
+ buildings.forEach(building => {
450
+ building.userData.windows.forEach(win => {
451
+ if (Math.random() < 0.05) { // Small chance to toggle a window
452
+ const isNight = dayFactor < 0.3;
453
+ const lightOnProb = isNight ? 0.6 : 0.15; // Higher chance of lights on at night
454
+
455
+ if (Math.random() < lightOnProb) {
456
+ win.material.emissive.setHex(0xffffaa);
457
+ win.material.emissiveIntensity = THREE.MathUtils.randFloat(0.5, 1.2);
458
+ win.material.opacity = 0.9;
459
+ } else {
460
+ win.material.emissive.setHex(0x000000);
461
+ win.material.emissiveIntensity = 0;
462
+ win.material.opacity = 0.6;
463
+ }
464
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
  });
466
+ });
467
+ }
468
+
469
+ // Animate Vehicles
470
+ const cityBoundary = citySize * buildingSpacing / 2;
471
+ vehicles.forEach(v => {
472
+ if (v.userData.axis === 'x') {
473
+ v.position.x += v.userData.speed;
474
+ if (v.position.x > cityBoundary && v.userData.speed > 0) v.position.x = -cityBoundary;
475
+ if (v.position.x < -cityBoundary && v.userData.speed < 0) v.position.x = cityBoundary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  } else {
477
+ v.position.z += v.userData.speed;
478
+ if (v.position.z > cityBoundary && v.userData.speed > 0) v.position.z = -cityBoundary;
479
+ if (v.position.z < -cityBoundary && v.userData.speed < 0) v.position.z = cityBoundary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  }
481
  });
482
+
483
+ // Animate Pedestrians (simple wander)
484
+ pedestrians.forEach(p => {
485
+ p.position.addScaledVector(p.userData.direction, p.userData.speed);
486
+ if (Math.random() < 0.01) { // Occasionally change direction
487
+ p.userData.direction.set(Math.random()-0.5, 0, Math.random()-0.5).normalize();
488
+ }
489
+ // Basic boundary containment (crude)
490
+ p.position.x = THREE.MathUtils.clamp(p.position.x, -cityBoundary, cityBoundary);
491
+ p.position.z = THREE.MathUtils.clamp(p.position.z, -cityBoundary, cityBoundary);
492
  });
493
+
494
+ // Animate Birds
495
+ birds.forEach(b => {
496
+ b.userData.angle += b.userData.angleSpeed;
497
+ b.position.x = Math.cos(b.userData.angle) * b.userData.radius;
498
+ b.position.z = Math.sin(b.userData.angle) * b.userData.radius;
499
+ b.position.y = (buildingMaxHeight + 5) + Math.sin(currentTime * 0.001 * b.userData.speed + b.userData.phase) * b.userData.amplitudeY;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  });
501
+
502
+
503
+ controls.update();
504
  renderer.render(scene, camera);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  }
506
+
507
+ // --- Window Resize Handler ---
508
+ function onWindowResize() {
509
+ camera.aspect = window.innerWidth / window.innerHeight;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  camera.updateProjectionMatrix();
511
+ renderer.setSize(window.innerWidth, window.innerHeight);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
+
514
+ // --- Start ---
515
+ init();
 
 
 
 
 
 
 
 
 
 
 
 
516
  </script>
517
  </body>
518
+ </html>