@2112-lab/central-plant 0.1.13 → 0.1.15

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.
@@ -4315,6 +4315,465 @@ var SceneExportManager = /*#__PURE__*/function () {
4315
4315
  }]);
4316
4316
  }();
4317
4317
 
4318
+ /**
4319
+ * Merges a set of geometries into a single instance. All geometries must have compatible attributes.
4320
+ *
4321
+ * @param {Array<BufferGeometry>} geometries - The geometries to merge.
4322
+ * @param {boolean} [useGroups=false] - Whether to use groups or not.
4323
+ * @return {?BufferGeometry} The merged geometry. Returns `null` if the merge does not succeed.
4324
+ */
4325
+ function mergeGeometries( geometries, useGroups = false ) {
4326
+
4327
+ const isIndexed = geometries[ 0 ].index !== null;
4328
+
4329
+ const attributesUsed = new Set( Object.keys( geometries[ 0 ].attributes ) );
4330
+ const morphAttributesUsed = new Set( Object.keys( geometries[ 0 ].morphAttributes ) );
4331
+
4332
+ const attributes = {};
4333
+ const morphAttributes = {};
4334
+
4335
+ const morphTargetsRelative = geometries[ 0 ].morphTargetsRelative;
4336
+
4337
+ const mergedGeometry = new THREE.BufferGeometry();
4338
+
4339
+ let offset = 0;
4340
+
4341
+ for ( let i = 0; i < geometries.length; ++ i ) {
4342
+
4343
+ const geometry = geometries[ i ];
4344
+ let attributesCount = 0;
4345
+
4346
+ // ensure that all geometries are indexed, or none
4347
+
4348
+ if ( isIndexed !== ( geometry.index !== null ) ) {
4349
+
4350
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them.' );
4351
+ return null;
4352
+
4353
+ }
4354
+
4355
+ // gather attributes, exit early if they're different
4356
+
4357
+ for ( const name in geometry.attributes ) {
4358
+
4359
+ if ( ! attributesUsed.has( name ) ) {
4360
+
4361
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.' );
4362
+ return null;
4363
+
4364
+ }
4365
+
4366
+ if ( attributes[ name ] === undefined ) attributes[ name ] = [];
4367
+
4368
+ attributes[ name ].push( geometry.attributes[ name ] );
4369
+
4370
+ attributesCount ++;
4371
+
4372
+ }
4373
+
4374
+ // ensure geometries have the same number of attributes
4375
+
4376
+ if ( attributesCount !== attributesUsed.size ) {
4377
+
4378
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. Make sure all geometries have the same number of attributes.' );
4379
+ return null;
4380
+
4381
+ }
4382
+
4383
+ // gather morph attributes, exit early if they're different
4384
+
4385
+ if ( morphTargetsRelative !== geometry.morphTargetsRelative ) {
4386
+
4387
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphTargetsRelative must be consistent throughout all geometries.' );
4388
+ return null;
4389
+
4390
+ }
4391
+
4392
+ for ( const name in geometry.morphAttributes ) {
4393
+
4394
+ if ( ! morphAttributesUsed.has( name ) ) {
4395
+
4396
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. .morphAttributes must be consistent throughout all geometries.' );
4397
+ return null;
4398
+
4399
+ }
4400
+
4401
+ if ( morphAttributes[ name ] === undefined ) morphAttributes[ name ] = [];
4402
+
4403
+ morphAttributes[ name ].push( geometry.morphAttributes[ name ] );
4404
+
4405
+ }
4406
+
4407
+ if ( useGroups ) {
4408
+
4409
+ let count;
4410
+
4411
+ if ( isIndexed ) {
4412
+
4413
+ count = geometry.index.count;
4414
+
4415
+ } else if ( geometry.attributes.position !== undefined ) {
4416
+
4417
+ count = geometry.attributes.position.count;
4418
+
4419
+ } else {
4420
+
4421
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed with geometry at index ' + i + '. The geometry must have either an index or a position attribute' );
4422
+ return null;
4423
+
4424
+ }
4425
+
4426
+ mergedGeometry.addGroup( offset, count, i );
4427
+
4428
+ offset += count;
4429
+
4430
+ }
4431
+
4432
+ }
4433
+
4434
+ // merge indices
4435
+
4436
+ if ( isIndexed ) {
4437
+
4438
+ let indexOffset = 0;
4439
+ const mergedIndex = [];
4440
+
4441
+ for ( let i = 0; i < geometries.length; ++ i ) {
4442
+
4443
+ const index = geometries[ i ].index;
4444
+
4445
+ for ( let j = 0; j < index.count; ++ j ) {
4446
+
4447
+ mergedIndex.push( index.getX( j ) + indexOffset );
4448
+
4449
+ }
4450
+
4451
+ indexOffset += geometries[ i ].attributes.position.count;
4452
+
4453
+ }
4454
+
4455
+ mergedGeometry.setIndex( mergedIndex );
4456
+
4457
+ }
4458
+
4459
+ // merge attributes
4460
+
4461
+ for ( const name in attributes ) {
4462
+
4463
+ const mergedAttribute = mergeAttributes( attributes[ name ] );
4464
+
4465
+ if ( ! mergedAttribute ) {
4466
+
4467
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' attribute.' );
4468
+ return null;
4469
+
4470
+ }
4471
+
4472
+ mergedGeometry.setAttribute( name, mergedAttribute );
4473
+
4474
+ }
4475
+
4476
+ // merge morph attributes
4477
+
4478
+ for ( const name in morphAttributes ) {
4479
+
4480
+ const numMorphTargets = morphAttributes[ name ][ 0 ].length;
4481
+
4482
+ if ( numMorphTargets === 0 ) break;
4483
+
4484
+ mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
4485
+ mergedGeometry.morphAttributes[ name ] = [];
4486
+
4487
+ for ( let i = 0; i < numMorphTargets; ++ i ) {
4488
+
4489
+ const morphAttributesToMerge = [];
4490
+
4491
+ for ( let j = 0; j < morphAttributes[ name ].length; ++ j ) {
4492
+
4493
+ morphAttributesToMerge.push( morphAttributes[ name ][ j ][ i ] );
4494
+
4495
+ }
4496
+
4497
+ const mergedMorphAttribute = mergeAttributes( morphAttributesToMerge );
4498
+
4499
+ if ( ! mergedMorphAttribute ) {
4500
+
4501
+ console.error( 'THREE.BufferGeometryUtils: .mergeGeometries() failed while trying to merge the ' + name + ' morphAttribute.' );
4502
+ return null;
4503
+
4504
+ }
4505
+
4506
+ mergedGeometry.morphAttributes[ name ].push( mergedMorphAttribute );
4507
+
4508
+ }
4509
+
4510
+ }
4511
+
4512
+ return mergedGeometry;
4513
+
4514
+ }
4515
+
4516
+ /**
4517
+ * Merges a set of attributes into a single instance. All attributes must have compatible properties and types.
4518
+ * Instances of {@link InterleavedBufferAttribute} are not supported.
4519
+ *
4520
+ * @param {Array<BufferAttribute>} attributes - The attributes to merge.
4521
+ * @return {?BufferAttribute} The merged attribute. Returns `null` if the merge does not succeed.
4522
+ */
4523
+ function mergeAttributes( attributes ) {
4524
+
4525
+ let TypedArray;
4526
+ let itemSize;
4527
+ let normalized;
4528
+ let gpuType = - 1;
4529
+ let arrayLength = 0;
4530
+
4531
+ for ( let i = 0; i < attributes.length; ++ i ) {
4532
+
4533
+ const attribute = attributes[ i ];
4534
+
4535
+ if ( TypedArray === undefined ) TypedArray = attribute.array.constructor;
4536
+ if ( TypedArray !== attribute.array.constructor ) {
4537
+
4538
+ console.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes.' );
4539
+ return null;
4540
+
4541
+ }
4542
+
4543
+ if ( itemSize === undefined ) itemSize = attribute.itemSize;
4544
+ if ( itemSize !== attribute.itemSize ) {
4545
+
4546
+ console.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes.' );
4547
+ return null;
4548
+
4549
+ }
4550
+
4551
+ if ( normalized === undefined ) normalized = attribute.normalized;
4552
+ if ( normalized !== attribute.normalized ) {
4553
+
4554
+ console.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes.' );
4555
+ return null;
4556
+
4557
+ }
4558
+
4559
+ if ( gpuType === - 1 ) gpuType = attribute.gpuType;
4560
+ if ( gpuType !== attribute.gpuType ) {
4561
+
4562
+ console.error( 'THREE.BufferGeometryUtils: .mergeAttributes() failed. BufferAttribute.gpuType must be consistent across matching attributes.' );
4563
+ return null;
4564
+
4565
+ }
4566
+
4567
+ arrayLength += attribute.count * itemSize;
4568
+
4569
+ }
4570
+
4571
+ const array = new TypedArray( arrayLength );
4572
+ const result = new THREE.BufferAttribute( array, itemSize, normalized );
4573
+ let offset = 0;
4574
+
4575
+ for ( let i = 0; i < attributes.length; ++ i ) {
4576
+
4577
+ const attribute = attributes[ i ];
4578
+ if ( attribute.isInterleavedBufferAttribute ) {
4579
+
4580
+ const tupleOffset = offset / itemSize;
4581
+ for ( let j = 0, l = attribute.count; j < l; j ++ ) {
4582
+
4583
+ for ( let c = 0; c < itemSize; c ++ ) {
4584
+
4585
+ const value = attribute.getComponent( j, c );
4586
+ result.setComponent( j + tupleOffset, c, value );
4587
+
4588
+ }
4589
+
4590
+ }
4591
+
4592
+ } else {
4593
+
4594
+ array.set( attribute.array, offset );
4595
+
4596
+ }
4597
+
4598
+ offset += attribute.count * itemSize;
4599
+
4600
+ }
4601
+
4602
+ if ( gpuType !== undefined ) {
4603
+
4604
+ result.gpuType = gpuType;
4605
+
4606
+ }
4607
+
4608
+ return result;
4609
+
4610
+ }
4611
+
4612
+ /**
4613
+ * Returns a new geometry with vertices for which all similar vertex attributes (within tolerance) are merged.
4614
+ *
4615
+ * @param {BufferGeometry} geometry - The geometry to merge vertices for.
4616
+ * @param {number} [tolerance=1e-4] - The tolerance value.
4617
+ * @return {BufferGeometry} - The new geometry with merged vertices.
4618
+ */
4619
+ function mergeVertices( geometry, tolerance = 1e-4 ) {
4620
+
4621
+ tolerance = Math.max( tolerance, Number.EPSILON );
4622
+
4623
+ // Generate an index buffer if the geometry doesn't have one, or optimize it
4624
+ // if it's already available.
4625
+ const hashToIndex = {};
4626
+ const indices = geometry.getIndex();
4627
+ const positions = geometry.getAttribute( 'position' );
4628
+ const vertexCount = indices ? indices.count : positions.count;
4629
+
4630
+ // next value for triangle indices
4631
+ let nextIndex = 0;
4632
+
4633
+ // attributes and new attribute arrays
4634
+ const attributeNames = Object.keys( geometry.attributes );
4635
+ const tmpAttributes = {};
4636
+ const tmpMorphAttributes = {};
4637
+ const newIndices = [];
4638
+ const getters = [ 'getX', 'getY', 'getZ', 'getW' ];
4639
+ const setters = [ 'setX', 'setY', 'setZ', 'setW' ];
4640
+
4641
+ // Initialize the arrays, allocating space conservatively. Extra
4642
+ // space will be trimmed in the last step.
4643
+ for ( let i = 0, l = attributeNames.length; i < l; i ++ ) {
4644
+
4645
+ const name = attributeNames[ i ];
4646
+ const attr = geometry.attributes[ name ];
4647
+
4648
+ tmpAttributes[ name ] = new attr.constructor(
4649
+ new attr.array.constructor( attr.count * attr.itemSize ),
4650
+ attr.itemSize,
4651
+ attr.normalized
4652
+ );
4653
+
4654
+ const morphAttributes = geometry.morphAttributes[ name ];
4655
+ if ( morphAttributes ) {
4656
+
4657
+ if ( ! tmpMorphAttributes[ name ] ) tmpMorphAttributes[ name ] = [];
4658
+ morphAttributes.forEach( ( morphAttr, i ) => {
4659
+
4660
+ const array = new morphAttr.array.constructor( morphAttr.count * morphAttr.itemSize );
4661
+ tmpMorphAttributes[ name ][ i ] = new morphAttr.constructor( array, morphAttr.itemSize, morphAttr.normalized );
4662
+
4663
+ } );
4664
+
4665
+ }
4666
+
4667
+ }
4668
+
4669
+ // convert the error tolerance to an amount of decimal places to truncate to
4670
+ const halfTolerance = tolerance * 0.5;
4671
+ const exponent = Math.log10( 1 / tolerance );
4672
+ const hashMultiplier = Math.pow( 10, exponent );
4673
+ const hashAdditive = halfTolerance * hashMultiplier;
4674
+ for ( let i = 0; i < vertexCount; i ++ ) {
4675
+
4676
+ const index = indices ? indices.getX( i ) : i;
4677
+
4678
+ // Generate a hash for the vertex attributes at the current index 'i'
4679
+ let hash = '';
4680
+ for ( let j = 0, l = attributeNames.length; j < l; j ++ ) {
4681
+
4682
+ const name = attributeNames[ j ];
4683
+ const attribute = geometry.getAttribute( name );
4684
+ const itemSize = attribute.itemSize;
4685
+
4686
+ for ( let k = 0; k < itemSize; k ++ ) {
4687
+
4688
+ // double tilde truncates the decimal value
4689
+ hash += `${ ~ ~ ( attribute[ getters[ k ] ]( index ) * hashMultiplier + hashAdditive ) },`;
4690
+
4691
+ }
4692
+
4693
+ }
4694
+
4695
+ // Add another reference to the vertex if it's already
4696
+ // used by another index
4697
+ if ( hash in hashToIndex ) {
4698
+
4699
+ newIndices.push( hashToIndex[ hash ] );
4700
+
4701
+ } else {
4702
+
4703
+ // copy data to the new index in the temporary attributes
4704
+ for ( let j = 0, l = attributeNames.length; j < l; j ++ ) {
4705
+
4706
+ const name = attributeNames[ j ];
4707
+ const attribute = geometry.getAttribute( name );
4708
+ const morphAttributes = geometry.morphAttributes[ name ];
4709
+ const itemSize = attribute.itemSize;
4710
+ const newArray = tmpAttributes[ name ];
4711
+ const newMorphArrays = tmpMorphAttributes[ name ];
4712
+
4713
+ for ( let k = 0; k < itemSize; k ++ ) {
4714
+
4715
+ const getterFunc = getters[ k ];
4716
+ const setterFunc = setters[ k ];
4717
+ newArray[ setterFunc ]( nextIndex, attribute[ getterFunc ]( index ) );
4718
+
4719
+ if ( morphAttributes ) {
4720
+
4721
+ for ( let m = 0, ml = morphAttributes.length; m < ml; m ++ ) {
4722
+
4723
+ newMorphArrays[ m ][ setterFunc ]( nextIndex, morphAttributes[ m ][ getterFunc ]( index ) );
4724
+
4725
+ }
4726
+
4727
+ }
4728
+
4729
+ }
4730
+
4731
+ }
4732
+
4733
+ hashToIndex[ hash ] = nextIndex;
4734
+ newIndices.push( nextIndex );
4735
+ nextIndex ++;
4736
+
4737
+ }
4738
+
4739
+ }
4740
+
4741
+ // generate result BufferGeometry
4742
+ const result = geometry.clone();
4743
+ for ( const name in geometry.attributes ) {
4744
+
4745
+ const tmpAttribute = tmpAttributes[ name ];
4746
+
4747
+ result.setAttribute( name, new tmpAttribute.constructor(
4748
+ tmpAttribute.array.slice( 0, nextIndex * tmpAttribute.itemSize ),
4749
+ tmpAttribute.itemSize,
4750
+ tmpAttribute.normalized,
4751
+ ) );
4752
+
4753
+ if ( ! ( name in tmpMorphAttributes ) ) continue;
4754
+
4755
+ for ( let j = 0; j < tmpMorphAttributes[ name ].length; j ++ ) {
4756
+
4757
+ const tmpMorphAttribute = tmpMorphAttributes[ name ][ j ];
4758
+
4759
+ result.morphAttributes[ name ][ j ] = new tmpMorphAttribute.constructor(
4760
+ tmpMorphAttribute.array.slice( 0, nextIndex * tmpMorphAttribute.itemSize ),
4761
+ tmpMorphAttribute.itemSize,
4762
+ tmpMorphAttribute.normalized,
4763
+ );
4764
+
4765
+ }
4766
+
4767
+ }
4768
+
4769
+ // indices
4770
+
4771
+ result.setIndex( newIndices );
4772
+
4773
+ return result;
4774
+
4775
+ }
4776
+
4318
4777
  /**
4319
4778
  * Returns a new indexed geometry based on `TrianglesDrawMode` draw mode.
4320
4779
  * This mode corresponds to the `gl.TRIANGLES` primitive in WebGL.
@@ -10165,7 +10624,680 @@ class OBJLoader extends THREE.Loader {
10165
10624
 
10166
10625
  }
10167
10626
 
10168
- }
10627
+ }
10628
+
10629
+ var ObjProcessor = /*#__PURE__*/function () {
10630
+ function ObjProcessor() {
10631
+ _classCallCheck(this, ObjProcessor);
10632
+ this.indexedGeometryCache = new Map(); // Cache for indexed geometries
10633
+ this.geometrySizeCache = new Map(); // Cache for geometry sizes
10634
+ this.idbSupported = this.checkIndexedDBSupport();
10635
+ this.dbName = 'CentralPlantGeometryDB';
10636
+ this.dbVersion = 1;
10637
+ this.storeName = 'indexedGeometries';
10638
+ console.log('🔧 ObjProcessor initialized');
10639
+ console.log("\uD83D\uDCE6 IndexedDB supported: ".concat(this.idbSupported));
10640
+ }
10641
+
10642
+ /**
10643
+ * Check if IndexedDB is supported
10644
+ * @returns {boolean} True if IndexedDB is supported
10645
+ */
10646
+ return _createClass(ObjProcessor, [{
10647
+ key: "checkIndexedDBSupport",
10648
+ value: function checkIndexedDBSupport() {
10649
+ if (typeof window === 'undefined') return false;
10650
+ return 'indexedDB' in window && window.indexedDB !== null;
10651
+ }
10652
+
10653
+ /**
10654
+ * Initialize IndexedDB for geometry storage
10655
+ * @returns {Promise<IDBDatabase>} Promise that resolves to the database
10656
+ */
10657
+ }, {
10658
+ key: "initializeIDB",
10659
+ value: (function () {
10660
+ var _initializeIDB = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
10661
+ var _this = this;
10662
+ return _regenerator().w(function (_context) {
10663
+ while (1) switch (_context.n) {
10664
+ case 0:
10665
+ if (this.idbSupported) {
10666
+ _context.n = 1;
10667
+ break;
10668
+ }
10669
+ throw new Error('IndexedDB not supported');
10670
+ case 1:
10671
+ return _context.a(2, new Promise(function (resolve, reject) {
10672
+ var request = indexedDB.open(_this.dbName, _this.dbVersion);
10673
+ request.onerror = function () {
10674
+ console.error('❌ Failed to open IndexedDB');
10675
+ reject(request.error);
10676
+ };
10677
+ request.onsuccess = function () {
10678
+ console.log('✅ IndexedDB opened successfully');
10679
+ resolve(request.result);
10680
+ };
10681
+ request.onupgradeneeded = function (event) {
10682
+ console.log('🔄 Upgrading IndexedDB schema');
10683
+ var db = event.target.result;
10684
+
10685
+ // Create object store for indexed geometries
10686
+ if (!db.objectStoreNames.contains(_this.storeName)) {
10687
+ var store = db.createObjectStore(_this.storeName, {
10688
+ keyPath: 'modelKey'
10689
+ });
10690
+ store.createIndex('modelType', 'modelType', {
10691
+ unique: false
10692
+ });
10693
+ store.createIndex('sizeKB', 'sizeKB', {
10694
+ unique: false
10695
+ });
10696
+ console.log('📦 Created geometry object store');
10697
+ }
10698
+ };
10699
+ }));
10700
+ }
10701
+ }, _callee, this);
10702
+ }));
10703
+ function initializeIDB() {
10704
+ return _initializeIDB.apply(this, arguments);
10705
+ }
10706
+ return initializeIDB;
10707
+ }()
10708
+ /**
10709
+ * Convert OBJ object to indexed BufferGeometry
10710
+ * @param {THREE.Object3D} objObject - The loaded OBJ object from THREE.OBJLoader
10711
+ * @param {string} modelKey - The model key for identification
10712
+ * @returns {Object} Object containing indexed geometry and metadata
10713
+ */
10714
+ )
10715
+ }, {
10716
+ key: "objToIndexedBufferGeometry",
10717
+ value: function objToIndexedBufferGeometry(objObject, modelKey) {
10718
+ var _this2 = this;
10719
+ console.log("\uD83D\uDD04 Converting OBJ to indexed BufferGeometry: ".concat(modelKey));
10720
+ var geometries = [];
10721
+ var materials = [];
10722
+
10723
+ // Traverse the OBJ object and collect all geometries
10724
+ objObject.traverse(function (child) {
10725
+ if (child.isMesh && child.geometry) {
10726
+ // Clone the geometry to avoid modifying the original
10727
+ var geometry = child.geometry.clone();
10728
+
10729
+ // Ensure the geometry has proper attributes
10730
+ if (!geometry.attributes.position) {
10731
+ console.warn("\u26A0\uFE0F Geometry missing position attribute: ".concat(modelKey));
10732
+ return;
10733
+ }
10734
+
10735
+ // Compute normals if missing
10736
+ if (!geometry.attributes.normal) {
10737
+ geometry.computeVertexNormals();
10738
+ console.log("\uD83D\uDCD0 Computed normals for geometry: ".concat(modelKey));
10739
+ }
10740
+
10741
+ // Compute UVs if missing (simple planar mapping)
10742
+ if (!geometry.attributes.uv) {
10743
+ _this2.computeSimpleUVs(geometry);
10744
+ console.log("\uD83D\uDDFA\uFE0F Computed UVs for geometry: ".concat(modelKey));
10745
+ }
10746
+ geometries.push(geometry);
10747
+ materials.push(child.material);
10748
+ }
10749
+ });
10750
+ if (geometries.length === 0) {
10751
+ console.warn("\u26A0\uFE0F No valid geometries found in OBJ: ".concat(modelKey));
10752
+ return null;
10753
+ }
10754
+
10755
+ // Merge all geometries into one
10756
+ var mergedGeometry;
10757
+ if (geometries.length === 1) {
10758
+ mergedGeometry = geometries[0];
10759
+ } else {
10760
+ console.log("\uD83D\uDD17 Merging ".concat(geometries.length, " geometries for: ").concat(modelKey));
10761
+ mergedGeometry = mergeGeometries(geometries);
10762
+ }
10763
+
10764
+ // Convert to indexed geometry if not already indexed
10765
+ var indexedGeometry = mergedGeometry;
10766
+ var originalGeometry = mergedGeometry; // Keep reference to original for comparison
10767
+
10768
+ if (!mergedGeometry.index) {
10769
+ console.log("\uD83D\uDCCA Converting to indexed geometry: ".concat(modelKey));
10770
+ indexedGeometry = mergeVertices(mergedGeometry);
10771
+ }
10772
+
10773
+ // Calculate geometry statistics with original geometry for comparison
10774
+ var stats = this.calculateGeometryStats(indexedGeometry, modelKey, originalGeometry);
10775
+
10776
+ // Prepare serializable data for storage
10777
+ var geometryData = this.serializeGeometry(indexedGeometry, modelKey, stats);
10778
+ console.log("\u2705 Successfully converted OBJ to indexed BufferGeometry: ".concat(modelKey));
10779
+ console.log("\uD83D\uDCCA Vertices: ".concat(stats.vertexCount, ", Faces: ").concat(stats.faceCount));
10780
+ console.log("\uD83D\uDCBE Indexed Size: ".concat(stats.indexedSizeKB, "KB"));
10781
+ if (stats.nonIndexedSizeKB > 0) {
10782
+ console.log("\uD83D\uDCBE Non-Indexed Size: ".concat(stats.nonIndexedSizeKB, "KB"));
10783
+ console.log("\uD83D\uDD04 Memory Reduction: ".concat(stats.memoryReduction, "% (").concat(stats.compressionRatio, "x smaller)"));
10784
+ }
10785
+ return {
10786
+ geometry: indexedGeometry,
10787
+ geometryData: geometryData,
10788
+ stats: stats,
10789
+ materials: materials[0] || new THREE__namespace.MeshStandardMaterial({
10790
+ color: 0x888888
10791
+ })
10792
+ };
10793
+ }
10794
+
10795
+ /**
10796
+ * Compute simple planar UVs for geometry
10797
+ * @param {THREE.BufferGeometry} geometry - The geometry to compute UVs for
10798
+ */
10799
+ }, {
10800
+ key: "computeSimpleUVs",
10801
+ value: function computeSimpleUVs(geometry) {
10802
+ var positions = geometry.attributes.position;
10803
+ var uvs = new Float32Array(positions.count * 2);
10804
+
10805
+ // Simple planar projection on XZ plane
10806
+ for (var i = 0; i < positions.count; i++) {
10807
+ var x = positions.getX(i);
10808
+ var z = positions.getZ(i);
10809
+
10810
+ // Normalize to 0-1 range (simple box projection)
10811
+ uvs[i * 2] = (x + 1) * 0.5;
10812
+ uvs[i * 2 + 1] = (z + 1) * 0.5;
10813
+ }
10814
+ geometry.setAttribute('uv', new THREE__namespace.BufferAttribute(uvs, 2));
10815
+ }
10816
+
10817
+ /**
10818
+ * Calculate geometry statistics
10819
+ * @param {THREE.BufferGeometry} geometry - The geometry to analyze
10820
+ * @param {string} modelKey - The model key for logging
10821
+ * @param {THREE.BufferGeometry} originalGeometry - Optional original non-indexed geometry for comparison
10822
+ * @returns {Object} Statistics object
10823
+ */
10824
+ }, {
10825
+ key: "calculateGeometryStats",
10826
+ value: function calculateGeometryStats(geometry, modelKey) {
10827
+ var originalGeometry = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
10828
+ var vertexCount = geometry.attributes.position.count;
10829
+ var faceCount = geometry.index ? geometry.index.count / 3 : vertexCount / 3;
10830
+
10831
+ // Calculate indexed geometry memory usage
10832
+ var indexedBytes = 0;
10833
+
10834
+ // Position attribute (3 floats per vertex)
10835
+ if (geometry.attributes.position) {
10836
+ indexedBytes += geometry.attributes.position.array.byteLength;
10837
+ }
10838
+
10839
+ // Normal attribute (3 floats per vertex)
10840
+ if (geometry.attributes.normal) {
10841
+ indexedBytes += geometry.attributes.normal.array.byteLength;
10842
+ }
10843
+
10844
+ // UV attribute (2 floats per vertex)
10845
+ if (geometry.attributes.uv) {
10846
+ indexedBytes += geometry.attributes.uv.array.byteLength;
10847
+ }
10848
+
10849
+ // Index buffer (if indexed)
10850
+ if (geometry.index) {
10851
+ indexedBytes += geometry.index.array.byteLength;
10852
+ }
10853
+ var indexedSizeKB = (indexedBytes / 1024).toFixed(2);
10854
+
10855
+ // Calculate non-indexed geometry memory usage for comparison
10856
+ var nonIndexedBytes = 0;
10857
+ var nonIndexedSizeKB = 0;
10858
+ var memoryReduction = 0;
10859
+ var compressionRatio = 1;
10860
+ if (originalGeometry) {
10861
+ // Calculate what the memory would be without indexing
10862
+ var originalVertexCount = originalGeometry.attributes.position ? originalGeometry.attributes.position.count : vertexCount;
10863
+
10864
+ // Position: 3 floats per vertex
10865
+ nonIndexedBytes += originalVertexCount * 3 * 4; // 4 bytes per float32
10866
+
10867
+ // Normals: 3 floats per vertex (if present)
10868
+ if (originalGeometry.attributes.normal || geometry.attributes.normal) {
10869
+ nonIndexedBytes += originalVertexCount * 3 * 4;
10870
+ }
10871
+
10872
+ // UVs: 2 floats per vertex (if present)
10873
+ if (originalGeometry.attributes.uv || geometry.attributes.uv) {
10874
+ nonIndexedBytes += originalVertexCount * 2 * 4;
10875
+ }
10876
+ nonIndexedSizeKB = (nonIndexedBytes / 1024).toFixed(2);
10877
+ memoryReduction = ((nonIndexedBytes - indexedBytes) / nonIndexedBytes * 100).toFixed(1);
10878
+ compressionRatio = (nonIndexedBytes / indexedBytes).toFixed(2);
10879
+ } else if (geometry.index) {
10880
+ // Estimate non-indexed size based on face count
10881
+ var estimatedNonIndexedVertices = faceCount * 3; // Each face has 3 vertices
10882
+
10883
+ // Position: 3 floats per vertex
10884
+ nonIndexedBytes += estimatedNonIndexedVertices * 3 * 4;
10885
+
10886
+ // Normals: 3 floats per vertex (if present)
10887
+ if (geometry.attributes.normal) {
10888
+ nonIndexedBytes += estimatedNonIndexedVertices * 3 * 4;
10889
+ }
10890
+
10891
+ // UVs: 2 floats per vertex (if present)
10892
+ if (geometry.attributes.uv) {
10893
+ nonIndexedBytes += estimatedNonIndexedVertices * 2 * 4;
10894
+ }
10895
+ nonIndexedSizeKB = (nonIndexedBytes / 1024).toFixed(2);
10896
+ memoryReduction = ((nonIndexedBytes - indexedBytes) / nonIndexedBytes * 100).toFixed(1);
10897
+ compressionRatio = (nonIndexedBytes / indexedBytes).toFixed(2);
10898
+ }
10899
+ var stats = {
10900
+ modelKey: modelKey,
10901
+ vertexCount: vertexCount,
10902
+ faceCount: faceCount,
10903
+ // Indexed geometry stats
10904
+ indexedBytes: indexedBytes,
10905
+ indexedSizeKB: parseFloat(indexedSizeKB),
10906
+ // Non-indexed geometry stats (for comparison)
10907
+ nonIndexedBytes: nonIndexedBytes,
10908
+ nonIndexedSizeKB: parseFloat(nonIndexedSizeKB),
10909
+ // Compression metrics
10910
+ memoryReduction: parseFloat(memoryReduction),
10911
+ // Percentage reduction
10912
+ compressionRatio: parseFloat(compressionRatio),
10913
+ // How many times smaller
10914
+ // Legacy compatibility
10915
+ totalBytes: indexedBytes,
10916
+ // Keep for backward compatibility
10917
+ sizeKB: parseFloat(indexedSizeKB),
10918
+ // Keep for backward compatibility
10919
+ // Features
10920
+ indexed: !!geometry.index,
10921
+ hasNormals: !!geometry.attributes.normal,
10922
+ hasUVs: !!geometry.attributes.uv,
10923
+ timestamp: Date.now()
10924
+ };
10925
+
10926
+ // Cache the size info
10927
+ this.geometrySizeCache.set(modelKey, stats);
10928
+ return stats;
10929
+ }
10930
+
10931
+ /**
10932
+ * Serialize geometry for storage
10933
+ * @param {THREE.BufferGeometry} geometry - The geometry to serialize
10934
+ * @param {string} modelKey - The model key
10935
+ * @param {Object} stats - The geometry statistics
10936
+ * @returns {Object} Serializable geometry data
10937
+ */
10938
+ }, {
10939
+ key: "serializeGeometry",
10940
+ value: function serializeGeometry(geometry, modelKey, stats) {
10941
+ var data = {
10942
+ modelKey: modelKey,
10943
+ modelType: 'obj',
10944
+ stats: stats,
10945
+ attributes: {}
10946
+ };
10947
+
10948
+ // Serialize position attribute
10949
+ if (geometry.attributes.position) {
10950
+ data.attributes.position = {
10951
+ array: Array.from(geometry.attributes.position.array),
10952
+ itemSize: geometry.attributes.position.itemSize,
10953
+ normalized: geometry.attributes.position.normalized
10954
+ };
10955
+ }
10956
+
10957
+ // Serialize normal attribute
10958
+ if (geometry.attributes.normal) {
10959
+ data.attributes.normal = {
10960
+ array: Array.from(geometry.attributes.normal.array),
10961
+ itemSize: geometry.attributes.normal.itemSize,
10962
+ normalized: geometry.attributes.normal.normalized
10963
+ };
10964
+ }
10965
+
10966
+ // Serialize UV attribute
10967
+ if (geometry.attributes.uv) {
10968
+ data.attributes.uv = {
10969
+ array: Array.from(geometry.attributes.uv.array),
10970
+ itemSize: geometry.attributes.uv.itemSize,
10971
+ normalized: geometry.attributes.uv.normalized
10972
+ };
10973
+ }
10974
+
10975
+ // Serialize index
10976
+ if (geometry.index) {
10977
+ data.index = {
10978
+ array: Array.from(geometry.index.array),
10979
+ itemSize: 1
10980
+ };
10981
+ }
10982
+ return data;
10983
+ }
10984
+
10985
+ /**
10986
+ * Deserialize geometry data back to BufferGeometry
10987
+ * @param {Object} geometryData - The serialized geometry data
10988
+ * @returns {THREE.BufferGeometry} The reconstructed geometry
10989
+ */
10990
+ }, {
10991
+ key: "deserializeGeometry",
10992
+ value: function deserializeGeometry(geometryData) {
10993
+ var geometry = new THREE__namespace.BufferGeometry();
10994
+
10995
+ // Restore attributes
10996
+ Object.keys(geometryData.attributes).forEach(function (attributeName) {
10997
+ var attrData = geometryData.attributes[attributeName];
10998
+ var array = new Float32Array(attrData.array);
10999
+ var attribute = new THREE__namespace.BufferAttribute(array, attrData.itemSize, attrData.normalized);
11000
+ geometry.setAttribute(attributeName, attribute);
11001
+ });
11002
+
11003
+ // Restore index if present
11004
+ if (geometryData.index) {
11005
+ var indexArray = new Uint32Array(geometryData.index.array);
11006
+ geometry.setIndex(new THREE__namespace.BufferAttribute(indexArray, 1));
11007
+ }
11008
+ return geometry;
11009
+ }
11010
+
11011
+ /**
11012
+ * Store indexed geometry in IndexedDB
11013
+ * @param {Object} geometryData - The serialized geometry data
11014
+ * @returns {Promise} Promise that resolves when stored
11015
+ */
11016
+ }, {
11017
+ key: "storeGeometryInIDB",
11018
+ value: (function () {
11019
+ var _storeGeometryInIDB = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(geometryData) {
11020
+ var _this3 = this;
11021
+ var db, _t;
11022
+ return _regenerator().w(function (_context2) {
11023
+ while (1) switch (_context2.n) {
11024
+ case 0:
11025
+ if (this.idbSupported) {
11026
+ _context2.n = 1;
11027
+ break;
11028
+ }
11029
+ console.warn('⚠️ IndexedDB not supported, skipping storage');
11030
+ return _context2.a(2);
11031
+ case 1:
11032
+ _context2.p = 1;
11033
+ _context2.n = 2;
11034
+ return this.initializeIDB();
11035
+ case 2:
11036
+ db = _context2.v;
11037
+ return _context2.a(2, new Promise(function (resolve, reject) {
11038
+ var transaction = db.transaction([_this3.storeName], 'readwrite');
11039
+ var store = transaction.objectStore(_this3.storeName);
11040
+ var request = store.put(geometryData);
11041
+ request.onsuccess = function () {
11042
+ console.log("\uD83D\uDCBE Stored geometry in IndexedDB: ".concat(geometryData.modelKey));
11043
+ resolve();
11044
+ };
11045
+ request.onerror = function () {
11046
+ console.error("\u274C Failed to store geometry: ".concat(geometryData.modelKey));
11047
+ reject(request.error);
11048
+ };
11049
+ }));
11050
+ case 3:
11051
+ _context2.p = 3;
11052
+ _t = _context2.v;
11053
+ console.error('❌ Error storing geometry in IndexedDB:', _t);
11054
+ throw _t;
11055
+ case 4:
11056
+ return _context2.a(2);
11057
+ }
11058
+ }, _callee2, this, [[1, 3]]);
11059
+ }));
11060
+ function storeGeometryInIDB(_x) {
11061
+ return _storeGeometryInIDB.apply(this, arguments);
11062
+ }
11063
+ return storeGeometryInIDB;
11064
+ }()
11065
+ /**
11066
+ * Load indexed geometry from IndexedDB
11067
+ * @param {string} modelKey - The model key to load
11068
+ * @returns {Promise<Object>} Promise that resolves to geometry data
11069
+ */
11070
+ )
11071
+ }, {
11072
+ key: "loadGeometryFromIDB",
11073
+ value: (function () {
11074
+ var _loadGeometryFromIDB = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(modelKey) {
11075
+ var _this4 = this;
11076
+ var db, _t2;
11077
+ return _regenerator().w(function (_context3) {
11078
+ while (1) switch (_context3.n) {
11079
+ case 0:
11080
+ if (this.idbSupported) {
11081
+ _context3.n = 1;
11082
+ break;
11083
+ }
11084
+ console.warn('⚠️ IndexedDB not supported, cannot load');
11085
+ return _context3.a(2, null);
11086
+ case 1:
11087
+ _context3.p = 1;
11088
+ _context3.n = 2;
11089
+ return this.initializeIDB();
11090
+ case 2:
11091
+ db = _context3.v;
11092
+ return _context3.a(2, new Promise(function (resolve, reject) {
11093
+ var transaction = db.transaction([_this4.storeName], 'readonly');
11094
+ var store = transaction.objectStore(_this4.storeName);
11095
+ var request = store.get(modelKey);
11096
+ request.onsuccess = function () {
11097
+ if (request.result) {
11098
+ console.log("\uD83D\uDCE6 Loaded geometry from IndexedDB: ".concat(modelKey));
11099
+ resolve(request.result);
11100
+ } else {
11101
+ console.log("\uD83D\uDCED No geometry found in IndexedDB: ".concat(modelKey));
11102
+ resolve(null);
11103
+ }
11104
+ };
11105
+ request.onerror = function () {
11106
+ console.error("\u274C Failed to load geometry: ".concat(modelKey));
11107
+ reject(request.error);
11108
+ };
11109
+ }));
11110
+ case 3:
11111
+ _context3.p = 3;
11112
+ _t2 = _context3.v;
11113
+ console.error('❌ Error loading geometry from IndexedDB:', _t2);
11114
+ throw _t2;
11115
+ case 4:
11116
+ return _context3.a(2);
11117
+ }
11118
+ }, _callee3, this, [[1, 3]]);
11119
+ }));
11120
+ function loadGeometryFromIDB(_x2) {
11121
+ return _loadGeometryFromIDB.apply(this, arguments);
11122
+ }
11123
+ return loadGeometryFromIDB;
11124
+ }()
11125
+ /**
11126
+ * Create a custom mesh from indexed geometry
11127
+ * @param {string} modelKey - The model key
11128
+ * @param {THREE.Material} material - Optional material to use
11129
+ * @returns {THREE.Mesh|null} The created mesh or null if not found
11130
+ */
11131
+ )
11132
+ }, {
11133
+ key: "createCustomMesh",
11134
+ value: function createCustomMesh(modelKey) {
11135
+ var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
11136
+ if (this.indexedGeometryCache.has(modelKey)) {
11137
+ var cachedData = this.indexedGeometryCache.get(modelKey);
11138
+ var geometry = cachedData.geometry.clone();
11139
+ var defaultMaterial = new THREE__namespace.MeshStandardMaterial({
11140
+ color: 0x888888,
11141
+ side: THREE__namespace.DoubleSide,
11142
+ wireframe: false
11143
+ });
11144
+ var mesh = new THREE__namespace.Mesh(geometry, material || defaultMaterial);
11145
+ mesh.userData.modelKey = modelKey;
11146
+ mesh.userData.stats = cachedData.stats;
11147
+ mesh.userData.isCustomGeometry = true;
11148
+ console.log("\uD83C\uDFAF Created custom mesh from indexed geometry: ".concat(modelKey));
11149
+ return mesh;
11150
+ }
11151
+ console.warn("\u26A0\uFE0F Indexed geometry not found in cache: ".concat(modelKey));
11152
+ return null;
11153
+ }
11154
+
11155
+ /**
11156
+ * Process an OBJ object and store the result
11157
+ * @param {THREE.Object3D} objObject - The loaded OBJ object
11158
+ * @param {string} modelKey - The model key
11159
+ * @param {boolean} storeInIDB - Whether to store in IndexedDB
11160
+ * @returns {Promise<Object>} Promise that resolves to the processed result
11161
+ */
11162
+ }, {
11163
+ key: "processObjObject",
11164
+ value: (function () {
11165
+ var _processObjObject = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(objObject, modelKey) {
11166
+ var storeInIDB,
11167
+ result,
11168
+ _args4 = arguments,
11169
+ _t3;
11170
+ return _regenerator().w(function (_context4) {
11171
+ while (1) switch (_context4.n) {
11172
+ case 0:
11173
+ storeInIDB = _args4.length > 2 && _args4[2] !== undefined ? _args4[2] : true;
11174
+ _context4.p = 1;
11175
+ // Convert to indexed BufferGeometry
11176
+ result = this.objToIndexedBufferGeometry(objObject, modelKey);
11177
+ if (result) {
11178
+ _context4.n = 2;
11179
+ break;
11180
+ }
11181
+ throw new Error("Failed to convert OBJ to indexed geometry: ".concat(modelKey));
11182
+ case 2:
11183
+ // Cache the result
11184
+ this.indexedGeometryCache.set(modelKey, result);
11185
+
11186
+ // Store in IndexedDB if requested
11187
+ if (!(storeInIDB && result.geometryData)) {
11188
+ _context4.n = 3;
11189
+ break;
11190
+ }
11191
+ _context4.n = 3;
11192
+ return this.storeGeometryInIDB(result.geometryData);
11193
+ case 3:
11194
+ console.log("\u2705 Successfully processed OBJ: ".concat(modelKey));
11195
+ return _context4.a(2, result);
11196
+ case 4:
11197
+ _context4.p = 4;
11198
+ _t3 = _context4.v;
11199
+ console.error("\u274C Error processing OBJ: ".concat(modelKey), _t3);
11200
+ throw _t3;
11201
+ case 5:
11202
+ return _context4.a(2);
11203
+ }
11204
+ }, _callee4, this, [[1, 4]]);
11205
+ }));
11206
+ function processObjObject(_x3, _x4) {
11207
+ return _processObjObject.apply(this, arguments);
11208
+ }
11209
+ return processObjObject;
11210
+ }()
11211
+ /**
11212
+ * Get all processed geometry statistics
11213
+ * @returns {Array} Array of geometry statistics
11214
+ */
11215
+ )
11216
+ }, {
11217
+ key: "getAllGeometryStats",
11218
+ value: function getAllGeometryStats() {
11219
+ var stats = [];
11220
+ this.geometrySizeCache.forEach(function (stat, modelKey) {
11221
+ stats.push(stat);
11222
+ });
11223
+ return stats.sort(function (a, b) {
11224
+ return b.sizeKB - a.sizeKB;
11225
+ }); // Sort by size descending
11226
+ }
11227
+
11228
+ /**
11229
+ * Get total memory usage of cached geometries
11230
+ * @returns {Object} Memory usage statistics
11231
+ */
11232
+ }, {
11233
+ key: "getMemoryUsage",
11234
+ value: function getMemoryUsage() {
11235
+ var totalIndexedBytes = 0;
11236
+ var totalNonIndexedBytes = 0;
11237
+ var totalGeometries = 0;
11238
+ this.geometrySizeCache.forEach(function (stats) {
11239
+ totalIndexedBytes += stats.indexedBytes;
11240
+ totalNonIndexedBytes += stats.nonIndexedBytes;
11241
+ totalGeometries++;
11242
+ });
11243
+ var totalMemoryReduction = totalNonIndexedBytes > 0 ? ((totalNonIndexedBytes - totalIndexedBytes) / totalNonIndexedBytes * 100).toFixed(1) : 0;
11244
+ var totalCompressionRatio = totalIndexedBytes > 0 ? (totalNonIndexedBytes / totalIndexedBytes).toFixed(2) : 1;
11245
+ return {
11246
+ totalGeometries: totalGeometries,
11247
+ // Indexed geometry stats
11248
+ indexedBytes: totalIndexedBytes,
11249
+ indexedKB: (totalIndexedBytes / 1024).toFixed(2),
11250
+ indexedMB: (totalIndexedBytes / (1024 * 1024)).toFixed(3),
11251
+ // Non-indexed geometry stats
11252
+ nonIndexedBytes: totalNonIndexedBytes,
11253
+ nonIndexedKB: (totalNonIndexedBytes / 1024).toFixed(2),
11254
+ nonIndexedMB: (totalNonIndexedBytes / (1024 * 1024)).toFixed(3),
11255
+ // Compression stats
11256
+ memoryReduction: parseFloat(totalMemoryReduction),
11257
+ compressionRatio: parseFloat(totalCompressionRatio),
11258
+ // Legacy compatibility
11259
+ totalBytes: totalIndexedBytes,
11260
+ totalKB: (totalIndexedBytes / 1024).toFixed(2),
11261
+ totalMB: (totalIndexedBytes / (1024 * 1024)).toFixed(2)
11262
+ };
11263
+ }
11264
+
11265
+ /**
11266
+ * Clear all caches
11267
+ */
11268
+ }, {
11269
+ key: "clearCaches",
11270
+ value: function clearCaches() {
11271
+ console.log('🧹 Clearing OBJ processor caches...');
11272
+
11273
+ // Dispose of cached geometries
11274
+ this.indexedGeometryCache.forEach(function (data, modelKey) {
11275
+ if (data.geometry) {
11276
+ data.geometry.dispose();
11277
+ }
11278
+ console.log("\uD83D\uDDD1\uFE0F Disposed cached geometry: ".concat(modelKey));
11279
+ });
11280
+ this.indexedGeometryCache.clear();
11281
+ this.geometrySizeCache.clear();
11282
+ console.log('✅ OBJ processor caches cleared');
11283
+ }
11284
+
11285
+ /**
11286
+ * Get processing status
11287
+ * @returns {Object} Status information
11288
+ */
11289
+ }, {
11290
+ key: "getStatus",
11291
+ value: function getStatus() {
11292
+ return {
11293
+ cachedGeometries: Array.from(this.indexedGeometryCache.keys()),
11294
+ totalCached: this.indexedGeometryCache.size,
11295
+ idbSupported: this.idbSupported,
11296
+ memoryUsage: this.getMemoryUsage()
11297
+ };
11298
+ }
11299
+ }]);
11300
+ }(); // Export the class
10169
11301
 
