@inweb/viewer-three 27.2.3 → 27.2.4

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.
@@ -33644,6 +33644,41 @@ void main() {
33644
33644
  }
33645
33645
  }
33646
33646
 
33647
+ class PlaneHelper2 extends Line$1 {
33648
+ constructor(size = 1, color = 0xc0c0c0) {
33649
+ const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
33650
+ const geometry = new BufferGeometry();
33651
+ geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
33652
+ geometry.computeBoundingSphere();
33653
+ super(geometry, new LineBasicMaterial({ color, toneMapped: false }));
33654
+ this.type = "PlaneHelper2";
33655
+ this.size = size;
33656
+ const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
33657
+ const geometry2 = new BufferGeometry();
33658
+ geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
33659
+ geometry2.computeBoundingSphere();
33660
+ this.helper = new Mesh(geometry2, new MeshBasicMaterial({
33661
+ color,
33662
+ opacity: 0.2,
33663
+ transparent: true,
33664
+ depthWrite: false,
33665
+ toneMapped: false,
33666
+ side: DoubleSide,
33667
+ }));
33668
+ this.add(this.helper);
33669
+ }
33670
+ dispose() {
33671
+ this.geometry.dispose();
33672
+ this.material.dispose();
33673
+ this.helper.geometry.dispose();
33674
+ this.helper.material.dispose();
33675
+ }
33676
+ updateMatrixWorld(force) {
33677
+ this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
33678
+ super.updateMatrixWorld(force);
33679
+ }
33680
+ }
33681
+
33647
33682
  const _changeEvent = { type: "change" };
33648
33683
  const _startEvent = { type: "start" };
33649
33684
  const _endEvent = { type: "end" };
@@ -34302,166 +34337,6 @@ void main() {
34302
34337
  }
34303
34338
  }
34304
34339
 
