@inweb/viewer-three 26.9.6 → 26.9.8

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.
@@ -3509,11 +3509,11 @@
3509
3509
  if ( this.isEmpty() ) {
3510
3510
  return false;
3511
3511
  }
3512
- this.getCenter( _center );
3513
- _extents.subVectors( this.max, _center );
3514
- _v0$2.subVectors( triangle.a, _center );
3515
- _v1$7.subVectors( triangle.b, _center );
3516
- _v2$4.subVectors( triangle.c, _center );
3512
+ this.getCenter( _center$1 );
3513
+ _extents.subVectors( this.max, _center$1 );
3514
+ _v0$2.subVectors( triangle.a, _center$1 );
3515
+ _v1$7.subVectors( triangle.b, _center$1 );
3516
+ _v2$4.subVectors( triangle.c, _center$1 );
3517
3517
  _f0.subVectors( _v1$7, _v0$2 );
3518
3518
  _f1.subVectors( _v2$4, _v1$7 );
3519
3519
  _f2.subVectors( _v0$2, _v2$4 );
@@ -3610,7 +3610,7 @@
3610
3610
  const _f0 = new Vector3();
3611
3611
  const _f1 = new Vector3();
3612
3612
  const _f2 = new Vector3();
3613
- const _center = new Vector3();
3613
+ const _center$1 = new Vector3();
3614
3614
  const _extents = new Vector3();
3615
3615
  const _triangleNormal = new Vector3();
3616
3616
  const _testAxis = new Vector3();
@@ -8899,7 +8899,7 @@
8899
8899
  const _skinWeight = new Vector4();
8900
8900
  const _vector3 = new Vector3();
8901
8901
  const _matrix4 = new Matrix4();
8902
- const _vertex = new Vector3();
8902
+ const _vertex$1 = new Vector3();
8903
8903
  const _sphere$5 = new Sphere();
8904
8904
  const _inverseMatrix$2 = new Matrix4();
8905
8905
  const _ray$2 = new Ray();
@@ -8922,8 +8922,8 @@
8922
8922
  this.boundingBox.makeEmpty();
8923
8923
  const positionAttribute = geometry.getAttribute( 'position' );
8924
8924
  for ( let i = 0; i < positionAttribute.count; i ++ ) {
8925
- this.getVertexPosition( i, _vertex );
8926
- this.boundingBox.expandByPoint( _vertex );
8925
+ this.getVertexPosition( i, _vertex$1 );
8926
+ this.boundingBox.expandByPoint( _vertex$1 );
8927
8927
  }
8928
8928
  }
8929
8929
  computeBoundingSphere() {
@@ -8934,8 +8934,8 @@
8934
8934
  this.boundingSphere.makeEmpty();
8935
8935
  const positionAttribute = geometry.getAttribute( 'position' );
8936
8936
  for ( let i = 0; i < positionAttribute.count; i ++ ) {
8937
- this.getVertexPosition( i, _vertex );
8938
- this.boundingSphere.expandByPoint( _vertex );
8937
+ this.getVertexPosition( i, _vertex$1 );
8938
+ this.boundingSphere.expandByPoint( _vertex$1 );
8939
8939
  }
8940
8940
  }
8941
8941
  copy( source, recursive ) {
@@ -10588,8 +10588,8 @@
10588
10588
  object: object
10589
10589
  };
10590
10590
  }
