@2112-lab/central-plant 0.1.13 → 0.1.16

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.
@@ -6,6 +6,7 @@ var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelper
6
6
  var THREE = require('three');
7
7
  var GLTFLoader = require('../../node_modules/three/examples/jsm/loaders/GLTFLoader.js');
8
8
  var OBJLoader = require('../../node_modules/three/examples/jsm/loaders/OBJLoader.js');
9
+ var objProcessor = require('./objProcessor.js');
9
10
 
10
11
  function _interopNamespace(e) {
11
12
  if (e && e.__esModule) return e;
@@ -34,10 +35,12 @@ var ModelPreloader = /*#__PURE__*/function () {
34
35
  this.loadingPromises = new Map(); // Track ongoing loads to prevent duplicates
35
36
  this.gltfLoader = new GLTFLoader.GLTFLoader();
36
37
  this.objLoader = new OBJLoader.OBJLoader();
38
+ this.objProcessor = new objProcessor["default"](); // Initialize OBJ processor
37
39
  this.isPreloading = false;
38
40
  this.preloadingPromise = null;
39
41
  this.componentDictionary = null;
40
42
  console.log('🚀 ModelPreloader initialized with GLB and OBJ support');
43
+ console.log('🔧 OBJ Processor integrated for indexed BufferGeometry conversion');
41
44
  }
42
45
 
43
46
  /**
@@ -143,93 +146,137 @@ var ModelPreloader = /*#__PURE__*/function () {
143
146
  }, {
144
147
  key: "preloadSingleModel",
145
148
  value: (function () {
146
- var _preloadSingleModel = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee2(modelKey) {
149
+ var _preloadSingleModel = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee3(modelKey) {
147
150
  var _this2 = this;
148
151
  var modelType,
149
152
  loadPromise,
150
- _args2 = arguments;
151
- return _rollupPluginBabelHelpers.regenerator().w(function (_context2) {
152
- while (1) switch (_context2.n) {
153
+ _args3 = arguments;
154
+ return _rollupPluginBabelHelpers.regenerator().w(function (_context3) {
155
+ while (1) switch (_context3.n) {
153
156
  case 0:
154
- modelType = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : 'glb';
157
+ modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : 'glb';
155
158
  if (!this.modelCache.has(modelKey)) {
156
- _context2.n = 1;
159
+ _context3.n = 1;
157
160
  break;
158
161
  }
159
162
  console.log("\uD83C\uDFAF Model ".concat(modelKey, " already cached, skipping"));
160
- return _context2.a(2, this.modelCache.get(modelKey));
163
+ return _context3.a(2, this.modelCache.get(modelKey));
161
164
  case 1:
162
165
  if (!this.loadingPromises.has(modelKey)) {
163
- _context2.n = 2;
166
+ _context3.n = 2;
164
167
  break;
165
168
  }
166
169
  console.log("\u23F3 Model ".concat(modelKey, " already loading, waiting for completion"));
167
- return _context2.a(2, this.loadingPromises.get(modelKey));
170
+ return _context3.a(2, this.loadingPromises.get(modelKey));
168
171
  case 2:
169
172
  console.log("\uD83D\uDD04 Starting preload of ".concat(modelType.toUpperCase(), " model: ").concat(modelKey));
170
173
  loadPromise = new Promise(function (resolve, reject) {
171
174
  var modelPath = "/library/models/".concat(modelKey);
172
175
  if (modelType === 'obj') {
173
- // Load OBJ model
174
- _this2.objLoader.load(modelPath, function (object) {
175
- console.log("\u2705 Successfully preloaded OBJ model: ".concat(modelKey));
176
-
177
- // Apply double-sided materials to OBJ models with both solid and wireframe
178
- object.traverse(function (child) {
179
- if (child.isMesh) {
180
- // Create a solid material first
181
- var solidMaterial = new THREE__namespace.MeshStandardMaterial({
182
- color: child.material.color || 0x888888,
183
- side: THREE__namespace.DoubleSide,
184
- wireframe: false
185
- });
186
-
187
- // Set the solid material
188
- child.material = solidMaterial;
189
-
190
- // Create wireframe overlay by cloning the geometry
191
- var wireframeGeometry = child.geometry.clone();
192
- var wireframeMaterial = new THREE__namespace.MeshBasicMaterial({
193
- color: 0x000000,
194
- wireframe: true,
195
- transparent: true,
196
- opacity: 0.8
197
- });
198
-
199
- // Create wireframe mesh with same geometry
200
- var wireframeMesh = new THREE__namespace.Mesh(wireframeGeometry, wireframeMaterial);
201
- wireframeMesh.name = child.name + '_wireframe';
202
-
203
- // Position wireframe slightly forward to avoid z-fighting
204
- wireframeMesh.position.copy(child.position);
205
- wireframeMesh.rotation.copy(child.rotation);
206
- wireframeMesh.scale.copy(child.scale);
207
- wireframeMesh.scale.multiplyScalar(1.001); // Slightly larger to sit on top
208
-
209
- // Add wireframe as sibling to the parent
210
- if (child.parent) {
211
- child.parent.add(wireframeMesh);
176
+ // Load OBJ model with advanced processing
177
+ _this2.objLoader.load(modelPath, /*#__PURE__*/function () {
178
+ var _ref = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee2(object) {
179
+ var processedResult, modelData, _t;
180
+ return _rollupPluginBabelHelpers.regenerator().w(function (_context2) {
181
+ while (1) switch (_context2.n) {
182
+ case 0:
183
+ _context2.p = 0;
184
+ console.log("\u2705 Successfully loaded OBJ model: ".concat(modelKey));
185
+
186
+ // Process OBJ with the new processor for indexed BufferGeometry
187
+ _context2.n = 1;
188
+ return _this2.objProcessor.processObjObject(object, modelKey, true);
189
+ case 1:
190
+ processedResult = _context2.v;
191
+ if (!processedResult) {
192
+ _context2.n = 2;
193
+ break;
194
+ }
195
+ console.log("\uD83D\uDD27 OBJ processed to indexed BufferGeometry: ".concat(modelKey));
196
+ console.log("\uD83D\uDCCA Geometry stats:", processedResult.stats);
197
+
198
+ // Apply double-sided materials with solid + wireframe overlay
199
+ object.traverse(function (child) {
200
+ if (child.isMesh) {
201
+ // Create solid material
202
+ var solidMaterial = new THREE__namespace.MeshStandardMaterial({
203
+ color: child.material.color || 0x888888,
204
+ side: THREE__namespace.DoubleSide,
205
+ wireframe: false
206
+ // transparent: true,
207
+ // opacity: 0.8 // Slightly transparent to show wireframe better
208
+ });
209
+
210
+ // Create wireframe material
211
+ var wireframeMaterial = new THREE__namespace.MeshBasicMaterial({
212
+ color: 0x000000,
213
+ // Black wireframe
214
+ wireframe: true,
215
+ // transparent: true,
216
+ // opacity: 0.6,
217
+ side: THREE__namespace.DoubleSide
218
+ });
219
+
220
+ // Apply solid material to the original mesh
221
+ child.material = solidMaterial;
222
+
223
+ // Create a wireframe mesh clone and add it as a child
224
+ var wireframeMesh = new THREE__namespace.Mesh(child.geometry, wireframeMaterial);
225
+ wireframeMesh.position.copy(child.position);
226
+ wireframeMesh.rotation.copy(child.rotation);
227
+ wireframeMesh.scale.copy(child.scale);
228
+ wireframeMesh.name = child.name + '_wireframe';
229
+ wireframeMesh.userData.isWireframeOverlay = true;
230
+
231
+ // Add wireframe mesh to the same parent
232
+ if (child.parent) {
233
+ child.parent.add(wireframeMesh);
234
+ }
235
+ }
236
+ });
237
+ // Store both the original object and processed data
238
+ modelData = {
239
+ originalObject: object,
240
+ processedGeometry: processedResult.geometry,
241
+ geometryStats: processedResult.stats,
242
+ materials: processedResult.materials,
243
+ isObjModel: true
244
+ }; // Cache the model data
245
+ _this2.modelCache.set(modelKey, modelData);
246
+ _this2.loadingPromises.delete(modelKey);
247
+ resolve(modelData);
248
+ _context2.n = 3;
249
+ break;
250
+ case 2:
251
+ throw new Error('Failed to process OBJ to indexed geometry');
252
+ case 3:
253
+ _context2.n = 5;
254
+ break;
255
+ case 4:
256
+ _context2.p = 4;
257
+ _t = _context2.v;
258
+ console.error("\u274C Error processing OBJ model ".concat(modelKey, ":"), _t);
259
+ // Fallback: cache the original object without processing
260
+ _this2.modelCache.set(modelKey, object);
261
+ _this2.loadingPromises.delete(modelKey);
262
+ resolve(object);
263
+ case 5:
264
+ return _context2.a(2);
212
265
  }
213
- }
214
- });
215
-
216
- // Cache the object for future use
217
- _this2.modelCache.set(modelKey, object);
218
- // Remove from loading promises
219
- _this2.loadingPromises.delete(modelKey);
220
- resolve(object);
221
- }, function (progress) {
222
- // Optional: track loading progress
266
+ }, _callee2, null, [[0, 4]]);
267
+ }));
268
+ return function (_x3) {
269
+ return _ref.apply(this, arguments);
270
+ };
271
+ }(), function (progress) {
223
272
  if (progress.lengthComputable) {
224
273
  var percentage = progress.loaded / progress.total * 100;
225
274
  if (percentage % 25 === 0) {
226
- // Log every 25%
227
275
  console.log("\uD83D\uDCCA Loading OBJ ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
228
276
  }
229
277
  }
230
278
  }, function (error) {
231
279
  console.error("\u274C Failed to preload OBJ model ".concat(modelKey, ":"), error);
232
- // Remove from loading promises
233
280
  _this2.loadingPromises.delete(modelKey);
234
281
  reject(error);
235
282
  });
@@ -260,9 +307,9 @@ var ModelPreloader = /*#__PURE__*/function () {
260
307
  }
261
308
  }); // Cache the loading promise
262
309
  this.loadingPromises.set(modelKey, loadPromise);
263
- return _context2.a(2, loadPromise);
310
+ return _context3.a(2, loadPromise);
264
311
  }
265
- }, _callee2, this);
312
+ }, _callee3, this);
266
313
  }));
267
314
  function preloadSingleModel(_x2) {
268
315
  return _preloadSingleModel.apply(this, arguments);
@@ -272,18 +319,42 @@ var ModelPreloader = /*#__PURE__*/function () {
272
319
  /**
273
320
  * Get a cached model (cloned for use)
274
321
  * @param {string} modelKey - The model key
322
+ * @param {boolean} useIndexedGeometry - Whether to use indexed geometry for OBJ models
275
323
  * @returns {THREE.Object3D|null} Cloned model or null if not found
276
324
  */
277
325
  )
278
326
  }, {
279
327
  key: "getCachedModel",
280
328
  value: function getCachedModel(modelKey) {
329
+ var useIndexedGeometry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
281
330
  if (this.modelCache.has(modelKey)) {
282
331
  console.log("\uD83C\uDFAF Returning cached model: ".concat(modelKey));
283
- var clonedModel = this.modelCache.get(modelKey).clone();
332
+ var cachedData = this.modelCache.get(modelKey);
333
+
334
+ // Handle OBJ models with processed geometry
335
+ if (cachedData && cachedData.isObjModel && useIndexedGeometry && cachedData.processedGeometry) {
336
+ console.log("\uD83D\uDD27 Using indexed BufferGeometry for OBJ: ".concat(modelKey));
284
337
 
285
- // Determine model type from the modelKey extension
286
- modelKey.toLowerCase().endsWith('.obj') ? 'obj' : 'glb';
338
+ // Create a mesh from the processed indexed geometry
339
+ var mesh = new THREE__namespace.Mesh(cachedData.processedGeometry.clone(), cachedData.materials.clone());
340
+
341
+ // Add metadata
342
+ mesh.userData.modelKey = modelKey;
343
+ mesh.userData.geometryStats = cachedData.geometryStats;
344
+ mesh.userData.isIndexedGeometry = true;
345
+ mesh.userData.originalSizeKB = cachedData.geometryStats.sizeKB;
346
+ return mesh;
347
+ }
348
+
349
+ // Handle regular models or OBJ models without indexed geometry
350
+ var modelToClone = cachedData.isObjModel ? cachedData.originalObject : cachedData;
351
+ var clonedModel = modelToClone.clone();
352
+
353
+ // Add OBJ stats if available
354
+ if (cachedData.isObjModel && cachedData.geometryStats) {
355
+ clonedModel.userData.geometryStats = cachedData.geometryStats;
356
+ clonedModel.userData.isObjModel = true;
357
+ }
287
358
  return clonedModel;
288
359
  }
289
360
  console.warn("\u26A0\uFE0F Model ".concat(modelKey, " not found in cache"));
@@ -302,7 +373,26 @@ var ModelPreloader = /*#__PURE__*/function () {
302
373
  var libraryId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
303
374
  if (this.modelCache.has(modelKey)) {
304
375
  console.log("\uD83C\uDFAF Returning cached model with dimensions: ".concat(modelKey));
305
- var clonedModel = this.modelCache.get(modelKey).clone();
376
+ var cachedData = this.modelCache.get(modelKey);
377
+
378
+ // Handle OBJ models with processed geometry structure
379
+ var clonedModel;
380
+ if (cachedData && cachedData.isObjModel) {
381
+ // Clone the original OBJ object
382
+ clonedModel = cachedData.originalObject.clone();
383
+
384
+ // Add OBJ stats if available
385
+ if (cachedData.geometryStats) {
386
+ if (!clonedModel.userData) {
387
+ clonedModel.userData = {};
388
+ }
389
+ clonedModel.userData.geometryStats = cachedData.geometryStats;
390
+ clonedModel.userData.isObjModel = true;
391
+ }
392
+ } else {
393
+ // Handle regular GLB models
394
+ clonedModel = cachedData.clone();
395
+ }
306
396
 
307
397
  // Add dimensions from component dictionary if available
308
398
  if (libraryId && this.componentDictionary) {
@@ -391,41 +481,41 @@ var ModelPreloader = /*#__PURE__*/function () {
391
481
  }, {
392
482
  key: "reloadModel",
393
483
  value: (function () {
394
- var _reloadModel = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee3(modelKey) {
484
+ var _reloadModel = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee4(modelKey) {
395
485
  var modelType,
396
486
  _i,
397
487
  _Object$keys,
398
488
  componentType,
399
489
  component,
400
- _args3 = arguments;
401
- return _rollupPluginBabelHelpers.regenerator().w(function (_context3) {
402
- while (1) switch (_context3.n) {
490
+ _args4 = arguments;
491
+ return _rollupPluginBabelHelpers.regenerator().w(function (_context4) {
492
+ while (1) switch (_context4.n) {
403
493
  case 0:
404
- modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : null;
494
+ modelType = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : null;
405
495
  console.log("\uD83D\uDD04 Force reloading model: ".concat(modelKey));
406
496
 
407
497
  // Try to determine model type from component dictionary if not provided
408
498
  if (!(!modelType && this.componentDictionary)) {
409
- _context3.n = 3;
499
+ _context4.n = 3;
410
500
  break;
411
501
  }
412
502
  _i = 0, _Object$keys = Object.keys(this.componentDictionary);
413
503
  case 1:
414
504
  if (!(_i < _Object$keys.length)) {
415
- _context3.n = 3;
505
+ _context4.n = 3;
416
506
  break;
417
507
  }
418
508
  componentType = _Object$keys[_i];
419
509
  component = this.componentDictionary[componentType];
420
510
  if (!(component && component.modelKey === modelKey)) {
421
- _context3.n = 2;
511
+ _context4.n = 2;
422
512
  break;
423
513
  }
424
514
  modelType = component.modelType || 'glb';
425
- return _context3.a(3, 3);
515
+ return _context4.a(3, 3);
426
516
  case 2:
427
517
  _i++;
428
- _context3.n = 1;
518
+ _context4.n = 1;
429
519
  break;
430
520
  case 3:
431
521
  // Default to GLB if still not determined
@@ -436,11 +526,11 @@ var ModelPreloader = /*#__PURE__*/function () {
436
526
  this.loadingPromises.delete(modelKey);
437
527
 
438
528
  // Preload again
439
- return _context3.a(2, this.preloadSingleModel(modelKey, modelType));
529
+ return _context4.a(2, this.preloadSingleModel(modelKey, modelType));
440
530
  }
441
- }, _callee3, this);
531
+ }, _callee4, this);
442
532
  }));
443
- function reloadModel(_x3) {
533
+ function reloadModel(_x4) {
444
534
  return _reloadModel.apply(this, arguments);
445
535
  }
446
536
  return reloadModel;
@@ -457,7 +547,42 @@ var ModelPreloader = /*#__PURE__*/function () {
457
547
  // Dispose of all cached models
458
548
  this.modelCache.forEach(function (model, modelKey) {
459
549
  console.log("\uD83D\uDDD1\uFE0F Disposing cached model: ".concat(modelKey));
460
- if (model && model.traverse) {
550
+ if (model && model.isObjModel) {
551
+ // Handle OBJ model data structure
552
+ if (model.originalObject && model.originalObject.traverse) {
553
+ model.originalObject.traverse(function (child) {
554
+ if (child.geometry) {
555
+ child.geometry.dispose();
556
+ }
557
+ if (child.material) {
558
+ if (Array.isArray(child.material)) {
559
+ child.material.forEach(function (material) {
560
+ return material.dispose();
561
+ });
562
+ } else {
563
+ child.material.dispose();
564
+ }
565
+ }
566
+ });
567
+ }
568
+
569
+ // Dispose processed geometry
570
+ if (model.processedGeometry) {
571
+ model.processedGeometry.dispose();
572
+ }
573
+
574
+ // Dispose materials
575
+ if (model.materials) {
576
+ if (Array.isArray(model.materials)) {
577
+ model.materials.forEach(function (material) {
578
+ return material.dispose();
579
+ });
580
+ } else {
581
+ model.materials.dispose();
582
+ }
583
+ }
584
+ } else if (model && model.traverse) {
585
+ // Handle regular model
461
586
  model.traverse(function (child) {
462
587
  if (child.geometry) {
463
588
  child.geometry.dispose();
@@ -478,6 +603,9 @@ var ModelPreloader = /*#__PURE__*/function () {
478
603
  this.loadingPromises.clear();
479
604
  this.isPreloading = false;
480
605
  this.preloadingPromise = null;
606
+
607
+ // Clear OBJ processor caches
608
+ this.objProcessor.clearCaches();
481
609
  console.log('✅ Model preloader cache cleared');
482
610
  }
483
611
 
@@ -550,7 +678,24 @@ var ModelPreloader = /*#__PURE__*/function () {
550
678
  console.log("\uD83D\uDD04 Loading model for library ID ".concat(libraryId, ": ").concat(modelKey, " (").concat(modelType.toUpperCase(), ")"));
551
679
  this.preloadSingleModel(modelKey, modelType).then(function (model) {
552
680
  if (model) {
553
- var _clonedModel = model.clone();
681
+ // Handle OBJ models with processed geometry structure
682
+ var _clonedModel;
683
+ if (model && model.isObjModel) {
684
+ // Clone the original OBJ object
685
+ _clonedModel = model.originalObject.clone();
686
+
687
+ // Add OBJ stats if available
688
+ if (model.geometryStats) {
689
+ if (!_clonedModel.userData) {
690
+ _clonedModel.userData = {};
691
+ }
692
+ _clonedModel.userData.geometryStats = model.geometryStats;
693
+ _clonedModel.userData.isObjModel = true;
694
+ }
695
+ } else {
696
+ // Handle regular GLB models
697
+ _clonedModel = model.clone();
698
+ }
554
699
 
555
700
  // Add dimensions if available
556
701
  if (componentData.boundingBox) {
@@ -586,13 +731,15 @@ var ModelPreloader = /*#__PURE__*/function () {
586
731
  totalModels: this.modelCache.size,
587
732
  loadingModels: this.loadingPromises.size,
588
733
  isPreloading: this.isPreloading,
589
- memoryUsage: 0
734
+ memoryUsage: 0,
735
+ objProcessorStats: this.objProcessor.getStatus()
590
736
  };
591
737
 
592
738
  // Estimate memory usage (rough calculation)
593
739
  this.modelCache.forEach(function (model) {
594
740
  if (model && model.traverse) {
595
- model.traverse(function (child) {
741
+ var modelToAnalyze = model.isObjModel ? model.originalObject : model;
742
+ modelToAnalyze.traverse(function (child) {
596
743
  if (child.geometry) {
597
744
  var _child$geometry$attri;
598
745
  stats.memoryUsage += (((_child$geometry$attri = child.geometry.attributes.position) === null || _child$geometry$attri === void 0 ? void 0 : _child$geometry$attri.count) || 0) * 12; // Rough estimate
@@ -602,6 +749,124 @@ var ModelPreloader = /*#__PURE__*/function () {
602
749
  });
603
750
  return stats;
604
751
  }
752
+
753
+ /**
754
+ * Get all OBJ geometry statistics
755
+ * @returns {Array} Array of OBJ geometry statistics
756
+ */
757
+ }, {
758
+ key: "getObjGeometryStats",
759
+ value: function getObjGeometryStats() {
760
+ return this.objProcessor.getAllGeometryStats();
761
+ }
762
+
763
+ /**
764
+ * Get OBJ processor memory usage
765
+ * @returns {Object} Memory usage statistics
766
+ */
767
+ }, {
768
+ key: "getObjMemoryUsage",
769
+ value: function getObjMemoryUsage() {
770
+ return this.objProcessor.getMemoryUsage();
771
+ }
772
+
773
+ /**
774
+ * Create a custom mesh from indexed OBJ geometry
775
+ * @param {string} modelKey - The model key (must be an OBJ)
776
+ * @param {THREE.Material} material - Optional material to use
777
+ * @returns {THREE.Mesh|null} The created mesh or null if not found
778
+ */
779
+ }, {
780
+ key: "createCustomObjMesh",
781
+ value: function createCustomObjMesh(modelKey) {
782
+ var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
783
+ return this.objProcessor.createCustomMesh(modelKey, material);
784
+ }
785
+
786
+ /**
787
+ * Get indexed geometry directly from processor
788
+ * @param {string} modelKey - The model key
789
+ * @returns {THREE.BufferGeometry|null} The indexed geometry or null
790
+ */
791
+ }, {
792
+ key: "getIndexedGeometry",
793
+ value: function getIndexedGeometry(modelKey) {
794
+ var result = this.objProcessor.indexedGeometryCache.get(modelKey);
795
+ return result ? result.geometry.clone() : null;
796
+ }
797
+
798
+ /**
799
+ * Toggle wireframe visibility on an OBJ model
800
+ * @param {THREE.Object3D} model - The model to toggle wireframe on
801
+ * @param {boolean} visible - Whether wireframe should be visible
802
+ */
803
+ }, {
804
+ key: "toggleWireframe",
805
+ value: function toggleWireframe(model) {
806
+ var visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
807
+ if (!model) return;
808
+ model.traverse(function (child) {
809
+ if (child.userData && child.userData.isWireframeOverlay) {
810
+ child.visible = visible;
811
+ }
812
+ });
813
+ }
814
+
815
+ /**
816
+ * Update wireframe appearance on an OBJ model
817
+ * @param {THREE.Object3D} model - The model to update
818
+ * @param {Object} options - Wireframe options {color, opacity, visible}
819
+ */
820
+ }, {
821
+ key: "updateWireframeAppearance",
822
+ value: function updateWireframeAppearance(model) {
823
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
824
+ if (!model) return;
825
+ var _options$color = options.color,
826
+ color = _options$color === void 0 ? 0x000000 : _options$color,
827
+ _options$opacity = options.opacity,
828
+ opacity = _options$opacity === void 0 ? 0.6 : _options$opacity,
829
+ _options$visible = options.visible,
830
+ visible = _options$visible === void 0 ? true : _options$visible;
831
+ model.traverse(function (child) {
832
+ if (child.userData && child.userData.isWireframeOverlay && child.material) {
833
+ child.material.color.setHex(color);
834
+ child.material.opacity = opacity;
835
+ child.visible = visible;
836
+ }
837
+ });
838
+ }
839
+
840
+ /**
841
+ * Force reload and reprocess an OBJ model
842
+ * @param {string} modelKey - The model key to reload
843
+ * @returns {Promise} Promise that resolves with the reloaded model
844
+ */
845
+ }, {
846
+ key: "reloadObjModel",
847
+ value: (function () {
848
+ var _reloadObjModel = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee5(modelKey) {
849
+ return _rollupPluginBabelHelpers.regenerator().w(function (_context5) {
850
+ while (1) switch (_context5.n) {
851
+ case 0:
852
+ console.log("\uD83D\uDD04 Force reloading OBJ model: ".concat(modelKey));
853
+
854
+ // Clear from both caches
855
+ this.modelCache.delete(modelKey);
856
+ this.loadingPromises.delete(modelKey);
857
+ this.objProcessor.indexedGeometryCache.delete(modelKey);
858
+ this.objProcessor.geometrySizeCache.delete(modelKey);
859
+
860
+ // Reload with OBJ processing
861
+ return _context5.a(2, this.preloadSingleModel(modelKey, 'obj'));
862
+ }
863
+ }, _callee5, this);
864
+ }));
865
+ function reloadObjModel(_x5) {
866
+ return _reloadObjModel.apply(this, arguments);
867
+ }
868
+ return reloadObjModel;
869
+ }())
605
870
  }]);
606
871
  }(); // Create singleton instance
607
872
  var modelPreloader = new ModelPreloader();