@inweb/viewer-three 27.2.0 → 27.2.1

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.
@@ -2499,7 +2499,7 @@ class CameraComponent {
2499
2499
  camera = object;
2500
2500
  });
2501
2501
  if (camera) {
2502
- camera.isDefaultCamera = true;
2502
+ camera.userData.isDefaultCamera = true;
2503
2503
  camera.scale.set(1, 1, 1);
2504
2504
  this.switchCamera(camera);
2505
2505
  const mode = this.getCameraMode(camera);
@@ -2703,6 +2703,7 @@ class InfoComponent {
2703
2703
  this.viewer.info.optimizedScene.edges = 0;
2704
2704
  this.viewer.info.memory.geometries = 0;
2705
2705
  this.viewer.info.memory.geometryBytes = 0;
2706
+ this.viewer.info.memory.optimizedGeometryBytes = 0;
2706
2707
  this.viewer.info.memory.textures = 0;
2707
2708
  this.viewer.info.memory.textureBytes = 0;
2708
2709
  this.viewer.info.memory.materials = 0;
@@ -2739,6 +2740,7 @@ class InfoComponent {
2739
2740
  this.viewer.info.optimizedScene.edges += info.optimizedScene.edges;
2740
2741
  this.viewer.info.memory.geometries += info.memory.geometries;
2741
2742
  this.viewer.info.memory.geometryBytes += info.memory.geometryBytes;
2743
+ this.viewer.info.memory.optimizedGeometryBytes += info.memory.optimizedGeometryBytes;
2742
2744
  this.viewer.info.memory.textures += info.memory.textures;
2743
2745
  this.viewer.info.memory.textureBytes += info.memory.textureBytes;
2744
2746
  this.viewer.info.memory.materials += info.memory.materials;
@@ -2749,7 +2751,9 @@ class InfoComponent {
2749
2751
  this.viewer.info.performance.loadTime += performance.now() - this.startTime;
2750
2752
  console.log("Number of objects:", info.scene.objects);
2751
2753
  console.log("Number of objects after optimization:", info.optimizedScene.objects);
2752
- console.log("Total geometry size:", info.memory.totalEstimatedGpuBytes / (1024 * 1024), "MB");
2754
+ console.log("Geometry size:", info.memory.geometryBytes / (1024 * 1024), "MB");
2755
+ console.log("Optimized geometry size:", info.memory.optimizedGeometryBytes / (1024 * 1024), "MB");
2756
+ console.log("Estimated GPU used:", info.memory.totalEstimatedGpuBytes / (1024 * 1024), "MB");
2753
2757
  console.log("File load time:", this.viewer.info.performance.loadTime, "ms");
2754
2758
  };
2755
2759
  this.resize = () => {
@@ -3492,6 +3496,7 @@ class ModelImpl {
3492
3496
  info.scene.edges = Math.floor(totalEdges);
3493
3497
  info.memory.geometries = geometries.size;
3494
3498
  info.memory.geometryBytes = geometryBytes;
3499
+ info.memory.optimizedGeometryBytes = 0;
3495
3500
  info.memory.textures = textures.size;
3496
3501
  info.memory.textureBytes = Math.floor(textureBytes);
3497
3502
  info.memory.materials = materials.size;
@@ -3664,6 +3669,7 @@ class DynamicModelImpl extends ModelImpl {
3664
3669
  info.optimizedScene.edges = stats.scene.afterOptimization.edges;
3665
3670
  info.memory.geometries = stats.memory.geometries.count;
3666
3671
  info.memory.geometryBytes = stats.memory.geometries.bytes;
3672
+ info.memory.optimizedGeometryBytes = stats.memory.geometries.optimizedBytes;
3667
3673
  info.memory.textures = stats.memory.textures.count;
3668
3674
  info.memory.materials = stats.memory.materials.count;
3669
3675
  info.memory.totalEstimatedGpuBytes = stats.memory.totalEstimatedGpuBytes;
@@ -4335,11 +4341,14 @@ class DynamicGltfLoader {
4335
4341
  this.structures = [];
4336
4342
  this.structureRoots = new Map();
4337
4343
  this.memoryLimit = this.getAvailableMemory();
4344
+ this.optimizationMemoryMultiplier = 5;
4345
+ this.memoryEstimationFactor = 1.7;
4338
4346
  this.loadedGeometrySize = 0;
4339
4347
  this.geometryCache = new Map();
4340
4348
  this.materialCache = new Map();
4341
4349
  this.textureCache = new Map();
4342
4350
  this.currentMemoryUsage = 0;
4351
+ this.pendingMemoryUsage = 0;
4343
4352
  this.updateMemoryIndicator();
4344
4353
  this.loadedMaterials = new Map();
4345
4354
  this.abortController = new AbortController();
@@ -4395,7 +4404,7 @@ class DynamicGltfLoader {
4395
4404
  } catch (error) {
4396
4405
  console.warn("Error detecting available memory:", error);
4397
4406
  }
4398
- return memoryLimit / 3;
4407
+ return memoryLimit;
4399
4408
  }
4400
4409
  getAbortController() {
4401
4410
  return this.abortController;
@@ -4403,9 +4412,26 @@ class DynamicGltfLoader {
4403
4412
  abortLoading() {
4404
4413
  this.abortController.abort();
4405
4414
  }
4415
+ getOptimizedGeometrySize() {
4416
+ let total = 0;
4417
+ const addSize = (obj) => {
4418
+ if (obj && obj.geometry) total += this.estimateGeometrySize(obj);
4419
+ };
4420
+ this.mergedMesh?.forEach(addSize);
4421
+ this.mergedLines?.forEach(addSize);
4422
+ this.mergedLineSegments?.forEach(addSize);
4423
+ this.mergedPoints?.forEach(addSize);
4424
+ return total;
4425
+ }
4406
4426
  updateMemoryIndicator() {
4427
+ const optimizedUsage = this.getOptimizedGeometrySize();
4428
+ const totalUsage = this.currentMemoryUsage + optimizedUsage;
4429
+ const totalUsageEstimate = Math.round(totalUsage * this.memoryEstimationFactor);
4407
4430
  this.dispatchEvent("geometrymemory", {
4408
4431
  currentUsage: this.currentMemoryUsage,
4432
+ optimizedUsage,
4433
+ totalUsage,
4434
+ totalUsageEstimate,
4409
4435
  limit: this.memoryLimit,
4410
4436
  });
4411
4437
  }
@@ -4457,10 +4483,13 @@ class DynamicGltfLoader {
4457
4483
  for (const geo of geometries) {
4458
4484
  currentMemoryUsage += geo.size;
4459
4485
  }
4460
- if (currentMemoryUsage > this.memoryLimit) {
4461
- console.log(`Memory usage (${Math.round(currentMemoryUsage / (1024 * 1024))}MB) exceeds limit`);
4486
+ const effectiveLimitForEviction = this.memoryLimit / this.memoryEstimationFactor;
4487
+ if (currentMemoryUsage > effectiveLimitForEviction) {
4488
+ console.log(
4489
+ `Memory usage (${Math.round((currentMemoryUsage * this.memoryEstimationFactor) / (1024 * 1024))}MB est.) exceeds limit`
4490
+ );
4462
4491
  for (const geo of geometries) {
4463
- if (currentMemoryUsage <= this.memoryLimit) break;
4492
+ if (currentMemoryUsage <= effectiveLimitForEviction) break;
4464
4493
  if (this.abortController.signal.aborted) {
4465
4494
  throw new DOMException("Loading aborted", "AbortError");
4466
4495
  }
@@ -4544,7 +4573,9 @@ class DynamicGltfLoader {
4544
4573
  }
4545
4574
  const materialCount = uniqueMaterialIds.size;
4546
4575
  const textureCount = uniqueTextureIds.size;
4547
- const estimatedGpuMemoryBytes = geometryMemoryBytes;
4576
+ const optimizedUsageBytes = this.getOptimizedGeometrySize();
4577
+ const totalUsageBytes = geometryMemoryBytes + optimizedUsageBytes;
4578
+ const estimatedGpuMemoryBytes = Math.round(totalUsageBytes * this.memoryEstimationFactor);
4548
4579
  if (!this._webglInfoCache) {
4549
4580
  try {
4550
4581
  const gl = this.renderer.getContext();
@@ -4581,7 +4612,12 @@ class DynamicGltfLoader {
4581
4612
  },
4582
4613
  },
4583
4614
  memory: {
4584
- geometries: { count: geometryCount, bytes: geometryMemoryBytes },
4615
+ geometries: {
4616
+ count: geometryCount,
4617
+ bytes: geometryMemoryBytes,
4618
+ optimizedBytes: optimizedUsageBytes,
4619
+ totalRawBytes: totalUsageBytes,
4620
+ },
4585
4621
  textures: { count: textureCount },
4586
4622
  materials: { count: materialCount },
4587
4623
  totalEstimatedGpuBytes: estimatedGpuMemoryBytes,
@@ -4593,9 +4629,12 @@ class DynamicGltfLoader {
4593
4629
  },
4594
4630
  };
4595
4631
  }
4596
- async loadNode(nodeId, onLoadFinishCb) {
4632
+ async loadNode(nodeId, onLoadFinishCb, reservedEstimatedSize = 0) {
4597
4633
  const node = this.nodes.get(nodeId);
4598
- if (!node || node.loaded || node.loading) return;
4634
+ if (!node || node.loaded || node.loading) {
4635
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
4636
+ return;
4637
+ }
4599
4638
  node.loading = true;
4600
4639
  const meshDef = node.structure.getJson().meshes[node.meshIndex];
4601
4640
  try {
@@ -4678,6 +4717,7 @@ class DynamicGltfLoader {
4678
4717
  if (bufferRequests.length === 0) {
4679
4718
  node.loaded = true;
4680
4719
  node.loading = false;
4720
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
4681
4721
  return;
4682
4722
  }
4683
4723
  bufferRequests.sort((a, b) => a.offset - b.offset);
@@ -4789,6 +4829,7 @@ class DynamicGltfLoader {
4789
4829
  }
4790
4830
  node.loaded = true;
4791
4831
  node.loading = false;
4832
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
4792
4833
  const geometrySize = this.estimateGeometrySize(node.object);
4793
4834
  this.geometryCache.set(node.object.uuid, geometrySize);
4794
4835
  this.currentMemoryUsage += geometrySize;
@@ -4797,6 +4838,7 @@ class DynamicGltfLoader {
4797
4838
  }
4798
4839
  } catch (error) {
4799
4840
  node.loading = false;
4841
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
4800
4842
  if (error.name === "AbortError") {
4801
4843
  return;
4802
4844
  }
@@ -5012,15 +5054,18 @@ class DynamicGltfLoader {
5012
5054
  let loadedCount = 0;
5013
5055
  let lastLoadedCount = 0;
5014
5056
  const totalNodes = nodesToLoad.length;
5057
+ const progressTotal = { value: totalNodes };
5015
5058
  const loadProgress = async () => {
5016
5059
  loadedCount++;
5060
+ const total = progressTotal.value;
5061
+ const percentage = total > 0 ? Math.min(100, Math.round((loadedCount / total) * 100)) : 0;
5017
5062
  if (loadedCount - lastLoadedCount > 1000) {
5018
5063
  lastLoadedCount = loadedCount;
5019
5064
  this.updateMemoryIndicator();
5020
5065
  this.dispatchEvent("geometryprogress", {
5021
- percentage: Math.round((loadedCount / totalNodes) * 100),
5066
+ percentage,
5022
5067
  loaded: loadedCount,
5023
- total: totalNodes,
5068
+ total,
5024
5069
  });
5025
5070
  this.dispatchEvent("update");
5026
5071
  await new Promise((resolve) => {
@@ -5030,20 +5075,22 @@ class DynamicGltfLoader {
5030
5075
  };
5031
5076
  try {
5032
5077
  const loadOperations = [];
5078
+ let memoryLimitReached = false;
5033
5079
  for (const nodeId of nodesToLoad) {
5034
5080
  if (this.abortController.signal.aborted) {
5035
5081
  throw new DOMException("Loading aborted", "AbortError");
5036
5082
  }
5037
5083
  const estimatedSize = await this.estimateNodeSize(nodeId);
5038
- if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
5039
- console.log(`Memory limit reached after loading ${loadedCount} nodes`);
5040
- this.dispatchEvent("geometryerror", {
5041
- message: "Memory limit reached",
5042
- });
5043
- this.dispatchEvent("update");
5044
- return loadedCount;
5084
+ const estimated = Number(estimatedSize) || 0;
5085
+ const effectiveLimit = this.memoryLimit / this.optimizationMemoryMultiplier / this.memoryEstimationFactor;
5086
+ if (this.currentMemoryUsage + this.pendingMemoryUsage + estimated > effectiveLimit) {
5087
+ memoryLimitReached = true;
5088
+ progressTotal.value = loadOperations.length;
5089
+ console.log(`Memory limit reached after scheduling ${loadOperations.length} nodes`);
5090
+ break;
5045
5091
  }
5046
- loadOperations.push(this.loadNode(nodeId, loadProgress));
5092
+ this.pendingMemoryUsage += estimated;
5093
+ loadOperations.push(this.loadNode(nodeId, loadProgress, estimated));
5047
5094
  }
5048
5095
  for (const structure of this.structures) {
5049
5096
  loadOperations.push(structure.flushBufferRequests());
@@ -5051,7 +5098,8 @@ class DynamicGltfLoader {
5051
5098
  await Promise.all(loadOperations);
5052
5099
  this.dispatchEvent("geometryend", {
5053
5100
  totalLoaded: loadedCount,
5054
- totalNodes,
5101
+ totalNodes: progressTotal.value,
5102
+ memoryLimitReached,
5055
5103
  });
5056
5104
  return loadedCount;
5057
5105
  } catch (error) {
@@ -5361,6 +5409,7 @@ class DynamicGltfLoader {
5361
5409
  this.transformedGeometries.clear();
5362
5410
  this.totalLoadedObjects = 0;
5363
5411
  this.currentMemoryUsage = 0;
5412
+ this.pendingMemoryUsage = 0;
5364
5413
  this.loadedGeometrySize = 0;
5365
5414
  this.abortController = new AbortController();
5366
5415
  this.updateMemoryIndicator();
@@ -5567,6 +5616,7 @@ class DynamicGltfLoader {
5567
5616
  progress: 100,
5568
5617
  message: `Optimization complete! ${this.maxObjectId} objects processed.`,
5569
5618
  });
5619
+ this.updateMemoryIndicator();
5570
5620
  this.dispatchEvent("update");
5571
5621
  }
5572
5622
  async mergeMeshGroups(materialGroups, rootGroup) {