opencroc 1.8.2 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/package.json +1 -1
  2. package/dist/web/index.html +0 -12
  3. package/dist/web/public/botreview/char_0.png +0 -0
  4. package/dist/web/public/botreview/char_1.png +0 -0
  5. package/dist/web/public/botreview/char_2.png +0 -0
  6. package/dist/web/public/botreview/coffee-machine.gif +0 -0
  7. package/dist/web/public/botreview/server.gif +0 -0
  8. package/dist/web/public/botreview/walls.png +0 -0
  9. package/dist/web/public/star/desk-v3.webp +0 -0
  10. package/dist/web/public/star/office_bg_small.webp +0 -0
  11. package/dist/web/public/star/star-idle-v5.png +0 -0
  12. package/dist/web/public/star/star-working-spritesheet-grid.webp +0 -0
  13. package/dist/web/src/app/AppLayout.tsx +0 -34
  14. package/dist/web/src/app/AppRouter.tsx +0 -46
  15. package/dist/web/src/app/bootstrap.tsx +0 -22
  16. package/dist/web/src/app/routes.tsx +0 -52
  17. package/dist/web/src/features/office/runtime/index.ts +0 -1
  18. package/dist/web/src/features/office/runtime/mount.ts +0 -809
  19. package/dist/web/src/features/pixel/runtime/index.ts +0 -1
  20. package/dist/web/src/features/pixel/runtime/mount.ts +0 -728
  21. package/dist/web/src/features/studio/runtime/index.ts +0 -1
  22. package/dist/web/src/features/studio/runtime/mount.ts +0 -664
  23. package/dist/web/src/features/three/engine/index.ts +0 -1
  24. package/dist/web/src/main.tsx +0 -7
  25. package/dist/web/src/pages/office/index.ts +0 -1
  26. package/dist/web/src/pages/office/page.tsx +0 -283
  27. package/dist/web/src/pages/pixel/index.ts +0 -1
  28. package/dist/web/src/pages/pixel/page.tsx +0 -564
  29. package/dist/web/src/pages/studio/index.ts +0 -1
  30. package/dist/web/src/pages/studio/page.tsx +0 -446
  31. package/dist/web/src/runtime/agents.ts +0 -738
  32. package/dist/web/src/runtime/camera.ts +0 -132
  33. package/dist/web/src/runtime/dataviz.ts +0 -312
  34. package/dist/web/src/runtime/effects.ts +0 -482
  35. package/dist/web/src/runtime/engine.ts +0 -528
  36. package/dist/web/src/runtime/office.ts +0 -932
  37. package/dist/web/src/runtime/state.ts +0 -37
  38. package/dist/web/src/runtime/ui.ts +0 -388
  39. package/dist/web/src/shared/assets.ts +0 -4
  40. package/dist/web/src/shared/navigation.ts +0 -47
  41. package/dist/web/src/styles/app-layout.css +0 -19
  42. package/dist/web/src/styles/office.css +0 -268
  43. package/dist/web/tsconfig.json +0 -28
  44. package/dist/web/vite.config.ts +0 -93