10170
11302
  var ModelPreloader = /*#__PURE__*/function () {
10171
11303
  function ModelPreloader() {
@@ -10174,10 +11306,12 @@ var ModelPreloader = /*#__PURE__*/function () {
10174
11306
  this.loadingPromises = new Map(); // Track ongoing loads to prevent duplicates
10175
11307
  this.gltfLoader = new GLTFLoader();
10176
11308
  this.objLoader = new OBJLoader();
11309
+ this.objProcessor = new ObjProcessor(); // Initialize OBJ processor
10177
11310
  this.isPreloading = false;
10178
11311
  this.preloadingPromise = null;
10179
11312
  this.componentDictionary = null;
10180
11313
  console.log('🚀 ModelPreloader initialized with GLB and OBJ support');
11314
+ console.log('🔧 OBJ Processor integrated for indexed BufferGeometry conversion');
10181
11315
  }
10182
11316
 
10183
11317
  /**
@@ -10283,93 +11417,110 @@ var ModelPreloader = /*#__PURE__*/function () {
10283
11417
  }, {
10284
11418
  key: "preloadSingleModel",
10285
11419
  value: (function () {
10286
- var _preloadSingleModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(modelKey) {
11420
+ var _preloadSingleModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(modelKey) {
10287
11421
  var _this2 = this;
10288
11422
  var modelType,
10289
11423
  loadPromise,
10290
- _args2 = arguments;
10291
- return _regenerator().w(function (_context2) {
10292
- while (1) switch (_context2.n) {
11424
+ _args3 = arguments;
11425
+ return _regenerator().w(function (_context3) {
11426
+ while (1) switch (_context3.n) {
10293
11427
  case 0:
10294
- modelType = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : 'glb';
11428
+ modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : 'glb';
10295
11429
  if (!this.modelCache.has(modelKey)) {
10296
- _context2.n = 1;
11430
+ _context3.n = 1;
10297
11431
  break;
10298
11432
  }
10299
11433
  console.log("\uD83C\uDFAF Model ".concat(modelKey, " already cached, skipping"));
10300
- return _context2.a(2, this.modelCache.get(modelKey));
11434
+ return _context3.a(2, this.modelCache.get(modelKey));
10301
11435
  case 1:
10302
11436
  if (!this.loadingPromises.has(modelKey)) {
10303
- _context2.n = 2;
11437
+ _context3.n = 2;
10304
11438
  break;
10305
11439
  }
10306
11440
  console.log("\u23F3 Model ".concat(modelKey, " already loading, waiting for completion"));
10307
- return _context2.a(2, this.loadingPromises.get(modelKey));
11441
+ return _context3.a(2, this.loadingPromises.get(modelKey));
10308
11442
  case 2:
10309
11443
  console.log("\uD83D\uDD04 Starting preload of ".concat(modelType.toUpperCase(), " model: ").concat(modelKey));
10310
11444
  loadPromise = new Promise(function (resolve, reject) {
10311
11445
  var modelPath = "/library/models/".concat(modelKey);
10312
11446
  if (modelType === 'obj') {
10313
- // Load OBJ model
10314
- _this2.objLoader.load(modelPath, function (object) {
10315
- console.log("\u2705 Successfully preloaded OBJ model: ".concat(modelKey));
10316
-
10317
- // Apply double-sided materials to OBJ models with both solid and wireframe
10318
- object.traverse(function (child) {
10319
- if (child.isMesh) {
10320
- // Create a solid material first
10321
- var solidMaterial = new THREE__namespace.MeshStandardMaterial({
10322
- color: child.material.color || 0x888888,
10323
- side: THREE__namespace.DoubleSide,
10324
- wireframe: false
10325
- });
10326
-
10327
- // Set the solid material
10328
- child.material = solidMaterial;
10329
-
10330
- // Create wireframe overlay by cloning the geometry
10331
- var wireframeGeometry = child.geometry.clone();
10332
- var wireframeMaterial = new THREE__namespace.MeshBasicMaterial({
10333
- color: 0x000000,
10334
- wireframe: true,
10335
- transparent: true,
10336
- opacity: 0.8
10337
- });
10338
-
10339
- // Create wireframe mesh with same geometry
10340
- var wireframeMesh = new THREE__namespace.Mesh(wireframeGeometry, wireframeMaterial);
10341
- wireframeMesh.name = child.name + '_wireframe';
10342
-
10343
- // Position wireframe slightly forward to avoid z-fighting
10344
- wireframeMesh.position.copy(child.position);
10345
- wireframeMesh.rotation.copy(child.rotation);
10346
- wireframeMesh.scale.copy(child.scale);
10347
- wireframeMesh.scale.multiplyScalar(1.001); // Slightly larger to sit on top
10348
-
10349
- // Add wireframe as sibling to the parent
10350
- if (child.parent) {
10351
- child.parent.add(wireframeMesh);
11447
+ // Load OBJ model with advanced processing
11448
+ _this2.objLoader.load(modelPath, /*#__PURE__*/function () {
11449
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(object) {
11450
+ var processedResult, modelData, _t;
11451
+ return _regenerator().w(function (_context2) {
11452
+ while (1) switch (_context2.n) {
11453
+ case 0:
11454
+ _context2.p = 0;
11455
+ console.log("\u2705 Successfully loaded OBJ model: ".concat(modelKey));
11456
+
11457
+ // Process OBJ with the new processor for indexed BufferGeometry
11458
+ _context2.n = 1;
11459
+ return _this2.objProcessor.processObjObject(object, modelKey, true);
11460
+ case 1:
11461
+ processedResult = _context2.v;
11462
+ if (!processedResult) {
11463
+ _context2.n = 2;
11464
+ break;
11465
+ }
11466
+ console.log("\uD83D\uDD27 OBJ processed to indexed BufferGeometry: ".concat(modelKey));
11467
+ console.log("\uD83D\uDCCA Geometry stats:", processedResult.stats);
11468
+
11469
+ // Apply double-sided materials to original OBJ for compatibility
11470
+ object.traverse(function (child) {
11471
+ if (child.isMesh) {
11472
+ var solidMaterial = new THREE__namespace.MeshStandardMaterial({
11473
+ color: child.material.color || 0x888888,
11474
+ side: THREE__namespace.DoubleSide,
11475
+ wireframe: false
11476
+ });
11477
+ child.material = solidMaterial;
11478
+ }
11479
+ });
11480
+
11481
+ // Store both the original object and processed data
11482
+ modelData = {
11483
+ originalObject: object,
11484
+ processedGeometry: processedResult.geometry,
11485
+ geometryStats: processedResult.stats,
11486
+ materials: processedResult.materials,
11487
+ isObjModel: true
11488
+ }; // Cache the model data
11489
+ _this2.modelCache.set(modelKey, modelData);
11490
+ _this2.loadingPromises.delete(modelKey);
11491
+ resolve(modelData);
11492
+ _context2.n = 3;
11493
+ break;
11494
+ case 2:
11495
+ throw new Error('Failed to process OBJ to indexed geometry');
11496
+ case 3:
11497
+ _context2.n = 5;
11498
+ break;
11499
+ case 4:
11500
+ _context2.p = 4;
11501
+ _t = _context2.v;
11502
+ console.error("\u274C Error processing OBJ model ".concat(modelKey, ":"), _t);
11503
+ // Fallback: cache the original object without processing
11504
+ _this2.modelCache.set(modelKey, object);
11505
+ _this2.loadingPromises.delete(modelKey);
11506
+ resolve(object);
11507
+ case 5:
11508
+ return _context2.a(2);
10352
11509
  }
10353
- }
10354
- });
10355
-
10356
- // Cache the object for future use
10357
- _this2.modelCache.set(modelKey, object);
10358
- // Remove from loading promises
10359
- _this2.loadingPromises.delete(modelKey);
10360
- resolve(object);
10361
- }, function (progress) {
10362
- // Optional: track loading progress
11510
+ }, _callee2, null, [[0, 4]]);
11511
+ }));
11512
+ return function (_x3) {
11513
+ return _ref.apply(this, arguments);
11514
+ };
11515
+ }(), function (progress) {
10363
11516
  if (progress.lengthComputable) {
10364
11517
  var percentage = progress.loaded / progress.total * 100;
10365
11518
  if (percentage % 25 === 0) {
10366
- // Log every 25%
10367
11519
  console.log("\uD83D\uDCCA Loading OBJ ".concat(modelKey, ": ").concat(percentage.toFixed(0), "%"));
10368
11520
  }
10369
11521
  }
10370
11522
  }, function (error) {
10371
11523
  console.error("\u274C Failed to preload OBJ model ".concat(modelKey, ":"), error);
10372
- // Remove from loading promises
10373
11524
  _this2.loadingPromises.delete(modelKey);
10374
11525
  reject(error);
10375
11526
  });
@@ -10400,9 +11551,9 @@ var ModelPreloader = /*#__PURE__*/function () {
10400
11551
  }
10401
11552
  }); // Cache the loading promise
10402
11553
  this.loadingPromises.set(modelKey, loadPromise);
10403
- return _context2.a(2, loadPromise);
11554
+ return _context3.a(2, loadPromise);
10404
11555
  }
10405
- }, _callee2, this);
11556
+ }, _callee3, this);
10406
11557
  }));
10407
11558
  function preloadSingleModel(_x2) {
10408
11559
  return _preloadSingleModel.apply(this, arguments);
@@ -10412,18 +11563,42 @@ var ModelPreloader = /*#__PURE__*/function () {
10412
11563
  /**
10413
11564
  * Get a cached model (cloned for use)
10414
11565
  * @param {string} modelKey - The model key
11566
+ * @param {boolean} useIndexedGeometry - Whether to use indexed geometry for OBJ models
10415
11567
  * @returns {THREE.Object3D|null} Cloned model or null if not found
10416
11568
  */
10417
11569
  )
10418
11570
  }, {
10419
11571
  key: "getCachedModel",
10420
11572
  value: function getCachedModel(modelKey) {
11573
+ var useIndexedGeometry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
10421
11574
  if (this.modelCache.has(modelKey)) {
10422
11575
  console.log("\uD83C\uDFAF Returning cached model: ".concat(modelKey));
10423
- var clonedModel = this.modelCache.get(modelKey).clone();
11576
+ var cachedData = this.modelCache.get(modelKey);
11577
+
11578
+ // Handle OBJ models with processed geometry
11579
+ if (cachedData && cachedData.isObjModel && useIndexedGeometry && cachedData.processedGeometry) {
11580
+ console.log("\uD83D\uDD27 Using indexed BufferGeometry for OBJ: ".concat(modelKey));
11581
+
11582
+ // Create a mesh from the processed indexed geometry
11583
+ var mesh = new THREE__namespace.Mesh(cachedData.processedGeometry.clone(), cachedData.materials.clone());
10424
11584
 
10425
- // Determine model type from the modelKey extension
10426
- modelKey.toLowerCase().endsWith('.obj') ? 'obj' : 'glb';
11585
+ // Add metadata
11586
+ mesh.userData.modelKey = modelKey;
11587
+ mesh.userData.geometryStats = cachedData.geometryStats;
11588
+ mesh.userData.isIndexedGeometry = true;
11589
+ mesh.userData.originalSizeKB = cachedData.geometryStats.sizeKB;
11590
+ return mesh;
11591
+ }
11592
+
11593
+ // Handle regular models or OBJ models without indexed geometry
11594
+ var modelToClone = cachedData.isObjModel ? cachedData.originalObject : cachedData;
11595
+ var clonedModel = modelToClone.clone();
11596
+
11597
+ // Add OBJ stats if available
11598
+ if (cachedData.isObjModel && cachedData.geometryStats) {
11599
+ clonedModel.userData.geometryStats = cachedData.geometryStats;
11600
+ clonedModel.userData.isObjModel = true;
11601
+ }
10427
11602
  return clonedModel;
10428
11603
  }
10429
11604
  console.warn("\u26A0\uFE0F Model ".concat(modelKey, " not found in cache"));
@@ -10531,41 +11706,41 @@ var ModelPreloader = /*#__PURE__*/function () {
10531
11706
  }, {
10532
11707
  key: "reloadModel",
10533
11708
  value: (function () {
10534
- var _reloadModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(modelKey) {
11709
+ var _reloadModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(modelKey) {
10535
11710
  var modelType,
10536
11711
  _i,
10537
11712
  _Object$keys,
10538
11713
  componentType,
10539
11714
  component,
10540
- _args3 = arguments;
10541
- return _regenerator().w(function (_context3) {
10542
- while (1) switch (_context3.n) {
11715
+ _args4 = arguments;
11716
+ return _regenerator().w(function (_context4) {
11717
+ while (1) switch (_context4.n) {
10543
11718
  case 0:
10544
- modelType = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : null;
11719
+ modelType = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : null;
10545
11720
  console.log("\uD83D\uDD04 Force reloading model: ".concat(modelKey));
10546
11721
 
10547
11722
  // Try to determine model type from component dictionary if not provided
10548
11723
  if (!(!modelType && this.componentDictionary)) {
10549
- _context3.n = 3;
11724
+ _context4.n = 3;
10550
11725
  break;
10551
11726
  }
10552
11727
  _i = 0, _Object$keys = Object.keys(this.componentDictionary);
10553
11728
  case 1:
10554
11729
  if (!(_i < _Object$keys.length)) {
10555
- _context3.n = 3;
11730
+ _context4.n = 3;
10556
11731
  break;
10557
11732
  }
10558
11733
  componentType = _Object$keys[_i];
10559
11734
  component = this.componentDictionary[componentType];
10560
11735
  if (!(component && component.modelKey === modelKey)) {
10561
- _context3.n = 2;
11736
+ _context4.n = 2;
10562
11737
  break;
10563
11738
  }
10564
11739
  modelType = component.modelType || 'glb';
10565
- return _context3.a(3, 3);
11740
+ return _context4.a(3, 3);
10566
11741
  case 2:
10567
11742
  _i++;
10568
- _context3.n = 1;
11743
+ _context4.n = 1;
10569
11744
  break;
10570
11745
  case 3:
10571
11746
  // Default to GLB if still not determined
@@ -10576,11 +11751,11 @@ var ModelPreloader = /*#__PURE__*/function () {
10576
11751
  this.loadingPromises.delete(modelKey);
10577
11752
 
10578
11753
  // Preload again
10579
- return _context3.a(2, this.preloadSingleModel(modelKey, modelType));
11754
+ return _context4.a(2, this.preloadSingleModel(modelKey, modelType));
10580
11755
  }
10581
- }, _callee3, this);
11756
+ }, _callee4, this);
10582
11757
  }));
10583
- function reloadModel(_x3) {
11758
+ function reloadModel(_x4) {
10584
11759
  return _reloadModel.apply(this, arguments);
10585
11760
  }
10586
11761
  return reloadModel;
@@ -10597,7 +11772,42 @@ var ModelPreloader = /*#__PURE__*/function () {
10597
11772
  // Dispose of all cached models
10598
11773
  this.modelCache.forEach(function (model, modelKey) {
10599
11774
  console.log("\uD83D\uDDD1\uFE0F Disposing cached model: ".concat(modelKey));
10600
- if (model && model.traverse) {
11775
+ if (model && model.isObjModel) {
11776
+ // Handle OBJ model data structure
11777
+ if (model.originalObject && model.originalObject.traverse) {
11778
+ model.originalObject.traverse(function (child) {
11779
+ if (child.geometry) {
11780
+ child.geometry.dispose();
11781
+ }
11782
+ if (child.material) {
11783
+ if (Array.isArray(child.material)) {
11784
+ child.material.forEach(function (material) {
11785
+ return material.dispose();
11786
+ });
11787
+ } else {
11788
+ child.material.dispose();
11789
+ }
11790
+ }
11791
+ });
11792
+ }
11793
+
11794
+ // Dispose processed geometry
11795
+ if (model.processedGeometry) {
11796
+ model.processedGeometry.dispose();
11797
+ }
11798
+
11799
+ // Dispose materials
11800
+ if (model.materials) {
11801
+ if (Array.isArray(model.materials)) {
11802
+ model.materials.forEach(function (material) {
11803
+ return material.dispose();
11804
+ });
11805
+ } else {
11806
+ model.materials.dispose();
11807
+ }
11808
+ }
11809
+ } else if (model && model.traverse) {
11810
+ // Handle regular model
10601
11811
  model.traverse(function (child) {
10602
11812
  if (child.geometry) {
10603
11813
  child.geometry.dispose();
@@ -10618,6 +11828,9 @@ var ModelPreloader = /*#__PURE__*/function () {
10618
11828
  this.loadingPromises.clear();
10619
11829
  this.isPreloading = false;
10620
11830
  this.preloadingPromise = null;
11831
+
11832
+ // Clear OBJ processor caches
11833
+ this.objProcessor.clearCaches();
10621
11834
  console.log('✅ Model preloader cache cleared');
10622
11835
  }
10623
11836
 
@@ -10726,13 +11939,15 @@ var ModelPreloader = /*#__PURE__*/function () {
10726
11939
  totalModels: this.modelCache.size,
10727
11940
  loadingModels: this.loadingPromises.size,
10728
11941
  isPreloading: this.isPreloading,
10729
- memoryUsage: 0
11942
+ memoryUsage: 0,
11943
+ objProcessorStats: this.objProcessor.getStatus()
10730
11944
  };
10731
11945
 
10732
11946
  // Estimate memory usage (rough calculation)
10733
11947
  this.modelCache.forEach(function (model) {
10734
11948
  if (model && model.traverse) {
10735
- model.traverse(function (child) {
11949
+ var modelToAnalyze = model.isObjModel ? model.originalObject : model;
11950
+ modelToAnalyze.traverse(function (child) {
10736
11951
  if (child.geometry) {
10737
11952
  var _child$geometry$attri;
10738
11953
  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
@@ -10742,6 +11957,82 @@ var ModelPreloader = /*#__PURE__*/function () {
10742
11957
  });
10743
11958
  return stats;
10744
11959
  }
11960
+
11961
+ /**
11962
+ * Get all OBJ geometry statistics
11963
+ * @returns {Array} Array of OBJ geometry statistics
11964
+ */
11965
+ }, {
11966
+ key: "getObjGeometryStats",
11967
+ value: function getObjGeometryStats() {
11968
+ return this.objProcessor.getAllGeometryStats();
11969
+ }
11970
+
11971
+ /**
11972
+ * Get OBJ processor memory usage
11973
+ * @returns {Object} Memory usage statistics
11974
+ */
11975
+ }, {
11976
+ key: "getObjMemoryUsage",
11977
+ value: function getObjMemoryUsage() {
11978
+ return this.objProcessor.getMemoryUsage();
11979
+ }
11980
+
11981
+ /**
11982
+ * Create a custom mesh from indexed OBJ geometry
11983
+ * @param {string} modelKey - The model key (must be an OBJ)
11984
+ * @param {THREE.Material} material - Optional material to use
11985
+ * @returns {THREE.Mesh|null} The created mesh or null if not found
11986
+ */
11987
+ }, {
11988
+ key: "createCustomObjMesh",
11989
+ value: function createCustomObjMesh(modelKey) {
11990
+ var material = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
11991
+ return this.objProcessor.createCustomMesh(modelKey, material);
11992
+ }
11993
+
11994
+ /**
11995
+ * Get indexed geometry directly from processor
11996
+ * @param {string} modelKey - The model key
11997
+ * @returns {THREE.BufferGeometry|null} The indexed geometry or null
11998
+ */
11999
+ }, {
12000
+ key: "getIndexedGeometry",
12001
+ value: function getIndexedGeometry(modelKey) {
12002
+ var result = this.objProcessor.indexedGeometryCache.get(modelKey);
12003
+ return result ? result.geometry.clone() : null;
12004
+ }
12005
+
12006
+ /**
12007
+ * Force reload and reprocess an OBJ model
12008
+ * @param {string} modelKey - The model key to reload
12009
+ * @returns {Promise} Promise that resolves with the reloaded model
12010
+ */
12011
+ }, {
12012
+ key: "reloadObjModel",
12013
+ value: (function () {
12014
+ var _reloadObjModel = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(modelKey) {
12015
+ return _regenerator().w(function (_context5) {
12016
+ while (1) switch (_context5.n) {
12017
+ case 0:
12018
+ console.log("\uD83D\uDD04 Force reloading OBJ model: ".concat(modelKey));
12019
+
12020
+ // Clear from both caches
12021
+ this.modelCache.delete(modelKey);
12022
+ this.loadingPromises.delete(modelKey);
12023
+ this.objProcessor.indexedGeometryCache.delete(modelKey);
12024
+ this.objProcessor.geometrySizeCache.delete(modelKey);
12025
+
12026
+ // Reload with OBJ processing
12027
+ return _context5.a(2, this.preloadSingleModel(modelKey, 'obj'));
12028
+ }
12029
+ }, _callee5, this);
12030
+ }));
12031
+ function reloadObjModel(_x5) {
12032
+ return _reloadObjModel.apply(this, arguments);
12033
+ }
12034
+ return reloadObjModel;
12035
+ }())
10745
12036
  }]);
10746
12037
  }(); // Create singleton instance
10747
12038
  var modelPreloader = new ModelPreloader();
@@ -35283,6 +36574,250 @@ var testing = /*#__PURE__*/Object.freeze({
35283
36574
  Testing: Testing
35284
36575
  });
35285
36576
 
36577
+ var ObjProcessingDemo = /*#__PURE__*/function () {
36578
+ function ObjProcessingDemo() {
36579
+ _classCallCheck(this, ObjProcessingDemo);
36580
+ this.objProcessor = new ObjProcessor();
36581
+ this.componentDictionary = null;
36582
+ this.processedResults = new Map();
36583
+ }
36584
+
36585
+ /**
36586
+ * Load component dictionary
36587
+ * @returns {Promise<Object>} Component dictionary
36588
+ */
36589
+ return _createClass(ObjProcessingDemo, [{
36590
+ key: "loadComponentDictionary",
36591
+ value: (function () {
36592
+ var _loadComponentDictionary = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
36593
+ var response, _t;
36594
+ return _regenerator().w(function (_context) {
36595
+ while (1) switch (_context.n) {
36596
+ case 0:
36597
+ _context.p = 0;
36598
+ _context.n = 1;
36599
+ return fetch('/library/component-dictionary.json');
36600
+ case 1:
36601
+ response = _context.v;
36602
+ _context.n = 2;
36603
+ return response.json();
36604
+ case 2:
36605
+ this.componentDictionary = _context.v;
36606
+ return _context.a(2, this.componentDictionary);
36607
+ case 3:
36608
+ _context.p = 3;
36609
+ _t = _context.v;
36610
+ throw _t;
36611
+ case 4:
36612
+ return _context.a(2);
36613
+ }
36614
+ }, _callee, this, [[0, 3]]);
36615
+ }));
36616
+ function loadComponentDictionary() {
36617
+ return _loadComponentDictionary.apply(this, arguments);
36618
+ }
36619
+ return loadComponentDictionary;
36620
+ }()
36621
+ /**
36622
+ * Get all OBJ models from component dictionary
36623
+ * @returns {Array} Array of OBJ model configurations
36624
+ */
36625
+ )
36626
+ }, {
36627
+ key: "getObjModels",
36628
+ value: function getObjModels() {
36629
+ var _this = this;
36630
+ if (!this.componentDictionary) {
36631
+ return [];
36632
+ }
36633
+ var objModels = [];
36634
+ Object.keys(this.componentDictionary).forEach(function (componentId) {
36635
+ var component = _this.componentDictionary[componentId];
36636
+ if (component.modelType === 'obj') {
36637
+ objModels.push({
36638
+ componentId: componentId,
36639
+ modelKey: component.modelKey,
36640
+ name: component.name,
36641
+ boundingBox: component.boundingBox
36642
+ });
36643
+ }
36644
+ });
36645
+ return objModels;
36646
+ }
36647
+
36648
+ /**
36649
+ * Process all OBJ models and store in IndexedDB
36650
+ * @returns {Promise<Array>} Array of processing results
36651
+ */
36652
+ }, {
36653
+ key: "processAllObjModels",
36654
+ value: (function () {
36655
+ var _processAllObjModels = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
36656
+ var objModels, processingResults, _iterator, _step, objModel, cachedModelData, result, serializedData, _t3;
36657
+ return _regenerator().w(function (_context2) {
36658
+ while (1) switch (_context2.n) {
36659
+ case 0:
36660
+ if (this.componentDictionary) {
36661
+ _context2.n = 1;
36662
+ break;
36663
+ }
36664
+ _context2.n = 1;
36665
+ return this.loadComponentDictionary();
36666
+ case 1:
36667
+ // Get all OBJ models
36668
+ objModels = this.getObjModels();
36669
+ if (!(objModels.length === 0)) {
36670
+ _context2.n = 2;
36671
+ break;
36672
+ }
36673
+ return _context2.a(2, []);
36674
+ case 2:
36675
+ _context2.n = 3;
36676
+ return modelPreloader.preloadAllModels(this.componentDictionary);
36677
+ case 3:
36678
+ if (!this.objProcessor.idbSupported) {
36679
+ _context2.n = 4;
36680
+ break;
36681
+ }
36682
+ _context2.n = 4;
36683
+ return this.objProcessor.initializeIDB();
36684
+ case 4:
36685
+ processingResults = []; // Process each OBJ model
36686
+ _iterator = _createForOfIteratorHelper(objModels);
36687
+ _context2.p = 5;
36688
+ _iterator.s();
36689
+ case 6:
36690
+ if ((_step = _iterator.n()).done) {
36691
+ _context2.n = 12;
36692
+ break;
36693
+ }
36694
+ objModel = _step.value;
36695
+ _context2.p = 7;
36696
+ // Get the cached model from preloader
36697
+ cachedModelData = modelPreloader.modelCache.get(objModel.modelKey);
36698
+ if (!(!cachedModelData || !cachedModelData.isObjModel)) {
36699
+ _context2.n = 8;
36700
+ break;
36701
+ }
36702
+ return _context2.a(3, 11);
36703
+ case 8:
36704
+ // Extract processing results
36705
+ result = {
36706
+ componentId: objModel.componentId,
36707
+ modelKey: objModel.modelKey,
36708
+ name: objModel.name,
36709
+ boundingBox: objModel.boundingBox,
36710
+ stats: cachedModelData.geometryStats,
36711
+ originalObject: cachedModelData.originalObject,
36712
+ processedGeometry: cachedModelData.processedGeometry,
36713
+ materials: cachedModelData.materials
36714
+ };
36715
+ processingResults.push(result);
36716
+ this.processedResults.set(objModel.modelKey, result);
36717
+
36718
+ // Store in IndexedDB if supported
36719
+ if (!(this.objProcessor.idbSupported && result.processedGeometry)) {
36720
+ _context2.n = 9;
36721
+ break;
36722
+ }
36723
+ serializedData = this.objProcessor.serializeGeometry(result.processedGeometry);
36724
+ _context2.n = 9;
36725
+ return this.objProcessor.storeGeometryInIDB(objModel.modelKey, serializedData);
36726
+ case 9:
36727
+ _context2.n = 11;
36728
+ break;
36729
+ case 10:
36730
+ _context2.p = 10;
36731
+ _context2.v;
36732
+ return _context2.a(3, 11);
36733
+ case 11:
36734
+ _context2.n = 6;
36735
+ break;
36736
+ case 12:
36737
+ _context2.n = 14;
36738
+ break;
36739
+ case 13:
36740
+ _context2.p = 13;
36741
+ _t3 = _context2.v;
36742
+ _iterator.e(_t3);
36743
+ case 14:
36744
+ _context2.p = 14;
36745
+ _iterator.f();
36746
+ return _context2.f(14);
36747
+ case 15:
36748
+ return _context2.a(2, processingResults);
36749
+ }
36750
+ }, _callee2, this, [[7, 10], [5, 13, 14, 15]]);
36751
+ }));
36752
+ function processAllObjModels() {
36753
+ return _processAllObjModels.apply(this, arguments);
36754
+ }
36755
+ return processAllObjModels;
36756
+ }()
36757
+ /**
36758
+ * Run the simplified demo - process and store in IndexedDB
36759
+ * @returns {Promise<Object>} Demo results
36760
+ */
36761
+ )
36762
+ }, {
36763
+ key: "run",
36764
+ value: (function () {
36765
+ var _run = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
36766
+ var processingResults, _t4;
36767
+ return _regenerator().w(function (_context3) {
36768
+ while (1) switch (_context3.n) {
36769
+ case 0:
36770
+ _context3.p = 0;
36771
+ _context3.n = 1;
36772
+ return this.processAllObjModels();
36773
+ case 1:
36774
+ processingResults = _context3.v;
36775
+ return _context3.a(2, {
36776
+ processingResults: processingResults,
36777
+ totalModelsProcessed: processingResults.length,
36778
+ success: true
36779
+ });
36780
+ case 2:
36781
+ _context3.p = 2;
36782
+ _t4 = _context3.v;
36783
+ return _context3.a(2, {
36784
+ processingResults: [],
36785
+ totalModelsProcessed: 0,
36786
+ success: false,
36787
+ error: _t4.message
36788
+ });
36789
+ }
36790
+ }, _callee3, this, [[0, 2]]);
36791
+ }));
36792
+ function run() {
36793
+ return _run.apply(this, arguments);
36794
+ }
36795
+ return run;
36796
+ }()
36797
+ /**
36798
+ * Get processing results for external use
36799
+ * @returns {Map} Map of processing results
36800
+ */
36801
+ )
36802
+ }, {
36803
+ key: "getResults",
36804
+ value: function getResults() {
36805
+ return this.processedResults;
36806
+ }
36807
+
36808
+ /**
36809
+ * Get geometry by model key
36810
+ * @param {string} modelKey - The model key
36811
+ * @returns {Object|null} Processing result or null
36812
+ */
36813
+ }, {
36814
+ key: "getGeometry",
36815
+ value: function getGeometry(modelKey) {
36816
+ return this.processedResults.get(modelKey) || null;
36817
+ }
36818
+ }]);
36819
+ }(); // Export for use
36820
+
35286
36821
  exports.Analysis = analysis;
35287
36822
  exports.AnimationManager = AnimationManager;
35288
36823
  exports.CameraControlsManager = CameraControlsManager;
@@ -35298,6 +36833,8 @@ exports.ImportUtils = _import;
35298
36833
  exports.KeyboardControlsManager = KeyboardControlsManager;
35299
36834
  exports.MathUtils = MathUtils;
35300
36835
  exports.Numerics = numerics;
36836
+ exports.ObjProcessingDemo = ObjProcessingDemo;
36837
+ exports.ObjProcessor = ObjProcessor;
35301
36838
  exports.PathfindingManager = PathfindingManager;
35302
36839
  exports.PerformanceMonitor = PerformanceMonitor;
35303
36840
  exports.Rendering2D = rendering2D;