@2112-lab/central-plant 0.1.78 → 0.1.80

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.
@@ -1,4 +1,4 @@
1
- import { createClass as _createClass, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, regeneratorValues as _regeneratorValues, createForOfIteratorHelper as _createForOfIteratorHelper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
1
+ import { createClass as _createClass, classCallCheck as _classCallCheck, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, regeneratorValues as _regeneratorValues } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
2
  import * as THREE from 'three';
3
3
  import { RGBELoader } from '../../../node_modules/three/examples/jsm/loaders/RGBELoader.js';
4
4
  import { loadTextureSetAndCreateMaterial } from './textureConfig.js';
@@ -9,173 +9,88 @@ var EnvironmentManager = /*#__PURE__*/function () {
9
9
  this.sceneViewer = sceneViewer;
10
10
  }
11
11
 
12
+ // ──────────────────────────────────────────────
13
+ // Skybox / environment map
14
+ // ──────────────────────────────────────────────
15
+
12
16
  /**
13
- * Create skybox with HDR environment mapping
17
+ * Create a lightweight procedural sky (default).
18
+ *
19
+ * Builds a gradient-sky sphere + hemisphere light, then bakes a small
20
+ * PMREM environment map for PBR reflections. Total GPU cost is ~1-2 MB
21
+ * compared to ~50-70 MB for the previous HDR pipeline.
14
22
  */
15
23
  return _createClass(EnvironmentManager, [{
16
24
  key: "createSkybox",
17
- value: (function () {
25
+ value: function () {
18
26
  var _createSkybox = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
19
- var component, pmremGenerator, loaders, applyEnvironmentMap, _loop, _ret, _i, _loaders, ambientLight, skyScene;
20
- return _regenerator().w(function (_context3) {
21
- while (1) switch (_context3.n) {
27
+ var component, _t;
28
+ return _regenerator().w(function (_context) {
29
+ while (1) switch (_context.n) {
22
30
  case 0:
23
31
  component = this.sceneViewer;
24
- pmremGenerator = new THREE.PMREMGenerator(component.renderer);
25
- pmremGenerator.compileEquirectangularShader();
26
- loaders = [{
27
- type: 'hdr',
28
- loader: new RGBELoader(),
29
- paths: ['/skyboxes/kloofendal_48d_partly_cloudy_puresky_2k.hdr', '/skyboxes/kloofendal_48d_partly_cloudy_puresky_1k.hdr']
30
- }, {
31
- type: 'jpeg',
32
- loader: component.textureLoader,
33
- paths: ['/skyboxes/sky_fallback.jpg']
34
- }];
35
- applyEnvironmentMap = function applyEnvironmentMap(envTexture, type) {
36
- try {
37
- var _component$scene$envi, _component$scene$back;
38
- envTexture.mapping = THREE.EquirectangularReflectionMapping;
39
- var processedEnvMap = pmremGenerator.fromEquirectangular(envTexture).texture;
40
- if ((_component$scene$envi = component.scene.environment) !== null && _component$scene$envi !== void 0 && _component$scene$envi.dispose) component.scene.environment.dispose();
41
- if ((_component$scene$back = component.scene.background) !== null && _component$scene$back !== void 0 && _component$scene$back.dispose) component.scene.background.dispose();
42
- component.scene.environment = processedEnvMap;
43
- component.scene.background = processedEnvMap;
44
- envTexture.dispose();
45
- console.log("\u2705 ".concat(type.toUpperCase(), " environment map applied successfully"));
46
- return true;
47
- } catch (error) {
48
- console.warn("\u274C Failed to apply ".concat(type, " environment map:"), error);
49
- return false;
50
- }
51
- };
52
- _loop = /*#__PURE__*/_regenerator().m(function _loop() {
53
- var _loaders$_i, type, loader, paths, _iterator, _step, _loop2, _ret2, _t2;
54
- return _regenerator().w(function (_context2) {
55
- while (1) switch (_context2.n) {
56
- case 0:
57
- _loaders$_i = _loaders[_i], type = _loaders$_i.type, loader = _loaders$_i.loader, paths = _loaders$_i.paths;
58
- _iterator = _createForOfIteratorHelper(paths);
59
- _context2.p = 1;
60
- _loop2 = /*#__PURE__*/_regenerator().m(function _loop2() {
61
- var path, texture, _t;
62
- return _regenerator().w(function (_context) {
63
- while (1) switch (_context.n) {
64
- case 0:
65
- path = _step.value;
66
- _context.p = 1;
67
- console.log("\uD83D\uDD04 Attempting to load ".concat(type.toUpperCase(), ": ").concat(path));
68
- _context.n = 2;
69
- return new Promise(function (resolve, reject) {
70
- var timeout = setTimeout(function () {
71
- return reject(new Error('Timeout'));
72
- }, 10000);
73
- loader.load(path, function (tex) {
74
- clearTimeout(timeout);
75
- resolve(tex);
76
- }, undefined, function (err) {
77
- clearTimeout(timeout);
78
- reject(err);
79
- });
80
- });
81
- case 2:
82
- texture = _context.v;
83
- if (!applyEnvironmentMap(texture, type)) {
84
- _context.n = 3;
85
- break;
86
- }
87
- pmremGenerator.dispose();
88
- return _context.a(2, {
89
- v: {
90
- v: void 0
91
- }
92
- });
93
- case 3:
94
- _context.n = 5;
95
- break;
96
- case 4:
97
- _context.p = 4;
98
- _t = _context.v;
99
- console.warn("\u26A0\uFE0F Failed to load ".concat(path, ":"), _t.message);
100
- case 5:
101
- return _context.a(2);
102
- }
103
- }, _loop2, null, [[1, 4]]);
104
- });
105
- _iterator.s();
106
- case 2:
107
- if ((_step = _iterator.n()).done) {
108
- _context2.n = 5;
109
- break;
110
- }
111
- return _context2.d(_regeneratorValues(_loop2()), 3);
112
- case 3:
113
- _ret2 = _context2.v;
114
- if (!_ret2) {
115
- _context2.n = 4;
116
- break;
117
- }
118
- return _context2.a(2, _ret2.v);
119
- case 4:
120
- _context2.n = 2;
121
- break;
122
- case 5:
123
- _context2.n = 7;
124
- break;
125
- case 6:
126
- _context2.p = 6;
127
- _t2 = _context2.v;
128
- _iterator.e(_t2);
129
- case 7:
130
- _context2.p = 7;
131
- _iterator.f();
132
- return _context2.f(7);
133
- case 8:
134
- return _context2.a(2);
135
- }
136
- }, _loop, null, [[1, 6, 7, 8]]);
137
- });
138
- _i = 0, _loaders = loaders;
139
- case 1:
140
- if (!(_i < _loaders.length)) {
141
- _context3.n = 4;
142
- break;
143
- }
144
- return _context3.d(_regeneratorValues(_loop()), 2);
32
+ _context.p = 1;
33
+ _context.n = 2;
34
+ return this._applyProceduralSky(component);
145
35
  case 2:
146
- _ret = _context3.v;
147
- if (!_ret) {
148
- _context3.n = 3;
149
- break;
150
- }
151
- return _context3.a(2, _ret.v);
152
- case 3:
153
- _i++;
154
- _context3.n = 1;
36
+ console.log('✅ Procedural sky environment applied');
37
+ _context.n = 4;
155
38
  break;
39
+ case 3:
40
+ _context.p = 3;
41
+ _t = _context.v;
42
+ console.warn('⚠️ Procedural sky failed, applying plain color fallback:', _t);
43
+ this.setColorBackground();
156
44
  case 4:
157
- console.log('🎨 Using procedural sky fallback');
158
- ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
159
- component.scene.add(ambientLight);
160
- skyScene = new THREE.Scene(); // Create hemisphere light with Z-up orientation - sky color up, ground color down
161
- skyScene.add(new THREE.HemisphereLight(0x87CEEB, 0x444477, 1));
162
- component.scene.environment = pmremGenerator.fromScene(skyScene).texture;
163
- component.scene.background = new THREE.Color(0x87CEEB);
164
- pmremGenerator.dispose();
165
- case 5:
166
- return _context3.a(2);
45
+ return _context.a(2);
167
46
  }
168
- }, _callee, this);
47
+ }, _callee, this, [[1, 3]]);
169
48
  }));
170
49
  function createSkybox() {
171
50
  return _createSkybox.apply(this, arguments);
172
51
  }
173
52
  return createSkybox;
174
53
  }()
54
+ /**
55
+ * Build a procedural sky environment.
56
+ *
57
+ * Uses two separate, lightweight resources:
58
+ * - **Background**: Canvas-rendered gradient texture mapped as equirectangular
59
+ * (512 × 256 px ≈ 0.5 MB GPU).
60
+ * - **Environment**: PMREM baked from a HemisphereLight scene for PBR IBL
61
+ * reflections (~1 MB GPU).
62
+ *
63
+ * Custom ShaderMaterials are intentionally avoided inside the PMREM pipeline
64
+ * because `PMREMGenerator.fromScene()` uses its own cube-face cameras that
65
+ * can produce black output with non-standard shaders.
66
+ * @private
67
+ */
68
+ }, {
69
+ key: "_applyProceduralSky",
70
+ value: function _applyProceduralSky(component) {
71
+ var _component$scene$envi, _component$scene$back;
72
+ // Dispose of existing textures
73
+ if ((_component$scene$envi = component.scene.environment) !== null && _component$scene$envi !== void 0 && _component$scene$envi.dispose) component.scene.environment.dispose();
74
+ if ((_component$scene$back = component.scene.background) !== null && _component$scene$back !== void 0 && _component$scene$back.dispose) component.scene.background.dispose();
75
+
76
+ // ── 1. Solid-colour background ──────────────────────────────────────────
77
+ // A plain THREE.Color is coordinate-system agnostic (no equirectangular
78
+ // mapping that assumes Y-up), cheap (zero GPU textures), and looks clean.
79
+ component.scene.background = new THREE.Color(0xbcddeb); // light sky blue
80
+
81
+ // ── 2. PMREM env-map from HemisphereLight for PBR IBL reflections ───────
82
+ // Intensity must be high enough to light MeshPhysicalMaterial surfaces
83
+ // that the directional lights don't reach evenly (wall backs, crevices).
84
+ var pmremGenerator = new THREE.PMREMGenerator(component.renderer);
85
+ var lightScene = new THREE.Scene();
86
+ lightScene.add(new THREE.HemisphereLight(0xbcddeb, 0x444477, 3.0));
87
+ component.scene.environment = pmremGenerator.fromScene(lightScene).texture;
88
+ pmremGenerator.dispose();
89
+ }
90
+
175
91
  /**
176
92
  * Setup scene lighting
177
93
  */
178
- )
179
94
  }, {
180
95
  key: "setupLighting",
181
96
  value: function setupLighting() {
@@ -201,15 +116,27 @@ var EnvironmentManager = /*#__PURE__*/function () {
201
116
  component.scene.add(sunLight);
202
117
  // component.scene.add(sunLight.target)
203
118
 
204
- // // Ambient hemispheric light
205
- // const ambientLight = new THREE.HemisphereLight(0xffffff, 0x444466, 0.35)
206
- // component.scene.add(ambientLight)
119
+ // Flat ambient light – ensures no surface is ever fully black regardless
120
+ // of orientation. Low intensity so it doesn't wash out lit surfaces.
121
+ var flatAmbient = new THREE.AmbientLight(0xffffff, 1.0);
122
+ component.scene.add(flatAmbient);
123
+
124
+ // Hemispheric ambient – adds sky/ground colour tint on surfaces the
125
+ // directional lights miss (essential without an HDR environment map).
126
+ var ambientLight = new THREE.HemisphereLight(0xffffff, 0x444466, 1.0);
127
+ component.scene.add(ambientLight);
207
128
 
208
129
  // Fill light (secondary directional light) - adjusted for Z-up coordinate system with flipped Y
209
- var fillLight = new THREE.DirectionalLight(0xffffff, 2.0);
130
+ var fillLight = new THREE.DirectionalLight(0xffffff, 3.0);
210
131
  fillLight.position.set(10, -10, 10); // X=-10, Y=-10 (flipped), Z=10 (up in Z-up system)
211
132
  component.scene.add(fillLight);
212
133
 
134
+ // Back-fill light – illuminates rear-facing walls and equipment backs
135
+ // that the sun and primary fill can't reach.
136
+ var backFillLight = new THREE.DirectionalLight(0xddeeff, 3.0);
137
+ backFillLight.position.set(-10, 10, 8);
138
+ component.scene.add(backFillLight);
139
+
213
140
  // // Rim light (for edge definition)
214
141
  // const rimLight = new THREE.DirectionalLight(0xffffff, 0.9)
215
142
  // rimLight.position.set(0, 0, -20)
@@ -238,9 +165,9 @@ var EnvironmentManager = /*#__PURE__*/function () {
238
165
  key: "addTexturedGround",
239
166
  value: (function () {
240
167
  var _addTexturedGround = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
241
- var component, groundSize, groundGeometry, groundMaterial, ground, texturedMaterial, _t3;
242
- return _regenerator().w(function (_context4) {
243
- while (1) switch (_context4.n) {
168
+ var component, groundSize, groundGeometry, groundMaterial, ground, texturedMaterial, _t2;
169
+ return _regenerator().w(function (_context2) {
170
+ while (1) switch (_context2.n) {
244
171
  case 0:
245
172
  component = this.sceneViewer;
246
173
  console.debug('Starting addTexturedGround...');
@@ -259,23 +186,23 @@ var EnvironmentManager = /*#__PURE__*/function () {
259
186
  ground.uuid = 'GROUND'; // Set UUID to match JSON data structure
260
187
  ground.userData.isBaseGround = true;
261
188
  component.scene.add(ground);
262
- _context4.p = 1;
189
+ _context2.p = 1;
263
190
  console.debug('Loading concrete texture set...');
264
- _context4.n = 2;
191
+ _context2.n = 2;
265
192
  return loadTextureSetAndCreateMaterial('gravel_embedded_concrete', component.textureLoader);
266
193
  case 2:
267
- texturedMaterial = _context4.v;
194
+ texturedMaterial = _context2.v;
268
195
  ground.material = texturedMaterial;
269
196
  ground.material.needsUpdate = true;
270
197
  console.log('✅ Ground material updated with textures');
271
- _context4.n = 4;
198
+ _context2.n = 4;
272
199
  break;
273
200
  case 3:
274
- _context4.p = 3;
275
- _t3 = _context4.v;
276
- console.warn('Error loading ground textures:', _t3);
201
+ _context2.p = 3;
202
+ _t2 = _context2.v;
203
+ console.warn('Error loading ground textures:', _t2);
277
204
  case 4:
278
- return _context4.a(2);
205
+ return _context2.a(2);
279
206
  }
280
207
  }, _callee2, this, [[1, 3]]);
281
208
  }));
@@ -292,9 +219,9 @@ var EnvironmentManager = /*#__PURE__*/function () {
292
219
  key: "addBrickWalls",
293
220
  value: (function () {
294
221
  var _addBrickWalls = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
295
- var component, wallHeight, wallThickness, groundSize, halfGroundSize, brickMaterial, createWalls, texturedBrickMaterial, _t4;
296
- return _regenerator().w(function (_context5) {
297
- while (1) switch (_context5.n) {
222
+ var component, wallHeight, wallThickness, groundSize, halfGroundSize, brickMaterial, createWalls, texturedBrickMaterial, _t3;
223
+ return _regenerator().w(function (_context3) {
224
+ while (1) switch (_context3.n) {
298
225
  case 0:
299
226
  component = this.sceneViewer;
300
227
  console.debug('Starting addBrickWalls...');
@@ -396,12 +323,12 @@ var EnvironmentManager = /*#__PURE__*/function () {
396
323
  };
397
324
  createWalls(brickMaterial);
398
325
  console.debug('Basic brick walls created');
399
- _context5.p = 1;
326
+ _context3.p = 1;
400
327
  console.debug('Loading brick texture set...');
401
- _context5.n = 2;
328
+ _context3.n = 2;
402
329
  return loadTextureSetAndCreateMaterial('brick', component.textureLoader);
403
330
  case 2:
404
- texturedBrickMaterial = _context5.v;
331
+ texturedBrickMaterial = _context3.v;
405
332
  component.scene.traverse(function (object) {
406
333
  if (object.isMesh && object.userData.isBrickWall) {
407
334
  object.material = texturedBrickMaterial;
@@ -409,14 +336,14 @@ var EnvironmentManager = /*#__PURE__*/function () {
409
336
  }
410
337
  });
411
338
  console.log('✅ Brick walls updated with textures');
412
- _context5.n = 4;
339
+ _context3.n = 4;
413
340
  break;
414
341
  case 3:
415
- _context5.p = 3;
416
- _t4 = _context5.v;
417
- console.warn('Error loading brick textures:', _t4);
342
+ _context3.p = 3;
343
+ _t3 = _context3.v;
344
+ console.warn('Error loading brick textures:', _t3);
418
345
  case 4:
419
- return _context5.a(2);
346
+ return _context3.a(2);
420
347
  }
421
348
  }, _callee3, this, [[1, 3]]);
422
349
  }));
@@ -465,23 +392,23 @@ var EnvironmentManager = /*#__PURE__*/function () {
465
392
  key: "initializeEnvironment",
466
393
  value: (function () {
467
394
  var _initializeEnvironment = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
468
- return _regenerator().w(function (_context6) {
469
- while (1) switch (_context6.n) {
395
+ return _regenerator().w(function (_context4) {
396
+ while (1) switch (_context4.n) {
470
397
  case 0:
471
- _context6.n = 1;
398
+ _context4.n = 1;
472
399
  return this.createSkybox();
473
400
  case 1:
474
401
  this.setupLighting();
475
- _context6.n = 2;
402
+ _context4.n = 2;
476
403
  return this.addTexturedGround();
477
404
  case 2:
478
- _context6.n = 3;
405
+ _context4.n = 3;
479
406
  return this.addBrickWalls();
480
407
  case 3:
481
408
  this.addHorizonFog();
482
409
  console.log('Environment initialization completed');
483
410
  case 4:
484
- return _context6.a(2);
411
+ return _context4.a(2);
485
412
  }
486
413
  }, _callee4, this);
487
414
  }));
@@ -522,60 +449,50 @@ var EnvironmentManager = /*#__PURE__*/function () {
522
449
 
523
450
  /**
524
451
  * Set the skybox type dynamically
525
- * @param {string} skyboxType - 'HDR', 'Fallback', or 'Color'
452
+ * @param {'Procedural'|'HDR'|'Color'} skyboxType
526
453
  */
527
454
  }, {
528
455
  key: "setSkyboxType",
529
456
  value: (function () {
530
457
  var _setSkyboxType = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(skyboxType) {
531
- var component, _component$scene$envi3, _component$scene$back3, _pmremGenerator, _t5, _t6;
532
- return _regenerator().w(function (_context7) {
533
- while (1) switch (_context7.n) {
458
+ var component, _component$scene$envi3, _component$scene$back3, _t4, _t5;
459
+ return _regenerator().w(function (_context5) {
460
+ while (1) switch (_context5.n) {
534
461
  case 0:
535
462
  component = this.sceneViewer;
536
- _context7.p = 1;
463
+ _context5.p = 1;
537
464
  console.log("\uD83C\uDF0C Changing skybox type to: ".concat(skyboxType));
538
465
 
539
466
  // Dispose of current environment textures
540
- if ((_component$scene$envi3 = component.scene.environment) !== null && _component$scene$envi3 !== void 0 && _component$scene$envi3.dispose) {
541
- component.scene.environment.dispose();
542
- }
543
- if ((_component$scene$back3 = component.scene.background) !== null && _component$scene$back3 !== void 0 && _component$scene$back3.dispose) {
544
- component.scene.background.dispose();
545
- }
546
- _pmremGenerator = new THREE.PMREMGenerator(component.renderer);
547
- _pmremGenerator.compileEquirectangularShader();
548
- _t5 = skyboxType;
549
- _context7.n = _t5 === 'HDR' ? 2 : _t5 === 'Fallback' ? 4 : _t5 === 'Color' ? 6 : 7;
467
+ if ((_component$scene$envi3 = component.scene.environment) !== null && _component$scene$envi3 !== void 0 && _component$scene$envi3.dispose) component.scene.environment.dispose();
468
+ if ((_component$scene$back3 = component.scene.background) !== null && _component$scene$back3 !== void 0 && _component$scene$back3.dispose) component.scene.background.dispose();
469
+ _t4 = skyboxType;
470
+ _context5.n = _t4 === 'Procedural' ? 2 : _t4 === 'HDR' ? 3 : _t4 === 'Color' ? 5 : 6;
550
471
  break;
551
472
  case 2:
552
- _context7.n = 3;
553
- return this.loadHDRSkybox(_pmremGenerator);
473
+ this._applyProceduralSky(component);
474
+ return _context5.a(3, 7);
554
475
  case 3:
555
- return _context7.a(3, 8);
476
+ _context5.n = 4;
477
+ return this._loadHDRSkybox(component);
556
478
  case 4:
557
- _context7.n = 5;
558
- return this.loadFallbackSkybox(_pmremGenerator);
479
+ return _context5.a(3, 7);
559
480
  case 5:
560
- return _context7.a(3, 8);
481
+ this._setColorBackground(component);
482
+ return _context5.a(3, 7);
561
483
  case 6:
562
- this.setColorBackground();
563
- return _context7.a(3, 8);
484
+ console.warn("Unknown skybox type: ".concat(skyboxType, ", using Procedural"));
485
+ this._applyProceduralSky(component);
564
486
  case 7:
565
- console.warn("Unknown skybox type: ".concat(skyboxType, ", falling back to HDR"));
566
- _context7.n = 8;
567
- return this.loadHDRSkybox(_pmremGenerator);
487
+ console.log("\u2705 Skybox type changed to: ".concat(skyboxType));
488
+ return _context5.a(2, true);
568
489
  case 8:
569
- _pmremGenerator.dispose();
570
- console.log("Skybox type changed to: ".concat(skyboxType));
571
- return _context7.a(2, true);
572
- case 9:
573
- _context7.p = 9;
574
- _t6 = _context7.v;
575
- console.error('❌ Error setting skybox type:', _t6);
576
- return _context7.a(2, false);
490
+ _context5.p = 8;
491
+ _t5 = _context5.v;
492
+ console.error('❌ Error setting skybox type:', _t5);
493
+ return _context5.a(2, false);
577
494
  }
578
- }, _callee5, this, [[1, 9]]);
495
+ }, _callee5, this, [[1, 8]]);
579
496
  }));
580
497
  function setSkyboxType(_x) {
581
498
  return _setSkyboxType.apply(this, arguments);
@@ -583,29 +500,34 @@ var EnvironmentManager = /*#__PURE__*/function () {
583
500
  return setSkyboxType;
584
501
  }()
585
502
  /**
586
- * Load HDR skybox specifically
503
+ * Load HDR skybox on demand (high quality, high memory).
504
+ * Tries 1k first to save memory; falls back to color on failure.
505
+ * @private
587
506
  */
588
507
  )
589
508
  }, {
590
- key: "loadHDRSkybox",
509
+ key: "_loadHDRSkybox",
591
510
  value: (function () {
592
- var _loadHDRSkybox = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(pmremGenerator) {
593
- var component, rgbeLoader, hdrPaths, _loop3, _ret3, _i2, _hdrPaths;
594
- return _regenerator().w(function (_context9) {
595
- while (1) switch (_context9.n) {
511
+ var _loadHDRSkybox2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(component) {
512
+ var rgbeLoader, pmremGenerator, hdrPaths, _loop, _ret, _i, _hdrPaths;
513
+ return _regenerator().w(function (_context7) {
514
+ while (1) switch (_context7.n) {
596
515
  case 0:
597
- component = this.sceneViewer;
598
516
  rgbeLoader = new RGBELoader();
599
- hdrPaths = ['/skyboxes/kloofendal_48d_partly_cloudy_puresky_2k.hdr', '/skyboxes/kloofendal_48d_partly_cloudy_puresky_1k.hdr'];
600
- _loop3 = /*#__PURE__*/_regenerator().m(function _loop3() {
601
- var path, texture, processedEnvMap, _t7;
602
- return _regenerator().w(function (_context8) {
603
- while (1) switch (_context8.n) {
517
+ pmremGenerator = new THREE.PMREMGenerator(component.renderer);
518
+ pmremGenerator.compileEquirectangularShader();
519
+
520
+ // Prefer the 1k variant (~20 MB GPU) over 2k (~50 MB GPU)
521
+ hdrPaths = ['/skyboxes/kloofendal_48d_partly_cloudy_puresky_1k.hdr', '/skyboxes/kloofendal_48d_partly_cloudy_puresky_2k.hdr'];
522
+ _loop = /*#__PURE__*/_regenerator().m(function _loop() {
523
+ var path, texture, processedEnvMap, _t6;
524
+ return _regenerator().w(function (_context6) {
525
+ while (1) switch (_context6.n) {
604
526
  case 0:
605
- path = _hdrPaths[_i2];
606
- _context8.p = 1;
527
+ path = _hdrPaths[_i];
528
+ _context6.p = 1;
607
529
  console.log("\uD83D\uDD04 Loading HDR: ".concat(path));
608
- _context8.n = 2;
530
+ _context6.n = 2;
609
531
  return new Promise(function (resolve, reject) {
610
532
  var timeout = setTimeout(function () {
611
533
  return reject(new Error('Timeout'));
@@ -619,123 +541,79 @@ var EnvironmentManager = /*#__PURE__*/function () {
619
541
  });
620
542
  });
621
543
  case 2:
622
- texture = _context8.v;
544
+ texture = _context6.v;
623
545
  texture.mapping = THREE.EquirectangularReflectionMapping;
624
546
  processedEnvMap = pmremGenerator.fromEquirectangular(texture).texture;
625
547
  component.scene.environment = processedEnvMap;
626
548
  component.scene.background = processedEnvMap;
627
549
  texture.dispose();
550
+ pmremGenerator.dispose();
628
551
  console.log('✅ HDR skybox loaded successfully');
629
- return _context8.a(2, {
552
+ return _context6.a(2, {
630
553
  v: void 0
631
554
  });
632
555
  case 3:
633
- _context8.p = 3;
634
- _t7 = _context8.v;
635
- console.warn("\u26A0\uFE0F Failed to load HDR skybox ".concat(path, ":"), _t7.message);
556
+ _context6.p = 3;
557
+ _t6 = _context6.v;
558
+ console.warn("\u26A0\uFE0F Failed to load HDR skybox ".concat(path, ":"), _t6.message);
636
559
  case 4:
637
- return _context8.a(2);
560
+ return _context6.a(2);
638
561
  }
639
- }, _loop3, null, [[1, 3]]);
562
+ }, _loop, null, [[1, 3]]);
640
563
  });
641
- _i2 = 0, _hdrPaths = hdrPaths;
564
+ _i = 0, _hdrPaths = hdrPaths;
642
565
  case 1:
643
- if (!(_i2 < _hdrPaths.length)) {
644
- _context9.n = 4;
566
+ if (!(_i < _hdrPaths.length)) {
567
+ _context7.n = 4;
645
568
  break;
646
569
  }
647
- return _context9.d(_regeneratorValues(_loop3()), 2);
570
+ return _context7.d(_regeneratorValues(_loop()), 2);
648
571
  case 2:
649
- _ret3 = _context9.v;
650
- if (!_ret3) {
651
- _context9.n = 3;
572
+ _ret = _context7.v;
573
+ if (!_ret) {
574
+ _context7.n = 3;
652
575
  break;
653
576
  }
654
- return _context9.a(2, _ret3.v);
577
+ return _context7.a(2, _ret.v);
655
578
  case 3:
656
- _i2++;
657
- _context9.n = 1;
579
+ _i++;
580
+ _context7.n = 1;
658
581
  break;
659
582
  case 4:
583
+ pmremGenerator.dispose();
660
584
  throw new Error('Failed to load any HDR skybox');
661
585
  case 5:
662
- return _context9.a(2);
586
+ return _context7.a(2);
663
587
  }
664
- }, _callee6, this);
588
+ }, _callee6);
665
589
  }));
666
- function loadHDRSkybox(_x2) {
667
- return _loadHDRSkybox.apply(this, arguments);
590
+ function _loadHDRSkybox(_x2) {
591
+ return _loadHDRSkybox2.apply(this, arguments);
668
592
  }
669
- return loadHDRSkybox;
593
+ return _loadHDRSkybox;
670
594
  }()
671
595
  /**
672
- * Load fallback JPEG skybox
596
+ * Set solid color background with basic ambient lighting.
597
+ * @private
673
598
  */
674
599
  )
675
600
  }, {
676
- key: "loadFallbackSkybox",
677
- value: (function () {
678
- var _loadFallbackSkybox = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(pmremGenerator) {
679
- var component, texture, processedEnvMap, _t8;
680
- return _regenerator().w(function (_context0) {
681
- while (1) switch (_context0.n) {
682
- case 0:
683
- component = this.sceneViewer;
684
- _context0.p = 1;
685
- console.log('🔄 Loading fallback skybox');
686
- _context0.n = 2;
687
- return new Promise(function (resolve, reject) {
688
- var timeout = setTimeout(function () {
689
- return reject(new Error('Timeout'));
690
- }, 10000);
691
- component.textureLoader.load('/skyboxes/sky_fallback.jpg', function (tex) {
692
- clearTimeout(timeout);
693
- resolve(tex);
694
- }, undefined, function (err) {
695
- clearTimeout(timeout);
696
- reject(err);
697
- });
698
- });
699
- case 2:
700
- texture = _context0.v;
701
- texture.mapping = THREE.EquirectangularReflectionMapping;
702
- processedEnvMap = pmremGenerator.fromEquirectangular(texture).texture;
703
- component.scene.environment = processedEnvMap;
704
- component.scene.background = processedEnvMap;
705
- texture.dispose();
706
- console.log('✅ Fallback skybox loaded successfully');
707
- _context0.n = 4;
708
- break;
709
- case 3:
710
- _context0.p = 3;
711
- _t8 = _context0.v;
712
- console.warn('⚠️ Failed to load fallback skybox:', _t8.message);
713
- throw _t8;
714
- case 4:
715
- return _context0.a(2);
716
- }
717
- }, _callee7, this, [[1, 3]]);
718
- }));
719
- function loadFallbackSkybox(_x3) {
720
- return _loadFallbackSkybox.apply(this, arguments);
721
- }
722
- return loadFallbackSkybox;
723
- }()
601
+ key: "_setColorBackground",
602
+ value: function _setColorBackground(component) {
603
+ component.scene.environment = null;
604
+ component.scene.background = new THREE.Color(0xffffff);
605
+ var ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
606
+ component.scene.add(ambientLight);
607
+ console.log('✅ Color background set successfully');
608
+ }
609
+
724
610
  /**
725
- * Set solid color background
611
+ * Public convenience alias for setColorBackground (backwards compat)
726
612
  */
727
- )
728
613
  }, {
729
614
  key: "setColorBackground",
730
615
  value: function setColorBackground() {
731
- var component = this.sceneViewer;
732
- component.scene.environment = null;
733
- component.scene.background = new THREE.Color(0xffffff); // White background
734
-
735
- // Add basic ambient lighting since we don't have environment lighting
736
- var ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
737
- component.scene.add(ambientLight);
738
- console.log('✅ Color background set successfully');
616
+ this._setColorBackground(this.sceneViewer);
739
617
  }
740
618
  }]);
741
619
  }();