34305
- class PlaneHelper2 extends Object3D {
34306
- constructor(size = 1, color = 0xf0f0f0, opacity = 0.15) {
34307
- super();
34308
- this.type = "PlaneHelper2";
34309
- this.size = size;
34310
- const positions = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0];
34311
- const geometry = new BufferGeometry();
34312
- geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
34313
- geometry.computeBoundingSphere();
34314
- this.outline = new Line$1(geometry, new LineBasicMaterial({ color, toneMapped: false }));
34315
- const positions2 = [1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0];
34316
- const geometry2 = new BufferGeometry();
34317
- geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
34318
- geometry2.computeBoundingSphere();
34319
- this.mesh = new Mesh(geometry2, new MeshBasicMaterial({
34320
- color,
34321
- opacity,
34322
- transparent: true,
34323
- depthWrite: false,
34324
- toneMapped: false,
34325
- side: DoubleSide,
34326
- }));
34327
- this.add(this.outline);
34328
- this.add(this.mesh);
34329
- }
34330
- dispose() {
34331
- this.outline.geometry.dispose();
34332
- this.outline.material.dispose();
34333
- this.mesh.geometry.dispose();
34334
- this.mesh.material.dispose();
34335
- }
34336
- updateMatrixWorld(force) {
34337
- this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
34338
- super.updateMatrixWorld(force);
34339
- }
34340
- getLineMaterial() {
34341
- return this.outline.material;
34342
- }
34343
- getMeshMaterial() {
34344
- return this.mesh.material;
34345
- }
34346
- }
34347
-
34348
- const DESKTOP_SNAP_DISTANCE = 10;
34349
- const MOBILE_SNAP_DISTANCE = 50;
34350
- const _vertex = new Vector3();
34351
- const _start$1 = new Vector3();
34352
- const _end$1 = new Vector3();
34353
- const _line = new Line3();
34354
- const _center = new Vector3();
34355
- const _projection = new Vector3();
34356
- class Snapper {
34357
- constructor(camera, renderer, canvas) {
34358
- this.camera = camera;
34359
- this.renderer = renderer;
34360
- this.canvas = canvas;
34361
- this.threshold = 0.0001;
34362
- this.raycaster = new Raycaster();
34363
- this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
34364
- this.edgesCache = new WeakMap();
34365
- }
34366
- isMobile() {
34367
- if (typeof navigator === "undefined")
34368
- return false;
34369
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
34370
- }
34371
- getMousePosition(event, target) {
34372
- return target.set(event.clientX, event.clientY);
34373
- }
34374
- getPointerIntersects(mouse, objects, recursive = false, clip = true) {
34375
- const rect = this.canvas.getBoundingClientRect();
34376
- const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
34377
- const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
34378
- const coords = new Vector2(x, y);
34379
- this.raycaster.setFromCamera(coords, this.camera);
34380
- this.raycaster.params = {
34381
- Mesh: {},
34382
- Line: { threshold: this.threshold },
34383
- Line2: { threshold: this.threshold },
34384
- LOD: {},
34385
- Points: { threshold: this.threshold },
34386
- Sprite: {},
34387
- };
34388
- let intersects = this.raycaster.intersectObjects(objects, recursive);
34389
- if (clip) {
34390
- const clippingPlanes = this.renderer.clippingPlanes || [];
34391
- clippingPlanes.forEach((plane) => {
34392
- intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
34393
- });
34394
- }
34395
- return intersects;
34396
- }
34397
- getDetectRadius(point) {
34398
- const camera = this.camera;
34399
- if (camera.isOrthographicCamera) {
34400
- const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
34401
- const canvasHeight = this.canvas.height;
34402
- const worldUnitsPerPixel = fieldHeight / canvasHeight;
34403
- return this.detectRadiusInPixels * worldUnitsPerPixel;
34404
- }
34405
- if (camera.isPerspectiveCamera) {
34406
- const distance = camera.position.distanceTo(point);
34407
- const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
34408
- const canvasHeight = this.canvas.height;
34409
- const worldUnitsPerPixel = fieldHeight / canvasHeight;
34410
- return this.detectRadiusInPixels * worldUnitsPerPixel;
34411
- }
34412
- return 0.1;
34413
- }
34414
- getSnapPoint(mouse, objects) {
34415
- const intersections = this.getPointerIntersects(mouse, objects);
34416
- if (intersections.length === 0)
34417
- return undefined;
34418
- const object = intersections[0].object;
34419
- const intersectionPoint = intersections[0].point;
34420
- const localPoint = object.worldToLocal(intersectionPoint.clone());
34421
- let snapPoint;
34422
- let snapDistance = this.getDetectRadius(intersectionPoint);
34423
- const geometry = object.geometry;
34424
- const positions = geometry.attributes.position.array;
34425
- for (let i = 0; i < positions.length; i += 3) {
34426
- _vertex.set(positions[i], positions[i + 1], positions[i + 2]);
34427
- const distance = _vertex.distanceTo(localPoint);
34428
- if (distance < snapDistance) {
34429
- snapDistance = distance;
34430
- snapPoint = _vertex.clone();
34431
- }
34432
- }
34433
- if (snapPoint)
34434
- return object.localToWorld(snapPoint);
34435
- let edges = this.edgesCache.get(geometry);
34436
- if (!edges) {
34437
- edges = new EdgesGeometry(geometry);
34438
- this.edgesCache.set(geometry, edges);
34439
- }
34440
- const edgePositions = edges.attributes.position.array;
34441
- for (let i = 0; i < edgePositions.length; i += 6) {
34442
- _start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
34443
- _end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
34444
- _line.set(_start$1, _end$1);
34445
- _line.getCenter(_center);
34446
- const centerDistance = _center.distanceTo(localPoint);
34447
- if (centerDistance < snapDistance) {
34448
- snapDistance = centerDistance;
34449
- snapPoint = _center.clone();
34450
- continue;
34451
- }
34452
- _line.closestPointToPoint(localPoint, true, _projection);
34453
- const lineDistance = _projection.distanceTo(localPoint);
34454
- if (lineDistance < snapDistance) {
34455
- snapDistance = lineDistance;
34456
- snapPoint = _projection.clone();
34457
- }
34458
- }
34459
- if (snapPoint)
34460
- return object.localToWorld(snapPoint);
34461
- return intersectionPoint.clone();
34462
- }
34463
- }
34464
-
34465
34340
  class OrbitDragger {
34466
34341
  constructor(viewer) {
34467
34342
  this.updateControls = () => {
@@ -34554,18 +34429,12 @@ void main() {
34554
34429
  }
34555
34430
 
34556
34431
  class CuttingPlaneDragger extends OrbitDragger {
34557
- constructor(viewer) {
34432
+ constructor(viewer, normal) {
34558
34433
  super(viewer);
34559
- this.helpers = [];
34560
- this.activeHelper = null;
34561
34434
  this.transformChange = () => {
34562
- if (!this.activeHelper)
34563
- return;
34564
- const plane = this.activeHelper.plane;
34565
- plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.activeHelper.quaternion);
34566
- plane.constant = -this.activeHelper.position.dot(plane.normal);
34435
+ this.plane.normal.copy(new Vector3(0, 0, -1)).applyQuaternion(this.planeCenter.quaternion);
34436
+ this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
34567
34437
  this.viewer.update();
34568
- this.changed = true;
34569
34438
  };
34570
34439
  this.translateDrag = (event) => {
34571
34440
  this.orbit.enabled = !event.value;
@@ -34576,83 +34445,45 @@ void main() {
34576
34445
  this.translate.enabled = !event.value;
34577
34446
  };
34578
34447
  this.updatePlaneSize = () => {
34579
- const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
34580
- this.helpers.forEach((planeHelper) => (planeHelper.size = extentsSize));
34448
+ this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length() || 1;
34581
34449
  this.viewer.update();
34582
34450
  };
34583
34451
  this.updateTransformCamera = () => {
34584
34452
  this.translate.camera = this.viewer.camera;
34585
34453
  this.rotate.camera = this.viewer.camera;
34586
- this.snapper.camera = this.viewer.camera;
34587
- };
34588
- this.clearHelpers = () => {
34589
- this.setActiveHelper();
34590
- this.helpers.forEach((helper) => {
34591
- helper.removeFromParent();
34592
- helper.dispose();
34593
- });
34594
- this.helpers = [];
34595
- this.viewer.update();
34596
34454
  };
34597
34455
  this.onKeyDown = (event) => {
34598
34456
  if (event.key === "Shift")
34599
34457
  this.rotate.setRotationSnap(Math.PI / 4);
34600
- if (event.key === "Delete" || event.key === "Backspace")
34601
- this.deleteActivePlane();
34602
- if (event.key === "Escape" && (this.translate.dragging || this.rotate.dragging))
34603
- this.reset();
34604
34458
  };
34605
34459
  this.onKeyUp = (event) => {
34606
34460
  if (event.key === "Shift")
34607
34461
  this.rotate.setRotationSnap(null);
34608
34462
  };
34609
- this.onPointerDown = (event) => {
34610
- if (event.button !== 0 || !event.isPrimary)
34611
- return;
34612
- this.snapper.getMousePosition(event, this.downPosition);
34613
- this.saveState();
34614
- };
34615
- this.onPointerUp = (event) => {
34616
- if (event.button !== 0)
34617
- return;
34618
- const upPosition = this.snapper.getMousePosition(event, new Vector2());
34619
- if (upPosition.distanceTo(this.downPosition) !== 0)
34620
- return;
34621
- const intersects = this.snapper.getPointerIntersects(upPosition, this.helpers, true, false);
34622
- if (intersects.length === 0)
34623
- return;
34624
- this.setActiveHelper(intersects[0].object.parent);
34625
- };
34626
- this.onPointerCancel = (event) => {
34627
- this.viewer.canvas.dispatchEvent(new PointerEvent("pointerup", event));
34628
- };
34629
34463
  this.onDoubleClick = (event) => {
34630
- if (!this.activeHelper)
34631
- return;
34632
- const mousePosition = this.snapper.getMousePosition(event, new Vector2());
34633
- const intersects = this.snapper.getPointerIntersects(mousePosition, [this.activeHelper], true, false);
34634
- if (intersects.length === 0)
34635
- return;
34636
- this.activeHelper.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
34637
- this.transformChange();
34638
34464
  event.stopPropagation();
34465
+ this.planeCenter.rotateOnAxis(new Vector3(0, 1, 0), Math.PI);
34466
+ this.transformChange();
34639
34467
  };
34468
+ const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
34469
+ const extentsCenter = viewer.extents.getCenter(new Vector3());
34470
+ const constant = -extentsCenter.dot(normal);
34471
+ this.plane = new Plane(normal, constant);
34640
34472
  if (!viewer.renderer.clippingPlanes)
34641
34473
  viewer.renderer.clippingPlanes = [];
34642
- this.clippingPlanes = viewer.renderer.clippingPlanes;
34643
- this.clippingPlanes.forEach((plane) => this.addHelper(plane));
34644
- const extentsSize = viewer.extents.getSize(new Vector3()).length() || 1;
34645
- this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
34646
- this.snapper.threshold = extentsSize / 10000;
34647
- this.downPosition = new Vector2();
34648
- this.position0 = new Vector3();
34649
- this.quaternion0 = new Quaternion();
34474
+ viewer.renderer.clippingPlanes.push(this.plane);
34475
+ this.planeCenter = new Object3D();
34476
+ this.planeCenter.position.copy(extentsCenter);
34477
+ this.planeCenter.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), normal);
34478
+ this.viewer.helpers.add(this.planeCenter);
34479
+ this.planeHelper = new PlaneHelper2(extentsSize);
34480
+ this.planeCenter.add(this.planeHelper);
34650
34481
  this.translate = new TransformControls(viewer.camera, viewer.canvas);
34651
- this.translate.setMode("translate");
34652
34482
  this.translate.setSpace("local");
34653
34483
  this.translate.showX = false;
34654
34484
  this.translate.showY = false;
34655
34485
  this.translate.showZ = true;
34486
+ this.translate.attach(this.planeCenter);
34656
34487
  this.translate.addEventListener("change", this.transformChange);
34657
34488
  this.translate.addEventListener("dragging-changed", this.translateDrag);
34658
34489
  this.viewer.helpers.add(this.translate.getHelper());
@@ -34662,18 +34493,14 @@ void main() {
34662
34493
  this.rotate.showX = true;
34663
34494
  this.rotate.showY = true;
34664
34495
  this.rotate.showZ = false;
34496
+ this.rotate.attach(this.planeCenter);
34665
34497
  this.rotate.addEventListener("change", this.transformChange);
34666
34498
  this.rotate.addEventListener("dragging-changed", this.rotateDrag);
34667
34499
  this.viewer.helpers.add(this.rotate.getHelper());
34668
- this.setActiveHelper(this.helpers[this.helpers.length - 1]);
34669
34500
  this.viewer.addEventListener("explode", this.updatePlaneSize);
34670
34501
  this.viewer.addEventListener("show", this.updatePlaneSize);
34671
34502
  this.viewer.addEventListener("showall", this.updatePlaneSize);
34672
34503
  this.viewer.addEventListener("changecameramode", this.updateTransformCamera);
34673
- this.viewer.addEventListener("clearslices", this.clearHelpers);
34674
- this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown, true);
34675
- this.viewer.canvas.addEventListener("pointerup", this.onPointerUp, true);
34676
- this.viewer.canvas.addEventListener("pointercancel", this.onPointerCancel, true);
34677
34504
  this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
34678
34505
  window.addEventListener("keydown", this.onKeyDown);
34679
34506
  window.addEventListener("keyup", this.onKeyUp);
@@ -34684,10 +34511,6 @@ void main() {
34684
34511
  this.viewer.removeEventListener("show", this.updatePlaneSize);
34685
34512
  this.viewer.removeEventListener("showall", this.updatePlaneSize);
34686
34513
  this.viewer.removeEventListener("changecameramode", this.updateTransformCamera);
34687
- this.viewer.removeEventListener("clearslices", this.clearHelpers);
34688
- this.viewer.canvas.removeEventListener("pointerdown", this.onPointerDown, true);
34689
- this.viewer.canvas.removeEventListener("pointerup", this.onPointerUp, true);
34690
- this.viewer.canvas.removeEventListener("pointercancel", this.onPointerCancel, true);
34691
34514
  this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
34692
34515
  window.removeEventListener("keydown", this.onKeyDown);
34693
34516
  window.removeEventListener("keyup", this.onKeyUp);
@@ -34701,108 +34524,28 @@ void main() {
34701
34524
  this.rotate.getHelper().removeFromParent();
34702
34525
  this.rotate.detach();
34703
34526
  this.rotate.dispose();
34704
- this.helpers.forEach((helper) => {
34705
- helper.removeFromParent();
34706
- helper.dispose();
34707
- });
34708
- this.helpers = [];
34709
- this.activeHelper = null;
34527
+ this.planeHelper.removeFromParent();
34528
+ this.planeHelper.dispose();
34529
+ this.planeCenter.removeFromParent();
34710
34530
  super.dispose();
34711
34531
  }
34712
- addHelper(plane) {
34713
- const extentsSize = this.viewer.extents.getSize(new Vector3()).length() || 1;
34714
- const extentsCenter = this.viewer.extents.getCenter(new Vector3());
34715
- const helper = new PlaneHelper2(extentsSize);
34716
- helper.plane = plane;
34717
- helper.position.copy(plane.projectPoint(extentsCenter, new Vector3()));
34718
- helper.quaternion.setFromUnitVectors(new Vector3(0, 0, -1), plane.normal);
34719
- this.helpers.push(helper);
34720
- this.viewer.helpers.add(helper);
34721
- return helper;
34722
- }
34723
- setActiveHelper(helper) {
34724
- if (helper === this.activeHelper)
34725
- return;
34726
- if (this.activeHelper) {
34727
- this.activeHelper.getLineMaterial().color.setHex(0xf0f0f0);
34728
- this.activeHelper.getMeshMaterial().opacity = 0.15;
34729
- this.translate.detach();
34730
- this.rotate.detach();
34731
- }
34732
- this.activeHelper = helper;
34733
- if (this.activeHelper) {
34734
- this.activeHelper.getLineMaterial().color.setHex(0xd0d0d0);
34735
- this.activeHelper.getMeshMaterial().opacity = 0.3;
34736
- this.translate.attach(this.activeHelper);
34737
- this.rotate.attach(this.activeHelper);
34738
- }
34739
- this.viewer.update();
34740
- }
34741
- saveState() {
34742
- if (!this.activeHelper)
34743
- return;
34744
- this.position0.copy(this.activeHelper.position);
34745
- this.quaternion0.copy(this.activeHelper.quaternion);
34746
- }
34747
- reset() {
34748
- if (!this.activeHelper)
34749
- return;
34750
- this.translate.dragging = false;
34751
- this.rotate.dragging = false;
34752
- this.orbit.state = STATE.NONE;
34753
- this.activeHelper.position.copy(this.position0);
34754
- this.activeHelper.quaternion.copy(this.quaternion0);
34755
- this.transformChange();
34756
- }
34757
- addPlane(normal) {
34758
- const extentsCenter = this.viewer.extents.getCenter(new Vector3());
34759
- const constant = -extentsCenter.dot(normal);
34760
- const plane = new Plane(normal, constant);
34761
- this.clippingPlanes.push(plane);
34762
- const helper = this.addHelper(plane);
34763
- this.setActiveHelper(helper);
34764
- }
34765
- addPlaneX() {
34766
- this.addPlane(new Vector3(-1, 0, 0));
34767
- }
34768
- addPlaneY() {
34769
- this.addPlane(new Vector3(0, -1, 0));
34770
- }
34771
- addPlaneZ() {
34772
- this.addPlane(new Vector3(0, 0, -1));
34773
- }
34774
- deleteActivePlane() {
34775
- if (!this.activeHelper)
34776
- return;
34777
- const helper = this.activeHelper;
34778
- const index = this.clippingPlanes.indexOf(helper.plane);
34779
- if (index !== -1)
34780
- this.clippingPlanes.splice(index, 1);
34781
- this.helpers = this.helpers.filter((x) => x !== helper);
34782
- helper.removeFromParent();
34783
- helper.dispose();
34784
- this.setActiveHelper(this.helpers[this.helpers.length - 1]);
34785
- }
34786
34532
  }
34787
34533
 
34788
34534
  class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
34789
34535
  constructor(viewer) {
34790
- super(viewer);
34791
- this.addPlaneX();
34536
+ super(viewer, new Vector3(-1, 0, 0));
34792
34537
  }
34793
34538
  }
34794
34539
 
34795
34540
  class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
34796
34541
  constructor(viewer) {
34797
- super(viewer);
34798
- this.addPlaneY();
34542
+ super(viewer, new Vector3(0, -1, 0));
34799
34543
  }
34800
34544
  }
34801
34545
 
34802
34546
  class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
34803
34547
  constructor(viewer) {
34804
- super(viewer);
34805
- this.addPlaneZ();
34548
+ super(viewer, new Vector3(0, 0, -1));
34806
34549
  }
34807
34550
  }
34808
34551
 
@@ -34879,6 +34622,120 @@ void main() {
34879
34622
  }
34880
34623
  }
