@inweb/viewer-three 26.9.0 → 26.9.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.
@@ -82047,32 +82047,32 @@ void main() {
82047
82047
  function zoomTo(viewer, box) {
82048
82048
  if (box.isEmpty())
82049
82049
  return;
82050
- const center = box.getCenter(new Vector3());
82051
- const sphere = box.getBoundingSphere(new Sphere());
82050
+ const boxCenter = box.getCenter(new Vector3());
82051
+ const boxSize = box.getBoundingSphere(new Sphere()).radius;
82052
82052
  const rendererSize = viewer.renderer.getSize(new Vector2());
82053
82053
  const aspect = rendererSize.x / rendererSize.y;
82054
82054
  const camera = viewer.camera;
82055
82055
  if (camera.isPerspectiveCamera) {
82056
- const offset = new Vector3(0, 0, 1);
82057
- offset.applyQuaternion(camera.quaternion);
82058
- offset.multiplyScalar(sphere.radius / Math.tan(MathUtils.DEG2RAD * camera.fov * 0.5));
82059
- camera.position.copy(center).add(offset);
82056
+ const offset = new Vector3(0, 0, 1)
82057
+ .applyQuaternion(camera.quaternion)
82058
+ .multiplyScalar(boxSize / Math.tan(MathUtils.DEG2RAD * camera.fov * 0.5));
82059
+ camera.position.copy(offset).add(boxCenter);
82060
82060
  camera.updateMatrixWorld();
82061
82061
  }
82062
82062
  if (camera.isOrthographicCamera) {
82063
- camera.top = sphere.radius;
82064
- camera.bottom = -sphere.radius;
82063
+ camera.top = boxSize;
82064
+ camera.bottom = -boxSize;
82065
82065
  camera.left = camera.bottom * aspect;
82066
82066
  camera.right = camera.top * aspect;
82067
82067
  camera.zoom = 1;
82068
82068
  camera.updateProjectionMatrix();
82069
- const offset = new Vector3(0, 0, 1);
82070
- offset.applyQuaternion(camera.quaternion);
82071
- offset.multiplyScalar(viewer.extents.getBoundingSphere(new Sphere()).radius * 3);
82072
- camera.position.copy(center).add(offset);
82069
+ const offset = new Vector3(0, 0, 1)
82070
+ .applyQuaternion(camera.quaternion)
82071
+ .multiplyScalar(viewer.extents.getBoundingSphere(new Sphere()).radius * 3);
82072
+ camera.position.copy(offset).add(boxCenter);
82073
82073
  camera.updateMatrixWorld();
82074
82074
  }
82075
- viewer.target.copy(center);
82075
+ viewer.target.copy(boxCenter);
82076
82076
  viewer.update();
82077
82077
  viewer.emitEvent({ type: "zoom" });
82078
82078
  }
@@ -82100,27 +82100,30 @@ void main() {
82100
82100
  // acknowledge and accept the above terms.
82101
82101
  ///////////////////////////////////////////////////////////////////////////////
82102
82102
  const defaultViewPositions = {
82103
- front: new Vector3(0, 0, 1),
82104
- back: new Vector3(0, 0, -1),
82105
- left: new Vector3(-1, 0, 0),
82106
- right: new Vector3(1, 0, 0),
82103
+ front: new Vector3(0, 0, -1),
82104
+ back: new Vector3(0, 0, 1),
82105
+ left: new Vector3(1, 0, 0),
82106
+ right: new Vector3(-1, 0, 0),
82107
82107
  bottom: new Vector3(0, -1, 0),
82108
82108
  top: new Vector3(0, 1, 0),
82109
- ns: new Vector3(-0.5, 1.0, -0.5).normalize(),
82110
- sw: new Vector3(0.5, 1.0, -0.5).normalize(),
82111
- nw: new Vector3(0.5, 1.0, 0.5).normalize(),
82112
- se: new Vector3(-0.5, 1.0, 0.5).normalize(),
82109
+ se: new Vector3(-1, 1, -1).normalize(),
82110
+ sw: new Vector3(1, 1, -1).normalize(),
82111
+ ne: new Vector3(-1, 1, 1).normalize(),
82112
+ nw: new Vector3(1, 1, 1).normalize(),
82113
82113
  };
82114
82114
  function setDefaultViewPosition(viewer, position) {
82115
- const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
82116
- const center = viewer.extents.getCenter(new Vector3());
82117
- const sphere = viewer.extents.getBoundingSphere(new Sphere());
82118
- const offset = direction.clone().multiplyScalar(sphere.radius);
82115
+ const extentsCenter = viewer.extents.getCenter(new Vector3());
82116
+ const extentsSize = viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
82117
+ const upY = new Vector3(0, 1, 0);
82118
+ const offsetY = defaultViewPositions[position] || defaultViewPositions["sw"];
82119
+ const up = new Vector3().copy(viewer.camera.up);
82120
+ const quaternion = new Quaternion().setFromUnitVectors(upY, up);
82121
+ const offset = new Vector3().copy(offsetY).applyQuaternion(quaternion);
82119
82122
  const camera = viewer.camera;
82120
- camera.position.copy(center).add(offset);
82121
- camera.lookAt(center);
82123
+ camera.position.copy(offset).multiplyScalar(extentsSize).add(extentsCenter);
82124
+ camera.lookAt(extentsCenter);
82122
82125
  camera.updateMatrixWorld();
82123
- viewer.target.copy(center);
82126
+ viewer.target.copy(extentsCenter);
82124
82127
  viewer.update();
82125
82128
  viewer.emit({ type: "viewposition", data: position });
82126
82129
  zoomTo(viewer, viewer.extents);
@@ -82857,12 +82860,13 @@ void main() {
82857
82860
  return;
82858
82861
  const extentsCenter = this.viewer.extents.getCenter(new Vector3());
82859
82862
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
82860
- const front = new Vector3()
82861
- .copy(this.viewer.camera.up)
82862
- .cross(new Vector3(1, 0, 0))
82863
- .negate();
82863
+ const upY = new Vector3(0, 1, 0);
82864
+ const frontY = new Vector3(0, 0, -1);
82865
+ const up = new Vector3().copy(this.viewer.camera.up);
82866
+ const quaternion = new Quaternion().setFromUnitVectors(upY, up);
82867
+ const front = new Vector3().copy(frontY).applyQuaternion(quaternion).negate();
82864
82868
  this.directionalLight.position
82865
- .copy(this.viewer.camera.up)
82869
+ .copy(up)
82866
82870
  .applyAxisAngle(front, (-Math.PI * 30) / 180)
82867
82871
  .multiplyScalar(extentsSize * 2)
82868
82872
  .add(extentsCenter);
@@ -90265,11 +90269,12 @@ void main() {
90265
90269
  const MAX_CHUNK = 30 * 1024 * 1024; // 100 MB
90266
90270
 
90267
90271
  class GltfStructure {
90268
- constructor(id) {
90272
+ constructor(id, loadController) {
90269
90273
  this.id = `${id}`;
90270
90274
  this.json = null;
90271
90275
  this.baseUrl = "";
90272
- this.loadController = null;
90276
+ this.loadController = loadController;
90277
+ this.loader = null;
90273
90278
  this.batchDelay = 10;
90274
90279
  this.maxBatchSize = 5 * 1024 * 1024;
90275
90280
  this.maxRangesPerRequest = 512;
@@ -90281,10 +90286,10 @@ void main() {
90281
90286
  this.materialCache = new Map();
90282
90287
  }
90283
90288
 
90284
- async initialize(loadController) {
90285
- this.json = await loadController.loadJson();
90286
- this.baseUrl = await loadController.baseUrl();
90287
- this.loadController = loadController;
90289
+ async initialize(loader) {
90290
+ this.json = await this.loadController.loadJson();
90291
+ this.baseUrl = await this.loadController.baseUrl();
90292
+ this.loader = loader;
90288
90293
  }
90289
90294
 
90290
90295
  clear() {
@@ -90297,10 +90302,12 @@ void main() {
90297
90302
  this.batchTimeout = null;
90298
90303
  }
90299
90304
 
90300
- // Clear materials and textures
90301
90305
  this.disposeMaterials();
90302
90306
  this.textureCache.clear();
90303
90307
  this.materials.clear();
90308
+
90309
+ this.activeChunkLoads = 0;
90310
+ this.chunkQueue = [];
90304
90311
  }
90305
90312
 
90306
90313
  getJson() {
@@ -90379,35 +90386,32 @@ void main() {
90379
90386
  finalRanges.push({ start, end, requests });
90380
90387
  }
90381
90388
  }
90382
- /*
90383
- for (const range of finalRanges) {
90384
- const length = range.end - range.start;
90385
- const buffer = await this.loadController.loadBinaryData([
90386
- { offset: range.start, length: length }
90387
- ]);
90388
- for (const req of range.requests) {
90389
- const relOffset = req.offset - range.start;
90390
- try {
90391
- req._resolve({ buffer, relOffset, length: req.length });
90392
- } catch (e) {
90393
- req._reject(e);
90394
- }
90395
- }
90396
- }
90397
- */
90398
90389
 
90399
- const promises = finalRanges.map(async (range) => {
90400
- const length = range.end - range.start;
90401
- const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
90402
- for (const req of range.requests) {
90403
- const relOffset = req.offset - range.start;
90404
- try {
90405
- req._resolve({ buffer, relOffset, length: req.length });
90406
- } catch (e) {
90407
- req._reject(e);
90390
+ const promises = finalRanges.map(async (range, index) => {
90391
+ await this.loader.waitForChunkSlot();
90392
+
90393
+ try {
90394
+ const length = range.end - range.start;
90395
+ const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
90396
+
90397
+ for (const req of range.requests) {
90398
+ const relOffset = req.offset - range.start;
90399
+ try {
90400
+ req._resolve({ buffer, relOffset, length: req.length });
90401
+ } catch (e) {
90402
+ req._reject(e);
90403
+ }
90404
+ }
90405
+ } catch (error) {
90406
+ for (const req of range.requests) {
90407
+ req._reject(error);
90408
90408
  }
90409
+ console.warn(`Failed to load chunk ${index + 1}/${finalRanges.length} (${range.start}-${range.end}):`, error);
90410
+ } finally {
90411
+ this.loader.releaseChunkSlot();
90409
90412
  }
90410
90413
  });
90414
+
90411
90415
  await Promise.all(promises);
90412
90416
 
90413
90417
  this.pendingRequests = [];
@@ -90825,6 +90829,10 @@ void main() {
90825
90829
  this.hiddenHandles = new Set();
90826
90830
  this.newOptimizedObjects = new Set();
90827
90831
  this.oldOptimizeObjects = new Set();
90832
+
90833
+ this.maxConcurrentChunks = 8;
90834
+ this.activeChunkLoads = 0;
90835
+ this.chunkQueue = [];
90828
90836
  }
90829
90837
 
90830
90838
  setVisibleEdges(visible) {
@@ -91234,6 +91242,7 @@ void main() {
91234
91242
  const structureArray = Array.isArray(structures) ? structures : [structures];
91235
91243
 
91236
91244
  for (const structure of structureArray) {
91245
+ await structure.initialize(this);
91237
91246
  this.structures.push(structure);
91238
91247
  }
91239
91248
 
@@ -91625,13 +91634,6 @@ void main() {
91625
91634
  this.nodesToLoad = [];
91626
91635
  }
91627
91636
 
91628
- async addStructure(loadController) {
91629
- const structure = new GltfStructure();
91630
- await structure.initialize(loadController);
91631
- this.structures.push(structure);
91632
- return structure;
91633
- }
91634
-
91635
91637
  removeOptimization() {
91636
91638
  this.originalObjects.forEach((obj) => (obj.visible = true));
91637
91639
 
@@ -91663,7 +91665,8 @@ void main() {
91663
91665
  }
91664
91666
 
91665
91667
  clear() {
91666
- // Clear all structures
91668
+ this.chunkQueue = [];
91669
+
91667
91670
  this.structures.forEach((structure) => {
91668
91671
  if (structure) {
91669
91672
  structure.clear();
@@ -91704,7 +91707,6 @@ void main() {
91704
91707
  });
91705
91708
  this.loadedMeshes.clear();
91706
91709
 
91707
- // Clear all structure roots and their children
91708
91710
  this.structureRoots.forEach((rootGroup) => {
91709
91711
  if (rootGroup) {
91710
91712
  rootGroup.traverse((child) => {
@@ -91724,7 +91726,6 @@ void main() {
91724
91726
  });
91725
91727
  this.structureRoots.clear();
91726
91728
 
91727
- // Clear all optimized objects
91728
91729
  this.mergedMesh.forEach((mesh) => {
91729
91730
  if (mesh.geometry) mesh.geometry.dispose();
91730
91731
  if (mesh.material) {
@@ -92477,7 +92478,6 @@ void main() {
92477
92478
  });
92478
92479
  }
92479
92480
 
92480
- // Возвращает bounding box для конкретной структуры
92481
92481
  getStructureGeometryExtent(structureId) {
92482
92482
  const extent = new Box3();
92483
92483
  for (const [nodeId, node] of this.nodes.entries()) {
@@ -92495,6 +92495,35 @@ void main() {
92495
92495
  }
92496
92496
  return extent;
92497
92497
  }
92498
+
92499
+ setMaxConcurrentChunks(maxChunks) {
92500
+ if (maxChunks < 1) {
92501
+ console.warn("Max concurrent chunks must be at least 1");
92502
+ return;
92503
+ }
92504
+ this.maxConcurrentChunks = maxChunks;
92505
+ }
92506
+
92507
+ waitForChunkSlot() {
92508
+ if (this.activeChunkLoads < this.maxConcurrentChunks) {
92509
+ this.activeChunkLoads++;
92510
+ return Promise.resolve();
92511
+ }
92512
+
92513
+ return new Promise((resolve) => {
92514
+ this.chunkQueue.push(resolve);
92515
+ });
92516
+ }
92517
+
92518
+ releaseChunkSlot() {
92519
+ this.activeChunkLoads--;
92520
+
92521
+ if (this.chunkQueue.length > 0) {
92522
+ const nextResolve = this.chunkQueue.shift();
92523
+ this.activeChunkLoads++;
92524
+ nextResolve();
92525
+ }
92526
+ }
92498
92527
  }
92499
92528
 
92500
92529
  ///////////////////////////////////////////////////////////////////////////////
@@ -92540,6 +92569,7 @@ void main() {
92540
92569
  this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
92541
92570
  this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
92542
92571
  this.gltfLoader.setVisibleEdges(this.viewer.options.edgeModel);
92572
+ // this.gltfLoader.setMaxConcurrentChunks(this.viewer.options.maxConcurrentChunks);
92543
92573
  this.gltfLoader.addEventListener("databasechunk", (data) => {
92544
92574
  const modelImpl = new DynamicModelImpl(scene);
92545
92575
  modelImpl.loader = this;
@@ -92583,8 +92613,7 @@ void main() {
92583
92613
  },
92584
92614
  baseUrl: () => Promise.resolve(`${model.httpClient.serverUrl}${model.path}/`),
92585
92615
  };
92586
- const structure = new GltfStructure(model.id);
92587
- await structure.initialize(loadController);
92616
+ const structure = new GltfStructure(model.id, loadController);
92588
92617
  await this.gltfLoader.loadStructure(structure);
92589
92618
  await this.gltfLoader.loadNodes();
92590
92619
  return this;
@@ -109790,13 +109819,13 @@ void main() {
109790
109819
  this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
109791
109820
  this.scene = new Scene();
109792
109821
  this.helpers = new Helpers();
109793
- this.target = new Vector3();
109822
+ this.target = new Vector3(0, 0, 0);
109794
109823
  const pixelRatio = window.devicePixelRatio;
109795
109824
  const rect = canvas.parentElement.getBoundingClientRect();
109796
109825
  const width = rect.width || 1;
109797
109826
  const height = rect.height || 1;
109798
109827
  const aspect = width / height;
109799
- this.camera = new PerspectiveCamera(45, aspect, 0.01, 1000);
109828
+ this.camera = new PerspectiveCamera(45, aspect, 0.001, 1000);
109800
109829
  this.camera.up.set(0, 1, 0);
109801
109830
  this.camera.position.set(0, 0, 1);
109802
109831
  this.camera.lookAt(this.target);
@@ -110202,7 +110231,7 @@ void main() {
110202
110231
  camera.left = camera.bottom * aspect;
110203
110232
  camera.right = camera.top * aspect;
110204
110233
  camera.near = 0;
110205
- camera.far = extentsSize * 100;
110234
+ camera.far = extentsSize * 1000;
110206
110235
  camera.zoom = orthogonal_camera.view_to_world_scale;
110207
110236
  camera.updateProjectionMatrix();
110208
110237
  camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
@@ -110223,8 +110252,8 @@ void main() {
110223
110252
  const camera = new PerspectiveCamera();
110224
110253
  camera.fov = perspective_camera.field_of_view;
110225
110254
  camera.aspect = aspect;
110226
- camera.near = extentsSize / 100;
110227
- camera.far = extentsSize * 100;
110255
+ camera.near = extentsSize / 1000;
110256
+ camera.far = extentsSize * 1000;
110228
110257
  camera.updateProjectionMatrix();
110229
110258
  camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
110230
110259
  camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));