@inweb/viewer-three 26.7.6 → 26.8.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.
@@ -59894,6 +59894,7 @@ void main() {
59894
59894
  selection.clearSelection();
59895
59895
  viewer.models.forEach((model) => {
59896
59896
  const objects = model.getObjectsByHandles(handles);
59897
+ model.showObjects(objects);
59897
59898
  selection.select(objects, model);
59898
59899
  });
59899
59900
  viewer.update();
@@ -60074,9 +60075,9 @@ void main() {
60074
60075
  commands.registerCommand("clearMarkup", clearMarkup);
60075
60076
  commands.registerCommand("clearSelected", clearSelected);
60076
60077
  commands.registerCommand("clearSlices", clearSlices);
60078
+ commands.registerCommand("collect", collect);
60077
60079
  commands.registerCommand("createPreview", createPreview);
60078
60080
  commands.registerCommand("explode", explode);
60079
- commands.registerCommand("collect", collect);
60080
60081
  commands.registerCommand("getDefaultViewPositions", getDefaultViewPositions);
60081
60082
  commands.registerCommand("getModels", getModels);
60082
60083
  commands.registerCommand("getSelected", getSelected);
@@ -60308,31 +60309,35 @@ void main() {
60308
60309
  return;
60309
60310
  const extentsCenter = this.viewer.extents.getCenter(new Vector3());
60310
60311
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
60312
+ const front = new Vector3()
60313
+ .copy(this.viewer.camera.up)
60314
+ .cross(new Vector3(1, 0, 0))
60315
+ .negate();
60311
60316
  this.directionalLight.position
60312
- .set(0.5, 0, 0.866)
60317
+ .copy(this.viewer.camera.up)
60318
+ .applyAxisAngle(front, (-Math.PI * 30) / 180)
60313
60319
  .multiplyScalar(extentsSize * 2)
60314
60320
  .add(extentsCenter);
60315
60321
  this.directionalLight.target.position.copy(extentsCenter);
60316
- this.frontLight.position.set(0, extentsSize * 2, 0).add(extentsCenter);
60322
+ this.frontLight.position
60323
+ .copy(front)
60324
+ .multiplyScalar(extentsSize * 2)
60325
+ .add(extentsCenter);
60317
60326
  this.frontLight.target.position.copy(extentsCenter);
60318
- this.hemisphereLight.position.set(0, extentsSize * 3, 0).add(extentsCenter);
60327
+ this.hemisphereLight.position
60328
+ .copy(front)
60329
+ .multiplyScalar(extentsSize * 3)
60330
+ .add(extentsCenter);
60319
60331
  this.viewer.scene.add(this.ambientLight);
60320
60332
  this.viewer.scene.add(this.directionalLight);
60321
60333
  this.viewer.scene.add(this.frontLight);
60322
60334
  this.viewer.scene.add(this.hemisphereLight);
60323
60335
  };
60324
60336
  this.viewer = viewer;
60325
- this.ambientLight = new AmbientLight(0xffffff, 1);
60326
- this.viewer.scene.add(this.ambientLight);
60327
- this.directionalLight = new DirectionalLight(0xffffff, 1);
60328
- this.directionalLight.position.set(0.5, 0, 0.866); // ~60º
60329
- this.viewer.scene.add(this.directionalLight);
60337
+ this.ambientLight = new AmbientLight(0xffffff, 1.0);
60338
+ this.directionalLight = new DirectionalLight(0xffffff, 1.0);
60330
60339
  this.frontLight = new DirectionalLight(0xffffff, 1.25);
60331
- this.frontLight.position.set(0, 1, 0);
60332
- this.viewer.scene.add(this.frontLight);
60333
60340
  this.hemisphereLight = new HemisphereLight(0xffffff, 0x444444, 1.25);
60334
- this.hemisphereLight.position.set(0, 0, 1);
60335
- this.viewer.scene.add(this.hemisphereLight);
60336
60341
  this.viewer.addEventListener("databasechunk", this.geometryEnd);
60337
60342
  this.viewer.addEventListener("clear", this.geometryEnd);
60338
60343
  }
@@ -61430,19 +61435,25 @@ void main() {
61430
61435
  class HighlighterComponent {
61431
61436
  constructor(viewer) {
61432
61437
  this.geometryEnd = () => {
61433
- const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
61434
- this.highlightMaterial = new MeshBasicMaterial({
61438
+ const { facesColor, facesTransparancy, edgesColor, edgesOverlap, facesOverlap } = this.viewer.options;
61439
+ this.highlightMaterial = new MeshPhongMaterial({
61435
61440
  color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
61436
61441
  transparent: true,
61437
61442
  opacity: (255 - facesTransparancy) / 255,
61438
- depthTest: false,
61439
- depthWrite: false,
61443
+ depthTest: !facesOverlap,
61444
+ depthWrite: !facesOverlap,
61445
+ specular: 0x222222,
61446
+ shininess: 10,
61447
+ reflectivity: 0.05,
61448
+ polygonOffset: true,
61449
+ polygonOffsetFactor: 1,
61450
+ polygonOffsetUnits: 1,
61440
61451
  });
61441
61452
  this.outlineMaterial = new LineMaterial({
61442
61453
  color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
61443
61454
  linewidth: 1.5,
61444
- depthTest: false,
61445
- depthWrite: false,
61455
+ depthTest: !edgesOverlap,
61456
+ depthWrite: !edgesOverlap,
61446
61457
  resolution: new Vector2(window.innerWidth, window.innerHeight),
61447
61458
  });
61448
61459
  this.highlightLineMaterial = new LineBasicMaterial({
@@ -61455,18 +61466,27 @@ void main() {
61455
61466
  linewidth: 5,
61456
61467
  transparent: true,
61457
61468
  opacity: 0.8,
61458
- depthTest: true,
61459
- depthWrite: true,
61469
+ depthTest: !edgesOverlap,
61470
+ depthWrite: !edgesOverlap,
61460
61471
  resolution: new Vector2(window.innerWidth, window.innerHeight),
61461
61472
  });
61462
61473
  };
61463
61474
  this.optionsChange = () => {
61464
- const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
61475
+ const { facesColor, facesTransparancy, edgesColor, edgesVisibility, edgesOverlap, facesOverlap } = this.viewer.options;
61465
61476
  this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61466
61477
  this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
61478
+ this.highlightMaterial.depthTest = !facesOverlap;
61479
+ this.highlightMaterial.depthWrite = !facesOverlap;
61467
61480
  this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
61481
+ this.outlineMaterial.depthTest = !edgesOverlap;
61482
+ this.outlineMaterial.depthWrite = !edgesOverlap;
61468
61483
  this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61469
61484
  this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61485
+ this.viewer.selected.forEach((selected) => {
61486
+ const wireframe = selected.userData.highlightWireframe;
61487
+ if (wireframe)
61488
+ wireframe.visible = edgesVisibility;
61489
+ });
61470
61490
  this.viewer.update();
61471
61491
  };
61472
61492
  this.viewer = viewer;
@@ -61491,6 +61511,7 @@ void main() {
61491
61511
  this.viewer.removeEventListener("resize", this.viewerResize);
61492
61512
  }
61493
61513
  highlight(objects) {
61514
+ const { edgesVisibility } = this.viewer.options;
61494
61515
  if (!Array.isArray(objects))
61495
61516
  objects = [objects];
61496
61517
  if (!objects.length)
@@ -61508,21 +61529,23 @@ void main() {
61508
61529
  wireframe.position.copy(object.position);
61509
61530
  wireframe.rotation.copy(object.rotation);
61510
61531
  wireframe.scale.copy(object.scale);
61532
+ wireframe.visible = edgesVisibility;
61511
61533
  object.parent.add(wireframe);
61512
- object.userData.highlightwireframe = wireframe;
61534
+ object.userData.highlightWireframe = wireframe;
61513
61535
  object.userData.originalMaterial = object.material;
61514
61536
  object.material = this.highlightLineMaterial;
61515
61537
  object.isHighlighted = true;
61516
61538
  }
61517
61539
  else if (object.isMesh) {
61518
- const edgesGeometry = new EdgesGeometry(object.geometry, 30);
61540
+ const edgesGeometry = new EdgesGeometry(object.geometry, 60);
61519
61541
  const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
61520
61542
  const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
61521
61543
  wireframe.position.copy(object.position);
61522
61544
  wireframe.rotation.copy(object.rotation);
61523
61545
  wireframe.scale.copy(object.scale);
61546
+ wireframe.visible = edgesVisibility;
61524
61547
  object.parent.add(wireframe);
61525
- object.userData.highlightwireframe = wireframe;
61548
+ object.userData.highlightWireframe = wireframe;
61526
61549
  object.userData.originalMaterial = object.material;
61527
61550
  object.material = this.highlightMaterial;
61528
61551
  object.isHighlighted = true;
@@ -61539,9 +61562,9 @@ void main() {
61539
61562
  return;
61540
61563
  object.isHighlighted = false;
61541
61564
  object.material = object.userData.originalMaterial;
61542
- object.userData.highlightwireframe.removeFromParent();
61565
+ object.userData.highlightWireframe.removeFromParent();
61543
61566
  delete object.userData.originalMaterial;
61544
- delete object.userData.highlightwireframe;
61567
+ delete object.userData.highlightWireframe;
61545
61568
  });
61546
61569
  }
61547
61570
  viewerResize(event) {
@@ -61590,7 +61613,8 @@ void main() {
61590
61613
  this.viewer.models.forEach((model) => {
61591
61614
  const objects = model.getVisibleObjects();
61592
61615
  const intersects = this.getPointerIntersects(upPosition, objects);
61593
- intersections.push(...intersects.map((x) => ({ ...x, model })));
61616
+ if (intersects.length > 0)
61617
+ intersections.push({ ...intersects[0], model });
61594
61618
  });
61595
61619
  intersections = intersections.sort((a, b) => a.distance - b.distance);
61596
61620
  if (!event.shiftKey)
@@ -61657,7 +61681,6 @@ void main() {
61657
61681
  objects = [objects];
61658
61682
  if (!objects.length)
61659
61683
  return;
61660
- model.showObjects(objects);
61661
61684
  model.showOriginalObjects(objects);
61662
61685
  this.highlighter.highlight(objects);
61663
61686
  objects.forEach((object) => this.viewer.selected.push(object));
@@ -67313,10 +67336,8 @@ void main() {
67313
67336
  return objects;
67314
67337
  }
67315
67338
  hideObjects(objects) {
67316
- this.getOwnObjects(objects)
67317
- .map((object) => object.userData.handle)
67318
- .forEach((handle) => this.gltfLoader.hiddenHandles.add(handle));
67319
- this.gltfLoader.syncHiddenObjects();
67339
+ const handles = this.getHandlesByObjects(objects);
67340
+ this.gltfLoader.hideObjects(handles);
67320
67341
  return this;
67321
67342
  }
67322
67343
  isolateObjects(objects) {
@@ -67325,23 +67346,20 @@ void main() {
67325
67346
  return this;
67326
67347
  }
67327
67348
  showObjects(objects) {
67328
- this.getOwnObjects(objects)
67329
- .map((object) => object.userData.handle)
67330
- .forEach((handle) => this.gltfLoader.hiddenHandles.delete(handle));
67331
- this.gltfLoader.syncHiddenObjects();
67349
+ const handles = this.getHandlesByObjects(objects);
67350
+ this.gltfLoader.showObjects(handles);
67332
67351
  return this;
67333
67352
  }
67334
67353
  showAllObjects() {
67335
- this.gltfLoader.hiddenHandles.clear();
67336
- this.gltfLoader.syncHiddenObjects();
67354
+ this.gltfLoader.showAllHiddenObjects();
67337
67355
  return this;
67338
67356
  }
67339
67357
  showOriginalObjects(objects) {
67340
- this.getOwnObjects(objects).forEach((object) => (object.visible = true));
67358
+ this.gltfLoader.showOriginalObjects(objects);
67341
67359
  return this;
67342
67360
  }
67343
67361
  hideOriginalObjects(objects) {
67344
- this.getOwnObjects(objects).forEach((object) => (object.visible = false));
67362
+ this.gltfLoader.hideOriginalObjects(objects);
67345
67363
  return this;
67346
67364
  }
67347
67365
  }
@@ -67364,24 +67382,20 @@ void main() {
67364
67382
  TRIANGLE_STRIP: 5,
67365
67383
  TRIANGLE_FAN: 6};
67366
67384
 
67385
+ const MAX_GAP = 128 * 1024; // 128 KB
67386
+ const MAX_CHUNK = 30 * 1024 * 1024; // 100 MB
67387
+
67367
67388
  class GltfStructure {
67368
67389
  constructor(id) {
67369
67390
  this.id = `${id}`;
67370
67391
  this.json = null;
67371
67392
  this.baseUrl = "";
67372
-
67373
- // Binary manager properties
67374
67393
  this.loadController = null;
67375
- // Request batching parameters
67376
67394
  this.batchDelay = 10;
67377
67395
  this.maxBatchSize = 5 * 1024 * 1024;
67378
67396
  this.maxRangesPerRequest = 512;
67379
-
67380
- // Request queue
67381
67397
  this.pendingRequests = [];
67382
67398
  this.batchTimeout = null;
67383
-
67384
- // Material and texture properties
67385
67399
  this.textureLoader = new TextureLoader();
67386
67400
  this.materials = new Map();
67387
67401
  this.textureCache = new Map();
@@ -67413,57 +67427,110 @@ void main() {
67413
67427
  return this.json;
67414
67428
  }
67415
67429
 
67416
- // Schedule a request for processing
67417
67430
  scheduleRequest(request) {
67418
- this.pendingRequests.push(request);
67419
-
67420
- // Clear existing timeout
67421
- if (this.batchTimeout) {
67422
- clearTimeout(this.batchTimeout);
67423
- }
67424
-
67425
- // Set new timeout for batch processing
67426
- this.batchTimeout = setTimeout(() => this.processBatch(), this.batchDelay);
67427
-
67428
- // Return a promise that will resolve when the data is available
67429
67431
  return new Promise((resolve, reject) => {
67430
- request.resolve = resolve;
67431
- request.reject = reject;
67432
+ this.pendingRequests.push({
67433
+ ...request,
67434
+ _resolve: resolve,
67435
+ _reject: reject,
67436
+ });
67432
67437
  });
67433
67438
  }
67434
67439
 
67435
- async processBatch() {
67436
- if (this.pendingRequests.length === 0) return;
67437
-
67438
- // Take current batch of requests and clear timeout
67439
- const currentBatch = [...this.pendingRequests];
67440
+ async flushBufferRequests() {
67441
+ if (!this.pendingRequests || this.pendingRequests.length === 0) return;
67442
+ const requests = [...this.pendingRequests];
67440
67443
  this.pendingRequests = [];
67441
67444
 
67442
- if (this.batchTimeout) {
67443
- clearTimeout(this.batchTimeout);
67444
- this.batchTimeout = null;
67445
+ requests.sort((a, b) => a.offset - b.offset);
67446
+ const mergedRanges = [];
67447
+ let current = {
67448
+ start: requests[0].offset,
67449
+ end: requests[0].offset + requests[0].length,
67450
+ requests: [requests[0]],
67451
+ };
67452
+ for (let i = 1; i < requests.length; i++) {
67453
+ const req = requests[i];
67454
+ const gap = req.offset - current.end;
67455
+ const newEnd = Math.max(current.end, req.offset + req.length);
67456
+ const projectedSize = newEnd - current.start;
67457
+ if (gap <= MAX_GAP && projectedSize <= MAX_CHUNK) {
67458
+ current.end = newEnd;
67459
+ current.requests.push(req);
67460
+ } else {
67461
+ mergedRanges.push(current);
67462
+ current = {
67463
+ start: req.offset,
67464
+ end: req.offset + req.length,
67465
+ requests: [req],
67466
+ };
67467
+ }
67445
67468
  }
67446
- try {
67447
- // Split requests into smaller groups
67448
- for (let i = 0; i < currentBatch.length; i += this.maxRangesPerRequest) {
67449
- const batchRequests = currentBatch.slice(i, i + this.maxRangesPerRequest);
67450
- const buffer = await this.loadController.loadBinaryData(batchRequests);
67451
-
67452
- let currentOffset = 0;
67453
- batchRequests.forEach((request) => {
67454
- const view = this.createTypedArray(buffer, currentOffset, request.length, request.componentType);
67455
- request.resolve(view);
67456
- currentOffset += request.length;
67469
+ mergedRanges.push(current);
67470
+ const finalRanges = [];
67471
+ for (const range of mergedRanges) {
67472
+ let { start, end, requests } = range;
67473
+ while (end - start > MAX_CHUNK) {
67474
+ let splitIdx = 0;
67475
+ for (let i = 0; i < requests.length; i++) {
67476
+ if (requests[i].offset + requests[i].length - start > MAX_CHUNK) {
67477
+ break;
67478
+ }
67479
+ splitIdx = i;
67480
+ }
67481
+ const chunkRequests = requests.slice(0, splitIdx + 1);
67482
+ const chunkEnd =
67483
+ chunkRequests[chunkRequests.length - 1].offset + chunkRequests[chunkRequests.length - 1].length;
67484
+ finalRanges.push({
67485
+ start,
67486
+ end: chunkEnd,
67487
+ requests: chunkRequests,
67457
67488
  });
67489
+ requests = requests.slice(splitIdx + 1);
67490
+ if (requests.length > 0) {
67491
+ start = requests[0].offset;
67492
+ end = requests[0].offset + requests[0].length;
67493
+ for (let i = 1; i < requests.length; i++) {
67494
+ end = Math.max(end, requests[i].offset + requests[i].length);
67495
+ }
67496
+ }
67497
+ }
67498
+ if (requests.length > 0) {
67499
+ finalRanges.push({ start, end, requests });
67458
67500
  }
67459
- } catch (error) {
67460
- console.error("Error processing batch:", error);
67461
- currentBatch.forEach((request) => request.reject(error));
67462
67501
  }
67463
-
67464
- if (this.pendingRequests.length > 0) {
67465
- this.batchTimeout = setTimeout(() => this.processBatch(), this.batchDelay);
67502
+ /*
67503
+ for (const range of finalRanges) {
67504
+ const length = range.end - range.start;
67505
+ const buffer = await this.loadController.loadBinaryData([
67506
+ { offset: range.start, length: length }
67507
+ ]);
67508
+ for (const req of range.requests) {
67509
+ const relOffset = req.offset - range.start;
67510
+ try {
67511
+ req._resolve({ buffer, relOffset, length: req.length });
67512
+ } catch (e) {
67513
+ req._reject(e);
67514
+ }
67515
+ }
67466
67516
  }
67517
+ */
67518
+
67519
+ const promises = finalRanges.map(async (range) => {
67520
+ const length = range.end - range.start;
67521
+ const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
67522
+ for (const req of range.requests) {
67523
+ const relOffset = req.offset - range.start;
67524
+ try {
67525
+ req._resolve({ buffer, relOffset, length: req.length });
67526
+ } catch (e) {
67527
+ req._reject(e);
67528
+ }
67529
+ }
67530
+ });
67531
+ await Promise.all(promises);
67532
+
67533
+ this.pendingRequests = [];
67467
67534
  }
67468
67535
 
67469
67536
  getBufferView(byteOffset, byteLength, componentType) {
@@ -67476,12 +67543,10 @@ void main() {
67476
67543
 
67477
67544
  createTypedArray(buffer, offset, length, componentType) {
67478
67545
  try {
67479
- // Validate parameters
67480
67546
  if (!buffer || !(buffer instanceof ArrayBuffer)) {
67481
67547
  throw new Error("Invalid buffer");
67482
67548
  }
67483
67549
 
67484
- // Calculate element size for given type
67485
67550
  let elementSize;
67486
67551
  switch (componentType) {
67487
67552
  case 5120:
@@ -67500,18 +67565,15 @@ void main() {
67500
67565
  throw new Error(`Unsupported component type: ${componentType}`);
67501
67566
  }
67502
67567
 
67503
- // Check if requested length is correct
67504
67568
  const numElements = length / elementSize;
67505
67569
  if (!Number.isInteger(numElements)) {
67506
67570
  throw new Error(`Invalid length ${length} for component type ${componentType}`);
67507
67571
  }
67508
67572
 
67509
- // Check if buffer is large enough
67510
67573
  if (length > buffer.byteLength) {
67511
67574
  throw new Error(`Buffer too small: need ${length} bytes, but buffer is ${buffer.byteLength} bytes`);
67512
67575
  }
67513
67576
 
67514
- // Create appropriate typed array
67515
67577
  const ArrayType = GL_COMPONENT_TYPES[componentType];
67516
67578
  return new ArrayType(buffer, offset, numElements);
67517
67579
  } catch (error) {
@@ -67608,7 +67670,6 @@ void main() {
67608
67670
  const image = this.json.images[imageIndex];
67609
67671
 
67610
67672
  if (image.uri) {
67611
- // Handle base64 or URL
67612
67673
  if (image.uri.startsWith("data:")) {
67613
67674
  return await this.textureLoader.loadAsync(image.uri);
67614
67675
  } else {
@@ -67616,23 +67677,17 @@ void main() {
67616
67677
  return await this.textureLoader.loadAsync(fullUrl);
67617
67678
  }
67618
67679
  } else if (image.bufferView !== undefined) {
67619
- // Handle embedded binary data
67620
67680
  const bufferView = this.json.bufferViews[image.bufferView];
67621
- const array = await this.getBufferView(
67622
- bufferView.byteOffset || 0,
67623
- bufferView.byteLength,
67624
- 5121 // UNSIGNED_BYTE
67625
- );
67681
+ const array = await this.getBufferView(bufferView.byteOffset || 0, bufferView.byteLength, 5121);
67626
67682
  const blob = new Blob([array], { type: image.mimeType });
67627
67683
  const url = URL.createObjectURL(blob);
67628
67684
  const texture = await this.textureLoader.loadAsync(url);
67629
67685
  URL.revokeObjectURL(url);
67630
- texture.flipY = false; // GLTF standard
67686
+ texture.flipY = false;
67631
67687
  return texture;
67632
67688
  }
67633
67689
  };
67634
67690
 
67635
- // Load all textures
67636
67691
  const texturePromises = [];
67637
67692
  for (let i = 0; i < this.json.textures.length; i++) {
67638
67693
  texturePromises.push(
@@ -67642,82 +67697,56 @@ void main() {
67642
67697
  await Promise.all(texturePromises);
67643
67698
  }
67644
67699
 
67645
- loadMaterials() {
67700
+ async loadMaterials() {
67646
67701
  if (!this.json.materials) return this.materials;
67647
67702
 
67648
67703
  for (let i = 0; i < this.json.materials.length; i++) {
67649
67704
  const materialDef = this.json.materials[i];
67650
- const material = this.createMaterial(materialDef);
67705
+ const material = await this.createMaterial(materialDef);
67706
+ material.name = materialDef.name;
67651
67707
  this.materials.set(i, material);
67652
67708
  }
67653
67709
  return this.materials;
67654
67710
  }
67655
67711
 
67656
67712
  createMaterial(materialDef) {
67657
- const material = new MeshStandardMaterial();
67713
+ const params = {};
67658
67714
 
67659
- // Base color
67660
67715
  if (materialDef.pbrMetallicRoughness) {
67661
67716
  const pbr = materialDef.pbrMetallicRoughness;
67662
-
67663
67717
  if (pbr.baseColorFactor) {
67664
- material.color.fromArray(pbr.baseColorFactor);
67665
- material.opacity = pbr.baseColorFactor[3];
67718
+ params.color = new Color().fromArray(pbr.baseColorFactor);
67719
+ params.opacity = pbr.baseColorFactor[3];
67720
+ if (params.opacity < 1.0) params.transparent = true;
67666
67721
  }
67667
-
67668
67722
  if (pbr.baseColorTexture) {
67669
- material.map = this.textureCache.get(pbr.baseColorTexture.index);
67670
- }
67671
-
67672
- // Metallic and roughness
67673
- if (pbr.metallicFactor !== undefined) {
67674
- material.metalness = pbr.metallicFactor;
67675
- }
67676
- if (pbr.roughnessFactor !== undefined) {
67677
- material.roughness = pbr.roughnessFactor;
67678
- }
67679
- if (pbr.metallicRoughnessTexture) {
67680
- material.metalnessMap = this.textureCache.get(pbr.metallicRoughnessTexture.index);
67681
- material.roughnessMap = material.metalnessMap;
67723
+ params.map = this.textureCache.get(pbr.baseColorTexture.index);
67682
67724
  }
67683
67725
  }
67684
67726
 
67685
- // Normal map
67686
- if (materialDef.normalTexture) {
67687
- material.normalMap = this.textureCache.get(materialDef.normalTexture.index);
67688
- if (materialDef.normalTexture.scale !== undefined) {
67689
- material.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
67690
- }
67691
- }
67727
+ params.specular = 0x222222;
67728
+ params.shininess = 10;
67729
+ params.reflectivity = 0.05;
67730
+ params.polygonOffset = true;
67731
+ params.polygonOffsetFactor = 1;
67732
+ params.polygonOffsetUnits = 1;
67692
67733
 
67693
- // Emissive
67694
67734
  if (materialDef.emissiveFactor) {
67695
- material.emissive.fromArray(materialDef.emissiveFactor);
67696
- }
67697
- if (materialDef.emissiveTexture) {
67698
- material.emissiveMap = this.textureCache.get(materialDef.emissiveTexture.index);
67735
+ params.emissive = new Color().fromArray(materialDef.emissiveFactor);
67699
67736
  }
67700
67737
 
67701
- // Occlusion
67702
- if (materialDef.occlusionTexture) {
67703
- material.aoMap = this.textureCache.get(materialDef.occlusionTexture.index);
67704
- if (materialDef.occlusionTexture.strength !== undefined) {
67705
- material.aoMapIntensity = materialDef.occlusionTexture.strength;
67706
- }
67738
+ if (materialDef.normalTexture) {
67739
+ params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
67707
67740
  }
67708
67741
 
67709
- // Alpha mode
67710
67742
  if (materialDef.alphaMode === "BLEND") {
67711
- material.transparent = true;
67712
- } else if (materialDef.alphaMode === "MASK") {
67713
- material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
67743
+ params.transparent = true;
67714
67744
  }
67715
67745
 
67716
- // Double sided
67717
- material.side = materialDef.doubleSided ? DoubleSide : FrontSide;
67718
-
67719
- material.name = materialDef.name;
67720
-
67746
+ if (materialDef.doubleSided) {
67747
+ params.side = DoubleSide;
67748
+ }
67749
+ const material = new MeshPhongMaterial(params);
67721
67750
  return material;
67722
67751
  }
67723
67752
 
@@ -67750,12 +67779,8 @@ void main() {
67750
67779
  if (!meshDef || !meshDef.primitives) return 0;
67751
67780
 
67752
67781
  let totalSize = 0;
67753
-
67754
- // Estimate size for each primitive
67755
67782
  for (const primitive of meshDef.primitives) {
67756
- // Check for attributes
67757
67783
  if (primitive.attributes) {
67758
- // Calculate attributes size
67759
67784
  for (const [, accessorIndex] of Object.entries(primitive.attributes)) {
67760
67785
  if (accessorIndex === undefined) continue;
67761
67786
 
@@ -67768,7 +67793,6 @@ void main() {
67768
67793
  }
67769
67794
  }
67770
67795
 
67771
- // Calculate indices size if present
67772
67796
  if (primitive.indices !== undefined) {
67773
67797
  const accessor = this.json.accessors[primitive.indices];
67774
67798
  if (accessor) {
@@ -67841,7 +67865,9 @@ void main() {
67841
67865
  this.mergedPoints = new Set();
67842
67866
 
67843
67867
  this.isolatedObjects = [];
67844
- this.useVAO = !!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext;
67868
+ //!!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext
67869
+ this.useVAO = false;
67870
+ this.visibleEdges = true;
67845
67871
 
67846
67872
  this.handleToOptimizedObjects = new Map();
67847
67873
 
@@ -67850,6 +67876,10 @@ void main() {
67850
67876
  this.oldOptimizeObjects = new Set();
67851
67877
  }
67852
67878
 
67879
+ setVisibleEdges(visible) {
67880
+ this.visibleEdges = visible;
67881
+ }
67882
+
67853
67883
  getAvailableMemory() {
67854
67884
  let memoryLimit = 6 * 1024 * 1024 * 1024;
67855
67885
  try {
@@ -67870,7 +67900,7 @@ void main() {
67870
67900
  console.warn("Error detecting available memory:", error);
67871
67901
  }
67872
67902
 
67873
- return memoryLimit;
67903
+ return memoryLimit / 3;
67874
67904
  }
67875
67905
 
67876
67906
  getAbortController() {
@@ -67975,7 +68005,7 @@ void main() {
67975
68005
  console.log(`Final memory usage: ${Math.round(currentMemoryUsage / (1024 * 1024))}MB`);
67976
68006
  }
67977
68007
 
67978
- async loadNode(nodeId) {
68008
+ async loadNode(nodeId, onLoadFinishCb) {
67979
68009
  const node = this.nodes.get(nodeId);
67980
68010
  if (!node || node.loaded || node.loading) return;
67981
68011
 
@@ -67983,38 +68013,138 @@ void main() {
67983
68013
  const meshDef = node.structure.getJson().meshes[node.meshIndex];
67984
68014
 
67985
68015
  try {
67986
- for (const primitive of meshDef.primitives) {
67987
- const positionAccessor = primitive.attributes.POSITION;
67988
- const geometry = new BufferGeometry();
67989
- const attributes = new Map();
67990
-
67991
- attributes.set("position", node.structure.createBufferAttribute(positionAccessor));
68016
+ const bufferRequests = [];
68017
+ const primitiveReqMap = new Map();
68018
+ for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
68019
+ const primitive = meshDef.primitives[primIdx];
68020
+ const reqs = [];
68021
+
68022
+ if (primitive.attributes.POSITION !== undefined) {
68023
+ const accessorIndex = primitive.attributes.POSITION;
68024
+ const accessor = node.structure.json.accessors[accessorIndex];
68025
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68026
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68027
+ const components = node.structure.getNumComponents(accessor.type);
68028
+ const count = accessor.count;
68029
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68030
+ reqs.push({
68031
+ offset: byteOffset,
68032
+ length: byteLength,
68033
+ componentType: accessor.componentType,
68034
+ accessorIndex,
68035
+ type: "position",
68036
+ primIdx,
68037
+ });
68038
+ }
67992
68039
 
67993
68040
  if (primitive.attributes.NORMAL !== undefined) {
67994
- attributes.set("normal", node.structure.createBufferAttribute(primitive.attributes.NORMAL));
68041
+ const accessorIndex = primitive.attributes.NORMAL;
68042
+ const accessor = node.structure.json.accessors[accessorIndex];
68043
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68044
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68045
+ const components = node.structure.getNumComponents(accessor.type);
68046
+ const count = accessor.count;
68047
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68048
+ reqs.push({
68049
+ offset: byteOffset,
68050
+ length: byteLength,
68051
+ componentType: accessor.componentType,
68052
+ accessorIndex,
68053
+ type: "normal",
68054
+ primIdx,
68055
+ });
67995
68056
  }
67996
68057
 
67997
68058
  if (primitive.attributes.TEXCOORD_0 !== undefined) {
67998
- attributes.set("uv", node.structure.createBufferAttribute(primitive.attributes.TEXCOORD_0));
68059
+ const accessorIndex = primitive.attributes.TEXCOORD_0;
68060
+ const accessor = node.structure.json.accessors[accessorIndex];
68061
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68062
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68063
+ const components = node.structure.getNumComponents(accessor.type);
68064
+ const count = accessor.count;
68065
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68066
+ reqs.push({
68067
+ offset: byteOffset,
68068
+ length: byteLength,
68069
+ componentType: accessor.componentType,
68070
+ accessorIndex,
68071
+ type: "uv",
68072
+ primIdx,
68073
+ });
67999
68074
  }
68000
68075
 
68001
- const loadedAttributes = await Promise.all(
68002
- [...attributes.entries()].map(async ([name, promise]) => {
68003
- const attribute = await promise;
68004
- return [name, attribute];
68005
- })
68006
- );
68076
+ if (primitive.indices !== undefined) {
68077
+ const accessorIndex = primitive.indices;
68078
+ const accessor = node.structure.json.accessors[accessorIndex];
68079
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68080
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68081
+ const components = node.structure.getNumComponents(accessor.type);
68082
+ const count = accessor.count;
68083
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68084
+ reqs.push({
68085
+ offset: byteOffset,
68086
+ length: byteLength,
68087
+ componentType: accessor.componentType,
68088
+ accessorIndex,
68089
+ type: "index",
68090
+ primIdx,
68091
+ });
68092
+ }
68093
+ primitiveReqMap.set(primIdx, reqs);
68094
+ bufferRequests.push(...reqs);
68095
+ }
68007
68096
 
68008
- loadedAttributes.forEach(([name, attribute]) => {
68009
- geometry.setAttribute(name, attribute);
68010
- });
68097
+ if (bufferRequests.length === 0) {
68098
+ node.loaded = true;
68099
+ node.loading = false;
68100
+ return;
68101
+ }
68102
+ bufferRequests.sort((a, b) => a.offset - b.offset);
68103
+ const minOffset = bufferRequests[0].offset;
68104
+ const maxOffset = Math.max(...bufferRequests.map((r) => r.offset + r.length));
68105
+ const totalLength = maxOffset - minOffset;
68106
+
68107
+ const { buffer, relOffset: baseRelOffset } = await node.structure.scheduleRequest({
68108
+ offset: minOffset,
68109
+ length: totalLength,
68110
+ componentType: null,
68111
+ });
68011
68112
 
68012
- if (primitive.indices !== undefined) {
68013
- const indexAttribute = await node.structure.createBufferAttribute(primitive.indices);
68014
- geometry.setIndex(indexAttribute);
68113
+ for (const req of bufferRequests) {
68114
+ const relOffset = req.offset - minOffset;
68115
+ req.data = node.structure.createTypedArray(buffer, baseRelOffset + relOffset, req.length, req.componentType);
68116
+ }
68117
+
68118
+ for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
68119
+ const primitive = meshDef.primitives[primIdx];
68120
+ const geometry = new BufferGeometry();
68121
+ const reqs = primitiveReqMap.get(primIdx);
68122
+
68123
+ if (primitive.attributes.POSITION !== undefined) {
68124
+ const req = reqs.find((r) => r.type === "position" && r.accessorIndex === primitive.attributes.POSITION);
68125
+ const accessor = node.structure.json.accessors[primitive.attributes.POSITION];
68126
+ const components = node.structure.getNumComponents(accessor.type);
68127
+ geometry.setAttribute("position", new BufferAttribute(req.data, components));
68128
+ }
68129
+
68130
+ if (primitive.attributes.NORMAL !== undefined) {
68131
+ const req = reqs.find((r) => r.type === "normal" && r.accessorIndex === primitive.attributes.NORMAL);
68132
+ const accessor = node.structure.json.accessors[primitive.attributes.NORMAL];
68133
+ const components = node.structure.getNumComponents(accessor.type);
68134
+ geometry.setAttribute("normal", new BufferAttribute(req.data, components));
68015
68135
  }
68016
68136
 
68017
- this.currentPrimitiveMode = primitive.mode;
68137
+ if (primitive.attributes.TEXCOORD_0 !== undefined) {
68138
+ const req = reqs.find((r) => r.type === "uv" && r.accessorIndex === primitive.attributes.TEXCOORD_0);
68139
+ const accessor = node.structure.json.accessors[primitive.attributes.TEXCOORD_0];
68140
+ const components = node.structure.getNumComponents(accessor.type);
68141
+ geometry.setAttribute("uv", new BufferAttribute(req.data, components));
68142
+ }
68143
+
68144
+ if (primitive.indices !== undefined) {
68145
+ const req = reqs.find((r) => r.type === "index" && r.accessorIndex === primitive.indices);
68146
+ geometry.setIndex(new BufferAttribute(req.data, 1));
68147
+ }
68018
68148
 
68019
68149
  let material;
68020
68150
  if (primitive.material !== undefined) {
@@ -68029,8 +68159,7 @@ void main() {
68029
68159
  Material.prototype.copy.call(pointsMaterial, material);
68030
68160
  pointsMaterial.color.copy(material.color);
68031
68161
  pointsMaterial.map = material.map;
68032
- pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
68033
-
68162
+ pointsMaterial.sizeAttenuation = false;
68034
68163
  mesh = new Points(geometry, pointsMaterial);
68035
68164
  } else if (
68036
68165
  primitive.mode === GL_CONSTANTS.TRIANGLES ||
@@ -68039,7 +68168,6 @@ void main() {
68039
68168
  primitive.mode === undefined
68040
68169
  ) {
68041
68170
  mesh = new Mesh(geometry, material);
68042
-
68043
68171
  if (primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP) {
68044
68172
  mesh.drawMode = TriangleStripDrawMode;
68045
68173
  } else if (primitive.mode === GL_CONSTANTS.TRIANGLE_FAN) {
@@ -68052,39 +68180,30 @@ void main() {
68052
68180
  } else if (primitive.mode === GL_CONSTANTS.LINE_LOOP) {
68053
68181
  mesh = new LineLoop(geometry, material);
68054
68182
  }
68055
-
68056
68183
  if (node.extras) {
68057
68184
  mesh.userData = { ...mesh.userData, ...node.extras };
68058
68185
  }
68059
-
68060
68186
  if (meshDef.extras) {
68061
68187
  mesh.userData = { ...mesh.userData, ...meshDef.extras };
68062
68188
  }
68063
-
68064
68189
  if (primitive.extras) {
68065
68190
  mesh.userData = { ...mesh.userData, ...primitive.extras };
68066
68191
  }
68067
-
68068
68192
  if (node.handle) {
68069
68193
  mesh.userData.handle = node.handle;
68070
68194
  } else {
68071
68195
  mesh.userData.handle = `${node.structure.id}_${mesh.userData.handle}`;
68072
68196
  }
68073
-
68074
68197
  if (mesh.material.name === "edges") {
68075
68198
  mesh.userData.isEdge = true;
68076
68199
  } else {
68077
68200
  mesh.userData.isEdge = false;
68078
68201
  }
68079
-
68080
68202
  this.registerObjectWithHandle(mesh, mesh.userData.handle);
68081
-
68082
68203
  mesh.position.copy(node.position);
68083
-
68084
68204
  if (!geometry.attributes.normal) {
68085
68205
  geometry.computeVertexNormals();
68086
68206
  }
68087
-
68088
68207
  if (material.aoMap && geometry.attributes.uv) {
68089
68208
  geometry.setAttribute("uv2", geometry.attributes.uv);
68090
68209
  }
@@ -68094,17 +68213,17 @@ void main() {
68094
68213
  this.scene.add(mesh);
68095
68214
  }
68096
68215
  node.object = mesh;
68097
-
68098
68216
  this.totalLoadedObjects++;
68099
68217
  mesh.visible = this.totalLoadedObjects < this.graphicsObjectLimit;
68100
68218
  }
68101
-
68102
68219
  node.loaded = true;
68103
68220
  node.loading = false;
68104
-
68105
68221
  const geometrySize = this.estimateGeometrySize(node.object);
68106
68222
  this.geometryCache.set(node.object.uuid, geometrySize);
68107
68223
  this.currentMemoryUsage += geometrySize;
68224
+ if (onLoadFinishCb) {
68225
+ onLoadFinishCb();
68226
+ }
68108
68227
  } catch (error) {
68109
68228
  if (error.name !== "AbortError") {
68110
68229
  console.error(`Error loading node ${nodeId}:`, error);
@@ -68229,7 +68348,7 @@ void main() {
68229
68348
  return volumeB - volumeA;
68230
68349
  });
68231
68350
 
68232
- if (!ignoreEdges) {
68351
+ if (!ignoreEdges && this.visibleEdges) {
68233
68352
  this.nodesToLoad.push(...this.edgeNodes);
68234
68353
  }
68235
68354
 
@@ -68356,33 +68475,13 @@ void main() {
68356
68475
  async processNodes() {
68357
68476
  const nodesToLoad = this.nodesToLoad;
68358
68477
  let loadedCount = 0;
68478
+ let lastLoadedCount = 0;
68359
68479
  const totalNodes = nodesToLoad.length;
68360
68480
 
68361
- try {
68362
- while (loadedCount < totalNodes) {
68363
- const batch = nodesToLoad.slice(loadedCount, loadedCount + this.batchSize);
68364
- const batchPromises = [];
68365
-
68366
- for (const nodeId of batch) {
68367
- if (this.abortController.signal.aborted) {
68368
- throw new DOMException("Loading aborted", "AbortError");
68369
- }
68370
-
68371
- const estimatedSize = await this.estimateNodeSize(nodeId);
68372
-
68373
- if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
68374
- console.log(`Memory limit reached after loading ${loadedCount} nodes`);
68375
- this.dispatchEvent("geometryerror", { message: "Memory limit reached" });
68376
- this.dispatchEvent("update");
68377
- return loadedCount;
68378
- }
68379
-
68380
- batchPromises.push(this.loadNode(nodeId));
68381
- }
68382
-
68383
- await Promise.all(batchPromises);
68384
- loadedCount += batch.length;
68385
-
68481
+ const loadProgress = async () => {
68482
+ loadedCount++;
68483
+ if (loadedCount - lastLoadedCount > 1000) {
68484
+ lastLoadedCount = loadedCount;
68386
68485
  this.updateMemoryIndicator();
68387
68486
  this.dispatchEvent("geometryprogress", {
68388
68487
  percentage: Math.round((loadedCount / totalNodes) * 100),
@@ -68400,6 +68499,34 @@ void main() {
68400
68499
  setTimeout(resolve, 0);
68401
68500
  });
68402
68501
  }
68502
+ };
68503
+
68504
+ try {
68505
+ const loadOperations = [];
68506
+ for (const nodeId of nodesToLoad) {
68507
+ if (this.abortController.signal.aborted) {
68508
+ throw new DOMException("Loading aborted", "AbortError");
68509
+ }
68510
+
68511
+ const estimatedSize = await this.estimateNodeSize(nodeId);
68512
+
68513
+ if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
68514
+ console.log(`Memory limit reached after loading ${loadedCount} nodes`);
68515
+ this.dispatchEvent("geometryerror", {
68516
+ message: "Memory limit reached",
68517
+ });
68518
+ this.dispatchEvent("update");
68519
+ return loadedCount;
68520
+ }
68521
+
68522
+ loadOperations.push(this.loadNode(nodeId, loadProgress));
68523
+ }
68524
+
68525
+ for (const structure of this.structures) {
68526
+ loadOperations.push(structure.flushBufferRequests());
68527
+ }
68528
+
68529
+ await Promise.all(loadOperations);
68403
68530
 
68404
68531
  this.dispatchEvent("geometryend", {
68405
68532
  totalLoaded: loadedCount,
@@ -69380,6 +69507,25 @@ void main() {
69380
69507
  }
69381
69508
  });
69382
69509
  }
69510
+
69511
+ // Возвращает bounding box для конкретной структуры
69512
+ getStructureGeometryExtent(structureId) {
69513
+ const extent = new Box3();
69514
+ for (const [nodeId, node] of this.nodes.entries()) {
69515
+ if (!node.geometryExtents) continue;
69516
+ if (!nodeId.startsWith(structureId + "_")) continue;
69517
+ if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
69518
+ const transformedBox = node.geometryExtents.clone();
69519
+ if (node.group && node.group.matrix) {
69520
+ transformedBox.applyMatrix4(node.group.matrix);
69521
+ if (node.group.parent && node.group.parent.matrix) {
69522
+ transformedBox.applyMatrix4(node.group.parent.matrix);
69523
+ }
69524
+ }
69525
+ extent.union(transformedBox);
69526
+ }
69527
+ return extent;
69528
+ }
69383
69529
  }
69384
69530
 
69385
69531
  ///////////////////////////////////////////////////////////////////////////////
@@ -69408,7 +69554,6 @@ void main() {
69408
69554
  constructor(viewer) {
69409
69555
  this.requestId = 0;
69410
69556
  this.viewer = viewer;
69411
- this.scene = new Group$1();
69412
69557
  }
69413
69558
  dispose() {
69414
69559
  if (this.gltfLoader)
@@ -69422,27 +69567,25 @@ void main() {
69422
69567
  /.gltf$/i.test(file.database));
69423
69568
  }
69424
69569
  async load(model, format, params) {
69425
- this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, this.viewer.scene, this.viewer.renderer);
69570
+ const scene = new Group$1();
69571
+ this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
69426
69572
  this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
69427
69573
  this.gltfLoader.addEventListener("databasechunk", (data) => {
69428
- const modelImpl = new DynamicModelImpl(this.scene);
69574
+ const modelImpl = new DynamicModelImpl(scene);
69429
69575
  modelImpl.loader = this;
69430
69576
  modelImpl.gltfLoader = this.gltfLoader;
69431
69577
  modelImpl.viewer = this.viewer;
69432
- this.viewer.scene.add(this.scene);
69578
+ this.viewer.scene.add(scene);
69433
69579
  this.viewer.models.push(modelImpl);
69434
69580
  this.viewer.syncOptions();
69435
69581
  this.viewer.syncOverlay();
69436
69582
  this.viewer.update();
69437
- this.viewer.emitEvent({ type: "databasechunk", data, file: model.file, model });
69583
+ this.viewer.emitEvent({ type: "databasechunk", data: scene, file: model.file, model });
69438
69584
  });
69439
69585
  this.gltfLoader.addEventListener("geometryprogress", (data) => {
69440
69586
  const progress = data.loaded / data.total;
69441
69587
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model });
69442
69588
  });
69443
- this.gltfLoader.addEventListener("geometrymemory", (data) => {
69444
- this.viewer.emit({ type: "geometryprogress", data });
69445
- });
69446
69589
  this.gltfLoader.addEventListener("geometryerror", (data) => {
69447
69590
  this.viewer.emitEvent({ type: "geometryerror", data, file: model.file, model });
69448
69591
  });
@@ -69476,9 +69619,8 @@ void main() {
69476
69619
  return this;
69477
69620
  }
69478
69621
  cancel() {
69479
- if (this.gltfLoader) {
69622
+ if (this.gltfLoader)
69480
69623
  this.gltfLoader.abortLoading();
69481
- }
69482
69624
  }
69483
69625
  }
69484
69626
 
@@ -69516,7 +69658,7 @@ void main() {
69516
69658
  *
69517
69659
  * The loader should do:
69518
69660
  *
69519
- * - Load scene from file. The scene must be a Three.js object of type `Object3D` or a descendant of it.
69661
+ * - Load raw data from file and convert it to the `Three.js` scene.
69520
69662
  * - Add scene to the viewer `scene`.
69521
69663
  * - Create `ModelImpl` for the scene and to the viewer `models` list.
69522
69664
  * - Synchronize viewer options and overlay.