34881
34624
 
34625
+ const DESKTOP_SNAP_DISTANCE = 10;
34626
+ const MOBILE_SNAP_DISTANCE = 50;
34627
+ const _vertex = new Vector3();
34628
+ const _start$1 = new Vector3();
34629
+ const _end$1 = new Vector3();
34630
+ const _line = new Line3();
34631
+ const _center = new Vector3();
34632
+ const _projection = new Vector3();
34633
+ class Snapper {
34634
+ constructor(camera, renderer, canvas) {
34635
+ this.camera = camera;
34636
+ this.renderer = renderer;
34637
+ this.canvas = canvas;
34638
+ this.threshold = 0.0001;
34639
+ this.raycaster = new Raycaster();
34640
+ this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
34641
+ this.edgesCache = new WeakMap();
34642
+ }
34643
+ isMobile() {
34644
+ if (typeof navigator === "undefined")
34645
+ return false;
34646
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
34647
+ }
34648
+ getMousePosition(event, target) {
34649
+ return target.set(event.clientX, event.clientY);
34650
+ }
34651
+ getPointerIntersects(mouse, objects) {
34652
+ const rect = this.canvas.getBoundingClientRect();
34653
+ const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
34654
+ const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
34655
+ const coords = new Vector2(x, y);
34656
+ this.raycaster.setFromCamera(coords, this.camera);
34657
+ this.raycaster.params = {
34658
+ Mesh: {},
34659
+ Line: { threshold: this.threshold },
34660
+ Line2: { threshold: this.threshold },
34661
+ LOD: {},
34662
+ Points: { threshold: this.threshold },
34663
+ Sprite: {},
34664
+ };
34665
+ let intersects = this.raycaster.intersectObjects(objects, false);
34666
+ (this.renderer.clippingPlanes || []).forEach((plane) => {
34667
+ intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
34668
+ });
34669
+ return intersects;
34670
+ }
34671
+ getDetectRadius(point) {
34672
+ const camera = this.camera;
34673
+ if (camera.isOrthographicCamera) {
34674
+ const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
34675
+ const canvasHeight = this.canvas.height;
34676
+ const worldUnitsPerPixel = fieldHeight / canvasHeight;
34677
+ return this.detectRadiusInPixels * worldUnitsPerPixel;
34678
+ }
34679
+ if (camera.isPerspectiveCamera) {
34680
+ const distance = camera.position.distanceTo(point);
34681
+ const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
34682
+ const canvasHeight = this.canvas.height;
34683
+ const worldUnitsPerPixel = fieldHeight / canvasHeight;
34684
+ return this.detectRadiusInPixels * worldUnitsPerPixel;
34685
+ }
34686
+ return 0.1;
34687
+ }
34688
+ getSnapPoint(mouse, objects) {
34689
+ const intersections = this.getPointerIntersects(mouse, objects);
34690
+ if (intersections.length === 0)
34691
+ return undefined;
34692
+ const object = intersections[0].object;
34693
+ const intersectionPoint = intersections[0].point;
34694
+ const localPoint = object.worldToLocal(intersectionPoint.clone());
34695
+ let snapPoint;
34696
+ let snapDistance = this.getDetectRadius(intersectionPoint);
34697
+ const geometry = object.geometry;
34698
+ const positions = geometry.attributes.position.array;
34699
+ for (let i = 0; i < positions.length; i += 3) {
34700
+ _vertex.set(positions[i], positions[i + 1], positions[i + 2]);
34701
+ const distance = _vertex.distanceTo(localPoint);
34702
+ if (distance < snapDistance) {
34703
+ snapDistance = distance;
34704
+ snapPoint = _vertex.clone();
34705
+ }
34706
+ }
34707
+ if (snapPoint)
34708
+ return object.localToWorld(snapPoint);
34709
+ let edges = this.edgesCache.get(geometry);
34710
+ if (!edges) {
34711
+ edges = new EdgesGeometry(geometry);
34712
+ this.edgesCache.set(geometry, edges);
34713
+ }
34714
+ const edgePositions = edges.attributes.position.array;
34715
+ for (let i = 0; i < edgePositions.length; i += 6) {
34716
+ _start$1.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
34717
+ _end$1.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
34718
+ _line.set(_start$1, _end$1);
34719
+ _line.getCenter(_center);
34720
+ const centerDistance = _center.distanceTo(localPoint);
34721
+ if (centerDistance < snapDistance) {
34722
+ snapDistance = centerDistance;
34723
+ snapPoint = _center.clone();
34724
+ continue;
34725
+ }
34726
+ _line.closestPointToPoint(localPoint, true, _projection);
34727
+ const lineDistance = _projection.distanceTo(localPoint);
34728
+ if (lineDistance < snapDistance) {
34729
+ snapDistance = lineDistance;
34730
+ snapPoint = _projection.clone();
34731
+ }
34732
+ }
34733
+ if (snapPoint)
34734
+ return object.localToWorld(snapPoint);
34735
+ return intersectionPoint.clone();
34736
+ }
34737
+ }
34738
+
34882
34739
  const _downPoint = new Vector2();