@@ -1,528 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════════════════════
2
- OpenCroc Studio 3D — Three.js Engine
3
- Scene, Renderer, Post-processing, Clock
4
- ~2500 lines
5
- ═══════════════════════════════════════════════════════════════════════════════ */
6
-
7
- import * as THREE from 'three';
8
- import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
9
- import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
10
- import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
11
- import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
12
- import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';
13
- import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
14
-
15
- /* ─── Module-level singletons ──────────────────────────────────────────────── */
16
- let renderer = null;
17
- let scene = null;
18
- let camera = null;
19
- let composer = null;
20
- let clock = null;
21
- let bloomPass = null;
22
- let fxaaPass = null;
23
-
24
- function disposeMaterial(material) {
25
- if (!material) return;
26
- for (const value of Object.values(material)) {
27
- if (value && typeof value === 'object' && value.isTexture) {
28
- value.dispose();
29
- }
30
- }
31
- material.dispose?.();
32
- }
33
-
34
- /* ═══════════════════════════════════════════════════════════════════════════════
35
- 1. createEngine — Initialize the full Three.js rendering pipeline
36
- ═══════════════════════════════════════════════════════════════════════════════ */
37
- export async function createEngine(canvas, theme = 'dark') {
38
- clock = new THREE.Clock();
39
-
40
- /* ─── Scene ────────────────────────────────────────────────────────────── */
41
- scene = new THREE.Scene();
42
- scene.fog = theme === 'dark'
43
- ? new THREE.FogExp2(0x050510, 0.012)
44
- : new THREE.FogExp2(0xe8ecf4, 0.008);
45
-
46
- /* ─── Camera ───────────────────────────────────────────────────────────── */
47
- const aspect = window.innerWidth / window.innerHeight;
48
- camera = new THREE.PerspectiveCamera(55, aspect, 0.1, 500);
49
- camera.position.set(18, 14, 18);
50
- camera.lookAt(0, 0, 0);
51
-
52
- /* ─── Renderer ─────────────────────────────────────────────────────────── */
53
- renderer = new THREE.WebGLRenderer({
54
- canvas,
55
- antialias: true,
56
- alpha: false,
57
- powerPreference: 'high-performance',
58
- });
59
- renderer.setSize(window.innerWidth, window.innerHeight);
60
- renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
61
- renderer.outputColorSpace = THREE.SRGBColorSpace;
62
- renderer.toneMapping = THREE.ACESFilmicToneMapping;
63
- renderer.toneMappingExposure = theme === 'dark' ? 1.0 : 1.4;
64
- renderer.shadowMap.enabled = true;
65
- renderer.shadowMap.type = THREE.PCFSoftShadowMap;
66
-
67
- if (theme === 'dark') {
68
- renderer.setClearColor(0x050510);
69
- } else {
70
- renderer.setClearColor(0xe8ecf4);
71
- }
72
-
73
- /* ─── Lighting ─────────────────────────────────────────────────────────── */
74
- setupLighting(scene, theme);
75
-
76
- /* ─── Post-processing ──────────────────────────────────────────────────── */
77
- setupPostProcessing(theme);
78
-
79
- /* ─── Ground Grid ──────────────────────────────────────────────────────── */
80
- createGroundGrid(theme);
81
-
82
- /* ─── Sky ──────────────────────────────────────────────────────────────── */
83
- createSkyDome(theme);
84
-
85
- return { renderer, scene, camera, composer, clock };
86
- }
87
-
88
- /* ═══════════════════════════════════════════════════════════════════════════════
89
- 2. Lighting Setup
90
- ═══════════════════════════════════════════════════════════════════════════════ */
91
- function setupLighting(scene, theme) {
92
- // Remove existing lights
93
- scene.children.filter(c => c.isLight).forEach(l => scene.remove(l));
94
-
95
- if (theme === 'dark') {
96
- /* ── Dark theme: moody blue-green ambient + dramatic spots ────────── */
97
- const ambient = new THREE.AmbientLight(0x1a2a4a, 0.4);
98
- ambient.name = 'ambient';
99
- scene.add(ambient);
100
-
101
- const hemi = new THREE.HemisphereLight(0x0d1b2a, 0x0a0f1e, 0.3);
102
- hemi.name = 'hemi';
103
- scene.add(hemi);
104
-
105
- // Main directional (moonlight)
106
- const dir = new THREE.DirectionalLight(0x4488cc, 0.6);
107
- dir.name = 'dir-main';
108
- dir.position.set(-10, 20, 10);
109
- dir.castShadow = true;
110
- dir.shadow.mapSize.set(2048, 2048);
111
- dir.shadow.camera.near = 0.5;
112
- dir.shadow.camera.far = 60;
113
- dir.shadow.camera.left = -25;
114
- dir.shadow.camera.right = 25;
115
- dir.shadow.camera.top = 25;
116
- dir.shadow.camera.bottom = -25;
117
- dir.shadow.bias = -0.002;
118
- dir.shadow.normalBias = 0.02;
119
- scene.add(dir);
120
-
121
- // Accent spot (green glow from center)
122
- const accent = new THREE.PointLight(0x34d399, 2.0, 30, 1.5);
123
- accent.name = 'accent-glow';
124
- accent.position.set(0, 6, 0);
125
- accent.castShadow = false;
126
- scene.add(accent);
127
-
128
- // Rim light (purple back-light)
129
- const rim = new THREE.PointLight(0xa78bfa, 1.0, 25, 1.5);
130
- rim.name = 'rim-light';
131
- rim.position.set(-12, 8, -12);
132
- scene.add(rim);
133
-
134
- // Warm light (desk area)
135
- const warm = new THREE.PointLight(0xfbbf24, 0.8, 15, 2);
136
- warm.name = 'warm-desk';
137
- warm.position.set(6, 4, 6);
138
- scene.add(warm);
139
-
140
- } else {
141
- /* ── Light theme: bright natural lighting ─────────────────────────── */
142
- const ambient = new THREE.AmbientLight(0xf0f4fa, 0.6);
143
- ambient.name = 'ambient';
144
- scene.add(ambient);
145
-
146
- const hemi = new THREE.HemisphereLight(0xddeeff, 0xf0ece0, 0.5);
147
- hemi.name = 'hemi';
148
- scene.add(hemi);
149
-
150
- // Sun
151
- const dir = new THREE.DirectionalLight(0xfff5e6, 1.2);
152
- dir.name = 'dir-main';
153
- dir.position.set(12, 25, 8);
154
- dir.castShadow = true;
155
- dir.shadow.mapSize.set(2048, 2048);
156
- dir.shadow.camera.near = 0.5;
157
- dir.shadow.camera.far = 60;
158
- dir.shadow.camera.left = -25;
159
- dir.shadow.camera.right = 25;
160
- dir.shadow.camera.top = 25;
161
- dir.shadow.camera.bottom = -25;
162
- dir.shadow.bias = -0.002;
163
- dir.shadow.normalBias = 0.02;
164
- scene.add(dir);
165
-
166
- // Soft fill
167
- const fill = new THREE.DirectionalLight(0xb3d4ff, 0.4);
168
- fill.name = 'fill-light';
169
- fill.position.set(-8, 12, -5);
170
- scene.add(fill);
171
-
172
- // Subtle accent
173
- const accent = new THREE.PointLight(0x059669, 0.6, 20, 2);
174
- accent.name = 'accent-glow';
175
- accent.position.set(0, 5, 0);
176
- scene.add(accent);
177
- }
178
- }
179
-
180
- /* ═══════════════════════════════════════════════════════════════════════════════
181
- 3. Post-processing Pipeline
182
- ═══════════════════════════════════════════════════════════════════════════════ */
183
- function setupPostProcessing(theme) {
184
- const size = renderer.getSize(new THREE.Vector2());
185
-
186
- composer = new EffectComposer(renderer);
187
-
188
- // Render pass
189
- const renderPass = new RenderPass(scene, camera);
190
- composer.addPass(renderPass);
191
-
192
- // Bloom pass — gives the neon glow effect
193
- bloomPass = new UnrealBloomPass(
194
- new THREE.Vector2(size.x, size.y),
195
- theme === 'dark' ? 0.6 : 0.15, // strength
196
- 0.4, // radius
197
- theme === 'dark' ? 0.85 : 0.95 // threshold
198
- );
199
- composer.addPass(bloomPass);
200
-
201
- // FXAA anti-aliasing
202
- fxaaPass = new ShaderPass(FXAAShader);
203
- fxaaPass.uniforms['resolution'].value.set(1 / size.x, 1 / size.y);
204
- composer.addPass(fxaaPass);
205
-
206
- // Output pass (gamma correction)
207
- const outputPass = new OutputPass();
208
- composer.addPass(outputPass);
209
- }
210
-
211
- /* ═══════════════════════════════════════════════════════════════════════════════
212
- 4. Ground Grid — Procedural infinite grid
213
- ═══════════════════════════════════════════════════════════════════════════════ */
214
- function createGroundGrid(theme) {
215
- /* ── Ground plane ──────────────────────────────────────────────────────── */
216
- const groundGeo = new THREE.PlaneGeometry(200, 200);
217
- const groundMat = new THREE.MeshStandardMaterial({
218
- color: theme === 'dark' ? 0x0a0f1e : 0xdee4ed,
219
- roughness: 0.95,
220
- metalness: 0.0,
221
- });
222
- const ground = new THREE.Mesh(groundGeo, groundMat);
223
- ground.rotation.x = -Math.PI / 2;
224
- ground.position.y = -0.01;
225
- ground.receiveShadow = true;
226
- ground.name = 'ground';
227
- scene.add(ground);
228
-
229
- /* ── Grid lines ────────────────────────────────────────────────────────── */
230
- const gridSize = 80;
231
- const gridDiv = 40;
232
- const gridHelper = new THREE.GridHelper(
233
- gridSize, gridDiv,
234
- theme === 'dark' ? 0x1a2a3a : 0xbcc5d0,
235
- theme === 'dark' ? 0x0f1a2a : 0xd0d8e0,
236
- );
237
- gridHelper.position.y = 0.01;
238
- gridHelper.material.opacity = theme === 'dark' ? 0.3 : 0.2;
239
- gridHelper.material.transparent = true;
240
- gridHelper.name = 'grid';
241
- scene.add(gridHelper);
242
-
243
- /* ── Accent grid ring around center ────────────────────────────────────── */
244
- const ringGeo = new THREE.RingGeometry(8, 8.08, 64);
245
- const ringMat = new THREE.MeshBasicMaterial({
246
- color: theme === 'dark' ? 0x34d399 : 0x059669,
247
- transparent: true,
248
- opacity: theme === 'dark' ? 0.4 : 0.2,
249
- side: THREE.DoubleSide,
250
- });
251
- const ring = new THREE.Mesh(ringGeo, ringMat);
252
- ring.rotation.x = -Math.PI / 2;
253
- ring.position.y = 0.02;
254
- ring.name = 'center-ring';
255
- scene.add(ring);
256
-
257
- /* ── Second ring ───────────────────────────────────────────────────────── */
258
- const ring2Geo = new THREE.RingGeometry(14, 14.06, 64);
259
- const ring2Mat = new THREE.MeshBasicMaterial({
260
- color: theme === 'dark' ? 0x60a5fa : 0x2563eb,
261
- transparent: true,
262
- opacity: theme === 'dark' ? 0.2 : 0.1,
263
- side: THREE.DoubleSide,
264
- });
265
- const ring2 = new THREE.Mesh(ring2Geo, ring2Mat);
266
- ring2.rotation.x = -Math.PI / 2;
267
- ring2.position.y = 0.02;
268
- ring2.name = 'outer-ring';
269
- scene.add(ring2);
270
- }
271
-
272
- /* ═══════════════════════════════════════════════════════════════════════════════
273
- 5. Sky Dome — Gradient atmosphere
274
- ═══════════════════════════════════════════════════════════════════════════════ */
275
- function createSkyDome(theme) {
276
- const skyGeo = new THREE.SphereGeometry(150, 32, 32);
277
-
278
- // Custom shader for gradient sky
279
- const skyMat = new THREE.ShaderMaterial({
280
- uniforms: {
281
- topColor: { value: theme === 'dark' ? new THREE.Color(0x0a0f2e) : new THREE.Color(0x87ceeb) },
282
- bottomColor: { value: theme === 'dark' ? new THREE.Color(0x050510) : new THREE.Color(0xe8ecf4) },
283
- offset: { value: 20 },
284
- exponent: { value: 0.6 },
285
- },
286
- vertexShader: `
287
- varying vec3 vWorldPosition;
288
- void main() {
289
- vec4 worldPos = modelMatrix * vec4(position, 1.0);
290
- vWorldPosition = worldPos.xyz;
291
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
292
- }
293
- `,
294
- fragmentShader: `
295
- uniform vec3 topColor;
296
- uniform vec3 bottomColor;
297
- uniform float offset;
298
- uniform float exponent;
299
- varying vec3 vWorldPosition;
300
- void main() {
301
- float h = normalize(vWorldPosition + offset).y;
302
- gl_FragColor = vec4(mix(bottomColor, topColor, max(pow(max(h, 0.0), exponent), 0.0)), 1.0);
303
- }
304
- `,
305
- side: THREE.BackSide,
306
- depthWrite: false,
307
- });
308
-
309
- const sky = new THREE.Mesh(skyGeo, skyMat);
310
- sky.name = 'sky';
311
- scene.add(sky);
312
-
313
- /* ── Stars (dark theme only) ───────────────────────────────────────────── */
314
- if (theme === 'dark') {
315
- createStarField();
316
- }
317
- }
318
-
319
- /* ═══════════════════════════════════════════════════════════════════════════════
320
- 6. Star Field — Procedural stars
321
- ═══════════════════════════════════════════════════════════════════════════════ */
322
- function createStarField() {
323
- const count = 2000;
324
- const positions = new Float32Array(count * 3);
325
- const sizes = new Float32Array(count);
326
- const colors = new Float32Array(count * 3);
327
-
328
- const starColors = [
329
- new THREE.Color(0xffffff),
330
- new THREE.Color(0xccddff),
331
- new THREE.Color(0xffeedd),
332
- new THREE.Color(0xddeeff),
333
- new THREE.Color(0x34d399),
334
- ];
335
-
336
- for (let i = 0; i < count; i++) {
337
- // Distribute on upper hemisphere
338
- const theta = Math.random() * Math.PI * 2;
339
- const phi = Math.random() * Math.PI * 0.45; // Only upper portion
340
- const r = 100 + Math.random() * 40;
341
-
342
- positions[i * 3] = r * Math.sin(phi) * Math.cos(theta);
343
- positions[i * 3 + 1] = r * Math.cos(phi);
344
- positions[i * 3 + 2] = r * Math.sin(phi) * Math.sin(theta);
345
-
346
- sizes[i] = 0.3 + Math.random() * 1.2;
347
-
348
- const c = starColors[Math.floor(Math.random() * starColors.length)];
349
- colors[i * 3] = c.r;
350
- colors[i * 3 + 1] = c.g;
351
- colors[i * 3 + 2] = c.b;
352
- }
353
-
354
- const geo = new THREE.BufferGeometry();
355
- geo.setAttribute('position', new THREE.BufferAttribute(positions, 3));
356
- geo.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
357
- geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
358
-
359
- const mat = new THREE.ShaderMaterial({
360
- uniforms: {
361
- time: { value: 0 },
362
- },
363
- vertexShader: `
364
- attribute float size;
365
- attribute vec3 color;
366
- varying vec3 vColor;
367
- varying float vSize;
368
- uniform float time;
369
- void main() {
370
- vColor = color;
371
- vSize = size;
372
- vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
373
- float twinkle = 0.7 + 0.3 * sin(time * 2.0 + position.x * 10.0 + position.z * 7.0);
374
- gl_PointSize = size * twinkle * (200.0 / -mvPosition.z);
375
- gl_Position = projectionMatrix * mvPosition;
376
- }
377
- `,
378
- fragmentShader: `
379
- varying vec3 vColor;
380
- varying float vSize;
381
- void main() {
382
- vec2 center = gl_PointCoord - vec2(0.5);
383
- float dist = length(center);
384
- if (dist > 0.5) discard;
385
- float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
386
- float glow = exp(-dist * dist * 8.0);
387
- gl_FragColor = vec4(vColor * (0.8 + glow * 0.5), alpha * 0.9);
388
- }
389
- `,
390
- transparent: true,
391
- depthWrite: false,
392
- blending: THREE.AdditiveBlending,
393
- });
394
-
395
- const stars = new THREE.Points(geo, mat);
396
- stars.name = 'stars';
397
- scene.add(stars);
398
- }
399
-
400
- /* ═══════════════════════════════════════════════════════════════════════════════
401
- 7. Resize Handler
402
- ═══════════════════════════════════════════════════════════════════════════════ */
403
- export function resizeEngine() {
404
- if (!renderer || !camera) return;
405
- const w = window.innerWidth;
406
- const h = window.innerHeight;
407
- camera.aspect = w / h;
408
- camera.updateProjectionMatrix();
409
- renderer.setSize(w, h);
410
- if (composer) composer.setSize(w, h);
411
- if (fxaaPass) fxaaPass.uniforms['resolution'].value.set(1 / w, 1 / h);
412
- }
413
-
414
- /* ═══════════════════════════════════════════════════════════════════════════════
415
- 8. Update Functions
416
- ═══════════════════════════════════════════════════════════════════════════════ */
417
-
418
- /** Called each frame to update time-based uniforms */
419
- export function updateEngine(dt) {
420
- // Update star twinkle
421
- const stars = scene.getObjectByName('stars');
422
- if (stars && stars.material.uniforms) {
423
- stars.material.uniforms.time.value += dt;
424
- }
425
-
426
- // Animate center ring
427
- const ring = scene.getObjectByName('center-ring');
428
- if (ring) {
429
- ring.rotation.z += dt * 0.1;
430
- }
431
-
432
- const ring2 = scene.getObjectByName('outer-ring');
433
- if (ring2) {
434
- ring2.rotation.z -= dt * 0.05;
435
- }
436
- }
437
-
438
- /* ═══════════════════════════════════════════════════════════════════════════════
439
- 9. Theme Update
440
- ═══════════════════════════════════════════════════════════════════════════════ */
441
- export function updateEngineTheme(theme) {
442
- if (!renderer || !scene) return;
443
-
444
- // Update clear color
445
- renderer.setClearColor(theme === 'dark' ? 0x050510 : 0xe8ecf4);
446
- renderer.toneMappingExposure = theme === 'dark' ? 1.0 : 1.4;
447
-
448
- // Update fog
449
- scene.fog = theme === 'dark'
450
- ? new THREE.FogExp2(0x050510, 0.012)
451
- : new THREE.FogExp2(0xe8ecf4, 0.008);
452
-
453
- // Update lighting
454
- setupLighting(scene, theme);
455
-
456
- // Update bloom
457
- if (bloomPass) {
458
- bloomPass.strength = theme === 'dark' ? 0.6 : 0.15;
459
- bloomPass.threshold = theme === 'dark' ? 0.85 : 0.95;
460
- }
461
-
462
- // Update ground
463
- const ground = scene.getObjectByName('ground');
464
- if (ground) ground.material.color.setHex(theme === 'dark' ? 0x0a0f1e : 0xdee4ed);
465
-
466
- // Update grid
467
- const grid = scene.getObjectByName('grid');
468
- if (grid) {
469
- grid.material.opacity = theme === 'dark' ? 0.3 : 0.2;
470
- }
471
-
472
- // Update sky
473
- const sky = scene.getObjectByName('sky');
474
- if (sky && sky.material.uniforms) {
475
- sky.material.uniforms.topColor.value.setHex(theme === 'dark' ? 0x0a0f2e : 0x87ceeb);
476
- sky.material.uniforms.bottomColor.value.setHex(theme === 'dark' ? 0x050510 : 0xe8ecf4);
477
- }
478
-
479
- // Stars visibility
480
- const stars = scene.getObjectByName('stars');
481
- if (stars) stars.visible = theme === 'dark';
482
- if (!stars && theme === 'dark') createStarField();
483
-
484
- // Center ring
485
- const ring = scene.getObjectByName('center-ring');
486
- if (ring) {
487
- ring.material.color.setHex(theme === 'dark' ? 0x34d399 : 0x059669);
488
- ring.material.opacity = theme === 'dark' ? 0.4 : 0.2;
489
- }
490
- }
491
-
492
- /* ═══════════════════════════════════════════════════════════════════════════════
493
- 10. Getters
494
- ═══════════════════════════════════════════════════════════════════════════════ */
495
- export function disposeEngine() {
496
- if (scene) {
497
- scene.traverse((child) => {
498
- child.geometry?.dispose?.();
499
- if (Array.isArray(child.material)) {
500
- child.material.forEach(disposeMaterial);
501
- } else {
502
- disposeMaterial(child.material);
503
- }
504
- });
505
-
506
- while (scene.children.length > 0) {
507
- scene.remove(scene.children[0]);
508
- }
509
- }
510
-
511
- composer?.passes?.forEach?.((pass) => pass.dispose?.());
512
- composer?.dispose?.();
513
- renderer?.dispose?.();
514
-
515
- renderer = null;
516
- scene = null;
517
- camera = null;
518
- composer = null;
519
- clock = null;
520
- bloomPass = null;
521
- fxaaPass = null;
522
- }
523
-
524
- export function getRenderer() { return renderer; }
525
- export function getScene() { return scene; }
526
- export function getCamera() { return camera; }
527
- export function getComposer() { return composer; }
528
- export function getClock() { return clock; }