@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.
- package/dist/bundle/index.js +1731 -89
- package/dist/cjs/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +462 -0
- package/dist/cjs/src/index.js +4 -0
- package/dist/cjs/src/rendering/modelPreloader.js +348 -83
- package/dist/cjs/src/rendering/objProcessor.js +703 -0
- package/dist/cjs/src/testing/objProcessingDemo.js +254 -0
- package/dist/esm/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +461 -2
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/rendering/modelPreloader.js +348 -83
- package/dist/esm/src/rendering/objProcessor.js +678 -0
- package/dist/esm/src/testing/objProcessingDemo.js +249 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { createClass as _createClass, typeof as _typeof, classCallCheck as _clas
|
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import { GLTFLoader } from '../../node_modules/three/examples/jsm/loaders/GLTFLoader.js';
|
|
4
4
|
import { OBJLoader } from '../../node_modules/three/examples/jsm/loaders/OBJLoader.js';
|
|
5
|
+
import ObjProcessor from './objProcessor.js';
|
|
5
6
|
|
|
6
7
|
var ModelPreloader = /*#__PURE__*/function () {
|
|
7
8
|
function ModelPreloader() {
|
|
@@ -10,10 +11,12 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
10
11
|
this.loadingPromises = new Map(); // Track ongoing loads to prevent duplicates
|
|
11
12
|
this.gltfLoader = new GLTFLoader();
|
|
12
13
|
this.objLoader = new OBJLoader();
|
|
14
|
+
this.objProcessor = new ObjProcessor(); // Initialize OBJ processor
|
|
13
15
|
this.isPreloading = false;
|
|
14
16
|
this.preloadingPromise = null;
|
|
15
17
|
this.componentDictionary = null;
|
|
16
18
|
console.log('🚀 ModelPreloader initialized with GLB and OBJ support');
|
|
19
|
+
console.log('🔧 OBJ Processor integrated for indexed BufferGeometry conversion');
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
/**
|
|
@@ -119,93 +122,137 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
119
122
|
}, {
|
|
120
123
|
key: "preloadSingleModel",
|
|
121
124
|
value: (function () {
|
|
122
|
-
var _preloadSingleModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
125
|
+
var _preloadSingleModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(modelKey) {
|
|
123
126
|
var _this2 = this;
|
|
124
127
|
var modelType,
|
|
125
128
|
loadPromise,
|
|
126
|
-
|
|
127
|
-
return _regenerator().w(function (
|
|
128
|
-
while (1) switch (
|
|
129
|
+
_args3 = arguments;
|
|
130
|
+
return _regenerator().w(function (_context3) {
|
|
131
|
+
while (1) switch (_context3.n) {
|
|
129
132
|
case 0:
|
|
130
|
-
modelType =
|
|
133
|
+
modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : 'glb';
|
|
131
134
|
if (!this.modelCache.has(modelKey)) {
|
|
132
|
-
|
|
135
|
+
_context3.n = 1;
|
|
133
136
|
break;
|
|
134
137
|
}
|
|
135
138
|
console.log("\uD83C\uDFAF Model ".concat(modelKey, " already cached, skipping"));
|
|
136
|
-
return
|
|
139
|
+
return _context3.a(2, this.modelCache.get(modelKey));
|
|
137
140
|
case 1:
|
|
138
141
|
if (!this.loadingPromises.has(modelKey)) {
|
|
139
|
-
|
|
142
|
+
_context3.n = 2;
|
|
140
143
|
break;
|
|
141
144
|
}
|
|
142
145
|
console.log("\u23F3 Model ".concat(modelKey, " already loading, waiting for completion"));
|
|
143
|
-
return
|
|
146
|
+
return _context3.a(2, this.loadingPromises.get(modelKey));
|
|
144
147
|
case 2:
|
|
145
148
|
console.log("\uD83D\uDD04 Starting preload of ".concat(modelType.toUpperCase(), " model: ").concat(modelKey));
|
|
146
149
|
loadPromise = new Promise(function (resolve, reject) {
|
|
147
150
|
var modelPath = "/library/models/".concat(modelKey);
|
|
148
151
|
if (modelType === 'obj') {
|
|
149
|
-
// Load OBJ model
|
|
150
|
-
_this2.objLoader.load(modelPath, function (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
152
|
+
// Load OBJ model with advanced processing
|
|
153
|
+
_this2.objLoader.load(modelPath, /*#__PURE__*/function () {
|
|
154
|
+
var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(object) {
|
|
155
|
+
var processedResult, modelData, _t;
|
|
156
|
+
return _regenerator().w(function (_context2) {
|
|
157
|
+
while (1) switch (_context2.n) {
|
|
158
|
+
case 0:
|
|
159
|
+
_context2.p = 0;
|
|
160
|
+
console.log("\u2705 Successfully loaded OBJ model: ".concat(modelKey));
|
|
161
|
+
|
|
162
|
+
// Process OBJ with the new processor for indexed BufferGeometry
|
|
163
|
+
_context2.n = 1;
|
|
164
|
+
return _this2.objProcessor.processObjObject(object, modelKey, true);
|
|
165
|
+
case 1:
|
|
166
|
+
processedResult = _context2.v;
|
|
167
|
+
if (!processedResult) {
|
|
168
|
+
_context2.n = 2;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
console.log("\uD83D\uDD27 OBJ processed to indexed BufferGeometry: ".concat(modelKey));
|
|
172
|
+
console.log("\uD83D\uDCCA Geometry stats:", processedResult.stats);
|
|
173
|
+
|
|
174
|
+
// Apply double-sided materials with solid + wireframe overlay
|
|
175
|
+
object.traverse(function (child) {
|
|
176
|
+
if (child.isMesh) {
|
|
177
|
+
// Create solid material
|
|
178
|
+
var solidMaterial = new THREE.MeshStandardMaterial({
|
|
179
|
+
color: child.material.color || 0x888888,
|
|
180
|
+
side: THREE.DoubleSide,
|
|
181
|
+
wireframe: false
|
|
182
|
+
// transparent: true,
|
|
183
|
+
// opacity: 0.8 // Slightly transparent to show wireframe better
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Create wireframe material
|
|
187
|
+
var wireframeMaterial = new THREE.MeshBasicMaterial({
|
|
188
|
+
color: 0x000000,
|
|
189
|
+
// Black wireframe
|
|
190
|
+
wireframe: true,
|
|
191
|
+
// transparent: true,
|
|
192
|
+
// opacity: 0.6,
|
|
193
|
+
side: THREE.DoubleSide
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Apply solid material to the original mesh
|
|
197
|
+
child.material = solidMaterial;
|
|
198
|
+
|
|
199
|
+
// Create a wireframe mesh clone and add it as a child
|
|
200
|
+
var wireframeMesh = new THREE.Mesh(child.geometry, wireframeMaterial);
|
|
201
|
+
wireframeMesh.position.copy(child.position);
|
|
202
|
+
wireframeMesh.rotation.copy(child.rotation);
|
|
203
|
+
wireframeMesh.scale.copy(child.scale);
|
|
204
|
+
wireframeMesh.name = child.name + '_wireframe';
|
|
205
|
+
wireframeMesh.userData.isWireframeOverlay = true;
|
|
206
|
+
|
|
207
|
+
// Add wireframe mesh to the same parent
|
|
208
|
+
if (child.parent) {
|
|
209
|
+
child.parent.add(wireframeMesh);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
// Store both the original object and processed data
|
|
214
|
+
modelData = {
|
|
215
|
+
originalObject: object,
|
|
216
|
+
processedGeometry: processedResult.geometry,
|
|
217
|
+
geometryStats: processedResult.stats,
|
|
218
|
+
materials: processedResult.materials,
|
|
219
|
+
isObjModel: true
|
|
220
|
+
}; // Cache the model data
|
|
221
|
+
_this2.modelCache.set(modelKey, modelData);
|
|
222
|
+
_this2.loadingPromises.delete(modelKey);
|
|
223
|
+
resolve(modelData);
|
|
224
|
+
_context2.n = 3;
|
|
225
|
+
break;
|
|
226
|
+
case 2:
|
|
227
|
+
throw new Error('Failed to process OBJ to indexed geometry');
|
|
228
|
+
case 3:
|
|
229
|
+
_context2.n = 5;
|
|
230
|
+
break;
|
|
231
|
+
case 4:
|
|
232
|
+
_context2.p = 4;
|
|
233
|
+
_t = _context2.v;
|
|
234
|
+
console.error("\u274C Error processing OBJ model ".concat(modelKey, ":"), _t);
|
|
235
|
+
// Fallback: cache the original object without processing
|
|
236
|
+
_this2.modelCache.set(modelKey, object);
|
|
237
|
+
_this2.loadingPromises.delete(modelKey);
|
|
238
|
+
resolve(object);
|
|
239
|
+
case 5:
|
|
240
|
+
return _context2.a(2);
|
|
188
241
|
}
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
_this2.loadingPromises.delete(modelKey);
|
|
196
|
-
resolve(object);
|
|
197
|
-
}, function (progress) {
|
|
198
|
-
// Optional: track loading progress
|
|
242
|
+
}, _callee2, null, [[0, 4]]);
|
|
243
|
+
}));
|
|
244
|
+
return function (_x3) {
|
|
245
|
+
return _ref.apply(this, arguments);
|
|
246
|
+
};
|
|
247
|
+
}(), function (progress) {
|
|
199
248
|
if (progress.lengthComputable) {
|
|
200
249
|
var percentage = progress.loaded / progress.total * 100;
|
|
201
250
|
if (percentage % 25 === 0) {
|
|
202
|
-
// Log every 25%
|
|
203
251
|
console.log("\uD83D\uDCCA Loading OBJ ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
|
|
204
252
|
}
|
|
205
253
|
}
|
|
206
254
|
}, function (error) {
|
|
207
255
|
console.error("\u274C Failed to preload OBJ model ".concat(modelKey, ":"), error);
|
|
208
|
-
// Remove from loading promises
|
|
209
256
|
_this2.loadingPromises.delete(modelKey);
|
|
210
257
|
reject(error);
|
|
211
258
|
});
|
|
@@ -236,9 +283,9 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
236
283
|
}
|
|
237
284
|
}); // Cache the loading promise
|
|
238
285
|
this.loadingPromises.set(modelKey, loadPromise);
|
|
239
|
-
return
|
|
286
|
+
return _context3.a(2, loadPromise);
|
|
240
287
|
}
|
|
241
|
-
},
|
|
288
|
+
}, _callee3, this);
|
|
242
289
|
}));
|
|
243
290
|
function preloadSingleModel(_x2) {
|
|
244
291
|
return _preloadSingleModel.apply(this, arguments);
|
|
@@ -248,18 +295,42 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
248
295
|
/**
|
|
249
296
|
* Get a cached model (cloned for use)
|
|
250
297
|
* @param {string} modelKey - The model key
|
|
298
|
+
* @param {boolean} useIndexedGeometry - Whether to use indexed geometry for OBJ models
|
|
251
299
|
* @returns {THREE.Object3D|null} Cloned model or null if not found
|
|
252
300
|
*/
|
|
253
301
|
)
|
|
254
302
|
}, {
|
|
255
303
|
key: "getCachedModel",
|
|
256
304
|
value: function getCachedModel(modelKey) {
|
|
305
|
+
var useIndexedGeometry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
257
306
|
if (this.modelCache.has(modelKey)) {
|
|
258
307
|
console.log("\uD83C\uDFAF Returning cached model: ".concat(modelKey));
|
|
259
|
-
var
|
|
308
|
+
var cachedData = this.modelCache.get(modelKey);
|
|
309
|
+
|
|
310
|
+
// Handle OBJ models with processed geometry
|
|
311
|
+
if (cachedData && cachedData.isObjModel && useIndexedGeometry && cachedData.processedGeometry) {
|
|
312
|
+
console.log("\uD83D\uDD27 Using indexed BufferGeometry for OBJ: ".concat(modelKey));
|
|
260
313
|
|
|
261
|
-
|
|
262
|
-
|
|
314
|
+
// Create a mesh from the processed indexed geometry
|
|
315
|
+
var mesh = new THREE.Mesh(cachedData.processedGeometry.clone(), cachedData.materials.clone());
|
|
316
|
+
|
|
317
|
+
// Add metadata
|
|
318
|
+
mesh.userData.modelKey = modelKey;
|
|
319
|
+
mesh.userData.geometryStats = cachedData.geometryStats;
|
|
320
|
+
mesh.userData.isIndexedGeometry = true;
|
|
321
|
+
mesh.userData.originalSizeKB = cachedData.geometryStats.sizeKB;
|
|
322
|
+
return mesh;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Handle regular models or OBJ models without indexed geometry
|
|
326
|
+
var modelToClone = cachedData.isObjModel ? cachedData.originalObject : cachedData;
|
|
327
|
+
var clonedModel = modelToClone.clone();
|
|
328
|
+
|
|
329
|
+
// Add OBJ stats if available
|
|
330
|
+
if (cachedData.isObjModel && cachedData.geometryStats) {
|
|
331
|
+
clonedModel.userData.geometryStats = cachedData.geometryStats;
|
|
332
|
+
clonedModel.userData.isObjModel = true;
|
|
333
|
+
}
|
|
263
334
|
return clonedModel;
|
|
264
335
|
}
|
|
265
336
|
console.warn("\u26A0\uFE0F Model ".concat(modelKey, " not found in cache"));
|
|
@@ -278,7 +349,26 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
278
349
|
var libraryId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
279
350
|
if (this.modelCache.has(modelKey)) {
|
|
280
351
|
console.log("\uD83C\uDFAF Returning cached model with dimensions: ".concat(modelKey));
|
|
281
|
-
var
|
|
352
|
+
var cachedData = this.modelCache.get(modelKey);
|
|
353
|
+
|
|
354
|
+
// Handle OBJ models with processed geometry structure
|
|
355
|
+
var clonedModel;
|
|
356
|
+
if (cachedData && cachedData.isObjModel) {
|
|
357
|
+
// Clone the original OBJ object
|
|
358
|
+
clonedModel = cachedData.originalObject.clone();
|
|
359
|
+
|
|
360
|
+
// Add OBJ stats if available
|
|
361
|
+
if (cachedData.geometryStats) {
|
|
362
|
+
if (!clonedModel.userData) {
|
|
363
|
+
clonedModel.userData = {};
|
|
364
|
+
}
|
|
365
|
+
clonedModel.userData.geometryStats = cachedData.geometryStats;
|
|
366
|
+
clonedModel.userData.isObjModel = true;
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
// Handle regular GLB models
|
|
370
|
+
clonedModel = cachedData.clone();
|
|
371
|
+
}
|
|
282
372
|
|
|
283
373
|
// Add dimensions from component dictionary if available
|
|
284
374
|
if (libraryId && this.componentDictionary) {
|
|
@@ -367,41 +457,41 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
367
457
|
}, {
|
|
368
458
|
key: "reloadModel",
|
|
369
459
|
value: (function () {
|
|
370
|
-
var _reloadModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
460
|
+
var _reloadModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(modelKey) {
|
|
371
461
|
var modelType,
|
|
372
462
|
_i,
|
|
373
463
|
_Object$keys,
|
|
374
464
|
componentType,
|
|
375
465
|
component,
|
|
376
|
-
|
|
377
|
-
return _regenerator().w(function (
|
|
378
|
-
while (1) switch (
|
|
466
|
+
_args4 = arguments;
|
|
467
|
+
return _regenerator().w(function (_context4) {
|
|
468
|
+
while (1) switch (_context4.n) {
|
|
379
469
|
case 0:
|
|
380
|
-
modelType =
|
|
470
|
+
modelType = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : null;
|
|
381
471
|
console.log("\uD83D\uDD04 Force reloading model: ".concat(modelKey));
|
|
382
472
|
|
|
383
473
|
// Try to determine model type from component dictionary if not provided
|
|
384
474
|
if (!(!modelType && this.componentDictionary)) {
|
|
385
|
-
|
|
475
|
+
_context4.n = 3;
|
|
386
476
|
break;
|
|
387
477
|
}
|
|
388
478
|
_i = 0, _Object$keys = Object.keys(this.componentDictionary);
|
|
389
479
|
case 1:
|
|
390
480
|
if (!(_i < _Object$keys.length)) {
|
|
391
|
-
|
|
481
|
+
_context4.n = 3;
|
|
392
482
|
break;
|
|
393
483
|
}
|
|
394
484
|
componentType = _Object$keys[_i];
|
|
395
485
|
component = this.componentDictionary[componentType];
|
|
396
486
|
if (!(component && component.modelKey === modelKey)) {
|
|
397
|
-
|
|
487
|
+
_context4.n = 2;
|
|
398
488
|
break;
|
|
399
489
|
}
|
|
400
490
|
modelType = component.modelType || 'glb';
|
|
401
|
-
return
|
|
491
|
+
return _context4.a(3, 3);
|
|
402
492
|
case 2:
|
|
403
493
|
_i++;
|
|
404
|
-
|
|
494
|
+
_context4.n = 1;
|
|
405
495
|
break;
|
|
406
496
|
case 3:
|
|
407
497
|
// Default to GLB if still not determined
|
|
@@ -412,11 +502,11 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
412
502
|
this.loadingPromises.delete(modelKey);
|
|
413
503
|
|
|
414
504
|
// Preload again
|
|
415
|
-
return
|
|
505
|
+
return _context4.a(2, this.preloadSingleModel(modelKey, modelType));
|
|
416
506
|
}
|
|
417
|
-
},
|
|
507
|
+
}, _callee4, this);
|
|
418
508
|
}));
|
|
419
|
-
function reloadModel(
|
|
509
|
+
function reloadModel(_x4) {
|
|
420
510
|
return _reloadModel.apply(this, arguments);
|
|
421
511
|
}
|
|
422
512
|
return reloadModel;
|
|
@@ -433,7 +523,42 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
433
523
|
// Dispose of all cached models
|
|
434
524
|
this.modelCache.forEach(function (model, modelKey) {
|
|
435
525
|
console.log("\uD83D\uDDD1\uFE0F Disposing cached model: ".concat(modelKey));
|
|
436
|
-
if (model && model.
|
|
526
|
+
if (model && model.isObjModel) {
|
|
527
|
+
// Handle OBJ model data structure
|
|
528
|
+
if (model.originalObject && model.originalObject.traverse) {
|
|
529
|
+
model.originalObject.traverse(function (child) {
|
|
530
|
+
if (child.geometry) {
|
|
531
|
+
child.geometry.dispose();
|
|
532
|
+
}
|
|
533
|
+
if (child.material) {
|
|
534
|
+
if (Array.isArray(child.material)) {
|
|
535
|
+
child.material.forEach(function (material) {
|
|
536
|
+
return material.dispose();
|
|
537
|
+
});
|
|
538
|
+
} else {
|
|
539
|
+
child.material.dispose();
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Dispose processed geometry
|
|
546
|
+
if (model.processedGeometry) {
|
|
547
|
+
model.processedGeometry.dispose();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Dispose materials
|
|
551
|
+
if (model.materials) {
|
|
552
|
+
if (Array.isArray(model.materials)) {
|
|
553
|
+
model.materials.forEach(function (material) {
|
|
554
|
+
return material.dispose();
|
|
555
|
+
});
|
|
556
|
+
} else {
|
|
557
|
+
model.materials.dispose();
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
} else if (model && model.traverse) {
|
|
561
|
+
// Handle regular model
|
|
437
562
|
model.traverse(function (child) {
|
|
438
563
|
if (child.geometry) {
|
|
439
564
|
child.geometry.dispose();
|
|
@@ -454,6 +579,9 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
454
579
|
this.loadingPromises.clear();
|
|
455
580
|
this.isPreloading = false;
|
|
456
581
|
this.preloadingPromise = null;
|
|
582
|
+
|
|
583
|
+
// Clear OBJ processor caches
|
|
584
|
+
this.objProcessor.clearCaches();
|
|
457
585
|
console.log('✅ Model preloader cache cleared');
|
|
458
586
|
}
|
|
459
587
|
|
|
@@ -526,7 +654,24 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
526
654
|
console.log("\uD83D\uDD04 Loading model for library ID ".concat(libraryId, ": ").concat(modelKey, " (").concat(modelType.toUpperCase(), ")"));
|
|
527
655
|
this.preloadSingleModel(modelKey, modelType).then(function (model) {
|
|
528
656
|
if (model) {
|
|
529
|
-
|
|
657
|
+
// Handle OBJ models with processed geometry structure
|
|
658
|
+
var _clonedModel;
|
|
659
|
+
if (model && model.isObjModel) {
|
|
660
|
+
// Clone the original OBJ object
|
|
661
|
+
_clonedModel = model.originalObject.clone();
|
|
662
|
+
|
|
663
|
+
// Add OBJ stats if available
|
|
664
|
+
if (model.geometryStats) {
|
|
665
|
+
if (!_clonedModel.userData) {
|
|
666
|
+
_clonedModel.userData = {};
|
|
667
|
+
}
|
|
668
|
+
_clonedModel.userData.geometryStats = model.geometryStats;
|
|
669
|
+
_clonedModel.userData.isObjModel = true;
|
|
670
|
+
}
|
|
671
|
+
} else {
|
|
672
|
+
// Handle regular GLB models
|
|
673
|
+
_clonedModel = model.clone();
|
|
674
|
+
}
|
|
530
675
|
|
|
531
676
|
// Add dimensions if available
|
|
532
677
|
if (componentData.boundingBox) {
|
|
@@ -562,13 +707,15 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
562
707
|
totalModels: this.modelCache.size,
|
|
563
708
|
loadingModels: this.loadingPromises.size,
|
|
564
709
|
isPreloading: this.isPreloading,
|
|
565
|
-
memoryUsage: 0
|
|
710
|
+
memoryUsage: 0,
|
|
711
|
+
objProcessorStats: this.objProcessor.getStatus()
|
|
566
712
|
};
|
|
567
713
|
|
|
568
714
|
// Estimate memory usage (rough calculation)
|
|
569
715
|
this.modelCache.forEach(function (model) {
|
|
570
716
|
if (model && model.traverse) {
|
|
571
|
-
model.
|
|
717
|
+
var modelToAnalyze = model.isObjModel ? model.originalObject : model;
|
|
718
|
+
modelToAnalyze.traverse(function (child) {
|
|
572
719
|
if (child.geometry) {
|
|
573
720
|
var _child$geometry$attri;
|
|
574
721
|
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
|
|
@@ -578,6 +725,124 @@ var ModelPreloader = /*#__PURE__*/function () {
|
|
|
578
725
|
});
|
|
579
726
|
return stats;
|
|
580
727
|
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Get all OBJ geometry statistics
|
|
731
|
+
* @returns {Array} Array of OBJ geometry statistics
|
|
732
|
+
*/
|
|
733
|
+
}, {
|
|
734
|
+
key: "getObjGeometryStats",
|
|
735
|
+
value: function getObjGeometryStats() {
|
|
736
|
+
return this.objProcessor.getAllGeometryStats();
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Get OBJ processor memory usage
|
|
741
|
+
* @returns {Object} Memory usage statistics
|
|
742
|
+
*/
|
|
743
|
+
}, {
|
|
744
|
+
key: "getObjMemoryUsage",
|
|
745
|
+
value: function getObjMemoryUsage() {
|
|
746
|
+
return this.objProcessor.getMemoryUsage();
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Create a custom mesh from indexed OBJ geometry
|
|
751
|
+
* @param {string} modelKey - The model key (must be an OBJ)
|
|
752
|
+
* @param {THREE.Material} material - Optional material to use
|
|
753
|
+
* @returns {THREE.Mesh|null} The created mesh or null if not found
|
|
754
|
+
*/
|
|
755
|
+
}, {
|
|
756
|
+
key: "createCustomObjMesh",
|
|
757
|
+
value: function createCustomObjMesh(modelKey) {
|
|
758
|
+
var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
759
|
+
return this.objProcessor.createCustomMesh(modelKey, material);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Get indexed geometry directly from processor
|
|
764
|
+
* @param {string} modelKey - The model key
|
|
765
|
+
* @returns {THREE.BufferGeometry|null} The indexed geometry or null
|
|
766
|
+
*/
|
|
767
|
+
}, {
|
|
768
|
+
key: "getIndexedGeometry",
|
|
769
|
+
value: function getIndexedGeometry(modelKey) {
|
|
770
|
+
var result = this.objProcessor.indexedGeometryCache.get(modelKey);
|
|
771
|
+
return result ? result.geometry.clone() : null;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Toggle wireframe visibility on an OBJ model
|
|
776
|
+
* @param {THREE.Object3D} model - The model to toggle wireframe on
|
|
777
|
+
* @param {boolean} visible - Whether wireframe should be visible
|
|
778
|
+
*/
|
|
779
|
+
}, {
|
|
780
|
+
key: "toggleWireframe",
|
|
781
|
+
value: function toggleWireframe(model) {
|
|
782
|
+
var visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
783
|
+
if (!model) return;
|
|
784
|
+
model.traverse(function (child) {
|
|
785
|
+
if (child.userData && child.userData.isWireframeOverlay) {
|
|
786
|
+
child.visible = visible;
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Update wireframe appearance on an OBJ model
|
|
793
|
+
* @param {THREE.Object3D} model - The model to update
|
|
794
|
+
* @param {Object} options - Wireframe options {color, opacity, visible}
|
|
795
|
+
*/
|
|
796
|
+
}, {
|
|
797
|
+
key: "updateWireframeAppearance",
|
|
798
|
+
value: function updateWireframeAppearance(model) {
|
|
799
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
800
|
+
if (!model) return;
|
|
801
|
+
var _options$color = options.color,
|
|
802
|
+
color = _options$color === void 0 ? 0x000000 : _options$color,
|
|
803
|
+
_options$opacity = options.opacity,
|
|
804
|
+
opacity = _options$opacity === void 0 ? 0.6 : _options$opacity,
|
|
805
|
+
_options$visible = options.visible,
|
|
806
|
+
visible = _options$visible === void 0 ? true : _options$visible;
|
|
807
|
+
model.traverse(function (child) {
|
|
808
|
+
if (child.userData && child.userData.isWireframeOverlay && child.material) {
|
|
809
|
+
child.material.color.setHex(color);
|
|
810
|
+
child.material.opacity = opacity;
|
|
811
|
+
child.visible = visible;
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Force reload and reprocess an OBJ model
|
|
818
|
+
* @param {string} modelKey - The model key to reload
|
|
819
|
+
* @returns {Promise} Promise that resolves with the reloaded model
|
|
820
|
+
*/
|
|
821
|
+
}, {
|
|
822
|
+
key: "reloadObjModel",
|
|
823
|
+
value: (function () {
|
|
824
|
+
var _reloadObjModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(modelKey) {
|
|
825
|
+
return _regenerator().w(function (_context5) {
|
|
826
|
+
while (1) switch (_context5.n) {
|
|
827
|
+
case 0:
|
|
828
|
+
console.log("\uD83D\uDD04 Force reloading OBJ model: ".concat(modelKey));
|
|
829
|
+
|
|
830
|
+
// Clear from both caches
|
|
831
|
+
this.modelCache.delete(modelKey);
|
|
832
|
+
this.loadingPromises.delete(modelKey);
|
|
833
|
+
this.objProcessor.indexedGeometryCache.delete(modelKey);
|
|
834
|
+
this.objProcessor.geometrySizeCache.delete(modelKey);
|
|
835
|
+
|
|
836
|
+
// Reload with OBJ processing
|
|
837
|
+
return _context5.a(2, this.preloadSingleModel(modelKey, 'obj'));
|
|
838
|
+
}
|
|
839
|
+
}, _callee5, this);
|
|
840
|
+
}));
|
|
841
|
+
function reloadObjModel(_x5) {
|
|
842
|
+
return _reloadObjModel.apply(this, arguments);
|
|
843
|
+
}
|
|
844
|
+
return reloadObjModel;
|
|
845
|
+
}())
|
|
581
846
|
}]);
|
|
582
847
|
}(); // Create singleton instance
|
|
583
848
|
var modelPreloader = new ModelPreloader();
|