34883
34740
  class MeasureLineDragger extends OrbitDragger {
34884
34741
  constructor(viewer) {
@@ -35290,12 +35147,6 @@ void main() {
35290
35147
  this.movementSpeed = 0.1;
35291
35148
  this.multiplier = 3;
35292
35149
  this.groundFollowingSkippedFrames = 0;
35293
- this.GROUND_BOX_HALF_SIZE = 20;
35294
- this.GROUND_BOX_REFRESH_THRESHOLD = 0.3;
35295
- this._groundObjectBoxes = new Map();
35296
- this._activeGroundObjects = [];
35297
- this._groundBox = new Box3();
35298
- this._groundBoxCenter = new Vector3();
35299
35150
  this.moveWheel = 0;
35300
35151
  this.mouseDragOn = false;
35301
35152
  this._up = new Vector3();
@@ -35362,20 +35213,11 @@ void main() {
35362
35213
  }
35363
35214
  };
35364
35215
  this.onKeyUp = (event) => {
35365
- if (this.moveKeys.delete(event.code)) {
35366
- if (this.moveKeys.size === 0) {
35367
- this._rebuildGroundBox(this.object.position);
35368
- }
35216
+ if (this.moveKeys.delete(event.code))
35369
35217
  this.update();
35370
- }
35371
35218
  };
35372
35219
  this.camera = camera;
35373
35220
  this.groundObjects = groundObjects;
35374
- for (const obj of groundObjects) {
35375
- this._groundObjectBoxes.set(obj, new Box3().setFromObject(obj));
35376
- }
35377
- const pos = this.object.position;
35378
- this._rebuildGroundBox(pos);
35379
35221
  this.raycaster = new Raycaster();
35380
35222
  this.raycaster.near = 0;
35381
35223
  this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
@@ -35410,29 +35252,10 @@ void main() {
35410
35252
  window.removeEventListener("keyup", this.onKeyUp);
35411
35253
  super.dispose();
35412
35254
  }
35413
- _rebuildGroundBox(center) {
35414
- const h = this.GROUND_BOX_HALF_SIZE;
35415
- this._groundBoxCenter.copy(center);
35416
- this._groundBox.set(new Vector3(center.x - h, center.y - h * 4, center.z - h), new Vector3(center.x + h, center.y + h * 4, center.z + h));
35417
- this._activeGroundObjects = this.groundObjects.filter((obj) => {
35418
- const objectBox = this._groundObjectBoxes.get(obj);
35419
- return objectBox !== undefined && this._groundBox.intersectsBox(objectBox);
35420
- });
35421
- }
35422
- _needsGroundBoxRebuild(pos) {
35423
- if (this._activeGroundObjects.length === 0 && this.groundObjects.length > 0)
35424
- return true;
35425
- const threshold = this.GROUND_BOX_HALF_SIZE * this.GROUND_BOX_REFRESH_THRESHOLD;
35426
- return (Math.abs(pos.x - this._groundBoxCenter.x) > threshold || Math.abs(pos.z - this._groundBoxCenter.z) > threshold);
35427
- }
35428
35255
  updateGroundFollowing() {
35429
- const pos = this.object.position;
35430
- if (this._needsGroundBoxRebuild(pos)) {
35431
- this._rebuildGroundBox(pos);
35432
- }
35433
35256
  this._up.copy(this.camera.up).negate();
35434
- this.raycaster.set(pos, this._up);
35435
- const intersects = this.raycaster.intersectObjects(this._activeGroundObjects, false);
35257
+ this.raycaster.set(this.object.position, this._up);
35258
+ const intersects = this.raycaster.intersectObjects(this.groundObjects, false);
35436
35259
  if (intersects.length > 0) {
35437
35260
  const groundY = intersects[0].point.y;
35438
35261
  const targetY = groundY + this.EYE_HEIGHT;
@@ -35984,7 +35807,6 @@ void main() {
35984
35807
  draggers.registerDragger("Orbit", (viewer) => new OrbitDragger(viewer));
35985
35808
  draggers.registerDragger("Zoom", (viewer) => new ZoomDragger(viewer));
35986
35809
  draggers.registerDragger("MeasureLine", (viewer) => new MeasureLineDragger(viewer));
35987
- draggers.registerDragger("CuttingPlane", (viewer) => new CuttingPlaneDragger(viewer));
35988
35810
  draggers.registerDragger("CuttingPlaneXAxis", (viewer) => new CuttingPlaneXAxisDragger(viewer));
35989
35811
  draggers.registerDragger("CuttingPlaneYAxis", (viewer) => new CuttingPlaneYAxisDragger(viewer));
35990
35812
  draggers.registerDragger("CuttingPlaneZAxis", (viewer) => new CuttingPlaneZAxisDragger(viewer));
@@ -37519,7 +37341,7 @@ void main() {
37519
37341
  this.getMousePosition(event, this.downPosition);
37520
37342
  };
37521
37343
  this.onPointerUp = (event) => {
37522
- if (!event.isPrimary || event.button !== 0)
37344
+ if (!event.isPrimary)
37523
37345
  return;
37524
37346
  const upPosition = this.getMousePosition(event, new Vector2());
37525
37347
  if (upPosition.distanceTo(this.downPosition) !== 0)
@@ -38982,81 +38804,6 @@ void main() {
38982
38804
  this.mergedObjectMap = new Map();
38983
38805
  this.mergedGeometryVisibility = new Map();
38984
38806
  this._webglInfoCache = null;
38985
- this.transformTextureSize = 1024;
38986
- this.transformTexture = this.createDummyTexture();
38987
- this.transformData = null;
38988
- this.identityTransformData = null;
38989
- this.visibilityMaterials = new Set();
38990
- }
38991
- createDummyTexture() {
38992
- const data = new Float32Array(16);
38993
- const identity = new Matrix4();
38994
- identity.toArray(data);
38995
- const dummyData = new Float32Array(16);
38996
- identity.toArray(dummyData);
38997
- const dummyTexture = new DataTexture(dummyData, 4, 1, RGBAFormat, FloatType);
38998
- dummyTexture.minFilter = NearestFilter;
38999
- dummyTexture.magFilter = NearestFilter;
39000
- dummyTexture.needsUpdate = true;
39001
- return dummyTexture;
39002
- }
39003
- initTransformTexture() {
39004
- if (this.transformTexture) {
39005
- this.transformTexture.dispose();
39006
- }
39007
- const maxInstanceCount = this.maxObjectId + 1;
39008
- let size = Math.sqrt(maxInstanceCount * 4);
39009
- size = Math.ceil(size / 4) * 4;
39010
- size = Math.max(size, 4);
39011
- this.transformTextureSize = size;
39012
- const arraySize = size * size * 4;
39013
- this.transformData = new Float32Array(arraySize);
39014
- this.identityTransformData = new Float32Array(arraySize);
39015
- for (let i = 0; i <= this.maxObjectId; i++) {
39016
- const base = i * 16;
39017
- if (base + 15 < arraySize) {
39018
- this.identityTransformData[base + 0] = 1;
39019
- this.identityTransformData[base + 5] = 1;
39020
- this.identityTransformData[base + 10] = 1;
39021
- this.identityTransformData[base + 15] = 1;
39022
- }
39023
- }
39024
- this._resetTransformData(false);
39025
- this.transformTexture = new DataTexture(this.transformData, size, size, RGBAFormat, FloatType);
39026
- this.transformTexture.needsUpdate = true;
39027
- this.transformTexture.generateMipmaps = false;
39028
- console.log(`Initialized transform texture: ${size}x${size} for ${maxInstanceCount} objects`);
39029
- this.updateMaterialUniforms();
39030
- this.visibilityMaterials.forEach((material) => {
39031
- material.needsUpdate = true;
39032
- });
39033
- }
39034
- _resetTransformData(updateTexture = true) {
39035
- if (!this.transformData || !this.identityTransformData) return;
39036
- this.transformData.set(this.identityTransformData);
39037
- if (updateTexture) {
39038
- this.updateTransformTexture();
39039
- }
39040
- }
39041
- updateMaterialUniforms() {
39042
- if (
39043
- this._lastTransformTexture === this.transformTexture &&
39044
- this._lastTransformTextureSize === this.transformTextureSize
39045
- ) {
39046
- return;
39047
- }
39048
- this._lastTransformTexture = this.transformTexture;
39049
- this._lastTransformTextureSize = this.transformTextureSize;
39050
- this.visibilityMaterials.forEach((material) => {
39051
- if (material.userData && material.userData.visibilityUniforms) {
39052
- material.userData.visibilityUniforms.transformTexture.value = this.transformTexture;
39053
- material.userData.visibilityUniforms.transformTextureSize.value = this.transformTextureSize;
39054
- }
39055
- });
39056
- }
39057
- updateTransformTexture() {
39058
- if (!this.transformTexture) return;
39059
- this.transformTexture.needsUpdate = true;
39060
38807
  }
39061
38808
  setVisibleEdges(visible) {
39062
38809
  this.visibleEdges = visible;
@@ -39946,82 +39693,36 @@ void main() {
39946
39693
  }
39947
39694
  }
39948
39695
  createVisibilityMaterial(material) {
39949
- this.visibilityMaterials.add(material);
39950
- const uniforms = {
39951
- transformTexture: { value: this.transformTexture },
39952
- transformTextureSize: { value: this.transformTextureSize },
39953
- };
39954
- material.userData.visibilityUniforms = uniforms;
39955
39696
  material.onBeforeCompile = (shader) => {
39956
- shader.uniforms.transformTexture = uniforms.transformTexture;
39957
- shader.uniforms.transformTextureSize = uniforms.transformTextureSize;
39958
39697
  shader.vertexShader = shader.vertexShader.replace(
39959
39698
  "#include <common>",
39960
39699
  `
39961
39700
  #include <common>
39962
-
39963
39701
  attribute float visibility;
39964
- attribute float objectId;
39965
39702
  varying float vVisibility;
39966
- uniform highp sampler2D transformTexture;
39967
- uniform float transformTextureSize;
39968
-
39969
- mat4 getTransformMatrix(float instanceId) {
39970
- int size = int(transformTextureSize);
39971
- int index = int(instanceId) * 4;
39972
-
39973
- int x0 = index % size;
39974
- int y0 = index / size;
39975
-
39976
- vec4 row0 = texelFetch(transformTexture, ivec2(x0, y0), 0);
39977
- vec4 row1 = texelFetch(transformTexture, ivec2(x0 + 1, y0), 0);
39978
- vec4 row2 = texelFetch(transformTexture, ivec2(x0 + 2, y0), 0);
39979
- vec4 row3 = texelFetch(transformTexture, ivec2(x0 + 3, y0), 0);
39980
-
39981
- return mat4(row0, row1, row2, row3);
39982
- }
39983
39703
  `
39984
39704
  );
39985
- shader.vertexShader = shader.vertexShader.replace(
39986
- "void main() {",
39705
+ shader.fragmentShader = shader.fragmentShader.replace(
39706
+ "#include <common>",
39987
39707
  `
39988
- void main() {
39989
- mat4 batchingMatrix = getTransformMatrix(objectId);
39990
- vVisibility = visibility;
39708
+ #include <common>
39709
+ varying float vVisibility;
39991
39710
  `
39992
39711
  );
39993
- if (shader.vertexShader.includes("#include <beginnormal_vertex>")) {
39994
- shader.vertexShader = shader.vertexShader.replace(
39995
- "#include <beginnormal_vertex>",
39996
- `
39997
- vec3 objectNormal = vec3( normal );
39998
- mat3 bm = mat3( batchingMatrix );
39999
- objectNormal = bm * objectNormal;
40000
- `
40001
- );
40002
- }
40003
39712
  shader.vertexShader = shader.vertexShader.replace(
40004
- "#include <begin_vertex>",
39713
+ "void main() {",
40005
39714
  `
40006
- vec3 transformed = vec3( position );
40007
- transformed = ( batchingMatrix * vec4( transformed, 1.0 ) ).xyz;
39715
+ void main() {
39716
+ vVisibility = visibility;
40008
39717
  `
40009
39718
  );
40010
- shader.fragmentShader = shader.fragmentShader
40011
- .replace(
40012
- "#include <common>",
40013
- `
40014
- #include <common>
40015
- varying float vVisibility;
40016
- `
40017
- )
40018
- .replace(
40019
- "void main() {",
40020
- `
39719
+ shader.fragmentShader = shader.fragmentShader.replace(
39720
+ "void main() {",
39721
+ `
40021
39722
  void main() {
40022
39723
  if (vVisibility < 0.5) discard;
40023
39724
  `
40024
- );
39725
+ );
40025
39726
  };
40026
39727
  material.needsUpdate = true;
40027
39728
  return material;
@@ -40136,8 +39837,6 @@ void main() {
40136
39837
  this.objectIdToIndex.clear();
40137
39838
  this.maxObjectId = 0;
40138
39839
  this.objectVisibility = new Float32Array();
40139
- this.meshToNodeMap = null;
40140
- this.visibilityMaterials.clear();
40141
39840
  }
40142
39841
  setStructureTransform(structureId, matrix) {
40143
39842
  const rootGroup = this.structureRoots.get(structureId);
@@ -40253,15 +39952,12 @@ void main() {
40253
39952
  });
40254
39953
  this.originalObjects.clear();
40255
39954
  this.originalObjectsToSelection.clear();
40256
- this.objectIdToIndex.clear();
40257
- this.maxObjectId = 0;
40258
39955
  const structureGroups = new Map();
40259
39956
  this.dispatchEvent("optimizationprogress", {
40260
39957
  phase: "collecting",
40261
39958
  progress: 5,
40262
39959
  message: "Collecting scene objects...",
40263
39960
  });
40264
- let totalObjectsToMerge = 0;
40265
39961
  this.scene.traverse((object) => {
40266
39962
  if (object.userData.structureId) {
40267
39963
  const structureId = object.userData.structureId;
@@ -40279,32 +39975,17 @@ void main() {
40279
39975
  });
40280
39976
  }
40281
39977
  const group = structureGroups.get(structureId);
40282
- let added = false;
40283
39978
  if (object instanceof Mesh) {
40284
39979
  this.addToMaterialGroup(object, group.mapMeshes, group.meshes);
40285
- added = true;
40286
39980
  } else if (object instanceof LineSegments) {
40287
39981
  this.addToMaterialGroup(object, group.mapLineSegments, group.lineSegments);
40288
- added = true;
40289
39982
  } else if (object instanceof Line$1) {
40290
39983
  this.addToMaterialGroup(object, group.mapLines, group.lines);
40291
- added = true;
40292
39984
  } else if (object instanceof Points) {
40293
39985
  this.addToMaterialGroup(object, group.mapPoints, group.points);
40294
- added = true;
40295
- }
40296
- if (added) {
40297
- totalObjectsToMerge++;
40298
39986
  }
40299
39987
  }
40300
39988
  });
40301
- if (totalObjectsToMerge > 0) {
40302
- console.log(`Pre-allocating transform texture for ${totalObjectsToMerge} objects`);
40303
- this.maxObjectId = totalObjectsToMerge;
40304
- this.initTransformTexture();
40305
- this.initializeObjectVisibility();
40306
- this.maxObjectId = 0;
40307
- }
40308
39989
  let processedGroups = 0;
40309
39990
  const totalGroups = structureGroups.size;
40310
39991
  this.dispatchEvent("optimizationprogress", {
@@ -40349,6 +40030,7 @@ void main() {
40349
40030
  this.originalObjectsToSelection.add(obj);
40350
40031
  }
40351
40032
  });
40033
+ this.initializeObjectVisibility();
40352
40034
  console.log(`Optimization complete. Total objects: ${this.maxObjectId}`);
40353
40035
  this.dispatchEvent("optimizationprogress", {
40354
40036
  phase: "complete",
@@ -40417,7 +40099,6 @@ void main() {
40417
40099
  }
40418
40100
  const visibilityMaterial = this.createVisibilityMaterial(group.material);
40419
40101
  const mergedMesh = new Mesh(mergedGeometry, visibilityMaterial);
40420
- mergedMesh.frustumCulled = false;
40421
40102
  mergedMesh.userData.isOptimized = true;
40422
40103
  rootGroup.add(mergedMesh);
40423
40104
  this.mergedMesh.add(mergedMesh);
@@ -40534,7 +40215,6 @@ void main() {
40534
40215
  geometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40535
40216
  const visibilityMaterial = this.createVisibilityMaterial(group.material);
40536
40217
  const mergedLine = new LineSegments(geometry, visibilityMaterial);
40537
- mergedLine.frustumCulled = false;
40538
40218
  mergedLine.userData.isEdge = isEdge;
40539
40219
  mergedLine.userData.isOptimized = true;
40540
40220
  const mergedObjects = [mergedLine];
@@ -40623,7 +40303,6 @@ void main() {
40623
40303
  mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40624
40304
  const visibilityMaterial = this.createVisibilityMaterial(group.material);
40625
40305
  const mergedLine = new LineSegments(mergedGeometry, visibilityMaterial);
40626
- mergedLine.frustumCulled = false;
40627
40306
  mergedLine.userData.isEdge = isEdge;
40628
40307
  mergedLine.userData.isOptimized = true;
40629
40308
  if (this.useVAO) {
@@ -40693,27 +40372,7 @@ void main() {
40693
40372
  const mergedObjects = [];
40694
40373
  if (geometries.length > 0) {
40695
40374
  const mergedGeometry = mergeGeometries(geometries, false);
40696
- const totalVertices = mergedGeometry.attributes.position.count;
40697
- const objectIds = new Float32Array(totalVertices);
40698
- let vertexOffset = 0;
40699
- group.objects.forEach((points) => {
40700
- const handle = points.userData.handle;
40701
- if (!this.objectIdToIndex.has(handle)) {
40702
- this.objectIdToIndex.set(handle, this.maxObjectId++);
40703
- }
40704
- const objectId = this.objectIdToIndex.get(handle);
40705
- const count = points.geometry.attributes.position.count;
40706
- for (let i = 0; i < count; i++) {
40707
- objectIds[vertexOffset++] = objectId;
40708
- }
40709
- });
40710
- mergedGeometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
40711
- const visibilityArray = new Float32Array(totalVertices);
40712
- visibilityArray.fill(1.0);
40713
- mergedGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40714
- const visibilityMaterial = this.createVisibilityMaterial(group.material);
40715
- const mergedPoints = new Points(mergedGeometry, visibilityMaterial);
40716
- mergedPoints.frustumCulled = false;
40375
+ const mergedPoints = new Points(mergedGeometry, group.material);
40717
40376
  mergedPoints.userData.isOptimized = true;
40718
40377
  if (this.useVAO) {
40719
40378
  this.createVAO(mergedPoints);
@@ -40782,33 +40441,13 @@ void main() {
40782
40441
  geometriesWithIndex.push(clonedGeometry);
40783
40442
  });
40784
40443
  const finalGeometry = mergeGeometries(geometriesWithIndex, false);
40785
- const totalVertices = finalGeometry.attributes.position.count;
40786
- const objectIds = new Float32Array(totalVertices);
40787
- let vertexOffset = 0;
40788
- lineSegmentsArray.forEach((segment) => {
40789
- const handle = segment.userData.handle;
40790
- if (!this.objectIdToIndex.has(handle)) {
40791
- this.objectIdToIndex.set(handle, this.maxObjectId++);
40792
- }
40793
- const objectId = this.objectIdToIndex.get(handle);
40794
- const count = segment.geometry.attributes.position.count;
40795
- for (let i = 0; i < count; i++) {
40796
- objectIds[vertexOffset++] = objectId;
40797
- }
40798
- });
40799
- finalGeometry.setAttribute("objectId", new BufferAttribute(objectIds, 1));
40800
- const visibilityArray = new Float32Array(totalVertices);
40801
- visibilityArray.fill(1.0);
40802
- finalGeometry.setAttribute("visibility", new BufferAttribute(visibilityArray, 1));
40803
40444
  const material = new LineBasicMaterial({
40804
40445
  vertexColors: true,
40805
40446
  });
40806
- const visibilityMaterial = this.createVisibilityMaterial(material);
40807
40447
  if (this.useVAO) {
40808
40448
  this.createVAO(finalGeometry);
40809
40449
  }
40810
- const mergedLine = new LineSegments(finalGeometry, visibilityMaterial);
40811
- mergedLine.frustumCulled = false;
40450
+ const mergedLine = new LineSegments(finalGeometry, material);
40812
40451
  mergedLine.userData.structureId = structureId;
40813
40452
  mergedLine.userData.isOptimized = true;
40814
40453
  rootGroup.add(mergedLine);
@@ -40927,50 +40566,18 @@ void main() {
40927
40566
  console.warn("No merged objects to transform");
40928
40567
  return;
40929
40568
  }
40930
- if (!this.transformData) {
40931
- console.warn("Transform texture not initialized");
40932
- return;
40569
+ this.objectTransforms = new Map(objectTransformMap);
40570
+ for (const mesh of this.mergedMesh) {
40571
+ this._applyTransformToMergedObject(mesh);
40933
40572
  }
40934
- this.objectTransforms = objectTransformMap;
40935
- this._resetTransformData(false);
40936
- const transformData = this.transformData;
40937
- const objectIdToIndex = this.objectIdToIndex;
40938
- let textureNeedsUpdate = false;
40939
- if (objectTransformMap instanceof Map) {
40940
- for (const [object, matrix] of objectTransformMap.entries()) {
40941
- const userData = object.userData;
40942
- if (!userData) continue;
40943
- const handle = userData.handle;
40944
- if (handle === undefined) continue;
40945
- const objectId = objectIdToIndex.get(handle);
40946
- if (objectId !== undefined) {
40947
- transformData.set(matrix.elements, objectId * 16);
40948
- textureNeedsUpdate = true;
40949
- }
40950
- }
40951
- } else {
40952
- const len = objectTransformMap.length;
40953
- for (let i = 0; i < len; i++) {
40954
- const pair = objectTransformMap[i];
40955
- const userData = pair[0].userData;
40956
- if (!userData) continue;
40957
- const handle = userData.handle;
40958
- if (handle === undefined) continue;
40959
- const objectId = objectIdToIndex.get(handle);
40960
- if (objectId !== undefined) {
40961
- transformData.set(pair[1].elements, objectId * 16);
40962
- textureNeedsUpdate = true;
40963
- }
40964
- }
40573
+ for (const line of this.mergedLines) {
40574
+ this._applyTransformToMergedObject(line);
40965
40575
  }
40966
- if (textureNeedsUpdate) {
40967
- this.updateTransformTexture();
40968
- if (
40969
- this._lastTransformTexture !== this.transformTexture ||
40970
- this._lastTransformTextureSize !== this.transformTextureSize
40971
- ) {
40972
- this.updateMaterialUniforms();
40973
- }
40576
+ for (const lineSegment of this.mergedLineSegments) {
40577
+ this._applyTransformToMergedObject(lineSegment);
40578
+ }
40579
+ for (const point of this.mergedPoints) {
40580
+ this._applyTransformToMergedObject(point);
40974
40581
  }
40975
40582
  }
40976
40583
  createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
@@ -40987,66 +40594,21 @@ void main() {
40987
40594
  ? objects
40988
40595
  : Array.from(objects)
40989
40596
  : Array.from(this.originalObjects);
40990
- const structureInverseMatrices = new Map();
40991
- if (!this.meshToNodeMap) {
40992
- this.meshToNodeMap = new Map();
40993
- for (const node of this.nodes.values()) {
40994
- if (node.object) {
40995
- this.meshToNodeMap.set(node.object, node);
40996
- }
40997
- }
40998
- }
40999
40597
  for (const obj of objectsArray) {
41000
40598
  if (!obj.geometry || !obj.geometry.attributes.position) continue;
41001
- if (!obj.userData.explodeVector) {
41002
- let center = null;
41003
- const node = this.meshToNodeMap.get(obj);
41004
- if (node && node.geometryExtents) {
41005
- const box = node.geometryExtents.clone();
41006
- box.applyMatrix4(obj.matrixWorld);
41007
- center = new Vector3();
41008
- box.getCenter(center);
41009
- }
41010
- if (!center) {
41011
- if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
41012
- const box = obj.geometry.boundingBox.clone();
41013
- box.applyMatrix4(obj.matrixWorld);
41014
- center = new Vector3();
41015
- box.getCenter(center);
41016
- }
41017
- const explodeVector = center.sub(explodeCenter);
41018
- obj.userData.explodeVector = explodeVector;
40599
+ const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
40600
+ if (obj.matrixWorld) {
40601
+ boundingBox.applyMatrix4(obj.matrixWorld);
41019
40602
  }
41020
- const explodeVector = obj.userData.explodeVector;
41021
- const distance = explodeVector.length();
40603
+ if (boundingBox.isEmpty()) continue;
40604
+ const objectCenter = new Vector3();
40605
+ boundingBox.getCenter(objectCenter);
40606
+ const direction = objectCenter.clone().sub(explodeCenter);
40607
+ const distance = direction.length();
41022
40608
  if (distance > 0) {
41023
- const offset = explodeVector.clone().multiplyScalar(explodeFactor - 1.0);
41024
- const localOffset = offset.clone();
41025
- if (obj.userData.structureId) {
41026
- const structureId = obj.userData.structureId;
41027
- let inverseMatrix = structureInverseMatrices.get(structureId);
41028
- if (!inverseMatrix) {
41029
- const rootGroup = this.structureRoots.get(structureId);
41030
- if (rootGroup) {
41031
- if (!rootGroup.userData.inverseWorldMatrix) {
41032
- rootGroup.userData.inverseWorldMatrix = new Matrix4().copy(rootGroup.matrixWorld).invert();
41033
- }
41034
- inverseMatrix = rootGroup.userData.inverseWorldMatrix;
41035
- structureInverseMatrices.set(structureId, inverseMatrix);
41036
- }
41037
- }
41038
- if (inverseMatrix) {
41039
- const zero = new Vector3(0, 0, 0).applyMatrix4(inverseMatrix);
41040
- const vec = offset.clone().applyMatrix4(inverseMatrix).sub(zero);
41041
- localOffset.copy(vec);
41042
- }
41043
- }
41044
- let matrix = obj.userData.explodeMatrix;
41045
- if (!matrix) {
41046
- matrix = new Matrix4();
41047
- obj.userData.explodeMatrix = matrix;
41048
- }
41049
- matrix.makeTranslation(localOffset.x, localOffset.y, localOffset.z);
40609
+ direction.normalize();
40610
+ const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
40611
+ const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
41050
40612
  transformMap.set(obj, matrix);
41051
40613
  }
41052
40614
  }
@@ -41054,11 +40616,116 @@ void main() {
41054
40616
  }
41055
40617
  clearTransforms() {
41056
40618
  this.objectTransforms.clear();
41057
- this._resetTransformData(true);
40619
+ for (const mesh of this.mergedMesh) {
40620
+ this._restoreOriginalGeometry(mesh);
40621
+ }
40622
+ for (const line of this.mergedLines) {
40623
+ this._restoreOriginalGeometry(line);
40624
+ }
40625
+ for (const lineSegment of this.mergedLineSegments) {
40626
+ this._restoreOriginalGeometry(lineSegment);
40627
+ }
40628
+ for (const point of this.mergedPoints) {
40629
+ this._restoreOriginalGeometry(point);
40630
+ }
41058
40631
  }
41059
40632
  clearHandleTransforms() {
41060
40633
  this.clearTransforms();
41061
40634
  }
40635
+ _applyTransformToMergedObject(mergedObject) {
40636
+ const objectData = this.mergedObjectMap.get(mergedObject.uuid);
40637
+ if (!objectData || !objectData.objectMapping) return;
40638
+ const geometry = mergedObject.geometry;
40639
+ if (!geometry || !geometry.attributes.position) return;
40640
+ const positionAttr = geometry.attributes.position;
40641
+ const positions = positionAttr.array;
40642
+ if (!this.transformedGeometries.has(mergedObject.uuid)) {
40643
+ this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
40644
+ }
40645
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
40646
+ const tempVector = new Vector3();
40647
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
40648
+ const transform = this.objectTransforms.get(originalMesh);
40649
+ if (!transform) {
40650
+ const startIdx = mappingData.startVertexIndex * 3;
40651
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
40652
+ for (let i = startIdx; i < endIdx; i++) {
40653
+ positions[i] = originalPositions[i];
40654
+ }
40655
+ continue;
40656
+ }
40657
+ const startVertex = mappingData.startVertexIndex;
40658
+ const vertexCount = mappingData.vertexCount;
40659
+ for (let i = 0; i < vertexCount; i++) {
40660
+ const idx = (startVertex + i) * 3;
40661
+ tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
40662
+ tempVector.applyMatrix4(transform);
40663
+ positions[idx] = tempVector.x;
40664
+ positions[idx + 1] = tempVector.y;
40665
+ positions[idx + 2] = tempVector.z;
40666
+ }
40667
+ }
40668
+ if (geometry.attributes.normal) {
40669
+ this._updateNormalsForTransform(geometry, objectData, originalPositions);
40670
+ }
40671
+ positionAttr.needsUpdate = true;
40672
+ geometry.computeBoundingSphere();
40673
+ geometry.computeBoundingBox();
40674
+ }
40675
+ _updateNormalsForTransform(geometry, objectData, originalPositions) {
40676
+ const normalAttr = geometry.attributes.normal;
40677
+ if (!normalAttr) return;
40678
+ const normals = normalAttr.array;
40679
+ const tempVector = new Vector3();
40680
+ const normalMatrix = new Matrix4();
40681
+ const normalsKey = `${geometry.uuid}_normals`;
40682
+ if (!this.transformedGeometries.has(normalsKey)) {
40683
+ this.transformedGeometries.set(normalsKey, new Float32Array(normals));
40684
+ }
40685
+ const originalNormals = this.transformedGeometries.get(normalsKey);
40686
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
40687
+ const transform = this.objectTransforms.get(originalMesh);
40688
+ if (!transform) {
40689
+ const startIdx = mappingData.startVertexIndex * 3;
40690
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
40691
+ for (let i = startIdx; i < endIdx; i++) {
40692
+ normals[i] = originalNormals[i];
40693
+ }
40694
+ continue;
40695
+ }
40696
+ normalMatrix.copy(transform).invert().transpose();
40697
+ const startVertex = mappingData.startVertexIndex;
40698
+ const vertexCount = mappingData.vertexCount;
40699
+ for (let i = 0; i < vertexCount; i++) {
40700
+ const idx = (startVertex + i) * 3;
40701
+ tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
40702
+ tempVector.applyMatrix4(normalMatrix).normalize();
40703
+ normals[idx] = tempVector.x;
40704
+ normals[idx + 1] = tempVector.y;
40705
+ normals[idx + 2] = tempVector.z;
40706
+ }
40707
+ }
40708
+ normalAttr.needsUpdate = true;
40709
+ }
40710
+ _restoreOriginalGeometry(mergedObject) {
40711
+ const geometry = mergedObject.geometry;
40712
+ if (!geometry || !geometry.attributes.position) return;
40713
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
40714
+ if (originalPositions) {
40715
+ const positions = geometry.attributes.position.array;
40716
+ positions.set(originalPositions);
40717
+ geometry.attributes.position.needsUpdate = true;
40718
+ }
40719
+ const normalsKey = `${geometry.uuid}_normals`;
40720
+ const originalNormals = this.transformedGeometries.get(normalsKey);
40721
+ if (originalNormals && geometry.attributes.normal) {
40722
+ const normals = geometry.attributes.normal.array;
40723
+ normals.set(originalNormals);
40724
+ geometry.attributes.normal.needsUpdate = true;
40725
+ }
40726
+ geometry.computeBoundingSphere();
40727
+ geometry.computeBoundingBox();
40728
+ }
41062
40729
  syncHiddenObjects() {
41063
40730
  if (this.mergedObjectMap.size === 0) {
41064
40731
  console.log("No merged objects to sync");