@inweb/viewer-three 26.7.2 → 26.8.0

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);
@@ -60197,7 +60198,6 @@ void main() {
60197
60198
  });
60198
60199
  if (sceneCamera) {
60199
60200
  this.viewer.camera = sceneCamera.clone();
60200
- this.viewer.camera.up.set(0, 0, 1);
60201
60201
  this.viewer.camera.scale.set(1, 1, 1); // <- Visualize fix
60202
60202
  }
60203
60203
  const camera = this.viewer.camera;
@@ -60310,30 +60310,29 @@ void main() {
60310
60310
  const extentsCenter = this.viewer.extents.getCenter(new Vector3());
60311
60311
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
60312
60312
  this.directionalLight.position
60313
- .set(0.5, 0, 0.866)
60313
+ .set(0.5, 0.866, 0) // ~60º
60314
60314
  .multiplyScalar(extentsSize * 2)
60315
60315
  .add(extentsCenter);
60316
60316
  this.directionalLight.target.position.copy(extentsCenter);
60317
- this.frontLight.position.set(0, extentsSize * 2, 0).add(extentsCenter);
60317
+ this.frontLight.position
60318
+ .set(0, 0, 1)
60319
+ .multiplyScalar(extentsSize * 2)
60320
+ .add(extentsCenter);
60318
60321
  this.frontLight.target.position.copy(extentsCenter);
60319
- this.hemisphereLight.position.set(0, extentsSize * 3, 0).add(extentsCenter);
60322
+ this.hemisphereLight.position
60323
+ .set(0, 0, 1)
60324
+ .multiplyScalar(extentsSize * 3)
60325
+ .add(extentsCenter);
60320
60326
  this.viewer.scene.add(this.ambientLight);
60321
60327
  this.viewer.scene.add(this.directionalLight);
60322
60328
  this.viewer.scene.add(this.frontLight);
60323
60329
  this.viewer.scene.add(this.hemisphereLight);
60324
60330
  };
60325
60331
  this.viewer = viewer;
60326
- this.ambientLight = new AmbientLight(0xffffff, 1);
60327
- this.viewer.scene.add(this.ambientLight);
60328
- this.directionalLight = new DirectionalLight(0xffffff, 1);
60329
- this.directionalLight.position.set(0.5, 0, 0.866); // ~60º
60330
- this.viewer.scene.add(this.directionalLight);
60332
+ this.ambientLight = new AmbientLight(0xffffff, 1.0);
60333
+ this.directionalLight = new DirectionalLight(0xffffff, 1.0);
60331
60334
  this.frontLight = new DirectionalLight(0xffffff, 1.25);
60332
- this.frontLight.position.set(0, 1, 0);
60333
- this.viewer.scene.add(this.frontLight);
60334
60335
  this.hemisphereLight = new HemisphereLight(0xffffff, 0x444444, 1.25);
60335
- this.hemisphereLight.position.set(0, 0, 1);
60336
- this.viewer.scene.add(this.hemisphereLight);
60337
60336
  this.viewer.addEventListener("databasechunk", this.geometryEnd);
60338
60337
  this.viewer.addEventListener("clear", this.geometryEnd);
60339
60338
  }