10591
- const _start$1 = new Vector3();
10592
- const _end$1 = new Vector3();
10591
+ const _start$2 = new Vector3();
10592
+ const _end$2 = new Vector3();
10593
10593
  class LineSegments extends Line$1 {
10594
10594
  constructor( geometry, material ) {
10595
10595
  super( geometry, material );
@@ -10602,10 +10602,10 @@
10602
10602
  const positionAttribute = geometry.attributes.position;
10603
10603
  const lineDistances = [];
10604
10604
  for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
10605
- _start$1.fromBufferAttribute( positionAttribute, i );
10606
- _end$1.fromBufferAttribute( positionAttribute, i + 1 );
10605
+ _start$2.fromBufferAttribute( positionAttribute, i );
10606
+ _end$2.fromBufferAttribute( positionAttribute, i + 1 );
10607
10607
  lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
10608
- lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
10608
+ lineDistances[ i + 1 ] = lineDistances[ i ] + _start$2.distanceTo( _end$2 );
10609
10609
  }
10610
10610
  geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
10611
10611
  } else {
@@ -33831,6 +33831,8 @@ void main() {
33831
33831
  }
33832
33832
 
33833
33833
  const PRECISION = 0.01;
33834
+ const DESKTOP_SNAP_DISTANCE = 10;
33835
+ const MOBILE_SNAP_DISTANCE = 50;
33834
33836
  class MeasureLineDragger extends OrbitDragger {
33835
33837
  constructor(viewer) {
33836
33838
  super(viewer);
@@ -33845,7 +33847,10 @@ void main() {
33845
33847
  this.onPointerMove = (event) => {
33846
33848
  if (this.orbit.enabled && this.orbit.state !== -1)
33847
33849
  return;
33848
- this.line.endPoint = this.snapper.getSnapPoint(event);
33850
+ const snapPoint = this.snapper.getSnapPoint(event);
33851
+ if (snapPoint && this.line.endPoint && snapPoint.equals(this.line.endPoint))
33852
+ return;
33853
+ this.line.endPoint = snapPoint;
33849
33854
  this.line.render();
33850
33855
  if (this.line.startPoint)
33851
33856
  this.changed = true;
@@ -33874,14 +33879,14 @@ void main() {
33874
33879
  this.overlay.render();
33875
33880
  };
33876
33881
  this.updateSnapper = () => {
33877
- this.snapper.update(this.viewer.scene);
33882
+ this.snapper.update(this.viewer);
33878
33883
  };
33879
33884
  this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
33880
33885
  this.overlay.attach();
33881
33886
  this.line = new MeasureLine(this.overlay);
33882
33887
  this.overlay.addLine(this.line);
33883
33888
  this.snapper = new MeasureSnapper(viewer.camera, viewer.canvas);
33884
- this.snapper.update(viewer.scene);
33889
+ this.updateSnapper();
33885
33890
  this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown);
33886
33891
  this.viewer.canvas.addEventListener("pointermove", this.onPointerMove);
33887
33892
  this.viewer.canvas.addEventListener("pointerup", this.onPointerUp);
@@ -33904,20 +33909,39 @@ void main() {
33904
33909
  this.viewer.removeEventListener("isolate", this.updateSnapper);
33905
33910
  this.viewer.removeEventListener("show", this.updateSnapper);
33906
33911
  this.viewer.removeEventListener("showall", this.updateSnapper);
33912
+ this.snapper.dispose();
33907
33913
  this.overlay.detach();
33908
33914
  this.overlay.dispose();
33909
33915
  super.dispose();
33910
33916
  }
33911
33917
  }
33918
+ const _vertex = new Vector3();
33919
+ const _start$1 = new Vector3();
33920
+ const _end$1 = new Vector3();
33921
+ const _line = new Line3();
33922
+ const _center = new Vector3();
33923
+ const _projection = new Vector3();
33912
33924
  class MeasureSnapper {
33913
33925
  constructor(camera, canvas) {
33914
- this.objects = [];
33915
33926
  this.camera = camera;
33916
33927
  this.canvas = canvas;
33928
+ this.objects = [];
33917
33929
  this.raycaster = new Raycaster();
33930
+ this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
33931
+ this.edgesCache = new WeakMap();
33918
33932
  }
33919
- getSnapPoint(event) {
33920
- const mouse = new Vector2(event.clientX, event.clientY);
33933
+ dispose() {
33934
+ this.objects = [];
33935
+ }
33936
+ isMobile() {
33937
+ if (typeof navigator === "undefined")
33938
+ return false;
33939
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
33940
+ }
33941
+ getMousePosition(event, target) {
33942
+ return target.set(event.clientX, event.clientY);
33943
+ }
33944
+ getPointerIntersects(mouse, objects) {
33921
33945
  const rect = this.canvas.getBoundingClientRect();
33922
33946
  const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
33923
33947
  const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
@@ -33925,20 +33949,86 @@ void main() {
33925
33949
  this.raycaster.setFromCamera(coords, this.camera);
33926
33950
  this.raycaster.params = {
33927
33951
  Mesh: {},
33928
- Line: { threshold: 0.25 },
33929
- Line2: { threshold: 0.25 },
33952
+ Line: { threshold: 0.05 },
33953
+ Line2: { threshold: 0.05 },
33930
33954
  LOD: {},
33931
- Points: { threshold: 0.1 },
33955
+ Points: { threshold: 0.01 },
33932
33956
  Sprite: {},
33933
33957
  };
33934
- const intersects = this.raycaster.intersectObjects(this.objects, false);
33935
- if (intersects.length === 0)
33936
- return undefined;
33937
- return intersects[0].point;
33958
+ return this.raycaster.intersectObjects(objects, false);
33938
33959
  }
33939
- update(scene) {
33940
- this.objects = [];
33941
- scene.traverseVisible((child) => this.objects.push(child));
33960
+ getDetectRadius(point) {
33961
+ const camera = this.camera;
33962
+ if (camera.isOrthographicCamera) {
33963
+ const worldHeight = camera.top - camera.bottom;
33964
+ const canvasHeight = this.canvas.height;
33965
+ const worldUnitsPerPixel = worldHeight / canvasHeight;
33966
+ return this.detectRadiusInPixels * worldUnitsPerPixel;
33967
+ }
33968
+ if (camera.isPerspectiveCamera) {
33969
+ const distance = camera.position.distanceTo(point);
33970
+ const worldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
33971
+ const canvasHeight = this.canvas.height;
33972
+ const worldUnitsPerPixel = worldHeight / canvasHeight;
33973
+ return this.detectRadiusInPixels * worldUnitsPerPixel;
33974
+ }
33975
+ return 0.1;
33976
+ }
33977
+ getSnapPoint(event) {
33978
+ const mouse = this.getMousePosition(event, new Vector2());
33979
+ const intersections = this.getPointerIntersects(mouse, this.objects);
33980
+ if (intersections.length === 0)
33981
+ return undefined;
33982
+ const object = intersections[0].object;
33983
+ const intersectionPoint = intersections[0].point;
33984
+ const localPoint = object.worldToLocal(intersectionPoint.clone());
33985
+ let snapPoint;
33986
+ let snapDistance = this.getDetectRadius(intersectionPoint);
33987
+ const geometry = object.geometry;
33988
+ const positions = geometry.attributes.position.array;
33989
+ for (let i = 0; i < positions.length; i += 3) {
33990
+ _vertex.set(positions[i], positions[i + 1], positions[i + 2]);
33991
+ const distance = _vertex.distanceTo(localPoint);
33992
+ if (distance < snapDistance) {
33993
+ snapDistance = distance;
33994
+ snapPoint = _vertex.clone();
33995
+ }
33996
+ }
33997
+ if (snapPoint)
33998
+ return object.localToWorld(snapPoint);
33999
+ let edges = this.edgesCache.get(geometry);
34000
+ if (!edges) {
34001
+ edges = new EdgesGeometry(geometry);
34002
+ this.edgesCache.set(geometry, edges);
34003
+ }
34004
+ const edgePositions = edges.attributes.position.array;
34005
+ for (let i = 0; i < edgePositions.length; i += 6) {
34006
+ _start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
34007
+ _end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
34008
+ _line.set(_start$1, _end$1);
34009
+ _line.getCenter(_center);
34010
+ const centerDistance = _center.distanceTo(localPoint);
34011
+ if (centerDistance < snapDistance) {
34012
+ snapDistance = centerDistance;
34013
+ snapPoint = _center.clone();
34014
+ continue;
34015
+ }
34016
+ _line.closestPointToPoint(localPoint, true, _projection);
34017
+ const lineDistance = _projection.distanceTo(localPoint);
34018
+ if (lineDistance < snapDistance) {
34019
+ snapDistance = lineDistance;
34020
+ snapPoint = _projection.clone();
34021
+ }
34022
+ }
34023
+ if (snapPoint)
34024
+ return object.localToWorld(snapPoint);
34025
+ return intersectionPoint.clone();
34026
+ }
34027
+ update(viewer) {
34028
+ this.objects.length = 0;
34029
+ viewer.models.forEach((model) => {
34030
+ model.getVisibleObjects().forEach((object) => this.objects.push(object));
34031
+ });
33942
34032
  }
33943
34033
  }
33944
34034
  class MeasureOverlay {
@@ -33960,6 +34050,8 @@ void main() {
33960
34050
  this.container.style.outline = "none";
33961
34051
  this.container.style.pointerEvents = "none";
33962
34052
  this.container.style.overflow = "hidden";
34053
+ if (!this.canvas.parentElement)
34054
+ return;
33963
34055
  this.canvas.parentElement.appendChild(this.container);
33964
34056
  }
33965
34057
  dispose() {
@@ -33990,7 +34082,7 @@ void main() {
33990
34082
  const _middlePoint = new Vector3();
33991
34083
  class MeasureLine {
33992
34084
  constructor(overlay) {
33993
- this.id = Date.now();
34085
+ this.id = MathUtils.generateUUID();
33994
34086
  this.unit = "";
33995
34087
  this.scale = 1.0;
33996
34088
  this.size = 10.0;
@@ -34014,6 +34106,10 @@ void main() {
34014
34106
  this.elementEndPoint.remove();
34015
34107
  this.elementLine.remove();
34016
34108
  this.elementLabel.remove();
34109
+ this.elementStartPoint = undefined;
34110
+ this.elementEndPoint = undefined;
34111
+ this.elementLine = undefined;
34112
+ this.elementLabel = undefined;
34017
34113
  }
34018
34114
  render() {
34019
34115
  const projector = this.overlay.projector;
@@ -34670,7 +34766,7 @@ void main() {
34670
34766
  if (camera.isPerspectiveCamera) {
34671
34767
  const offset = new Vector3(0, 0, 1)
34672
34768
  .applyQuaternion(camera.quaternion)
34673
- .multiplyScalar(boxSize / Math.tan(MathUtils.DEG2RAD * camera.fov * 0.5));
34769
+ .multiplyScalar(boxSize / Math.tan(MathUtils.degToRad(camera.fov * 0.5)));
34674
34770
  camera.position.copy(offset).add(boxCenter);
34675
34771
  camera.updateMatrixWorld();
34676
34772
  }
@@ -34756,6 +34852,7 @@ void main() {
34756
34852
  }
34757
34853
 
34758
34854
  function resetView(viewer) {
34855
+ const reset = viewer.getComponent("ResetComponent");
34759
34856
  viewer.executeCommand("setActiveDragger");
34760
34857
  viewer.executeCommand("clearSlices");
34761
34858
  viewer.executeCommand("clearOverlay");
@@ -34764,7 +34861,7 @@ void main() {
34764
34861
  viewer.executeCommand("showAll");
34765
34862
  viewer.executeCommand("explode", 0);
34766
34863
  viewer.executeCommand("zoomToExtents", true);
34767
- viewer.executeCommand("k3DViewSW");
34864
+ reset.resetCameraPosition();
34768
34865
  viewer.emit({ type: "resetview" });
34769
34866
  }
34770
34867
 
@@ -35970,12 +36067,12 @@ void main() {
35970
36067
  const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
35971
36068
  const coords = new Vector2(x, y);
35972
36069
  this.raycaster.setFromCamera(coords, this.viewer.camera);
35973
- this.raycaster.params = this.raycaster.params = {
36070
+ this.raycaster.params = {
35974
36071
  Mesh: {},
35975
- Line: { threshold: 0.25 },
35976
- Line2: { threshold: 0.25 },
36072
+ Line: { threshold: 0.05 },
36073
+ Line2: { threshold: 0.05 },
35977
36074
  LOD: {},
35978
- Points: { threshold: 0.1 },
36075
+ Points: { threshold: 0.01 },
35979
36076
  Sprite: {},
35980
36077
  };
35981
36078
  return this.raycaster.intersectObjects(objects, false);
@@ -36141,6 +36238,31 @@ void main() {
36141
36238
  }
36142
36239
  }
36143
36240
 
36241
+ class ResetComponent {
36242
+ constructor(viewer) {
36243
+ this.savedCameraPosition = null;
36244
+ this.onDatabaseChunk = () => {
36245
+ this.savedCameraPosition = {
36246
+ position: this.viewer.camera.position.clone(),
36247
+ up: this.viewer.camera.up.clone(),
36248
+ direction: this.viewer.camera.getWorldDirection(new Vector3()),
36249
+ };
36250
+ };
36251
+ this.viewer = viewer;
36252
+ this.viewer.addEventListener("databasechunk", this.onDatabaseChunk);
36253
+ }
36254
+ dispose() {
36255
+ this.viewer.removeEventListener("databasechunk", this.onDatabaseChunk);
36256
+ }
36257
+ resetCameraPosition() {
36258
+ if (this.savedCameraPosition) {
36259
+ this.viewer.camera.position.copy(this.savedCameraPosition.position);
36260
+ this.viewer.camera.up.copy(this.savedCameraPosition.up);
36261
+ this.viewer.camera.lookAt(this.savedCameraPosition.position.clone().add(this.savedCameraPosition.direction));
36262
+ }
36263
+ }
36264
+ }
36265
+
36144
36266
  const components = componentsRegistry("threejs");
36145
36267
  components.registerComponent("ExtentsComponent", (viewer) => new ExtentsComponent(viewer));
36146
36268
  components.registerComponent("CameraComponent", (viewer) => new CameraComponent(viewer));
@@ -36151,6 +36273,7 @@ void main() {
36151
36273
  components.registerComponent("HighlighterComponent", (viewer) => new HighlighterComponent(viewer));
36152
36274
  components.registerComponent("SelectionComponent", (viewer) => new SelectionComponent(viewer));
36153
36275
  components.registerComponent("WCSHelperComponent", (viewer) => new WCSHelperComponent(viewer));
36276
+ components.registerComponent("ResetComponent", (viewer) => new ResetComponent(viewer));
36154
36277
 
36155
36278
  function mergeGeometries( geometries, useGroups = false ) {
36156
36279
  const isIndexed = geometries[ 0 ].index !== null;
@@ -39507,6 +39630,12 @@ void main() {
39507
39630
  this.maxConcurrentChunks = 8;
39508
39631
  this.activeChunkLoads = 0;
39509
39632
  this.chunkQueue = [];
39633
+ this.objectIdToIndex = new Map();
39634
+ this.maxObjectId = 0;
39635
+ this.objectVisibility = new Float32Array();
39636
+ this.maxConcurrentChunks = 6;
39637
+ this.mergedObjectMap = new Map();
39638
+ this.mergedGeometryVisibility = new Map();
39510
39639
  }
39511
39640
  setVisibleEdges(visible) {
39512
39641
  this.visibleEdges = visible;
@@ -40213,6 +40342,50 @@ void main() {
40213
40342
  this.originalObjects.clear();
40214
40343
  this.originalObjectsToSelection.clear();
40215
40344
  }
40345
+ initializeObjectVisibility() {
40346
+ if (this.maxObjectId > 0) {
40347
+ this.objectVisibility = new Float32Array(this.maxObjectId);
40348
+ for (let i = 0; i < this.maxObjectId; i++) {
40349
+ this.objectVisibility[i] = 1.0;
40350
+ }
40351
+ console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
40352
+ }
40353
+ }
40354
+ createVisibilityMaterial(material) {
40355
+ material.onBeforeCompile = (shader) => {
40356
+ shader.vertexShader = shader.vertexShader.replace(
40357
+ "#include <common>",
40358
+ `
40359
+ #include <common>
40360
+ attribute float visibility;
40361
+ varying float vVisibility;
40362
+ `
40363
+ );
40364
+ shader.fragmentShader = shader.fragmentShader.replace(
40365
+ "#include <common>",
40366
+ `
40367
+ #include <common>
40368
+ varying float vVisibility;
40369
+ `
40370
+ );
40371
+ shader.vertexShader = shader.vertexShader.replace(
40372
+ "void main() {",
40373
+ `
40374
+ void main() {
40375
+ vVisibility = visibility;
40376
+ `
40377
+ );
40378
+ shader.fragmentShader = shader.fragmentShader.replace(
40379
+ "void main() {",
40380
+ `
40381
+ void main() {
40382
+ if (vVisibility < 0.5) discard;
40383
+ `
40384
+ );
40385
+ };
40386
+ material.needsUpdate = true;
40387
+ return material;
40388
+ }
40216
40389
  clear() {
40217
40390
  this.chunkQueue = [];
40218
40391
  this.structures.forEach((structure) => {
@@ -40318,6 +40491,9 @@ void main() {
40318
40491
  this.loadedGeometrySize = 0;
40319
40492
  this.abortController = new AbortController();
40320
40493
  this.updateMemoryIndicator();
40494
+ this.objectIdToIndex.clear();
40495
+ this.maxObjectId = 0;
40496
+ this.objectVisibility = new Float32Array();
40321
40497
  }
40322
40498
  setStructureTransform(structureId, matrix) {
40323
40499
  const rootGroup = this.structureRoots.get(structureId);
@@ -40467,18 +40643,43 @@ void main() {
40467
40643
  this.originalObjectsToSelection.add(obj);
40468
40644
  }
40469
40645
  });
40646
+ this.initializeObjectVisibility();
40647
+ console.log(`Optimization complete. Total objects: ${this.maxObjectId}`);
40470
40648
  this.dispatchEvent("update");
40471
40649
  }
40472
40650
  mergeMeshGroups(materialGroups, rootGroup) {
40473
40651
  for (const group of materialGroups) {
40652
+ if (!group.material) {
40653
+ console.warn("Skipping mesh group with null material");
40654
+ continue;
40655
+ }
40474
40656
  try {
40475
40657
  const geometries = [];
40476
40658
  const handles = new Set();
40477
40659
  const optimizedObjects = [];
40660
+ const objectMapping = new Map();
40661
+ let currentVertexOffset = 0;
40478
40662
  for (const mesh of group.objects) {
40479
40663
  const geometry = mesh.geometry.clone();
40480
40664
  mesh.updateWorldMatrix(true, false);
40481
40665
  geometry.applyMatrix4(mesh.matrixWorld);
40666
+ const handle = mesh.userData.handle;
40667
+ if (!this.objectIdToIndex.has(handle)) {
40668
+ this.objectIdToIndex.set(handle, this.maxObjectId++);
40669
+ }
40670
+ const objectId = this.objectIdToIndex.get(handle);
40671
+ const vertexCount = geometry.attributes.position.count;
40672
+ const objectIds = new Float32Array(vertexCount);
40673
+ for (let i = 0; i < vertexCount; i++) {
40674
+ objectIds[i] = objectId;
40675
+ }
40676
+ geometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
40677
+ objectMapping.set(mesh, {
40678
+ geometry,
40679
+ startVertexIndex: currentVertexOffset,
40680
+ vertexCount: geometry.attributes.position.count,
40681
+ });
40682
+ currentVertexOffset += geometry.attributes.position.count;
40482
40683
  geometries.push(geometry);
40483
40684
  optimizedObjects.push(mesh);
40484
40685
  handles.add(mesh.userData.handle);
@@ -40486,13 +40687,26 @@ void main() {
40486
40687
  const mergedObjects = [];
40487
40688
  if (geometries.length > 0) {
40488
40689
  const mergedGeometry = mergeGeometries(geometries);
40690
+ const totalVertices = mergedGeometry.attributes.position.count;
40691
+ const visibilityArray = new Float32Array(totalVertices);
40692
+ for (let i = 0; i < totalVertices; i++) {
40693
+ visibilityArray[i] = 1.0;
40694
+ }
40695
+ mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40489
40696
  if (this.useVAO) {
40490
40697
  this.createVAO(mergedGeometry);
40491
40698
  }
40492
- const mergedMesh = new Mesh(mergedGeometry, group.material);
40699
+ const visibilityMaterial = this.createVisibilityMaterial(group.material);
40700
+ const mergedMesh = new Mesh(mergedGeometry, visibilityMaterial);
40493
40701
  rootGroup.add(mergedMesh);
40494
40702
  this.mergedMesh.add(mergedMesh);
40495
40703
  this.optimizedOriginalMap.set(mergedMesh, optimizedObjects);
40704
+ this.mergedObjectMap.set(mergedMesh.uuid, {
40705
+ objectMapping,
40706
+ visibilityArray,
40707
+ totalVertices,
40708
+ });
40709
+ this.mergedGeometryVisibility.set(mergedMesh, visibilityArray);
40496
40710
  mergedObjects.push(mergedMesh);
40497
40711
  geometries.forEach((geometry) => {
40498
40712
  geometry.dispose();
@@ -40518,8 +40732,14 @@ void main() {
40518
40732
  mergeLineGroups(materialGroups, rootGroup) {
40519
40733
  for (const group of materialGroups) {
40520
40734
  if (group.objects.length === 0) continue;
40735
+ if (!group.material) {
40736
+ console.warn("Skipping line group with null material");
40737
+ continue;
40738
+ }
40521
40739
  const handles = new Set();
40522
40740
  let totalVertices = 0;
40741
+ const objectMapping = new Map();
40742
+ let currentVertexOffset = 0;
40523
40743
  group.objects.map((line) => {
40524
40744
  handles.add(line.userData.handle);
40525
40745
  totalVertices += line.geometry.attributes.position.count;
@@ -40532,6 +40752,15 @@ void main() {
40532
40752
  const geometry = line.geometry;
40533
40753
  const positionAttr = geometry.attributes.position;
40534
40754
  const vertexCount = positionAttr.count;
40755
+ const handle = line.userData.handle;
40756
+ if (!this.objectIdToIndex.has(handle)) {
40757
+ this.objectIdToIndex.set(handle, this.maxObjectId++);
40758
+ }
40759
+ objectMapping.set(line, {
40760
+ startVertexIndex: currentVertexOffset,
40761
+ vertexCount,
40762
+ });
40763
+ currentVertexOffset += vertexCount;
40535
40764
  line.updateWorldMatrix(true, false);
40536
40765
  const matrix = line.matrixWorld;
40537
40766
  const vector = new Vector3();
@@ -40552,7 +40781,24 @@ void main() {
40552
40781
  geometry.setIndex(indices);
40553
40782
  geometry.computeBoundingSphere();
40554
40783
  geometry.computeBoundingBox();
40555
- const mergedLine = new LineSegments(geometry, group.material);
40784
+ const objectIds = new Float32Array(totalVertices);
40785
+ let vertexIndex = 0;
40786
+ group.objects.forEach((line) => {
40787
+ const vertexCount = line.geometry.attributes.position.count;
40788
+ const handle = line.userData.handle;
40789
+ const objectId = this.objectIdToIndex.get(handle);
40790
+ for (let i = 0; i < vertexCount; i++) {
40791
+ objectIds[vertexIndex++] = objectId;
40792
+ }
40793
+ });
40794
+ geometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
40795
+ const visibilityArray = new Float32Array(totalVertices);
40796
+ for (let i = 0; i < totalVertices; i++) {
40797
+ visibilityArray[i] = 1.0;
40798
+ }
40799
+ geometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40800
+ const visibilityMaterial = this.createVisibilityMaterial(group.material);
40801
+ const mergedLine = new LineSegments(geometry, visibilityMaterial);
40556
40802
  const mergedObjects = [mergedLine];
40557
40803
  if (this.useVAO) {
40558
40804
  this.createVAO(mergedLine);
@@ -40560,6 +40806,12 @@ void main() {
40560
40806
  rootGroup.add(mergedLine);
40561
40807
  this.mergedLines.add(mergedLine);
40562
40808
  this.optimizedOriginalMap.set(mergedLine, group.objects);
40809
+ this.mergedObjectMap.set(mergedLine.uuid, {
40810
+ objectMapping,
40811
+ visibilityArray,
40812
+ totalVertices,
40813
+ });
40814
+ this.mergedGeometryVisibility.set(mergedLine, visibilityArray);
40563
40815
  handles.forEach((handle) => {
40564
40816
  if (this.handleToOptimizedObjects.has(handle)) {
40565
40817
  const existingObjects = this.handleToOptimizedObjects.get(handle);
@@ -40573,14 +40825,37 @@ void main() {
40573
40825
  }
40574
40826
  mergeLineSegmentGroups(materialGroups, rootGroup) {
40575
40827
  for (const group of materialGroups) {
40828
+ if (!group.material) {
40829
+ console.warn("Skipping line segment group with null material");
40830
+ continue;
40831
+ }
40576
40832
  try {
40577
40833
  const geometries = [];
40578
40834
  const optimizedObjects = [];
40579
40835
  const handles = new Set();
40836
+ const objectMapping = new Map();
40837
+ let currentVertexOffset = 0;
40580
40838
  for (const line of group.objects) {
40581
40839
  const geometry = line.geometry.clone();
40582
40840
  line.updateWorldMatrix(true, false);
40583
40841
  geometry.applyMatrix4(line.matrixWorld);
40842
+ const handle = line.userData.handle;
40843
+ if (!this.objectIdToIndex.has(handle)) {
40844
+ this.objectIdToIndex.set(handle, this.maxObjectId++);
40845
+ }
40846
+ const objectId = this.objectIdToIndex.get(handle);
40847
+ const vertexCount = geometry.attributes.position.count;
40848
+ const objectIds = new Float32Array(vertexCount);
40849
+ for (let i = 0; i < vertexCount; i++) {
40850
+ objectIds[i] = objectId;
40851
+ }
40852
+ geometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
40853
+ objectMapping.set(line, {
40854
+ geometry,
40855
+ startVertexIndex: currentVertexOffset,
40856
+ vertexCount: geometry.attributes.position.count,
40857
+ });
40858
+ currentVertexOffset += geometry.attributes.position.count;
40584
40859
  geometries.push(geometry);
40585
40860
  optimizedObjects.push(line);
40586
40861
  handles.add(line.userData.handle);
@@ -40588,13 +40863,26 @@ void main() {
40588
40863
  const mergedObjects = [];
40589
40864
  if (geometries.length > 0) {
40590
40865
  const mergedGeometry = mergeGeometries(geometries, false);
40591
- const mergedLine = new LineSegments(mergedGeometry, group.material);
40866
+ const totalVertices = mergedGeometry.attributes.position.count;
40867
+ const visibilityArray = new Float32Array(totalVertices);
40868
+ for (let i = 0; i < totalVertices; i++) {
40869
+ visibilityArray[i] = 1.0;
40870
+ }
40871
+ mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40872
+ const visibilityMaterial = this.createVisibilityMaterial(group.material);
40873
+ const mergedLine = new LineSegments(mergedGeometry, visibilityMaterial);
40592
40874
  if (this.useVAO) {
40593
40875
  this.createVAO(mergedLine);
40594
40876
  }
40595
40877
  rootGroup.add(mergedLine);
40596
40878
  this.mergedLineSegments.add(mergedLine);
40597
40879
  this.optimizedOriginalMap.set(mergedLine, optimizedObjects);
40880
+ this.mergedObjectMap.set(mergedLine.uuid, {
40881
+ objectMapping,
40882
+ visibilityArray,
40883
+ totalVertices,
40884
+ });
40885
+ this.mergedGeometryVisibility.set(mergedLine, visibilityArray);
40598
40886
  mergedObjects.push(mergedLine);
40599
40887
  geometries.forEach((geometry) => {
40600
40888
  geometry.dispose();
@@ -40619,6 +40907,10 @@ void main() {
40619
40907
  }
40620
40908
  mergePointsGroups(materialGroups, rootGroup) {
40621
40909
  for (const group of materialGroups) {
40910
+ if (!group.material) {
40911
+ console.warn("Skipping points group with null material");
40912
+ continue;
40913
+ }
40622
40914
  try {
40623
40915
  const geometries = [];
40624
40916
  const optimizedObjects = [];
@@ -40801,97 +41093,51 @@ void main() {
40801
41093
  });
40802
41094
  this.syncHiddenObjects();
40803
41095
  }
40804
- syncHiddenObjects() {
40805
- if (this.oldOptimizeObjects.size !== 0) {
40806
- for (const obj of this.oldOptimizeObjects) {
40807
- obj.visible = true;
40808
- }
40809
- this.oldOptimizeObjects.clear();
40810
- }
40811
- if (this.newOptimizedObjects.size !== 0) {
40812
- for (const obj of this.newOptimizedObjects) {
40813
- obj.visible = false;
40814
- obj.geometry.dispose();
40815
- obj.parent.remove(obj);
41096
+ _updateVisibilityAttribute(mergedObject) {
41097
+ if (
41098
+ mergedObject.geometry &&
41099
+ mergedObject.geometry.attributes.visibility &&
41100
+ mergedObject.geometry.attributes.objectId
41101
+ ) {
41102
+ const visibilityArray = mergedObject.geometry.attributes.visibility.array;
41103
+ const objectIdArray = mergedObject.geometry.attributes.objectId.array;
41104
+ for (let i = 0; i < visibilityArray.length; i++) {
41105
+ const objectId = objectIdArray[i];
41106
+ if (objectId < this.objectVisibility.length) {
41107
+ visibilityArray[i] = this.objectVisibility[objectId];
41108
+ }
40816
41109
  }
40817
- this.newOptimizedObjects.clear();
41110
+ mergedObject.geometry.attributes.visibility.needsUpdate = true;
40818
41111
  }
40819
- if (this.hiddenHandles.size === 0) {
41112
+ }
41113
+ syncHiddenObjects() {
41114
+ if (this.mergedObjectMap.size === 0) {
41115
+ console.log("No merged objects to sync");
40820
41116
  return;
40821
41117
  }
40822
- this.hiddenHandles.forEach((handle) => {
40823
- const objects = this.handleToOptimizedObjects.get(handle);
40824
- if (objects) {
40825
- objects.forEach((x) => this.oldOptimizeObjects.add(x));
41118
+ if (this.objectVisibility.length > 0) {
41119
+ for (let i = 0; i < this.objectVisibility.length; i++) {
41120
+ this.objectVisibility[i] = 1.0;
40826
41121
  }
40827
- });
40828
- this.oldOptimizeObjects.forEach((optimizedObject) => {
40829
- optimizedObject.visible = false;
40830
- const originObjects = this.optimizedOriginalMap.get(optimizedObject);
40831
- const updateListToOptimize = [];
40832
- originObjects.forEach((obj) => {
40833
- if (!this.hiddenHandles.has(obj.userData.handle)) {
40834
- updateListToOptimize.push(obj);
41122
+ this.hiddenHandles.forEach((handle) => {
41123
+ const index = this.objectIdToIndex.get(handle);
41124
+ if (index !== undefined && index < this.objectVisibility.length) {
41125
+ this.objectVisibility[index] = 0.0;
40835
41126
  }
40836
41127
  });
40837
- const firstObject = updateListToOptimize[0];
40838
- if (firstObject instanceof Mesh || firstObject instanceof LineSegments) {
40839
- const geometries = updateListToOptimize.map((obj) => {
40840
- const geometry = obj.geometry.clone();
40841
- obj.updateWorldMatrix(true, false);
40842
- geometry.applyMatrix4(obj.matrixWorld);
40843
- return geometry;
40844
- });
40845
- const newMergedGeometry = mergeGeometries(geometries);
40846
- const mergedObject =
40847
- firstObject instanceof Mesh
40848
- ? new Mesh(newMergedGeometry, optimizedObject.material)
40849
- : new LineSegments(newMergedGeometry, optimizedObject.material);
40850
- mergedObject.visible = true;
40851
- optimizedObject.parent.add(mergedObject);
40852
- this.newOptimizedObjects.add(mergedObject);
40853
- geometries.forEach((geometry) => {
40854
- geometry.dispose();
40855
- });
40856
- } else if (firstObject instanceof Line$1) {
40857
- let totalVertices = 0;
40858
- updateListToOptimize.map((line) => {
40859
- totalVertices += line.geometry.attributes.position.count;
40860
- });
40861
- const positions = new Float32Array(totalVertices * 3);
40862
- let posOffset = 0;
40863
- const indices = [];
40864
- let vertexOffset = 0;
40865
- updateListToOptimize.forEach((line) => {
40866
- const geometry = line.geometry;
40867
- const positionAttr = geometry.attributes.position;
40868
- const vertexCount = positionAttr.count;
40869
- line.updateWorldMatrix(true, false);
40870
- const matrix = line.matrixWorld;
40871
- const vector = new Vector3();
40872
- for (let i = 0; i < vertexCount; i++) {
40873
- vector.fromBufferAttribute(positionAttr, i);
40874
- vector.applyMatrix4(matrix);
40875
- positions[posOffset++] = vector.x;
40876
- positions[posOffset++] = vector.y;
40877
- positions[posOffset++] = vector.z;
40878
- }
40879
- for (let i = 0; i < vertexCount - 1; i++) {
40880
- indices.push(vertexOffset + i, vertexOffset + i + 1);
40881
- }
40882
- vertexOffset += vertexCount;
40883
- });
40884
- const geometry = new BufferGeometry();
40885
- geometry.setAttribute("position", new BufferAttribute(positions, 3));
40886
- geometry.setIndex(indices);
40887
- geometry.computeBoundingSphere();
40888
- geometry.computeBoundingBox();
40889
- const mergedLine = new LineSegments(geometry, optimizedObject.material);
40890
- mergedLine.visible = true;
40891
- optimizedObject.parent.add(mergedLine);
40892
- this.newOptimizedObjects.add(mergedLine);
40893
- }
40894
- });
41128
+ }
41129
+ for (const mesh of this.mergedMesh) {
41130
+ this._updateVisibilityAttribute(mesh);
41131
+ }
41132
+ for (const line of this.mergedLines) {
41133
+ this._updateVisibilityAttribute(line);
41134
+ }
41135
+ for (const lineSegment of this.mergedLineSegments) {
41136
+ this._updateVisibilityAttribute(lineSegment);
41137
+ }
41138
+ for (const point of this.mergedPoints) {
41139
+ this._updateVisibilityAttribute(point);
41140
+ }
40895
41141
  }
40896
41142
  getStructureGeometryExtent(structureId) {
40897
41143
  const extent = new Box3();