@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.
@@ -572,6 +572,7 @@
572
572
  this.memory = {
573
573
  geometries: 0,
574
574
  geometryBytes: 0,
575
+ optimizedGeometryBytes: 0,
575
576
  textures: 0,
576
577
  textureBytes: 0,
577
578
  materials: 0,
@@ -36101,7 +36102,7 @@ void main() {
36101
36102
  camera = object;
36102
36103
  });
36103
36104
  if (camera) {
36104
- camera.isDefaultCamera = true;
36105
+ camera.userData.isDefaultCamera = true;
36105
36106
  camera.scale.set(1, 1, 1);
36106
36107
  this.switchCamera(camera);
36107
36108
  const mode = this.getCameraMode(camera);
@@ -36305,6 +36306,7 @@ void main() {
36305
36306
  this.viewer.info.optimizedScene.edges = 0;
36306
36307
  this.viewer.info.memory.geometries = 0;
36307
36308
  this.viewer.info.memory.geometryBytes = 0;
36309
+ this.viewer.info.memory.optimizedGeometryBytes = 0;
36308
36310
  this.viewer.info.memory.textures = 0;
36309
36311
  this.viewer.info.memory.textureBytes = 0;
36310
36312
  this.viewer.info.memory.materials = 0;
@@ -36341,6 +36343,7 @@ void main() {
36341
36343
  this.viewer.info.optimizedScene.edges += info.optimizedScene.edges;
36342
36344
  this.viewer.info.memory.geometries += info.memory.geometries;
36343
36345
  this.viewer.info.memory.geometryBytes += info.memory.geometryBytes;
36346
+ this.viewer.info.memory.optimizedGeometryBytes += info.memory.optimizedGeometryBytes;
36344
36347
  this.viewer.info.memory.textures += info.memory.textures;
36345
36348
  this.viewer.info.memory.textureBytes += info.memory.textureBytes;
36346
36349
  this.viewer.info.memory.materials += info.memory.materials;
@@ -36351,7 +36354,9 @@ void main() {
36351
36354
  this.viewer.info.performance.loadTime += performance.now() - this.startTime;
36352
36355
  console.log("Number of objects:", info.scene.objects);
36353
36356
  console.log("Number of objects after optimization:", info.optimizedScene.objects);
36354
- console.log("Total geometry size:", info.memory.totalEstimatedGpuBytes / (1024 * 1024), "MB");
36357
+ console.log("Geometry size:", info.memory.geometryBytes / (1024 * 1024), "MB");
36358
+ console.log("Optimized geometry size:", info.memory.optimizedGeometryBytes / (1024 * 1024), "MB");
36359
+ console.log("Estimated GPU used:", info.memory.totalEstimatedGpuBytes / (1024 * 1024), "MB");
36355
36360
  console.log("File load time:", this.viewer.info.performance.loadTime, "ms");
36356
36361
  };
36357
36362
  this.resize = () => {
@@ -37733,6 +37738,7 @@ void main() {
37733
37738
  info.scene.edges = Math.floor(totalEdges);
37734
37739
  info.memory.geometries = geometries.size;
37735
37740
  info.memory.geometryBytes = geometryBytes;
37741
+ info.memory.optimizedGeometryBytes = 0;
37736
37742
  info.memory.textures = textures.size;
37737
37743
  info.memory.textureBytes = Math.floor(textureBytes);
37738
37744
  info.memory.materials = materials.size;
@@ -37905,6 +37911,7 @@ void main() {
37905
37911
  info.optimizedScene.edges = stats.scene.afterOptimization.edges;
37906
37912
  info.memory.geometries = stats.memory.geometries.count;
37907
37913
  info.memory.geometryBytes = stats.memory.geometries.bytes;
37914
+ info.memory.optimizedGeometryBytes = stats.memory.geometries.optimizedBytes;
37908
37915
  info.memory.textures = stats.memory.textures.count;
37909
37916
  info.memory.materials = stats.memory.materials.count;
37910
37917
  info.memory.totalEstimatedGpuBytes = stats.memory.totalEstimatedGpuBytes;
@@ -38725,11 +38732,14 @@ void main() {
38725
38732
  this.structures = [];
38726
38733
  this.structureRoots = new Map();
38727
38734
  this.memoryLimit = this.getAvailableMemory();
38735
+ this.optimizationMemoryMultiplier = 5;
38736
+ this.memoryEstimationFactor = 1.7;
38728
38737
  this.loadedGeometrySize = 0;
38729
38738
  this.geometryCache = new Map();
38730
38739
  this.materialCache = new Map();
38731
38740
  this.textureCache = new Map();
38732
38741
  this.currentMemoryUsage = 0;
38742
+ this.pendingMemoryUsage = 0;
38733
38743
  this.updateMemoryIndicator();
38734
38744
  this.loadedMaterials = new Map();
38735
38745
  this.abortController = new AbortController();
@@ -38785,7 +38795,7 @@ void main() {
38785
38795
  } catch (error) {
38786
38796
  console.warn("Error detecting available memory:", error);
38787
38797
  }
38788
- return memoryLimit / 3;
38798
+ return memoryLimit;
38789
38799
  }
38790
38800
  getAbortController() {
38791
38801
  return this.abortController;
@@ -38793,9 +38803,26 @@ void main() {
38793
38803
  abortLoading() {
38794
38804
  this.abortController.abort();
38795
38805
  }
38806
+ getOptimizedGeometrySize() {
38807
+ let total = 0;
38808
+ const addSize = (obj) => {
38809
+ if (obj && obj.geometry) total += this.estimateGeometrySize(obj);
38810
+ };
38811
+ this.mergedMesh?.forEach(addSize);
38812
+ this.mergedLines?.forEach(addSize);
38813
+ this.mergedLineSegments?.forEach(addSize);
38814
+ this.mergedPoints?.forEach(addSize);
38815
+ return total;
38816
+ }
38796
38817
  updateMemoryIndicator() {
38818
+ const optimizedUsage = this.getOptimizedGeometrySize();
38819
+ const totalUsage = this.currentMemoryUsage + optimizedUsage;
38820
+ const totalUsageEstimate = Math.round(totalUsage * this.memoryEstimationFactor);
38797
38821
  this.dispatchEvent("geometrymemory", {
38798
38822
  currentUsage: this.currentMemoryUsage,
38823
+ optimizedUsage,
38824
+ totalUsage,
38825
+ totalUsageEstimate,
38799
38826
  limit: this.memoryLimit,
38800
38827
  });
38801
38828
  }
@@ -38847,10 +38874,13 @@ void main() {
38847
38874
  for (const geo of geometries) {
38848
38875
  currentMemoryUsage += geo.size;
38849
38876
  }
38850
- if (currentMemoryUsage > this.memoryLimit) {
38851
- console.log(`Memory usage (${Math.round(currentMemoryUsage / (1024 * 1024))}MB) exceeds limit`);
38877
+ const effectiveLimitForEviction = this.memoryLimit / this.memoryEstimationFactor;
38878
+ if (currentMemoryUsage > effectiveLimitForEviction) {
38879
+ console.log(
38880
+ `Memory usage (${Math.round((currentMemoryUsage * this.memoryEstimationFactor) / (1024 * 1024))}MB est.) exceeds limit`
38881
+ );
38852
38882
  for (const geo of geometries) {
38853
- if (currentMemoryUsage <= this.memoryLimit) break;
38883
+ if (currentMemoryUsage <= effectiveLimitForEviction) break;
38854
38884
  if (this.abortController.signal.aborted) {
38855
38885
  throw new DOMException("Loading aborted", "AbortError");
38856
38886
  }
@@ -38934,7 +38964,9 @@ void main() {
38934
38964
  }
38935
38965
  const materialCount = uniqueMaterialIds.size;
38936
38966
  const textureCount = uniqueTextureIds.size;
38937
- const estimatedGpuMemoryBytes = geometryMemoryBytes;
38967
+ const optimizedUsageBytes = this.getOptimizedGeometrySize();
38968
+ const totalUsageBytes = geometryMemoryBytes + optimizedUsageBytes;
38969
+ const estimatedGpuMemoryBytes = Math.round(totalUsageBytes * this.memoryEstimationFactor);
38938
38970
  if (!this._webglInfoCache) {
38939
38971
  try {
38940
38972
  const gl = this.renderer.getContext();
@@ -38971,7 +39003,12 @@ void main() {
38971
39003
  },
38972
39004
  },
38973
39005
  memory: {
38974
- geometries: { count: geometryCount, bytes: geometryMemoryBytes },
39006
+ geometries: {
39007
+ count: geometryCount,
39008
+ bytes: geometryMemoryBytes,
39009
+ optimizedBytes: optimizedUsageBytes,
39010
+ totalRawBytes: totalUsageBytes,
39011
+ },
38975
39012
  textures: { count: textureCount },
38976
39013
  materials: { count: materialCount },
38977
39014
  totalEstimatedGpuBytes: estimatedGpuMemoryBytes,
@@ -38983,9 +39020,12 @@ void main() {
38983
39020
  },
38984
39021
  };
38985
39022
  }
38986
- async loadNode(nodeId, onLoadFinishCb) {
39023
+ async loadNode(nodeId, onLoadFinishCb, reservedEstimatedSize = 0) {
38987
39024
  const node = this.nodes.get(nodeId);
38988
- if (!node || node.loaded || node.loading) return;
39025
+ if (!node || node.loaded || node.loading) {
39026
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
39027
+ return;
39028
+ }
38989
39029
  node.loading = true;
38990
39030
  const meshDef = node.structure.getJson().meshes[node.meshIndex];
38991
39031
  try {
@@ -39068,6 +39108,7 @@ void main() {
39068
39108
  if (bufferRequests.length === 0) {
39069
39109
  node.loaded = true;
39070
39110
  node.loading = false;
39111
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
39071
39112
  return;
39072
39113
  }
39073
39114
  bufferRequests.sort((a, b) => a.offset - b.offset);
@@ -39179,6 +39220,7 @@ void main() {
39179
39220
  }
39180
39221
  node.loaded = true;
39181
39222
  node.loading = false;
39223
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
39182
39224
  const geometrySize = this.estimateGeometrySize(node.object);
39183
39225
  this.geometryCache.set(node.object.uuid, geometrySize);
39184
39226
  this.currentMemoryUsage += geometrySize;
@@ -39187,6 +39229,7 @@ void main() {
39187
39229
  }
39188
39230
  } catch (error) {
39189
39231
  node.loading = false;
39232
+ this.pendingMemoryUsage = Math.max(0, this.pendingMemoryUsage - reservedEstimatedSize);
39190
39233
  if (error.name === "AbortError") {
39191
39234
  return;
39192
39235
  }
@@ -39402,15 +39445,18 @@ void main() {
39402
39445
  let loadedCount = 0;
39403
39446
  let lastLoadedCount = 0;
39404
39447
  const totalNodes = nodesToLoad.length;
39448
+ const progressTotal = { value: totalNodes };
39405
39449
  const loadProgress = async () => {
39406
39450
  loadedCount++;
39451
+ const total = progressTotal.value;
39452
+ const percentage = total > 0 ? Math.min(100, Math.round((loadedCount / total) * 100)) : 0;
39407
39453
  if (loadedCount - lastLoadedCount > 1000) {
39408
39454
  lastLoadedCount = loadedCount;
39409
39455
  this.updateMemoryIndicator();
39410
39456
  this.dispatchEvent("geometryprogress", {
39411
- percentage: Math.round((loadedCount / totalNodes) * 100),
39457
+ percentage,
39412
39458
  loaded: loadedCount,
39413
- total: totalNodes,
39459
+ total,
39414
39460
  });
39415
39461
  this.dispatchEvent("update");
39416
39462
  await new Promise((resolve) => {
@@ -39420,20 +39466,22 @@ void main() {
39420
39466
  };
39421
39467
  try {
39422
39468
  const loadOperations = [];
39469
+ let memoryLimitReached = false;
39423
39470
  for (const nodeId of nodesToLoad) {
39424
39471
  if (this.abortController.signal.aborted) {
39425
39472
  throw new DOMException("Loading aborted", "AbortError");
39426
39473
  }
39427
39474
  const estimatedSize = await this.estimateNodeSize(nodeId);
39428
- if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
39429
- console.log(`Memory limit reached after loading ${loadedCount} nodes`);
39430
- this.dispatchEvent("geometryerror", {
39431
- message: "Memory limit reached",
39432
- });
39433
- this.dispatchEvent("update");
39434
- return loadedCount;
39475
+ const estimated = Number(estimatedSize) || 0;
39476
+ const effectiveLimit = this.memoryLimit / this.optimizationMemoryMultiplier / this.memoryEstimationFactor;
39477
+ if (this.currentMemoryUsage + this.pendingMemoryUsage + estimated > effectiveLimit) {
39478
+ memoryLimitReached = true;
39479
+ progressTotal.value = loadOperations.length;
39480
+ console.log(`Memory limit reached after scheduling ${loadOperations.length} nodes`);
39481
+ break;
39435
39482
  }
39436
- loadOperations.push(this.loadNode(nodeId, loadProgress));
39483
+ this.pendingMemoryUsage += estimated;
39484
+ loadOperations.push(this.loadNode(nodeId, loadProgress, estimated));
39437
39485
  }
39438
39486
  for (const structure of this.structures) {
39439
39487
  loadOperations.push(structure.flushBufferRequests());
@@ -39441,7 +39489,8 @@ void main() {
39441
39489
  await Promise.all(loadOperations);
39442
39490
  this.dispatchEvent("geometryend", {
39443
39491
  totalLoaded: loadedCount,
39444
- totalNodes,
39492
+ totalNodes: progressTotal.value,
39493
+ memoryLimitReached,
39445
39494
  });
39446
39495
  return loadedCount;
39447
39496
  } catch (error) {
@@ -39751,6 +39800,7 @@ void main() {
39751
39800
  this.transformedGeometries.clear();
39752
39801
  this.totalLoadedObjects = 0;
39753
39802
  this.currentMemoryUsage = 0;
39803
+ this.pendingMemoryUsage = 0;
39754
39804
  this.loadedGeometrySize = 0;
39755
39805
  this.abortController = new AbortController();
39756
39806
  this.updateMemoryIndicator();
@@ -39957,6 +40007,7 @@ void main() {
39957
40007
  progress: 100,
39958
40008
  message: `Optimization complete! ${this.maxObjectId} objects processed.`,
39959
40009
  });
40010
+ this.updateMemoryIndicator();
39960
40011
  this.dispatchEvent("update");
39961
40012
  }
39962
40013
  async mergeMeshGroups(materialGroups, rootGroup) {