@@ -61431,19 +61430,25 @@ void main() {
61431
61430
  class HighlighterComponent {
61432
61431
  constructor(viewer) {
61433
61432
  this.geometryEnd = () => {
61434
- const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
61435
- this.highlightMaterial = new MeshBasicMaterial({
61433
+ const { facesColor, facesTransparancy, edgesColor, edgesOverlap, facesOverlap } = this.viewer.options;
61434
+ this.highlightMaterial = new MeshPhongMaterial({
61436
61435
  color: new Color(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255),
61437
61436
  transparent: true,
61438
61437
  opacity: (255 - facesTransparancy) / 255,
61439
- depthTest: false,
61440
- depthWrite: false,
61438
+ depthTest: !facesOverlap,
61439
+ depthWrite: !facesOverlap,
61440
+ specular: 0x222222,
61441
+ shininess: 10,
61442
+ reflectivity: 0.05,
61443
+ polygonOffset: true,
61444
+ polygonOffsetFactor: 1,
61445
+ polygonOffsetUnits: 1,
61441
61446
  });
61442
61447
  this.outlineMaterial = new LineMaterial({
61443
61448
  color: new Color(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255),
61444
61449
  linewidth: 1.5,
61445
- depthTest: false,
61446
- depthWrite: false,
61450
+ depthTest: !edgesOverlap,
61451
+ depthWrite: !edgesOverlap,
61447
61452
  resolution: new Vector2(window.innerWidth, window.innerHeight),
61448
61453
  });
61449
61454
  this.highlightLineMaterial = new LineBasicMaterial({
@@ -61456,18 +61461,27 @@ void main() {
61456
61461
  linewidth: 5,
61457
61462
  transparent: true,
61458
61463
  opacity: 0.8,
61459
- depthTest: true,
61460
- depthWrite: true,
61464
+ depthTest: !edgesOverlap,
61465
+ depthWrite: !edgesOverlap,
61461
61466
  resolution: new Vector2(window.innerWidth, window.innerHeight),
61462
61467
  });
61463
61468
  };
61464
61469
  this.optionsChange = () => {
61465
- const { facesColor, facesTransparancy, edgesColor } = this.viewer.options;
61470
+ const { facesColor, facesTransparancy, edgesColor, edgesVisibility, edgesOverlap, facesOverlap } = this.viewer.options;
61466
61471
  this.highlightMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61467
61472
  this.highlightMaterial.opacity = (255 - facesTransparancy) / 255;
61473
+ this.highlightMaterial.depthTest = !facesOverlap;
61474
+ this.highlightMaterial.depthWrite = !facesOverlap;
61468
61475
  this.outlineMaterial.color.setRGB(edgesColor.r / 255, edgesColor.g / 255, edgesColor.b / 255);
61476
+ this.outlineMaterial.depthTest = !edgesOverlap;
61477
+ this.outlineMaterial.depthWrite = !edgesOverlap;
61469
61478
  this.highlightLineMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61470
61479
  this.highlightLineGlowMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
61480
+ this.viewer.selected.forEach((selected) => {
61481
+ const wireframe = selected.userData.highlightWireframe;
61482
+ if (wireframe)
61483
+ wireframe.visible = edgesVisibility;
61484
+ });
61471
61485
  this.viewer.update();
61472
61486
  };
61473
61487
  this.viewer = viewer;
@@ -61492,6 +61506,7 @@ void main() {
61492
61506
  this.viewer.removeEventListener("resize", this.viewerResize);
61493
61507
  }
61494
61508
  highlight(objects) {
61509
+ const { edgesVisibility } = this.viewer.options;
61495
61510
  if (!Array.isArray(objects))
61496
61511
  objects = [objects];
61497
61512
  if (!objects.length)
@@ -61509,21 +61524,23 @@ void main() {
61509
61524
  wireframe.position.copy(object.position);
61510
61525
  wireframe.rotation.copy(object.rotation);
61511
61526
  wireframe.scale.copy(object.scale);
61527
+ wireframe.visible = edgesVisibility;
61512
61528
  object.parent.add(wireframe);
61513
- object.userData.highlightwireframe = wireframe;
61529
+ object.userData.highlightWireframe = wireframe;
61514
61530
  object.userData.originalMaterial = object.material;
61515
61531
  object.material = this.highlightLineMaterial;
61516
61532
  object.isHighlighted = true;
61517
61533
  }
61518
61534
  else if (object.isMesh) {
61519
- const edgesGeometry = new EdgesGeometry(object.geometry, 30);
61535
+ const edgesGeometry = new EdgesGeometry(object.geometry, 60);
61520
61536
  const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
61521
61537
  const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
61522
61538
  wireframe.position.copy(object.position);
61523
61539
  wireframe.rotation.copy(object.rotation);
61524
61540
  wireframe.scale.copy(object.scale);
61541
+ wireframe.visible = edgesVisibility;
61525
61542
  object.parent.add(wireframe);
61526
- object.userData.highlightwireframe = wireframe;
61543
+ object.userData.highlightWireframe = wireframe;
61527
61544
  object.userData.originalMaterial = object.material;
61528
61545
  object.material = this.highlightMaterial;
61529
61546
  object.isHighlighted = true;
@@ -61540,9 +61557,9 @@ void main() {
61540
61557
  return;
61541
61558
  object.isHighlighted = false;
61542
61559
  object.material = object.userData.originalMaterial;
61543
- object.userData.highlightwireframe.removeFromParent();
61560
+ object.userData.highlightWireframe.removeFromParent();
61544
61561
  delete object.userData.originalMaterial;
61545
- delete object.userData.highlightwireframe;
61562
+ delete object.userData.highlightWireframe;
61546
61563
  });
61547
61564
  }
61548
61565
  viewerResize(event) {
@@ -61591,7 +61608,8 @@ void main() {
61591
61608
  this.viewer.models.forEach((model) => {
61592
61609
  const objects = model.getVisibleObjects();
61593
61610
  const intersects = this.getPointerIntersects(upPosition, objects);
61594
- intersections.push(...intersects.map((x) => ({ ...x, model })));
61611
+ if (intersects.length > 0)
61612
+ intersections.push({ ...intersects[0], model });
61595
61613
  });
61596
61614
  intersections = intersections.sort((a, b) => a.distance - b.distance);
61597
61615
  if (!event.shiftKey)
@@ -61658,7 +61676,6 @@ void main() {
61658
61676
  objects = [objects];
61659
61677
  if (!objects.length)
61660
61678
  return;
61661
- model.showObjects(objects);
61662
61679
  model.showOriginalObjects(objects);
61663
61680
  this.highlighter.highlight(objects);
61664
61681
  objects.forEach((object) => this.viewer.selected.push(object));
@@ -67314,10 +67331,8 @@ void main() {
67314
67331
  return objects;
67315
67332
  }
67316
67333
  hideObjects(objects) {
67317
- this.getOwnObjects(objects)
67318
- .map((object) => object.userData.handle)
67319
- .forEach((handle) => this.gltfLoader.hiddenHandles.add(handle));
67320
- this.gltfLoader.syncHiddenObjects();
67334
+ const handles = this.getHandlesByObjects(objects);
67335
+ this.gltfLoader.hideObjects(handles);
67321
67336
  return this;
67322
67337
  }
67323
67338
  isolateObjects(objects) {
@@ -67326,23 +67341,20 @@ void main() {
67326
67341
  return this;
67327
67342
  }
67328
67343
  showObjects(objects) {
67329
- this.getOwnObjects(objects)
67330
- .map((object) => object.userData.handle)
67331
- .forEach((handle) => this.gltfLoader.hiddenHandles.delete(handle));
67332
- this.gltfLoader.syncHiddenObjects();
67344
+ const handles = this.getHandlesByObjects(objects);
67345
+ this.gltfLoader.showObjects(handles);
67333
67346
  return this;
67334
67347
  }
67335
67348
  showAllObjects() {
67336
- this.gltfLoader.hiddenHandles.clear();
67337
- this.gltfLoader.syncHiddenObjects();
67349
+ this.gltfLoader.showAllHiddenObjects();
67338
67350
  return this;
67339
67351
  }
67340
67352
  showOriginalObjects(objects) {
67341
- this.getOwnObjects(objects).forEach((object) => (object.visible = true));
67353
+ this.gltfLoader.showOriginalObjects(objects);
67342
67354
  return this;
67343
67355
  }
67344
67356
  hideOriginalObjects(objects) {
67345
- this.getOwnObjects(objects).forEach((object) => (object.visible = false));
67357
+ this.gltfLoader.hideOriginalObjects(objects);
67346
67358
  return this;
67347
67359
  }
67348
67360
  }
@@ -67365,24 +67377,20 @@ void main() {
67365
67377
  TRIANGLE_STRIP: 5,
67366
67378
  TRIANGLE_FAN: 6};
67367
67379
 
67380
+ const MAX_GAP = 128 * 1024; // 128 KB
67381
+ const MAX_CHUNK = 30 * 1024 * 1024; // 100 MB
67382
+
67368
67383
  class GltfStructure {
67369
67384
  constructor(id) {
67370
67385
  this.id = `${id}`;
67371
67386
  this.json = null;
67372
67387
  this.baseUrl = "";
67373
-
67374
- // Binary manager properties
67375
67388
  this.loadController = null;
67376
- // Request batching parameters
67377
67389
  this.batchDelay = 10;
67378
67390
  this.maxBatchSize = 5 * 1024 * 1024;
67379
67391
  this.maxRangesPerRequest = 512;
67380
-
67381
- // Request queue
67382
67392
  this.pendingRequests = [];
67383
67393
  this.batchTimeout = null;
67384
-
67385
- // Material and texture properties
67386
67394
  this.textureLoader = new TextureLoader();
67387
67395
  this.materials = new Map();
67388
67396
  this.textureCache = new Map();
@@ -67414,57 +67422,110 @@ void main() {
67414
67422
  return this.json;
67415
67423
  }
67416
67424
 
67417
- // Schedule a request for processing
67418
67425
  scheduleRequest(request) {
67419
- this.pendingRequests.push(request);
67420
-
67421
- // Clear existing timeout
67422
- if (this.batchTimeout) {
67423
- clearTimeout(this.batchTimeout);
67424
- }
67425
-
67426
- // Set new timeout for batch processing
67427
- this.batchTimeout = setTimeout(() => this.processBatch(), this.batchDelay);
67428
-
67429
- // Return a promise that will resolve when the data is available
67430
67426
  return new Promise((resolve, reject) => {
67431
- request.resolve = resolve;
67432
- request.reject = reject;
67427
+ this.pendingRequests.push({
67428
+ ...request,
67429
+ _resolve: resolve,
67430
+ _reject: reject,
67431
+ });
67433
67432
  });
67434
67433
  }
67435
67434
 
67436
- async processBatch() {
67437
- if (this.pendingRequests.length === 0) return;
67438
-
67439
- // Take current batch of requests and clear timeout
67440
- const currentBatch = [...this.pendingRequests];
67435
+ async flushBufferRequests() {
67436
+ if (!this.pendingRequests || this.pendingRequests.length === 0) return;
67437
+ const requests = [...this.pendingRequests];
67441
67438
  this.pendingRequests = [];
67442
67439
 
67443
- if (this.batchTimeout) {
67444
- clearTimeout(this.batchTimeout);
67445
- this.batchTimeout = null;
67440
+ requests.sort((a, b) => a.offset - b.offset);
67441
+ const mergedRanges = [];
67442
+ let current = {
67443
+ start: requests[0].offset,
67444
+ end: requests[0].offset + requests[0].length,
67445
+ requests: [requests[0]],
67446
+ };
67447
+ for (let i = 1; i < requests.length; i++) {
67448
+ const req = requests[i];
67449
+ const gap = req.offset - current.end;
67450
+ const newEnd = Math.max(current.end, req.offset + req.length);
67451
+ const projectedSize = newEnd - current.start;
67452
+ if (gap <= MAX_GAP && projectedSize <= MAX_CHUNK) {
67453
+ current.end = newEnd;
67454
+ current.requests.push(req);
67455
+ } else {
67456
+ mergedRanges.push(current);
67457
+ current = {
67458
+ start: req.offset,
67459
+ end: req.offset + req.length,
67460
+ requests: [req],
67461
+ };
67462
+ }
67446
67463
  }
67447
- try {
67448
- // Split requests into smaller groups
67449
- for (let i = 0; i < currentBatch.length; i += this.maxRangesPerRequest) {
67450
- const batchRequests = currentBatch.slice(i, i + this.maxRangesPerRequest);
67451
- const buffer = await this.loadController.loadBinaryData(batchRequests);
67452
-
67453
- let currentOffset = 0;
67454
- batchRequests.forEach((request) => {
67455
- const view = this.createTypedArray(buffer, currentOffset, request.length, request.componentType);
67456
- request.resolve(view);
67457
- currentOffset += request.length;
67464
+ mergedRanges.push(current);
67465
+ const finalRanges = [];
67466
+ for (const range of mergedRanges) {
67467
+ let { start, end, requests } = range;
67468
+ while (end - start > MAX_CHUNK) {
67469
+ let splitIdx = 0;
67470
+ for (let i = 0; i < requests.length; i++) {
67471
+ if (requests[i].offset + requests[i].length - start > MAX_CHUNK) {
67472
+ break;
67473
+ }
67474
+ splitIdx = i;
67475
+ }
67476
+ const chunkRequests = requests.slice(0, splitIdx + 1);
67477
+ const chunkEnd =
67478
+ chunkRequests[chunkRequests.length - 1].offset + chunkRequests[chunkRequests.length - 1].length;
67479
+ finalRanges.push({
67480
+ start,
67481
+ end: chunkEnd,
67482
+ requests: chunkRequests,
67458
67483
  });
67484
+ requests = requests.slice(splitIdx + 1);
67485
+ if (requests.length > 0) {
67486
+ start = requests[0].offset;
67487
+ end = requests[0].offset + requests[0].length;
67488
+ for (let i = 1; i < requests.length; i++) {
67489
+ end = Math.max(end, requests[i].offset + requests[i].length);
67490
+ }
67491
+ }
67492
+ }
67493
+ if (requests.length > 0) {
67494
+ finalRanges.push({ start, end, requests });
67459
67495
  }
67460
- } catch (error) {
67461
- console.error("Error processing batch:", error);
67462
- currentBatch.forEach((request) => request.reject(error));
67463
67496
  }
67464
-
67465
- if (this.pendingRequests.length > 0) {
67466
- this.batchTimeout = setTimeout(() => this.processBatch(), this.batchDelay);
67497
+ /*
67498
+ for (const range of finalRanges) {
67499
+ const length = range.end - range.start;
67500
+ const buffer = await this.loadController.loadBinaryData([
67501
+ { offset: range.start, length: length }
67502
+ ]);
67503
+ for (const req of range.requests) {
67504
+ const relOffset = req.offset - range.start;
67505
+ try {
67506
+ req._resolve({ buffer, relOffset, length: req.length });
67507
+ } catch (e) {
67508
+ req._reject(e);
67509
+ }
67510
+ }
67467
67511
  }
67512
+ */
67513
+
67514
+ const promises = finalRanges.map(async (range) => {
67515
+ const length = range.end - range.start;
67516
+ const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
67517
+ for (const req of range.requests) {
67518
+ const relOffset = req.offset - range.start;
67519
+ try {
67520
+ req._resolve({ buffer, relOffset, length: req.length });
67521
+ } catch (e) {
67522
+ req._reject(e);
67523
+ }
67524
+ }
67525
+ });
67526
+ await Promise.all(promises);
67527
+
67528
+ this.pendingRequests = [];
67468
67529
  }
67469
67530
 
67470
67531
  getBufferView(byteOffset, byteLength, componentType) {
@@ -67477,12 +67538,10 @@ void main() {
67477
67538
 
67478
67539
  createTypedArray(buffer, offset, length, componentType) {
67479
67540
  try {
67480
- // Validate parameters
67481
67541
  if (!buffer || !(buffer instanceof ArrayBuffer)) {
67482
67542
  throw new Error("Invalid buffer");
67483
67543
  }
67484
67544
 
67485
- // Calculate element size for given type
67486
67545
  let elementSize;
67487
67546
  switch (componentType) {
67488
67547
  case 5120:
@@ -67501,18 +67560,15 @@ void main() {
67501
67560
  throw new Error(`Unsupported component type: ${componentType}`);
67502
67561
  }
67503
67562
 
67504
- // Check if requested length is correct
67505
67563
  const numElements = length / elementSize;
67506
67564
  if (!Number.isInteger(numElements)) {
67507
67565
  throw new Error(`Invalid length ${length} for component type ${componentType}`);
67508
67566
  }
67509
67567
 
67510
- // Check if buffer is large enough
67511
67568
  if (length > buffer.byteLength) {
67512
67569
  throw new Error(`Buffer too small: need ${length} bytes, but buffer is ${buffer.byteLength} bytes`);
67513
67570
  }
67514
67571
 
67515
- // Create appropriate typed array
67516
67572
  const ArrayType = GL_COMPONENT_TYPES[componentType];
67517
67573
  return new ArrayType(buffer, offset, numElements);
67518
67574
  } catch (error) {
@@ -67609,7 +67665,6 @@ void main() {
67609
67665
  const image = this.json.images[imageIndex];
67610
67666
 
67611
67667
  if (image.uri) {
67612
- // Handle base64 or URL
67613
67668
  if (image.uri.startsWith("data:")) {
67614
67669
  return await this.textureLoader.loadAsync(image.uri);
67615
67670
  } else {
@@ -67617,23 +67672,17 @@ void main() {
67617
67672
  return await this.textureLoader.loadAsync(fullUrl);
67618
67673
  }
67619
67674
  } else if (image.bufferView !== undefined) {
67620
- // Handle embedded binary data
67621
67675
  const bufferView = this.json.bufferViews[image.bufferView];
67622
- const array = await this.getBufferView(
67623
- bufferView.byteOffset || 0,
67624
- bufferView.byteLength,
67625
- 5121 // UNSIGNED_BYTE
67626
- );
67676
+ const array = await this.getBufferView(bufferView.byteOffset || 0, bufferView.byteLength, 5121);
67627
67677
  const blob = new Blob([array], { type: image.mimeType });
67628
67678
  const url = URL.createObjectURL(blob);
67629
67679
  const texture = await this.textureLoader.loadAsync(url);
67630
67680
  URL.revokeObjectURL(url);
67631
- texture.flipY = false; // GLTF standard
67681
+ texture.flipY = false;
67632
67682
  return texture;
67633
67683
  }
67634
67684
  };
67635
67685
 
67636
- // Load all textures
67637
67686
  const texturePromises = [];
67638
67687
  for (let i = 0; i < this.json.textures.length; i++) {
67639
67688
  texturePromises.push(
@@ -67643,82 +67692,56 @@ void main() {
67643
67692
  await Promise.all(texturePromises);
67644
67693
  }
67645
67694
 
67646
- loadMaterials() {
67695
+ async loadMaterials() {
67647
67696
  if (!this.json.materials) return this.materials;
67648
67697
 
67649
67698
  for (let i = 0; i < this.json.materials.length; i++) {
67650
67699
  const materialDef = this.json.materials[i];
67651
- const material = this.createMaterial(materialDef);
67700
+ const material = await this.createMaterial(materialDef);
67701
+ material.name = materialDef.name;
67652
67702
  this.materials.set(i, material);
67653
67703
  }
67654
67704
  return this.materials;
67655
67705
  }
67656
67706
 
67657
67707
  createMaterial(materialDef) {
67658
- const material = new MeshStandardMaterial();
67708
+ const params = {};
67659
67709
 
67660
- // Base color
67661
67710
  if (materialDef.pbrMetallicRoughness) {
67662
67711
  const pbr = materialDef.pbrMetallicRoughness;
67663
-
67664
67712
  if (pbr.baseColorFactor) {
67665
- material.color.fromArray(pbr.baseColorFactor);
67666
- material.opacity = pbr.baseColorFactor[3];
67713
+ params.color = new Color().fromArray(pbr.baseColorFactor);
67714
+ params.opacity = pbr.baseColorFactor[3];
67715
+ if (params.opacity < 1.0) params.transparent = true;
67667
67716
  }
67668
-
67669
67717
  if (pbr.baseColorTexture) {
67670
- material.map = this.textureCache.get(pbr.baseColorTexture.index);
67671
- }
67672
-
67673
- // Metallic and roughness
67674
- if (pbr.metallicFactor !== undefined) {
67675
- material.metalness = pbr.metallicFactor;
67676
- }
67677
- if (pbr.roughnessFactor !== undefined) {
67678
- material.roughness = pbr.roughnessFactor;
67679
- }
67680
- if (pbr.metallicRoughnessTexture) {
67681
- material.metalnessMap = this.textureCache.get(pbr.metallicRoughnessTexture.index);
67682
- material.roughnessMap = material.metalnessMap;
67718
+ params.map = this.textureCache.get(pbr.baseColorTexture.index);
67683
67719
  }
67684
67720
  }
67685
67721
 
67686
- // Normal map
67687
- if (materialDef.normalTexture) {
67688
- material.normalMap = this.textureCache.get(materialDef.normalTexture.index);
67689
- if (materialDef.normalTexture.scale !== undefined) {
67690
- material.normalScale.set(materialDef.normalTexture.scale, materialDef.normalTexture.scale);
67691
- }
67692
- }
67722
+ params.specular = 0x222222;
67723
+ params.shininess = 10;
67724
+ params.reflectivity = 0.05;
67725
+ params.polygonOffset = true;
67726
+ params.polygonOffsetFactor = 1;
67727
+ params.polygonOffsetUnits = 1;
67693
67728
 
67694
- // Emissive
67695
67729
  if (materialDef.emissiveFactor) {
67696
- material.emissive.fromArray(materialDef.emissiveFactor);
67697
- }
67698
- if (materialDef.emissiveTexture) {
67699
- material.emissiveMap = this.textureCache.get(materialDef.emissiveTexture.index);
67730
+ params.emissive = new Color().fromArray(materialDef.emissiveFactor);
67700
67731
  }
67701
67732
 
67702
- // Occlusion
67703
- if (materialDef.occlusionTexture) {
67704
- material.aoMap = this.textureCache.get(materialDef.occlusionTexture.index);
67705
- if (materialDef.occlusionTexture.strength !== undefined) {
67706
- material.aoMapIntensity = materialDef.occlusionTexture.strength;
67707
- }
67733
+ if (materialDef.normalTexture) {
67734
+ params.normalMap = this.textureCache.get(materialDef.normalTexture.index);
67708
67735
  }
67709
67736
 
67710
- // Alpha mode
67711
67737
  if (materialDef.alphaMode === "BLEND") {
67712
- material.transparent = true;
67713
- } else if (materialDef.alphaMode === "MASK") {
67714
- material.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
67738
+ params.transparent = true;
67715
67739
  }
67716
67740
 
67717
- // Double sided
67718
- material.side = materialDef.doubleSided ? DoubleSide : FrontSide;
67719
-
67720
- material.name = materialDef.name;
67721
-
67741
+ if (materialDef.doubleSided) {
67742
+ params.side = DoubleSide;
67743
+ }
67744
+ const material = new MeshPhongMaterial(params);
67722
67745
  return material;
67723
67746
  }
67724
67747
 
@@ -67751,12 +67774,8 @@ void main() {
67751
67774
  if (!meshDef || !meshDef.primitives) return 0;
67752
67775
 
67753
67776
  let totalSize = 0;
67754
-
67755
- // Estimate size for each primitive
67756
67777
  for (const primitive of meshDef.primitives) {
67757
- // Check for attributes
67758
67778
  if (primitive.attributes) {
67759
- // Calculate attributes size
67760
67779
  for (const [, accessorIndex] of Object.entries(primitive.attributes)) {
67761
67780
  if (accessorIndex === undefined) continue;
67762
67781
 
@@ -67769,7 +67788,6 @@ void main() {
67769
67788
  }
67770
67789
  }
67771
67790
 
67772
- // Calculate indices size if present
67773
67791
  if (primitive.indices !== undefined) {
67774
67792
  const accessor = this.json.accessors[primitive.indices];
67775
67793
  if (accessor) {
@@ -67842,7 +67860,9 @@ void main() {
67842
67860
  this.mergedPoints = new Set();
67843
67861
 
67844
67862
  this.isolatedObjects = [];
67845
- this.useVAO = !!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext;
67863
+ //!!window.WebGL2RenderingContext && this.renderer.getContext() instanceof WebGL2RenderingContext
67864
+ this.useVAO = false;
67865
+ this.visibleEdges = true;
67846
67866
 
67847
67867
  this.handleToOptimizedObjects = new Map();
67848
67868
 
@@ -67851,6 +67871,10 @@ void main() {
67851
67871
  this.oldOptimizeObjects = new Set();
67852
67872
  }
67853
67873
 
67874
+ setVisibleEdges(visible) {
67875
+ this.visibleEdges = visible;
67876
+ }
67877
+
67854
67878
  getAvailableMemory() {
67855
67879
  let memoryLimit = 6 * 1024 * 1024 * 1024;
67856
67880
  try {
@@ -67871,7 +67895,7 @@ void main() {
67871
67895
  console.warn("Error detecting available memory:", error);
67872
67896
  }
67873
67897
 
67874
- return memoryLimit;
67898
+ return memoryLimit / 3;
67875
67899
  }
67876
67900
 
67877
67901
  getAbortController() {
@@ -67976,7 +68000,7 @@ void main() {
67976
68000
  console.log(`Final memory usage: ${Math.round(currentMemoryUsage / (1024 * 1024))}MB`);
67977
68001
  }
67978
68002
 
67979
- async loadNode(nodeId) {
68003
+ async loadNode(nodeId, onLoadFinishCb) {
67980
68004
  const node = this.nodes.get(nodeId);
67981
68005
  if (!node || node.loaded || node.loading) return;
67982
68006
 
@@ -67984,38 +68008,138 @@ void main() {
67984
68008
  const meshDef = node.structure.getJson().meshes[node.meshIndex];
67985
68009
 
67986
68010
  try {
67987
- for (const primitive of meshDef.primitives) {
67988
- const positionAccessor = primitive.attributes.POSITION;
67989
- const geometry = new BufferGeometry();
67990
- const attributes = new Map();
67991
-
67992
- attributes.set("position", node.structure.createBufferAttribute(positionAccessor));
68011
+ const bufferRequests = [];
68012
+ const primitiveReqMap = new Map();
68013
+ for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
68014
+ const primitive = meshDef.primitives[primIdx];
68015
+ const reqs = [];
68016
+
68017
+ if (primitive.attributes.POSITION !== undefined) {
68018
+ const accessorIndex = primitive.attributes.POSITION;
68019
+ const accessor = node.structure.json.accessors[accessorIndex];
68020
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68021
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68022
+ const components = node.structure.getNumComponents(accessor.type);
68023
+ const count = accessor.count;
68024
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68025
+ reqs.push({
68026
+ offset: byteOffset,
68027
+ length: byteLength,
68028
+ componentType: accessor.componentType,
68029
+ accessorIndex,
68030
+ type: "position",
68031
+ primIdx,
68032
+ });
68033
+ }
67993
68034
 
67994
68035
  if (primitive.attributes.NORMAL !== undefined) {
67995
- attributes.set("normal", node.structure.createBufferAttribute(primitive.attributes.NORMAL));
68036
+ const accessorIndex = primitive.attributes.NORMAL;
68037
+ const accessor = node.structure.json.accessors[accessorIndex];
68038
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68039
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68040
+ const components = node.structure.getNumComponents(accessor.type);
68041
+ const count = accessor.count;
68042
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68043
+ reqs.push({
68044
+ offset: byteOffset,
68045
+ length: byteLength,
68046
+ componentType: accessor.componentType,
68047
+ accessorIndex,
68048
+ type: "normal",
68049
+ primIdx,
68050
+ });
67996
68051
  }
67997
68052
 
67998
68053
  if (primitive.attributes.TEXCOORD_0 !== undefined) {
67999
- attributes.set("uv", node.structure.createBufferAttribute(primitive.attributes.TEXCOORD_0));
68054
+ const accessorIndex = primitive.attributes.TEXCOORD_0;
68055
+ const accessor = node.structure.json.accessors[accessorIndex];
68056
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68057
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68058
+ const components = node.structure.getNumComponents(accessor.type);
68059
+ const count = accessor.count;
68060
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68061
+ reqs.push({
68062
+ offset: byteOffset,
68063
+ length: byteLength,
68064
+ componentType: accessor.componentType,
68065
+ accessorIndex,
68066
+ type: "uv",
68067
+ primIdx,
68068
+ });
68069
+ }
68070
+
68071
+ if (primitive.indices !== undefined) {
68072
+ const accessorIndex = primitive.indices;
68073
+ const accessor = node.structure.json.accessors[accessorIndex];
68074
+ const bufferView = node.structure.json.bufferViews[accessor.bufferView];
68075
+ const byteOffset = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0);
68076
+ const components = node.structure.getNumComponents(accessor.type);
68077
+ const count = accessor.count;
68078
+ const byteLength = count * components * node.structure.getComponentSize(accessor.componentType);
68079
+ reqs.push({
68080
+ offset: byteOffset,
68081
+ length: byteLength,
68082
+ componentType: accessor.componentType,
68083
+ accessorIndex,
68084
+ type: "index",
68085
+ primIdx,
68086
+ });
68000
68087
  }
68088
+ primitiveReqMap.set(primIdx, reqs);
68089
+ bufferRequests.push(...reqs);
68090
+ }
68001
68091
 
68002
- const loadedAttributes = await Promise.all(
68003
- [...attributes.entries()].map(async ([name, promise]) => {
68004
- const attribute = await promise;
68005
- return [name, attribute];
68006
- })
68007
- );
68092
+ if (bufferRequests.length === 0) {
68093
+ node.loaded = true;
68094
+ node.loading = false;
68095
+ return;
68096
+ }
68097
+ bufferRequests.sort((a, b) => a.offset - b.offset);
68098
+ const minOffset = bufferRequests[0].offset;
68099
+ const maxOffset = Math.max(...bufferRequests.map((r) => r.offset + r.length));
68100
+ const totalLength = maxOffset - minOffset;
68101
+
68102
+ const { buffer, relOffset: baseRelOffset } = await node.structure.scheduleRequest({
68103
+ offset: minOffset,
68104
+ length: totalLength,
68105
+ componentType: null,
68106
+ });
68008
68107
 
68009
- loadedAttributes.forEach(([name, attribute]) => {
68010
- geometry.setAttribute(name, attribute);
68011
- });
68108
+ for (const req of bufferRequests) {
68109
+ const relOffset = req.offset - minOffset;
68110
+ req.data = node.structure.createTypedArray(buffer, baseRelOffset + relOffset, req.length, req.componentType);
68111
+ }
68012
68112
 
68013
- if (primitive.indices !== undefined) {
68014
- const indexAttribute = await node.structure.createBufferAttribute(primitive.indices);
68015
- geometry.setIndex(indexAttribute);
68113
+ for (let primIdx = 0; primIdx < meshDef.primitives.length; primIdx++) {
68114
+ const primitive = meshDef.primitives[primIdx];
68115
+ const geometry = new BufferGeometry();
68116
+ const reqs = primitiveReqMap.get(primIdx);
68117
+
68118
+ if (primitive.attributes.POSITION !== undefined) {
68119
+ const req = reqs.find((r) => r.type === "position" && r.accessorIndex === primitive.attributes.POSITION);
68120
+ const accessor = node.structure.json.accessors[primitive.attributes.POSITION];
68121
+ const components = node.structure.getNumComponents(accessor.type);
68122
+ geometry.setAttribute("position", new BufferAttribute(req.data, components));
68016
68123
  }
68017
68124
 
68018
- this.currentPrimitiveMode = primitive.mode;
68125
+ if (primitive.attributes.NORMAL !== undefined) {
68126
+ const req = reqs.find((r) => r.type === "normal" && r.accessorIndex === primitive.attributes.NORMAL);
68127
+ const accessor = node.structure.json.accessors[primitive.attributes.NORMAL];
68128
+ const components = node.structure.getNumComponents(accessor.type);
68129
+ geometry.setAttribute("normal", new BufferAttribute(req.data, components));
68130
+ }
68131
+
68132
+ if (primitive.attributes.TEXCOORD_0 !== undefined) {
68133
+ const req = reqs.find((r) => r.type === "uv" && r.accessorIndex === primitive.attributes.TEXCOORD_0);
68134
+ const accessor = node.structure.json.accessors[primitive.attributes.TEXCOORD_0];
68135
+ const components = node.structure.getNumComponents(accessor.type);
68136
+ geometry.setAttribute("uv", new BufferAttribute(req.data, components));
68137
+ }
68138
+
68139
+ if (primitive.indices !== undefined) {
68140
+ const req = reqs.find((r) => r.type === "index" && r.accessorIndex === primitive.indices);
68141
+ geometry.setIndex(new BufferAttribute(req.data, 1));
68142
+ }
68019
68143
 
68020
68144
  let material;
68021
68145
  if (primitive.material !== undefined) {
@@ -68030,8 +68154,7 @@ void main() {
68030
68154
  Material.prototype.copy.call(pointsMaterial, material);
68031
68155
  pointsMaterial.color.copy(material.color);
68032
68156
  pointsMaterial.map = material.map;
68033
- pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
68034
-
68157
+ pointsMaterial.sizeAttenuation = false;
68035
68158
  mesh = new Points(geometry, pointsMaterial);
68036
68159
  } else if (
68037
68160
  primitive.mode === GL_CONSTANTS.TRIANGLES ||
@@ -68040,7 +68163,6 @@ void main() {
68040
68163
  primitive.mode === undefined
68041
68164
  ) {
68042
68165
  mesh = new Mesh(geometry, material);
68043
-
68044
68166
  if (primitive.mode === GL_CONSTANTS.TRIANGLE_STRIP) {
68045
68167
  mesh.drawMode = TriangleStripDrawMode;
68046
68168
  } else if (primitive.mode === GL_CONSTANTS.TRIANGLE_FAN) {
@@ -68053,39 +68175,30 @@ void main() {
68053
68175
  } else if (primitive.mode === GL_CONSTANTS.LINE_LOOP) {
68054
68176
  mesh = new LineLoop(geometry, material);
68055
68177
  }
68056
-
68057
68178
  if (node.extras) {
68058
68179
  mesh.userData = { ...mesh.userData, ...node.extras };
68059
68180
  }
68060
-
68061
68181
  if (meshDef.extras) {
68062
68182
  mesh.userData = { ...mesh.userData, ...meshDef.extras };
68063
68183
  }
68064
-
68065
68184
  if (primitive.extras) {
68066
68185
  mesh.userData = { ...mesh.userData, ...primitive.extras };
68067
68186
  }
68068
-
68069
68187
  if (node.handle) {
68070
68188
  mesh.userData.handle = node.handle;
68071
68189
  } else {
68072
68190
  mesh.userData.handle = `${node.structure.id}_${mesh.userData.handle}`;
68073
68191
  }
68074
-
68075
68192
  if (mesh.material.name === "edges") {
68076
68193
  mesh.userData.isEdge = true;
68077
68194
  } else {
68078
68195
  mesh.userData.isEdge = false;
68079
68196
  }
68080
-
68081
68197
  this.registerObjectWithHandle(mesh, mesh.userData.handle);
68082
-
68083
68198
  mesh.position.copy(node.position);
68084
-
68085
68199
  if (!geometry.attributes.normal) {
68086
68200
  geometry.computeVertexNormals();
68087
68201
  }
68088
-
68089
68202
  if (material.aoMap && geometry.attributes.uv) {
68090
68203
  geometry.setAttribute("uv2", geometry.attributes.uv);
68091
68204
  }
@@ -68095,17 +68208,17 @@ void main() {
68095
68208
  this.scene.add(mesh);
68096
68209
  }
68097
68210
  node.object = mesh;
68098
-
68099
68211
  this.totalLoadedObjects++;
68100
68212
  mesh.visible = this.totalLoadedObjects < this.graphicsObjectLimit;
68101
68213
  }
68102
-
68103
68214
  node.loaded = true;
68104
68215
  node.loading = false;
68105
-
68106
68216
  const geometrySize = this.estimateGeometrySize(node.object);
68107
68217
  this.geometryCache.set(node.object.uuid, geometrySize);
68108
68218
  this.currentMemoryUsage += geometrySize;
68219
+ if (onLoadFinishCb) {
68220
+ onLoadFinishCb();
68221
+ }
68109
68222
  } catch (error) {
68110
68223
  if (error.name !== "AbortError") {
68111
68224
  console.error(`Error loading node ${nodeId}:`, error);
@@ -68230,7 +68343,7 @@ void main() {
68230
68343
  return volumeB - volumeA;
68231
68344
  });
68232
68345
 
68233
- if (!ignoreEdges) {
68346
+ if (!ignoreEdges && this.visibleEdges) {
68234
68347
  this.nodesToLoad.push(...this.edgeNodes);
68235
68348
  }
68236
68349
 
@@ -68357,33 +68470,13 @@ void main() {
68357
68470
  async processNodes() {
68358
68471
  const nodesToLoad = this.nodesToLoad;
68359
68472
  let loadedCount = 0;
68473
+ let lastLoadedCount = 0;
68360
68474
  const totalNodes = nodesToLoad.length;
68361
68475
 
68362
- try {
68363
- while (loadedCount < totalNodes) {
68364
- const batch = nodesToLoad.slice(loadedCount, loadedCount + this.batchSize);
68365
- const batchPromises = [];
68366
-
68367
- for (const nodeId of batch) {
68368
- if (this.abortController.signal.aborted) {
68369
- throw new DOMException("Loading aborted", "AbortError");
68370
- }
68371
-
68372
- const estimatedSize = await this.estimateNodeSize(nodeId);
68373
-
68374
- if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
68375
- console.log(`Memory limit reached after loading ${loadedCount} nodes`);
68376
- this.dispatchEvent("geometryerror", { message: "Memory limit reached" });
68377
- this.dispatchEvent("update");
68378
- return loadedCount;
68379
- }
68380
-
68381
- batchPromises.push(this.loadNode(nodeId));
68382
- }
68383
-
68384
- await Promise.all(batchPromises);
68385
- loadedCount += batch.length;
68386
-
68476
+ const loadProgress = async () => {
68477
+ loadedCount++;
68478
+ if (loadedCount - lastLoadedCount > 1000) {
68479
+ lastLoadedCount = loadedCount;
68387
68480
  this.updateMemoryIndicator();
68388
68481
  this.dispatchEvent("geometryprogress", {
68389
68482
  percentage: Math.round((loadedCount / totalNodes) * 100),
@@ -68401,6 +68494,34 @@ void main() {
68401
68494
  setTimeout(resolve, 0);
68402
68495
  });
68403
68496
  }
68497
+ };
68498
+
68499
+ try {
68500
+ const loadOperations = [];
68501
+ for (const nodeId of nodesToLoad) {
68502
+ if (this.abortController.signal.aborted) {
68503
+ throw new DOMException("Loading aborted", "AbortError");
68504
+ }
68505
+
68506
+ const estimatedSize = await this.estimateNodeSize(nodeId);
68507
+
68508
+ if (this.currentMemoryUsage + estimatedSize > this.memoryLimit) {
68509
+ console.log(`Memory limit reached after loading ${loadedCount} nodes`);
68510
+ this.dispatchEvent("geometryerror", {
68511
+ message: "Memory limit reached",
68512
+ });
68513
+ this.dispatchEvent("update");
68514
+ return loadedCount;
68515
+ }
68516
+
68517
+ loadOperations.push(this.loadNode(nodeId, loadProgress));
68518
+ }
68519
+
68520
+ for (const structure of this.structures) {
68521
+ loadOperations.push(structure.flushBufferRequests());
68522
+ }
68523
+
68524
+ await Promise.all(loadOperations);
68404
68525
 
68405
68526
  this.dispatchEvent("geometryend", {
68406
68527
  totalLoaded: loadedCount,
@@ -69381,6 +69502,25 @@ void main() {
69381
69502
  }
69382
69503
  });
69383
69504
  }
69505
+
69506
+ // Возвращает bounding box для конкретной структуры
69507
+ getStructureGeometryExtent(structureId) {
69508
+ const extent = new Box3();
69509
+ for (const [nodeId, node] of this.nodes.entries()) {
69510
+ if (!node.geometryExtents) continue;
69511
+ if (!nodeId.startsWith(structureId + "_")) continue;
69512
+ if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
69513
+ const transformedBox = node.geometryExtents.clone();
69514
+ if (node.group && node.group.matrix) {
69515
+ transformedBox.applyMatrix4(node.group.matrix);
69516
+ if (node.group.parent && node.group.parent.matrix) {
69517
+ transformedBox.applyMatrix4(node.group.parent.matrix);
69518
+ }
69519
+ }
69520
+ extent.union(transformedBox);
69521
+ }
69522
+ return extent;
69523
+ }
69384
69524
  }
69385
69525
 
69386
69526
  ///////////////////////////////////////////////////////////////////////////////
@@ -69409,7 +69549,6 @@ void main() {
69409
69549
  constructor(viewer) {
69410
69550
  this.requestId = 0;
69411
69551
  this.viewer = viewer;
69412
- this.scene = new Group$1();
69413
69552
  }
69414
69553
  dispose() {
69415
69554
  if (this.gltfLoader)
@@ -69423,27 +69562,25 @@ void main() {
69423
69562
  /.gltf$/i.test(file.database));
69424
69563
  }
69425
69564
  async load(model, format, params) {
69426
- this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, this.viewer.scene, this.viewer.renderer);
69565
+ const scene = new Group$1();
69566
+ this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
69427
69567
  this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
69428
69568
  this.gltfLoader.addEventListener("databasechunk", (data) => {
69429
- const modelImpl = new DynamicModelImpl(this.scene);
69569
+ const modelImpl = new DynamicModelImpl(scene);
69430
69570
  modelImpl.loader = this;
69431
69571
  modelImpl.gltfLoader = this.gltfLoader;
69432
69572
  modelImpl.viewer = this.viewer;
69433
- this.viewer.scene.add(this.scene);
69573
+ this.viewer.scene.add(scene);
69434
69574
  this.viewer.models.push(modelImpl);
69435
69575
  this.viewer.syncOptions();
69436
69576
  this.viewer.syncOverlay();
69437
69577
  this.viewer.update();
69438
- this.viewer.emitEvent({ type: "databasechunk", data, file: model.file, model });
69578
+ this.viewer.emitEvent({ type: "databasechunk", data: scene, file: model.file, model });
69439
69579
  });
69440
69580
  this.gltfLoader.addEventListener("geometryprogress", (data) => {
69441
69581
  const progress = data.loaded / data.total;
69442
69582
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model });
69443
69583
  });
69444
- this.gltfLoader.addEventListener("geometrymemory", (data) => {
69445
- this.viewer.emit({ type: "geometryprogress", data });
69446
- });
69447
69584
  this.gltfLoader.addEventListener("geometryerror", (data) => {
69448
69585
  this.viewer.emitEvent({ type: "geometryerror", data, file: model.file, model });
69449
69586
  });
@@ -69477,9 +69614,8 @@ void main() {
69477
69614
  return this;
69478
69615
  }
69479
69616
  cancel() {
69480
- if (this.gltfLoader) {
69617
+ if (this.gltfLoader)
69481
69618
  this.gltfLoader.abortLoading();
69482
- }
69483
69619
  }
69484
69620
  }
69485
69621
 
@@ -69517,7 +69653,7 @@ void main() {
69517
69653
  *
69518
69654
  * The loader should do:
69519
69655
  *
69520
- * - Load scene from file. The scene must be a Three.js object of type `Object3D` or a descendant of it.
69656
+ * - Load raw data from file and convert it to the `Three.js` scene.
69521
69657
  * - Add scene to the viewer `scene`.
69522
69658
  * - Create `ModelImpl` for the scene and to the viewer `models` list.
69523
69659
  * - Synchronize viewer options and overlay.
@@ -81628,7 +81764,7 @@ void main() {
81628
81764
  const attrs = e.target.attrs;
81629
81765
  if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
81630
81766
  }));
81631
- this._ref.on("transformend", (e => {
81767
+ this._ref.on("transformend", (() => {
81632
81768
  const absoluteTransform = this._ref.getAbsoluteTransform();
81633
81769
  const wcsPoints = [];
81634
81770
  const points = this._ref.points();
@@ -81650,7 +81786,7 @@ void main() {
81650
81786
  }
81651
81787
  this._ref.setAttr("wcsPoints", wcsPoints);
81652
81788
  }));
81653
- this._ref.on("dragend", (e => {
81789
+ this._ref.on("dragend", (() => {
81654
81790
  const absoluteTransform = this._ref.getAbsoluteTransform();
81655
81791
  const wcsPoints = [];
81656
81792
  const points = this._ref.points();
@@ -81840,7 +81976,7 @@ void main() {
81840
81976
  });
81841
81977
  this._ref.setAttr("wcsStart", this._worldTransformer.screenToWorld(position));
81842
81978
  }));
81843
- this._ref.on("dragend", (e => {
81979
+ this._ref.on("dragend", (() => {
81844
81980
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
81845
81981
  const position = absoluteTransform.point({
81846
81982
  x: this._ref.x(),
@@ -82028,7 +82164,7 @@ void main() {
82028
82164
  y: position.y + this._ref.height()
82029
82165
  }));
82030
82166
  }));
82031
- this._ref.on("dragend", (e => {
82167
+ this._ref.on("dragend", (() => {
82032
82168
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82033
82169
  const position = absoluteTransform.point({
82034
82170
  x: this._ref.x(),
@@ -82253,7 +82389,7 @@ void main() {
82253
82389
  y: 1
82254
82390
  });
82255
82391
  }));
82256
- this._ref.on("transformend", (e => {
82392
+ this._ref.on("transformend", (() => {
82257
82393
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82258
82394
  const position = absoluteTransform.point({
82259
82395
  x: this._ref.x(),
@@ -82271,7 +82407,7 @@ void main() {
82271
82407
  });
82272
82408
  this._ref.setAttr("wcsRadiusY", this._worldTransformer.screenToWorld(radiusY));
82273
82409
  }));
82274
- this._ref.on("dragend", (e => {
82410
+ this._ref.on("dragend", (() => {
82275
82411
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82276
82412
  const position = absoluteTransform.point({
82277
82413
  x: this._ref.x(),
@@ -82685,7 +82821,7 @@ void main() {
82685
82821
  y: 1
82686
82822
  });
82687
82823
  }));
82688
- this._ref.on("transformend", (e => {
82824
+ this._ref.on("transformend", (() => {
82689
82825
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82690
82826
  const position = absoluteTransform.point({
82691
82827
  x: this._ref.x(),
@@ -82697,7 +82833,7 @@ void main() {
82697
82833
  y: position.y + this._ref.height()
82698
82834
  }));
82699
82835
  }));
82700
- this._ref.on("dragend", (e => {
82836
+ this._ref.on("dragend", (() => {
82701
82837
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82702
82838
  const position = absoluteTransform.point({
82703
82839
  x: this._ref.x(),
@@ -82986,7 +83122,7 @@ void main() {
82986
83122
  y: position.y + this._ref.height()
82987
83123
  }));
82988
83124
  }));
82989
- this._ref.on("dragend", (e => {
83125
+ this._ref.on("dragend", (() => {
82990
83126
  const absoluteTransform = this._ref.getStage().getAbsoluteTransform();
82991
83127
  const position = absoluteTransform.point({
82992
83128
  x: this._ref.x(),
@@ -83188,12 +83324,12 @@ void main() {
83188
83324
  markupObject.updateScreenCoordinates();
83189
83325
  }));
83190
83326
  };
83191
- this.pan = event => {
83327
+ this.pan = () => {
83192
83328
  this.getObjects().forEach((markupObject => {
83193
83329
  markupObject.updateScreenCoordinates();
83194
83330
  }));
83195
83331
  };
83196
- this.zoomAt = event => {
83332
+ this.zoomAt = () => {
83197
83333
  this.getObjects().forEach((markupObject => {
83198
83334
  markupObject.updateScreenCoordinates();
83199
83335
  }));
@@ -83456,7 +83592,7 @@ void main() {
83456
83592
  lastLine = this.addLine([ pos.x, pos.y, pos.x, pos.y ]);
83457
83593
  }
83458
83594
  }));
83459
- stage.on("mouseup touchend", (e => {
83595
+ stage.on("mouseup touchend", (() => {
83460
83596
  if (!this._markupIsActive) return;
83461
83597
  if (isPaint) {
83462
83598
  const pos = this.getRelativePointerPosition(stage);
@@ -83498,7 +83634,7 @@ void main() {
83498
83634
  lastObj = undefined;
83499
83635
  isPaint = false;
83500
83636
  }));
83501
- stage.on("mousemove touchmove", (e => {
83637
+ stage.on("mousemove touchmove", (() => {
83502
83638
  if (!this._markupIsActive) return;
83503
83639
  if (!isPaint) {
83504
83640
  return;
@@ -83878,7 +84014,7 @@ void main() {
83878
84014
  y: this._imageInputPos.y
83879
84015
  }, null, base64.toString(), 0, 0);
83880
84016
  };
83881
- this._imageInputRef.oncancel = event => {
84017
+ this._imageInputRef.oncancel = () => {
83882
84018
  this.removeImageInput();
83883
84019
  };
83884
84020
  document.body.appendChild(this._imageInputRef);
@@ -84065,13 +84201,17 @@ void main() {
84065
84201
  this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
84066
84202
  this.scene = new Scene();
84067
84203
  this.helpers = new Scene();
84204
+ this.target = new Vector3();
84068
84205
  const pixelRatio = window.devicePixelRatio;
84069
84206
  const rect = canvas.parentElement.getBoundingClientRect();
84070
84207
  const width = rect.width || 1;
84071
84208
  const height = rect.height || 1;
84072
84209
  const aspect = width / height;
84073
84210
  this.camera = new PerspectiveCamera(45, aspect, 0.01, 1000);
84074
- this.camera.up.set(0, 0, 1);
84211
+ this.camera.up.set(0, 1, 0);
84212
+ this.camera.position.set(0, 0, 1);
84213
+ this.camera.lookAt(this.target);
84214
+ this.camera.updateProjectionMatrix();
84075
84215
  this.renderer = new WebGLRenderer({
84076
84216
  canvas,
84077
84217
  antialias: true,