@inweb/viewer-three 25.11.2 → 25.12.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.
@@ -1,9 +1,11 @@
1
- import { Vector2, Raycaster, MeshBasicMaterial, Box3, Vector3, Sphere, LoadingManager, LoaderUtils, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Clock, Object3D, Euler, Matrix4, LineBasicMaterial, CylinderGeometry, BoxGeometry, BufferGeometry, Float32BufferAttribute, Mesh, OctahedronGeometry, Line, SphereGeometry, TorusGeometry, PlaneGeometry, DoubleSide, Plane, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Vector4, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
1
+ import { Vector2, Raycaster, MeshBasicMaterial, Box3, Vector3, Sphere, LoadingManager, LoaderUtils, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Controls, Clock, Line, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, DoubleSide, Plane, Object3D, Matrix4, Vector4, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
2
2
 
3
3
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
4
4
 
5
5
  import Konva from "konva";
6
6
 
7
+ import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
8
+
7
9
  import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment.js";
8
10
 
9
11
  class Commands {
@@ -459,6 +461,20 @@ class SelectionComponent {
459
461
  this.raycaster.setFromCamera(coords, this.viewer.camera);
460
462
  const objects = [];
461
463
  this.viewer.scene.traverseVisible((child => objects.push(child)));
464
+ this.raycaster.params = this.raycaster.params = {
465
+ Mesh: {},
466
+ Line: {
467
+ threshold: .25
468
+ },
469
+ Line2: {
470
+ threshold: .25
471
+ },
472
+ LOD: {},
473
+ Points: {
474
+ threshold: .1
475
+ },
476
+ Sprite: {}
477
+ };
462
478
  return this.raycaster.intersectObjects(objects, false);
463
479
  }
464
480
  select(object) {
@@ -786,10 +802,7 @@ function zoomToObjects(viewer, handles = []) {
786
802
  var _a;
787
803
  if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
788
804
  }));
789
- const extents = objects.reduce(((result, object) => {
790
- const objectExtents = (new Box3).setFromObject(object);
791
- return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
792
- }), new Box3);
805
+ const extents = objects.reduce(((result, object) => result.expandByObject(object)), new Box3);
793
806
  const center = extents.getCenter(new Vector3);
794
807
  const distance = extents.getBoundingSphere(new Sphere).radius;
795
808
  const delta = new Vector3(0, 0, 1);
@@ -806,10 +819,7 @@ function zoomToObjects(viewer, handles = []) {
806
819
  commands("ThreeJS").registerCommand("zoomToObjects", zoomToObjects);
807
820
 
808
821
  function zoomToSelected(viewer) {
809
- const extents = viewer.selected.reduce(((result, object) => {
810
- const objectExtents = (new Box3).setFromObject(object);
811
- return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
812
- }), new Box3);
822
+ const extents = viewer.selected.reduce(((result, object) => result.expandByObject(object)), new Box3);
813
823
  if (extents.isEmpty()) extents.copy(viewer.extents);
814
824
  const center = extents.getCenter(new Vector3);
815
825
  const distance = extents.getBoundingSphere(new Sphere).radius;
@@ -2740,7 +2750,7 @@ class KonvaMarkup {
2740
2750
  }
2741
2751
  }
2742
2752
 
2743
- const _changeEvent$2 = {
2753
+ const _changeEvent = {
2744
2754
  type: "change"
2745
2755
  };
2746
2756
 
@@ -2837,7 +2847,7 @@ class OrbitControls extends EventDispatcher {
2837
2847
  scope.object.position.copy(scope.position0);
2838
2848
  scope.object.zoom = scope.zoom0;
2839
2849
  scope.object.updateProjectionMatrix();
2840
- scope.dispatchEvent(_changeEvent$2);
2850
+ scope.dispatchEvent(_changeEvent);
2841
2851
  scope.update();
2842
2852
  scope.state = STATE.NONE;
2843
2853
  };
@@ -2898,7 +2908,7 @@ class OrbitControls extends EventDispatcher {
2898
2908
  }
2899
2909
  scope.scale = 1;
2900
2910
  if (scope.zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS || lastTargetPosition.distanceToSquared(scope.target) > 0) {
2901
- scope.dispatchEvent(_changeEvent$2);
2911
+ scope.dispatchEvent(_changeEvent);
2902
2912
  lastPosition.copy(scope.object.position);
2903
2913
  lastQuaternion.copy(scope.object.quaternion);
2904
2914
  lastTargetPosition.copy(scope.target);
@@ -3069,7 +3079,7 @@ class OrbitControls extends EventDispatcher {
3069
3079
  scope.update();
3070
3080
  if (event.deltaY !== 0) {
3071
3081
  scope.state = STATE.DOLLY;
3072
- scope.dispatchEvent(_changeEvent$2);
3082
+ scope.dispatchEvent(_changeEvent);
3073
3083
  scope.state = STATE.NONE;
3074
3084
  }
3075
3085
  }
@@ -3528,40 +3538,37 @@ class ZoomDragger extends OrbitDragger {
3528
3538
  }
3529
3539
  }
3530
3540
 
3531
- const _changeEvent$1 = {
3532
- type: "change"
3533
- };
3534
-
3535
- class WalkControls extends EventDispatcher {
3541
+ class WalkControls extends Controls {
3536
3542
  constructor(camera, canvas) {
3537
- super();
3543
+ super(camera, canvas);
3538
3544
  this.movementSpeed = .2;
3539
3545
  this.lookSpeed = 5;
3540
3546
  this.multiplier = 5;
3541
3547
  this.moveWheel = 0;
3542
3548
  this.mouseDragOn = false;
3543
3549
  this.onPointerDown = event => {
3544
- if (!event.isPrimary || event.button !== 0) return;
3545
- this.canvas.setPointerCapture(event.pointerId);
3550
+ if (event.button !== 0) return;
3551
+ this.domElement.setPointerCapture(event.pointerId);
3546
3552
  this.downPosition.set(event.clientX, event.clientY);
3547
- this.quaternion.copy(this.camera.quaternion);
3553
+ this.quaternion.copy(this.object.quaternion);
3548
3554
  this.mouseDragOn = true;
3549
3555
  };
3550
3556
  this.onPointerMove = event => {
3551
- if (!event.isPrimary || !this.mouseDragOn) return;
3557
+ if (!this.mouseDragOn) return;
3552
3558
  const movePosition = new Vector2(event.clientX, event.clientY);
3553
3559
  if (this.downPosition.distanceTo(movePosition) === 0) return;
3554
3560
  this.rotateDelta.copy(this.downPosition).sub(movePosition);
3555
3561
  this.rotateCamera(this.rotateDelta);
3556
- this.dispatchEvent(_changeEvent$1);
3562
+ this.dispatchEvent({
3563
+ type: "change"
3564
+ });
3557
3565
  };
3558
3566
  this.onPointerUp = event => {
3559
- if (!event.isPrimary || event.button !== 0) return;
3560
- this.canvas.releasePointerCapture(event.pointerId);
3567
+ this.domElement.releasePointerCapture(event.pointerId);
3561
3568
  this.mouseDragOn = false;
3562
3569
  };
3563
3570
  this.onPointerCancel = event => {
3564
- this.canvas.dispatchEvent(new PointerEvent("pointerup", event));
3571
+ this.domElement.dispatchEvent(new PointerEvent("pointerup", event));
3565
3572
  };
3566
3573
  this.onWheel = event => {
3567
3574
  this.moveWheel = event.deltaY;
@@ -3607,69 +3614,58 @@ class WalkControls extends EventDispatcher {
3607
3614
  }
3608
3615
  };
3609
3616
  this.onKeyUp = event => {
3610
- switch (event.code) {
3611
- case "ArrowLeft":
3612
- case "ArrowRight":
3613
- case "ArrowUp":
3614
- case "ArrowDown":
3615
- case "KeyW":
3616
- case "KeyS":
3617
- case "KeyA":
3618
- case "KeyD":
3619
- case "KeyQ":
3620
- case "KeyE":
3621
- this.moveKeys.delete(event.code);
3622
- this.update();
3623
- break;
3624
- }
3617
+ if (this.moveKeys.delete(event.code)) this.update();
3625
3618
  };
3626
- this.camera = camera;
3627
- this.canvas = canvas;
3628
3619
  this.moveKeys = new Set;
3629
3620
  this.moveClock = new Clock;
3630
3621
  this.quaternion = camera.quaternion.clone();
3631
3622
  this.downPosition = new Vector2(0, 0);
3632
3623
  this.rotateDelta = new Vector2(0, 0);
3633
- this.canvas.addEventListener("pointerdown", this.onPointerDown);
3634
- this.canvas.addEventListener("pointermove", this.onPointerMove);
3635
- this.canvas.addEventListener("pointerup", this.onPointerUp);
3636
- this.canvas.addEventListener("pointercancel", this.onPointerCancel);
3637
- this.canvas.addEventListener("wheel", this.onWheel);
3624
+ this.domElement.addEventListener("pointerdown", this.onPointerDown);
3625
+ this.domElement.addEventListener("pointermove", this.onPointerMove);
3626
+ this.domElement.addEventListener("pointerup", this.onPointerUp);
3627
+ this.domElement.addEventListener("pointercancel", this.onPointerCancel);
3628
+ this.domElement.addEventListener("wheel", this.onWheel);
3638
3629
  window.addEventListener("keydown", this.onKeyDown);
3639
3630
  window.addEventListener("keyup", this.onKeyUp);
3640
3631
  }
3641
3632
  dispose() {
3642
- this.canvas.removeEventListener("pointerdown", this.onPointerDown);
3643
- this.canvas.removeEventListener("pointermove", this.onPointerMove);
3644
- this.canvas.removeEventListener("pointerup", this.onPointerUp);
3645
- this.canvas.removeEventListener("pointercancel", this.onPointerCancel);
3646
- this.canvas.removeEventListener("wheel", this.onWheel);
3633
+ this.domElement.removeEventListener("pointerdown", this.onPointerDown);
3634
+ this.domElement.removeEventListener("pointermove", this.onPointerMove);
3635
+ this.domElement.removeEventListener("pointerup", this.onPointerUp);
3636
+ this.domElement.removeEventListener("pointercancel", this.onPointerCancel);
3637
+ this.domElement.removeEventListener("wheel", this.onWheel);
3647
3638
  window.removeEventListener("keydown", this.onKeyDown);
3648
3639
  window.removeEventListener("keyup", this.onKeyUp);
3640
+ super.dispose();
3649
3641
  }
3650
3642
  update() {
3651
3643
  if (this.moveKeys.size > 0) {
3652
3644
  const timeDelta = this.moveClock.getDelta();
3653
3645
  const moveDelta = timeDelta * this.movementSpeed * this.multiplier;
3654
- if (this.moveKeys.has("KeyW")) this.camera.translateZ(-moveDelta);
3655
- if (this.moveKeys.has("KeyS")) this.camera.translateZ(moveDelta);
3656
- if (this.moveKeys.has("KeyA")) this.camera.translateX(-moveDelta);
3657
- if (this.moveKeys.has("KeyD")) this.camera.translateX(moveDelta);
3658
- if (this.moveKeys.has("KeyQ")) this.camera.translateY(moveDelta);
3659
- if (this.moveKeys.has("KeyE")) this.camera.translateY(-moveDelta);
3646
+ if (this.moveKeys.has("KeyW")) this.object.translateZ(-moveDelta);
3647
+ if (this.moveKeys.has("KeyS")) this.object.translateZ(moveDelta);
3648
+ if (this.moveKeys.has("KeyA")) this.object.translateX(-moveDelta);
3649
+ if (this.moveKeys.has("KeyD")) this.object.translateX(moveDelta);
3650
+ if (this.moveKeys.has("KeyQ")) this.object.translateY(moveDelta);
3651
+ if (this.moveKeys.has("KeyE")) this.object.translateY(-moveDelta);
3660
3652
  const lookDelta = this.lookSpeed + (this.multiplier - 1);
3661
3653
  if (this.moveKeys.has("ArrowUp")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, -lookDelta / 2)));
3662
3654
  if (this.moveKeys.has("ArrowDown")) this.rotateCamera(this.rotateDelta.add(new Vector2(0, lookDelta / 2)));
3663
3655
  if (this.moveKeys.has("ArrowLeft")) this.rotateCamera(this.rotateDelta.add(new Vector2(lookDelta, 0)));
3664
3656
  if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
3665
3657
  this.moveWheel = 0;
3666
- this.dispatchEvent(_changeEvent$1);
3658
+ this.dispatchEvent({
3659
+ type: "change"
3660
+ });
3667
3661
  }
3668
3662
  if (this.moveWheel !== 0) {
3669
3663
  const moveDelta = this.moveWheel * 1e-4 * this.movementSpeed * this.multiplier;
3670
- this.camera.translateZ(-moveDelta);
3664
+ this.object.translateZ(-moveDelta);
3671
3665
  this.moveWheel += -1 * Math.sign(this.moveWheel);
3672
- this.dispatchEvent(_changeEvent$1);
3666
+ this.dispatchEvent({
3667
+ type: "change"
3668
+ });
3673
3669
  }
3674
3670
  if (this.moveKeys.size === 0 && this.moveWheel === 0) {
3675
3671
  this.moveClock.stop();
@@ -3677,15 +3673,15 @@ class WalkControls extends EventDispatcher {
3677
3673
  }
3678
3674
  }
3679
3675
  rotateCamera(delta) {
3680
- const rotateX = Math.PI * delta.x / this.canvas.clientWidth;
3681
- const rotateY = Math.PI * delta.y / this.canvas.clientHeight;
3676
+ const rotateX = Math.PI * delta.x / this.domElement.clientWidth;
3677
+ const rotateY = Math.PI * delta.y / this.domElement.clientHeight;
3682
3678
  const xRotation = new Quaternion;
3683
- xRotation.setFromAxisAngle(this.camera.up, rotateX);
3679
+ xRotation.setFromAxisAngle(this.object.up, rotateX);
3684
3680
  const yRotation = new Quaternion;
3685
3681
  yRotation.setFromAxisAngle(new Vector3(1, 0, 0), rotateY);
3686
3682
  const quaternion = this.quaternion.clone();
3687
3683
  quaternion.premultiply(xRotation).multiply(yRotation).normalize();
3688
- this.camera.setRotationFromQuaternion(quaternion);
3684
+ this.object.setRotationFromQuaternion(quaternion);
3689
3685
  }
3690
3686
  }
3691
3687
 
@@ -3724,895 +3720,6 @@ class WalkDragger {
3724
3720
  }
3725
3721
  }
3726
3722
 
3727
- const _raycaster = new Raycaster;
3728
-
3729
- const _tempVector = new Vector3;
3730
-
3731
- const _tempVector2 = new Vector3;
3732
-
3733
- const _tempQuaternion = new Quaternion;
3734
-
3735
- const _unit = {
3736
- X: new Vector3(1, 0, 0),
3737
- Y: new Vector3(0, 1, 0),
3738
- Z: new Vector3(0, 0, 1)
3739
- };
3740
-
3741
- const _changeEvent = {
3742
- type: "change"
3743
- };
3744
-
3745
- const _mouseDownEvent = {
3746
- type: "mouseDown"
3747
- };
3748
-
3749
- const _mouseUpEvent = {
3750
- type: "mouseUp",
3751
- mode: null
3752
- };
3753
-
3754
- const _objectChangeEvent = {
3755
- type: "objectChange"
3756
- };
3757
-
3758
- class TransformControls extends Object3D {
3759
- constructor(camera, domElement) {
3760
- super();
3761
- if (domElement === undefined) {
3762
- console.warn('THREE.TransformControls: The second parameter "domElement" is now mandatory.');
3763
- domElement = document;
3764
- }
3765
- this.isTransformControls = true;
3766
- this.visible = false;
3767
- this.domElement = domElement;
3768
- this.domElement.style.touchAction = "none";
3769
- const _gizmo = new TransformControlsGizmo;
3770
- this._gizmo = _gizmo;
3771
- this.add(_gizmo);
3772
- const _plane = new TransformControlsPlane;
3773
- this._plane = _plane;
3774
- this.add(_plane);
3775
- const scope = this;
3776
- function defineProperty(propName, defaultValue) {
3777
- let propValue = defaultValue;
3778
- Object.defineProperty(scope, propName, {
3779
- get: function() {
3780
- return propValue !== undefined ? propValue : defaultValue;
3781
- },
3782
- set: function(value) {
3783
- if (propValue !== value) {
3784
- propValue = value;
3785
- _plane[propName] = value;
3786
- _gizmo[propName] = value;
3787
- scope.dispatchEvent({
3788
- type: propName + "-changed",
3789
- value: value
3790
- });
3791
- scope.dispatchEvent(_changeEvent);
3792
- }
3793
- }
3794
- });
3795
- scope[propName] = defaultValue;
3796
- _plane[propName] = defaultValue;
3797
- _gizmo[propName] = defaultValue;
3798
- }
3799
- defineProperty("camera", camera);
3800
- defineProperty("object", undefined);
3801
- defineProperty("enabled", true);
3802
- defineProperty("axis", null);
3803
- defineProperty("mode", "translate");
3804
- defineProperty("translationSnap", null);
3805
- defineProperty("rotationSnap", null);
3806
- defineProperty("scaleSnap", null);
3807
- defineProperty("space", "world");
3808
- defineProperty("size", 1);
3809
- defineProperty("dragging", false);
3810
- defineProperty("showX", true);
3811
- defineProperty("showY", true);
3812
- defineProperty("showZ", true);
3813
- const worldPosition = new Vector3;
3814
- const worldPositionStart = new Vector3;
3815
- const worldQuaternion = new Quaternion;
3816
- const worldQuaternionStart = new Quaternion;
3817
- const cameraPosition = new Vector3;
3818
- const cameraQuaternion = new Quaternion;
3819
- const pointStart = new Vector3;
3820
- const pointEnd = new Vector3;
3821
- const rotationAxis = new Vector3;
3822
- const rotationAngle = 0;
3823
- const eye = new Vector3;
3824
- defineProperty("worldPosition", worldPosition);
3825
- defineProperty("worldPositionStart", worldPositionStart);
3826
- defineProperty("worldQuaternion", worldQuaternion);
3827
- defineProperty("worldQuaternionStart", worldQuaternionStart);
3828
- defineProperty("cameraPosition", cameraPosition);
3829
- defineProperty("cameraQuaternion", cameraQuaternion);
3830
- defineProperty("pointStart", pointStart);
3831
- defineProperty("pointEnd", pointEnd);
3832
- defineProperty("rotationAxis", rotationAxis);
3833
- defineProperty("rotationAngle", rotationAngle);
3834
- defineProperty("eye", eye);
3835
- this._offset = new Vector3;
3836
- this._startNorm = new Vector3;
3837
- this._endNorm = new Vector3;
3838
- this._cameraScale = new Vector3;
3839
- this._parentPosition = new Vector3;
3840
- this._parentQuaternion = new Quaternion;
3841
- this._parentQuaternionInv = new Quaternion;
3842
- this._parentScale = new Vector3;
3843
- this._worldScaleStart = new Vector3;
3844
- this._worldQuaternionInv = new Quaternion;
3845
- this._worldScale = new Vector3;
3846
- this._positionStart = new Vector3;
3847
- this._quaternionStart = new Quaternion;
3848
- this._scaleStart = new Vector3;
3849
- this._getPointer = getPointer.bind(this);
3850
- this._onPointerDown = onPointerDown.bind(this);
3851
- this._onPointerHover = onPointerHover.bind(this);
3852
- this._onPointerMove = onPointerMove.bind(this);
3853
- this._onPointerUp = onPointerUp.bind(this);
3854
- this.domElement.addEventListener("pointerdown", this._onPointerDown);
3855
- this.domElement.addEventListener("pointermove", this._onPointerHover);
3856
- this.domElement.addEventListener("pointerup", this._onPointerUp);
3857
- }
3858
- updateMatrixWorld() {
3859
- if (this.object !== undefined) {
3860
- this.object.updateMatrixWorld();
3861
- if (this.object.parent === null) {
3862
- console.error("TransformControls: The attached 3D object must be a part of the scene graph.");
3863
- } else {
3864
- this.object.parent.matrixWorld.decompose(this._parentPosition, this._parentQuaternion, this._parentScale);
3865
- }
3866
- this.object.matrixWorld.decompose(this.worldPosition, this.worldQuaternion, this._worldScale);
3867
- this._parentQuaternionInv.copy(this._parentQuaternion).invert();
3868
- this._worldQuaternionInv.copy(this.worldQuaternion).invert();
3869
- }
3870
- this.camera.updateMatrixWorld();
3871
- this.camera.matrixWorld.decompose(this.cameraPosition, this.cameraQuaternion, this._cameraScale);
3872
- if (this.camera.isOrthographicCamera) {
3873
- this.camera.getWorldDirection(this.eye).negate();
3874
- } else {
3875
- this.eye.copy(this.cameraPosition).sub(this.worldPosition).normalize();
3876
- }
3877
- super.updateMatrixWorld(this);
3878
- }
3879
- pointerHover(pointer) {
3880
- if (this.object === undefined || this.dragging === true) return;
3881
- _raycaster.setFromCamera(pointer, this.camera);
3882
- const intersect = intersectObjectWithRay(this._gizmo.picker[this.mode], _raycaster);
3883
- if (intersect) {
3884
- this.axis = intersect.object.name;
3885
- } else {
3886
- this.axis = null;
3887
- }
3888
- }
3889
- pointerDown(pointer) {
3890
- if (this.object === undefined || this.dragging === true || pointer.button !== 0) return;
3891
- if (this.axis !== null) {
3892
- _raycaster.setFromCamera(pointer, this.camera);
3893
- const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
3894
- if (planeIntersect) {
3895
- this.object.updateMatrixWorld();
3896
- this.object.parent.updateMatrixWorld();
3897
- this._positionStart.copy(this.object.position);
3898
- this._quaternionStart.copy(this.object.quaternion);
3899
- this._scaleStart.copy(this.object.scale);
3900
- this.object.matrixWorld.decompose(this.worldPositionStart, this.worldQuaternionStart, this._worldScaleStart);
3901
- this.pointStart.copy(planeIntersect.point).sub(this.worldPositionStart);
3902
- }
3903
- this.dragging = true;
3904
- _mouseDownEvent.mode = this.mode;
3905
- this.dispatchEvent(_mouseDownEvent);
3906
- }
3907
- }
3908
- pointerMove(pointer) {
3909
- const axis = this.axis;
3910
- const mode = this.mode;
3911
- const object = this.object;
3912
- let space = this.space;
3913
- if (mode === "scale") {
3914
- space = "local";
3915
- } else if (axis === "E" || axis === "XYZE" || axis === "XYZ") {
3916
- space = "world";
3917
- }
3918
- if (object === undefined || axis === null || this.dragging === false || pointer.button !== -1) return;
3919
- _raycaster.setFromCamera(pointer, this.camera);
3920
- const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true);
3921
- if (!planeIntersect) return;
3922
- this.pointEnd.copy(planeIntersect.point).sub(this.worldPositionStart);
3923
- if (mode === "translate") {
3924
- this._offset.copy(this.pointEnd).sub(this.pointStart);
3925
- if (space === "local" && axis !== "XYZ") {
3926
- this._offset.applyQuaternion(this._worldQuaternionInv);
3927
- }
3928
- if (axis.indexOf("X") === -1) this._offset.x = 0;
3929
- if (axis.indexOf("Y") === -1) this._offset.y = 0;
3930
- if (axis.indexOf("Z") === -1) this._offset.z = 0;
3931
- if (space === "local" && axis !== "XYZ") {
3932
- this._offset.applyQuaternion(this._quaternionStart).divide(this._parentScale);
3933
- } else {
3934
- this._offset.applyQuaternion(this._parentQuaternionInv).divide(this._parentScale);
3935
- }
3936
- object.position.copy(this._offset).add(this._positionStart);
3937
- if (this.translationSnap) {
3938
- if (space === "local") {
3939
- object.position.applyQuaternion(_tempQuaternion.copy(this._quaternionStart).invert());
3940
- if (axis.search("X") !== -1) {
3941
- object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
3942
- }
3943
- if (axis.search("Y") !== -1) {
3944
- object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
3945
- }
3946
- if (axis.search("Z") !== -1) {
3947
- object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
3948
- }
3949
- object.position.applyQuaternion(this._quaternionStart);
3950
- }
3951
- if (space === "world") {
3952
- if (object.parent) {
3953
- object.position.add(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
3954
- }
3955
- if (axis.search("X") !== -1) {
3956
- object.position.x = Math.round(object.position.x / this.translationSnap) * this.translationSnap;
3957
- }
3958
- if (axis.search("Y") !== -1) {
3959
- object.position.y = Math.round(object.position.y / this.translationSnap) * this.translationSnap;
3960
- }
3961
- if (axis.search("Z") !== -1) {
3962
- object.position.z = Math.round(object.position.z / this.translationSnap) * this.translationSnap;
3963
- }
3964
- if (object.parent) {
3965
- object.position.sub(_tempVector.setFromMatrixPosition(object.parent.matrixWorld));
3966
- }
3967
- }
3968
- }
3969
- } else if (mode === "scale") {
3970
- if (axis.search("XYZ") !== -1) {
3971
- let d = this.pointEnd.length() / this.pointStart.length();
3972
- if (this.pointEnd.dot(this.pointStart) < 0) d *= -1;
3973
- _tempVector2.set(d, d, d);
3974
- } else {
3975
- _tempVector.copy(this.pointStart);
3976
- _tempVector2.copy(this.pointEnd);
3977
- _tempVector.applyQuaternion(this._worldQuaternionInv);
3978
- _tempVector2.applyQuaternion(this._worldQuaternionInv);
3979
- _tempVector2.divide(_tempVector);
3980
- if (axis.search("X") === -1) {
3981
- _tempVector2.x = 1;
3982
- }
3983
- if (axis.search("Y") === -1) {
3984
- _tempVector2.y = 1;
3985
- }
3986
- if (axis.search("Z") === -1) {
3987
- _tempVector2.z = 1;
3988
- }
3989
- }
3990
- object.scale.copy(this._scaleStart).multiply(_tempVector2);
3991
- if (this.scaleSnap) {
3992
- if (axis.search("X") !== -1) {
3993
- object.scale.x = Math.round(object.scale.x / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
3994
- }
3995
- if (axis.search("Y") !== -1) {
3996
- object.scale.y = Math.round(object.scale.y / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
3997
- }
3998
- if (axis.search("Z") !== -1) {
3999
- object.scale.z = Math.round(object.scale.z / this.scaleSnap) * this.scaleSnap || this.scaleSnap;
4000
- }
4001
- }
4002
- } else if (mode === "rotate") {
4003
- this._offset.copy(this.pointEnd).sub(this.pointStart);
4004
- const ROTATION_SPEED = 20 / this.worldPosition.distanceTo(_tempVector.setFromMatrixPosition(this.camera.matrixWorld));
4005
- if (axis === "E") {
4006
- this.rotationAxis.copy(this.eye);
4007
- this.rotationAngle = this.pointEnd.angleTo(this.pointStart);
4008
- this._startNorm.copy(this.pointStart).normalize();
4009
- this._endNorm.copy(this.pointEnd).normalize();
4010
- this.rotationAngle *= this._endNorm.cross(this._startNorm).dot(this.eye) < 0 ? 1 : -1;
4011
- } else if (axis === "XYZE") {
4012
- this.rotationAxis.copy(this._offset).cross(this.eye).normalize();
4013
- this.rotationAngle = this._offset.dot(_tempVector.copy(this.rotationAxis).cross(this.eye)) * ROTATION_SPEED;
4014
- } else if (axis === "X" || axis === "Y" || axis === "Z") {
4015
- this.rotationAxis.copy(_unit[axis]);
4016
- _tempVector.copy(_unit[axis]);
4017
- if (space === "local") {
4018
- _tempVector.applyQuaternion(this.worldQuaternion);
4019
- }
4020
- this.rotationAngle = this._offset.dot(_tempVector.cross(this.eye).normalize()) * ROTATION_SPEED;
4021
- }
4022
- if (this.rotationSnap) this.rotationAngle = Math.round(this.rotationAngle / this.rotationSnap) * this.rotationSnap;
4023
- if (space === "local" && axis !== "E" && axis !== "XYZE") {
4024
- object.quaternion.copy(this._quaternionStart);
4025
- object.quaternion.multiply(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle)).normalize();
4026
- } else {
4027
- this.rotationAxis.applyQuaternion(this._parentQuaternionInv);
4028
- object.quaternion.copy(_tempQuaternion.setFromAxisAngle(this.rotationAxis, this.rotationAngle));
4029
- object.quaternion.multiply(this._quaternionStart).normalize();
4030
- }
4031
- }
4032
- this.dispatchEvent(_changeEvent);
4033
- this.dispatchEvent(_objectChangeEvent);
4034
- }
4035
- pointerUp(pointer) {
4036
- if (pointer.button !== 0) return;
4037
- if (this.dragging && this.axis !== null) {
4038
- _mouseUpEvent.mode = this.mode;
4039
- this.dispatchEvent(_mouseUpEvent);
4040
- }
4041
- this.dragging = false;
4042
- this.axis = null;
4043
- }
4044
- dispose() {
4045
- this.domElement.removeEventListener("pointerdown", this._onPointerDown);
4046
- this.domElement.removeEventListener("pointermove", this._onPointerHover);
4047
- this.domElement.removeEventListener("pointermove", this._onPointerMove);
4048
- this.domElement.removeEventListener("pointerup", this._onPointerUp);
4049
- this.traverse((function(child) {
4050
- if (child.geometry) child.geometry.dispose();
4051
- if (child.material) child.material.dispose();
4052
- }));
4053
- }
4054
- attach(object) {
4055
- this.object = object;
4056
- this.visible = true;
4057
- return this;
4058
- }
4059
- detach() {
4060
- this.object = undefined;
4061
- this.visible = false;
4062
- this.axis = null;
4063
- return this;
4064
- }
4065
- reset() {
4066
- if (!this.enabled) return;
4067
- if (this.dragging) {
4068
- this.object.position.copy(this._positionStart);
4069
- this.object.quaternion.copy(this._quaternionStart);
4070
- this.object.scale.copy(this._scaleStart);
4071
- this.dispatchEvent(_changeEvent);
4072
- this.dispatchEvent(_objectChangeEvent);
4073
- this.pointStart.copy(this.pointEnd);
4074
- }
4075
- }
4076
- getRaycaster() {
4077
- return _raycaster;
4078
- }
4079
- getMode() {
4080
- return this.mode;
4081
- }
4082
- setMode(mode) {
4083
- this.mode = mode;
4084
- }
4085
- setTranslationSnap(translationSnap) {
4086
- this.translationSnap = translationSnap;
4087
- }
4088
- setRotationSnap(rotationSnap) {
4089
- this.rotationSnap = rotationSnap;
4090
- }
4091
- setScaleSnap(scaleSnap) {
4092
- this.scaleSnap = scaleSnap;
4093
- }
4094
- setSize(size) {
4095
- this.size = size;
4096
- }
4097
- setSpace(space) {
4098
- this.space = space;
4099
- }
4100
- }
4101
-
4102
- function getPointer(event) {
4103
- if (this.domElement.ownerDocument.pointerLockElement) {
4104
- return {
4105
- x: 0,
4106
- y: 0,
4107
- button: event.button
4108
- };
4109
- } else {
4110
- const rect = this.domElement.getBoundingClientRect();
4111
- return {
4112
- x: (event.clientX - rect.left) / rect.width * 2 - 1,
4113
- y: -(event.clientY - rect.top) / rect.height * 2 + 1,
4114
- button: event.button
4115
- };
4116
- }
4117
- }
4118
-
4119
- function onPointerHover(event) {
4120
- if (!this.enabled) return;
4121
- switch (event.pointerType) {
4122
- case "mouse":
4123
- case "pen":
4124
- this.pointerHover(this._getPointer(event));
4125
- break;
4126
- }
4127
- }
4128
-
4129
- function onPointerDown(event) {
4130
- if (!this.enabled) return;
4131
- if (!document.pointerLockElement) {
4132
- this.domElement.setPointerCapture(event.pointerId);
4133
- }
4134
- this.domElement.addEventListener("pointermove", this._onPointerMove);
4135
- this.pointerHover(this._getPointer(event));
4136
- this.pointerDown(this._getPointer(event));
4137
- }
4138
-
4139
- function onPointerMove(event) {
4140
- if (!this.enabled) return;
4141
- this.pointerMove(this._getPointer(event));
4142
- }
4143
-
4144
- function onPointerUp(event) {
4145
- if (!this.enabled) return;
4146
- this.domElement.releasePointerCapture(event.pointerId);
4147
- this.domElement.removeEventListener("pointermove", this._onPointerMove);
4148
- this.pointerUp(this._getPointer(event));
4149
- }
4150
-
4151
- function intersectObjectWithRay(object, raycaster, includeInvisible) {
4152
- const allIntersections = raycaster.intersectObject(object, true);
4153
- for (let i = 0; i < allIntersections.length; i++) {
4154
- if (allIntersections[i].object.visible || includeInvisible) {
4155
- return allIntersections[i];
4156
- }
4157
- }
4158
- return false;
4159
- }
4160
-
4161
- const _tempEuler = new Euler;
4162
-
4163
- const _alignVector = new Vector3(0, 1, 0);
4164
-
4165
- const _zeroVector = new Vector3(0, 0, 0);
4166
-
4167
- const _lookAtMatrix = new Matrix4;
4168
-
4169
- const _tempQuaternion2 = new Quaternion;
4170
-
4171
- const _identityQuaternion = new Quaternion;
4172
-
4173
- const _dirVector = new Vector3;
4174
-
4175
- const _tempMatrix = new Matrix4;
4176
-
4177
- const _unitX = new Vector3(1, 0, 0);
4178
-
4179
- const _unitY = new Vector3(0, 1, 0);
4180
-
4181
- const _unitZ = new Vector3(0, 0, 1);
4182
-
4183
- const _v1 = new Vector3;
4184
-
4185
- const _v2 = new Vector3;
4186
-
4187
- const _v3 = new Vector3;
4188
-
4189
- class TransformControlsGizmo extends Object3D {
4190
- constructor() {
4191
- super();
4192
- this.isTransformControlsGizmo = true;
4193
- this.type = "TransformControlsGizmo";
4194
- const gizmoMaterial = new MeshBasicMaterial({
4195
- depthTest: false,
4196
- depthWrite: false,
4197
- fog: false,
4198
- toneMapped: false,
4199
- transparent: true
4200
- });
4201
- const gizmoLineMaterial = new LineBasicMaterial({
4202
- depthTest: false,
4203
- depthWrite: false,
4204
- fog: false,
4205
- toneMapped: false,
4206
- transparent: true
4207
- });
4208
- const matInvisible = gizmoMaterial.clone();
4209
- matInvisible.opacity = .15;
4210
- const matHelper = gizmoLineMaterial.clone();
4211
- matHelper.opacity = .5;
4212
- const matRed = gizmoMaterial.clone();
4213
- matRed.color.setHex(16711680);
4214
- const matGreen = gizmoMaterial.clone();
4215
- matGreen.color.setHex(65280);
4216
- const matBlue = gizmoMaterial.clone();
4217
- matBlue.color.setHex(255);
4218
- const matRedTransparent = gizmoMaterial.clone();
4219
- matRedTransparent.color.setHex(16711680);
4220
- matRedTransparent.opacity = .5;
4221
- const matGreenTransparent = gizmoMaterial.clone();
4222
- matGreenTransparent.color.setHex(65280);
4223
- matGreenTransparent.opacity = .5;
4224
- const matBlueTransparent = gizmoMaterial.clone();
4225
- matBlueTransparent.color.setHex(255);
4226
- matBlueTransparent.opacity = .5;
4227
- const matWhiteTransparent = gizmoMaterial.clone();
4228
- matWhiteTransparent.opacity = .25;
4229
- const matYellowTransparent = gizmoMaterial.clone();
4230
- matYellowTransparent.color.setHex(16776960);
4231
- matYellowTransparent.opacity = .25;
4232
- const matYellow = gizmoMaterial.clone();
4233
- matYellow.color.setHex(16776960);
4234
- const matGray = gizmoMaterial.clone();
4235
- matGray.color.setHex(7895160);
4236
- const arrowGeometry = new CylinderGeometry(0, .04, .1, 12);
4237
- arrowGeometry.translate(0, .05, 0);
4238
- const scaleHandleGeometry = new BoxGeometry(.08, .08, .08);
4239
- scaleHandleGeometry.translate(0, .04, 0);
4240
- const lineGeometry = new BufferGeometry;
4241
- lineGeometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 0, 0 ], 3));
4242
- const lineGeometry2 = new CylinderGeometry(.0075, .0075, .5, 3);
4243
- lineGeometry2.translate(0, .25, 0);
4244
- function CircleGeometry(radius, arc) {
4245
- const geometry = new TorusGeometry(radius, .0075, 3, 64, arc * Math.PI * 2);
4246
- geometry.rotateY(Math.PI / 2);
4247
- geometry.rotateX(Math.PI / 2);
4248
- return geometry;
4249
- }
4250
- function TranslateHelperGeometry() {
4251
- const geometry = new BufferGeometry;
4252
- geometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 1, 1, 1 ], 3));
4253
- return geometry;
4254
- }
4255
- const gizmoTranslate = {
4256
- X: [ [ new Mesh(arrowGeometry, matRed), [ .5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(arrowGeometry, matRed), [ -.5, 0, 0 ], [ 0, 0, Math.PI / 2 ] ], [ new Mesh(lineGeometry2, matRed), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] ],
4257
- Y: [ [ new Mesh(arrowGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(arrowGeometry, matGreen), [ 0, -.5, 0 ], [ Math.PI, 0, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ] ],
4258
- Z: [ [ new Mesh(arrowGeometry, matBlue), [ 0, 0, .5 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(arrowGeometry, matBlue), [ 0, 0, -.5 ], [ -Math.PI / 2, 0, 0 ] ], [ new Mesh(lineGeometry2, matBlue), null, [ Math.PI / 2, 0, 0 ] ] ],
4259
- XYZ: [ [ new Mesh(new OctahedronGeometry(.1, 0), matWhiteTransparent.clone()), [ 0, 0, 0 ] ] ],
4260
- XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent.clone()), [ .15, .15, 0 ] ] ],
4261
- YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent.clone()), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
4262
- XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent.clone()), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
4263
- };
4264
- const pickerTranslate = {
4265
- X: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ .3, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ -.3, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
4266
- Y: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, .3, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, -.3, 0 ], [ 0, 0, Math.PI ] ] ],
4267
- Z: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, .3 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, -.3 ], [ -Math.PI / 2, 0, 0 ] ] ],
4268
- XYZ: [ [ new Mesh(new OctahedronGeometry(.2, 0), matInvisible) ] ],
4269
- XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
4270
- YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
4271
- XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ]
4272
- };
4273
- const helperTranslate = {
4274
- START: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
4275
- END: [ [ new Mesh(new OctahedronGeometry(.01, 2), matHelper), null, null, null, "helper" ] ],
4276
- DELTA: [ [ new Line(TranslateHelperGeometry(), matHelper), null, null, null, "helper" ] ],
4277
- X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
4278
- Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
4279
- Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
4280
- };
4281
- const gizmoRotate = {
4282
- XYZE: [ [ new Mesh(CircleGeometry(.5, 1), matGray), null, [ 0, Math.PI / 2, 0 ] ] ],
4283
- X: [ [ new Mesh(CircleGeometry(.5, .5), matRed) ] ],
4284
- Y: [ [ new Mesh(CircleGeometry(.5, .5), matGreen), null, [ 0, 0, -Math.PI / 2 ] ] ],
4285
- Z: [ [ new Mesh(CircleGeometry(.5, .5), matBlue), null, [ 0, Math.PI / 2, 0 ] ] ],
4286
- E: [ [ new Mesh(CircleGeometry(.75, 1), matYellowTransparent), null, [ 0, Math.PI / 2, 0 ] ] ]
4287
- };
4288
- const helperRotate = {
4289
- AXIS: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ]
4290
- };
4291
- const pickerRotate = {
4292
- XYZE: [ [ new Mesh(new SphereGeometry(.25, 10, 8), matInvisible) ] ],
4293
- X: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ] ],
4294
- Y: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ] ],
4295
- Z: [ [ new Mesh(new TorusGeometry(.5, .1, 4, 24), matInvisible), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ] ],
4296
- E: [ [ new Mesh(new TorusGeometry(.75, .1, 2, 24), matInvisible) ] ]
4297
- };
4298
- const gizmoScale = {
4299
- X: [ [ new Mesh(scaleHandleGeometry, matRed), [ .5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(lineGeometry2, matRed), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(scaleHandleGeometry, matRed), [ -.5, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
4300
- Y: [ [ new Mesh(scaleHandleGeometry, matGreen), [ 0, .5, 0 ] ], [ new Mesh(lineGeometry2, matGreen) ], [ new Mesh(scaleHandleGeometry, matGreen), [ 0, -.5, 0 ], [ 0, 0, Math.PI ] ] ],
4301
- Z: [ [ new Mesh(scaleHandleGeometry, matBlue), [ 0, 0, .5 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(lineGeometry2, matBlue), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(scaleHandleGeometry, matBlue), [ 0, 0, -.5 ], [ -Math.PI / 2, 0, 0 ] ] ],
4302
- XY: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matBlueTransparent), [ .15, .15, 0 ] ] ],
4303
- YZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matRedTransparent), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
4304
- XZ: [ [ new Mesh(new BoxGeometry(.15, .15, .01), matGreenTransparent), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
4305
- XYZ: [ [ new Mesh(new BoxGeometry(.1, .1, .1), matWhiteTransparent.clone()) ] ]
4306
- };
4307
- const pickerScale = {
4308
- X: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ .3, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ -.3, 0, 0 ], [ 0, 0, Math.PI / 2 ] ] ],
4309
- Y: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, .3, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, -.3, 0 ], [ 0, 0, Math.PI ] ] ],
4310
- Z: [ [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, .3 ], [ Math.PI / 2, 0, 0 ] ], [ new Mesh(new CylinderGeometry(.2, 0, .6, 4), matInvisible), [ 0, 0, -.3 ], [ -Math.PI / 2, 0, 0 ] ] ],
4311
- XY: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, .15, 0 ] ] ],
4312
- YZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ 0, .15, .15 ], [ 0, Math.PI / 2, 0 ] ] ],
4313
- XZ: [ [ new Mesh(new BoxGeometry(.2, .2, .01), matInvisible), [ .15, 0, .15 ], [ -Math.PI / 2, 0, 0 ] ] ],
4314
- XYZ: [ [ new Mesh(new BoxGeometry(.2, .2, .2), matInvisible), [ 0, 0, 0 ] ] ]
4315
- };
4316
- const helperScale = {
4317
- X: [ [ new Line(lineGeometry, matHelper.clone()), [ -1e3, 0, 0 ], null, [ 1e6, 1, 1 ], "helper" ] ],
4318
- Y: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, -1e3, 0 ], [ 0, 0, Math.PI / 2 ], [ 1e6, 1, 1 ], "helper" ] ],
4319
- Z: [ [ new Line(lineGeometry, matHelper.clone()), [ 0, 0, -1e3 ], [ 0, -Math.PI / 2, 0 ], [ 1e6, 1, 1 ], "helper" ] ]
4320
- };
4321
- function setupGizmo(gizmoMap) {
4322
- const gizmo = new Object3D;
4323
- for (const name in gizmoMap) {
4324
- for (let i = gizmoMap[name].length; i--; ) {
4325
- const object = gizmoMap[name][i][0].clone();
4326
- const position = gizmoMap[name][i][1];
4327
- const rotation = gizmoMap[name][i][2];
4328
- const scale = gizmoMap[name][i][3];
4329
- const tag = gizmoMap[name][i][4];
4330
- object.name = name;
4331
- object.tag = tag;
4332
- if (position) {
4333
- object.position.set(position[0], position[1], position[2]);
4334
- }
4335
- if (rotation) {
4336
- object.rotation.set(rotation[0], rotation[1], rotation[2]);
4337
- }
4338
- if (scale) {
4339
- object.scale.set(scale[0], scale[1], scale[2]);
4340
- }
4341
- object.updateMatrix();
4342
- const tempGeometry = object.geometry.clone();
4343
- tempGeometry.applyMatrix4(object.matrix);
4344
- object.geometry = tempGeometry;
4345
- object.renderOrder = Infinity;
4346
- object.position.set(0, 0, 0);
4347
- object.rotation.set(0, 0, 0);
4348
- object.scale.set(1, 1, 1);
4349
- gizmo.add(object);
4350
- }
4351
- }
4352
- return gizmo;
4353
- }
4354
- this.gizmo = {};
4355
- this.picker = {};
4356
- this.helper = {};
4357
- this.add(this.gizmo["translate"] = setupGizmo(gizmoTranslate));
4358
- this.add(this.gizmo["rotate"] = setupGizmo(gizmoRotate));
4359
- this.add(this.gizmo["scale"] = setupGizmo(gizmoScale));
4360
- this.add(this.picker["translate"] = setupGizmo(pickerTranslate));
4361
- this.add(this.picker["rotate"] = setupGizmo(pickerRotate));
4362
- this.add(this.picker["scale"] = setupGizmo(pickerScale));
4363
- this.add(this.helper["translate"] = setupGizmo(helperTranslate));
4364
- this.add(this.helper["rotate"] = setupGizmo(helperRotate));
4365
- this.add(this.helper["scale"] = setupGizmo(helperScale));
4366
- this.picker["translate"].visible = false;
4367
- this.picker["rotate"].visible = false;
4368
- this.picker["scale"].visible = false;
4369
- }
4370
- updateMatrixWorld(force) {
4371
- const space = this.mode === "scale" ? "local" : this.space;
4372
- const quaternion = space === "local" ? this.worldQuaternion : _identityQuaternion;
4373
- this.gizmo["translate"].visible = this.mode === "translate";
4374
- this.gizmo["rotate"].visible = this.mode === "rotate";
4375
- this.gizmo["scale"].visible = this.mode === "scale";
4376
- this.helper["translate"].visible = this.mode === "translate";
4377
- this.helper["rotate"].visible = this.mode === "rotate";
4378
- this.helper["scale"].visible = this.mode === "scale";
4379
- let handles = [];
4380
- handles = handles.concat(this.picker[this.mode].children);
4381
- handles = handles.concat(this.gizmo[this.mode].children);
4382
- handles = handles.concat(this.helper[this.mode].children);
4383
- for (let i = 0; i < handles.length; i++) {
4384
- const handle = handles[i];
4385
- handle.visible = true;
4386
- handle.rotation.set(0, 0, 0);
4387
- handle.position.copy(this.worldPosition);
4388
- let factor;
4389
- if (this.camera.isOrthographicCamera) {
4390
- factor = (this.camera.top - this.camera.bottom) / this.camera.zoom;
4391
- } else {
4392
- factor = this.worldPosition.distanceTo(this.cameraPosition) * Math.min(1.9 * Math.tan(Math.PI * this.camera.fov / 360) / this.camera.zoom, 7);
4393
- }
4394
- handle.scale.set(1, 1, 1).multiplyScalar(factor * this.size / 4);
4395
- if (handle.tag === "helper") {
4396
- handle.visible = false;
4397
- if (handle.name === "AXIS") {
4398
- handle.visible = !!this.axis;
4399
- if (this.axis === "X") {
4400
- _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0));
4401
- handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
4402
- if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > .9) {
4403
- handle.visible = false;
4404
- }
4405
- }
4406
- if (this.axis === "Y") {
4407
- _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, Math.PI / 2));
4408
- handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
4409
- if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > .9) {
4410
- handle.visible = false;
4411
- }
4412
- }
4413
- if (this.axis === "Z") {
4414
- _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
4415
- handle.quaternion.copy(quaternion).multiply(_tempQuaternion);
4416
- if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > .9) {
4417
- handle.visible = false;
4418
- }
4419
- }
4420
- if (this.axis === "XYZE") {
4421
- _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0));
4422
- _alignVector.copy(this.rotationAxis);
4423
- handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY));
4424
- handle.quaternion.multiply(_tempQuaternion);
4425
- handle.visible = this.dragging;
4426
- }
4427
- if (this.axis === "E") {
4428
- handle.visible = false;
4429
- }
4430
- } else if (handle.name === "START") {
4431
- handle.position.copy(this.worldPositionStart);
4432
- handle.visible = this.dragging;
4433
- } else if (handle.name === "END") {
4434
- handle.position.copy(this.worldPosition);
4435
- handle.visible = this.dragging;
4436
- } else if (handle.name === "DELTA") {
4437
- handle.position.copy(this.worldPositionStart);
4438
- handle.quaternion.copy(this.worldQuaternionStart);
4439
- _tempVector.set(1e-10, 1e-10, 1e-10).add(this.worldPositionStart).sub(this.worldPosition).multiplyScalar(-1);
4440
- _tempVector.applyQuaternion(this.worldQuaternionStart.clone().invert());
4441
- handle.scale.copy(_tempVector);
4442
- handle.visible = this.dragging;
4443
- } else {
4444
- handle.quaternion.copy(quaternion);
4445
- if (this.dragging) {
4446
- handle.position.copy(this.worldPositionStart);
4447
- } else {
4448
- handle.position.copy(this.worldPosition);
4449
- }
4450
- if (this.axis) {
4451
- handle.visible = this.axis.search(handle.name) !== -1;
4452
- }
4453
- }
4454
- continue;
4455
- }
4456
- handle.quaternion.copy(quaternion);
4457
- if (this.mode === "translate" || this.mode === "scale") {
4458
- const AXIS_HIDE_THRESHOLD = .99;
4459
- const PLANE_HIDE_THRESHOLD = .2;
4460
- if (handle.name === "X") {
4461
- if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
4462
- handle.scale.set(1e-10, 1e-10, 1e-10);
4463
- handle.visible = false;
4464
- }
4465
- }
4466
- if (handle.name === "Y") {
4467
- if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
4468
- handle.scale.set(1e-10, 1e-10, 1e-10);
4469
- handle.visible = false;
4470
- }
4471
- }
4472
- if (handle.name === "Z") {
4473
- if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) > AXIS_HIDE_THRESHOLD) {
4474
- handle.scale.set(1e-10, 1e-10, 1e-10);
4475
- handle.visible = false;
4476
- }
4477
- }
4478
- if (handle.name === "XY") {
4479
- if (Math.abs(_alignVector.copy(_unitZ).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
4480
- handle.scale.set(1e-10, 1e-10, 1e-10);
4481
- handle.visible = false;
4482
- }
4483
- }
4484
- if (handle.name === "YZ") {
4485
- if (Math.abs(_alignVector.copy(_unitX).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
4486
- handle.scale.set(1e-10, 1e-10, 1e-10);
4487
- handle.visible = false;
4488
- }
4489
- }
4490
- if (handle.name === "XZ") {
4491
- if (Math.abs(_alignVector.copy(_unitY).applyQuaternion(quaternion).dot(this.eye)) < PLANE_HIDE_THRESHOLD) {
4492
- handle.scale.set(1e-10, 1e-10, 1e-10);
4493
- handle.visible = false;
4494
- }
4495
- }
4496
- } else if (this.mode === "rotate") {
4497
- _tempQuaternion2.copy(quaternion);
4498
- _alignVector.copy(this.eye).applyQuaternion(_tempQuaternion.copy(quaternion).invert());
4499
- if (handle.name.search("E") !== -1) {
4500
- handle.quaternion.setFromRotationMatrix(_lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY));
4501
- }
4502
- if (handle.name === "X") {
4503
- _tempQuaternion.setFromAxisAngle(_unitX, Math.atan2(-_alignVector.y, _alignVector.z));
4504
- _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
4505
- handle.quaternion.copy(_tempQuaternion);
4506
- }
4507
- if (handle.name === "Y") {
4508
- _tempQuaternion.setFromAxisAngle(_unitY, Math.atan2(_alignVector.x, _alignVector.z));
4509
- _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
4510
- handle.quaternion.copy(_tempQuaternion);
4511
- }
4512
- if (handle.name === "Z") {
4513
- _tempQuaternion.setFromAxisAngle(_unitZ, Math.atan2(_alignVector.y, _alignVector.x));
4514
- _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion);
4515
- handle.quaternion.copy(_tempQuaternion);
4516
- }
4517
- }
4518
- handle.visible = handle.visible && (handle.name.indexOf("X") === -1 || this.showX);
4519
- handle.visible = handle.visible && (handle.name.indexOf("Y") === -1 || this.showY);
4520
- handle.visible = handle.visible && (handle.name.indexOf("Z") === -1 || this.showZ);
4521
- handle.visible = handle.visible && (handle.name.indexOf("E") === -1 || this.showX && this.showY && this.showZ);
4522
- handle.material._color = handle.material._color || handle.material.color.clone();
4523
- handle.material._opacity = handle.material._opacity || handle.material.opacity;
4524
- handle.material.color.copy(handle.material._color);
4525
- handle.material.opacity = handle.material._opacity;
4526
- if (this.enabled && this.axis) {
4527
- if (handle.name === this.axis) {
4528
- handle.material.color.setHex(16776960);
4529
- handle.material.opacity = 1;
4530
- } else if (this.axis.split("").some((function(a) {
4531
- return handle.name === a;
4532
- }))) {
4533
- handle.material.color.setHex(16776960);
4534
- handle.material.opacity = 1;
4535
- }
4536
- }
4537
- }
4538
- super.updateMatrixWorld(force);
4539
- }
4540
- }
4541
-
4542
- class TransformControlsPlane extends Mesh {
4543
- constructor() {
4544
- super(new PlaneGeometry(1e5, 1e5, 2, 2), new MeshBasicMaterial({
4545
- visible: false,
4546
- wireframe: true,
4547
- side: DoubleSide,
4548
- transparent: true,
4549
- opacity: .1,
4550
- toneMapped: false
4551
- }));
4552
- this.isTransformControlsPlane = true;
4553
- this.type = "TransformControlsPlane";
4554
- }
4555
- updateMatrixWorld(force) {
4556
- let space = this.space;
4557
- this.position.copy(this.worldPosition);
4558
- if (this.mode === "scale") space = "local";
4559
- _v1.copy(_unitX).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
4560
- _v2.copy(_unitY).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
4561
- _v3.copy(_unitZ).applyQuaternion(space === "local" ? this.worldQuaternion : _identityQuaternion);
4562
- _alignVector.copy(_v2);
4563
- switch (this.mode) {
4564
- case "translate":
4565
- case "scale":
4566
- switch (this.axis) {
4567
- case "X":
4568
- _alignVector.copy(this.eye).cross(_v1);
4569
- _dirVector.copy(_v1).cross(_alignVector);
4570
- break;
4571
-
4572
- case "Y":
4573
- _alignVector.copy(this.eye).cross(_v2);
4574
- _dirVector.copy(_v2).cross(_alignVector);
4575
- break;
4576
-
4577
- case "Z":
4578
- _alignVector.copy(this.eye).cross(_v3);
4579
- _dirVector.copy(_v3).cross(_alignVector);
4580
- break;
4581
-
4582
- case "XY":
4583
- _dirVector.copy(_v3);
4584
- break;
4585
-
4586
- case "YZ":
4587
- _dirVector.copy(_v1);
4588
- break;
4589
-
4590
- case "XZ":
4591
- _alignVector.copy(_v3);
4592
- _dirVector.copy(_v2);
4593
- break;
4594
-
4595
- case "XYZ":
4596
- case "E":
4597
- _dirVector.set(0, 0, 0);
4598
- break;
4599
- }
4600
- break;
4601
-
4602
- case "rotate":
4603
- default:
4604
- _dirVector.set(0, 0, 0);
4605
- }
4606
- if (_dirVector.length() === 0) {
4607
- this.quaternion.copy(this.cameraQuaternion);
4608
- } else {
4609
- _tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector);
4610
- this.quaternion.setFromRotationMatrix(_tempMatrix);
4611
- }
4612
- super.updateMatrixWorld(force);
4613
- }
4614
- }
4615
-
4616
3723
  class PlaneHelper extends Line {
4617
3724
  constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
4618
3725
  const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
@@ -4694,7 +3801,7 @@ class CuttingPlaneDragger extends OrbitDragger {
4694
3801
  this.transform.attach(this.planeCenter);
4695
3802
  this.transform.addEventListener("change", this.transformChange);
4696
3803
  this.transform.addEventListener("dragging-changed", this.transformDrag);
4697
- this.viewer.helpers.add(this.transform);
3804
+ this.viewer.helpers.add(this.transform.getHelper());
4698
3805
  this.viewer.on("explode", this.viewerExplode);
4699
3806
  this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
4700
3807
  this.viewer.update();
@@ -4704,7 +3811,8 @@ class CuttingPlaneDragger extends OrbitDragger {
4704
3811
  this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
4705
3812
  this.transform.removeEventListener("change", this.transformChange);
4706
3813
  this.transform.removeEventListener("dragging-changed", this.transformDrag);
4707
- this.transform.removeFromParent();
3814
+ this.transform.getHelper().removeFromParent();
3815
+ this.transform.detach();
4708
3816
  this.transform.dispose();
4709
3817
  this.planeHelper.removeFromParent();
4710
3818
  this.planeHelper.dispose();
@@ -4731,13 +3839,362 @@ class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
4731
3839
  }
4732
3840
  }
4733
3841
 
3842
+ const PRECISION = .01;
3843
+
3844
+ class MeasureLineDragger extends OrbitDragger {
3845
+ constructor(viewer) {
3846
+ super(viewer);
3847
+ this.onPointerDown = event => {
3848
+ if (event.button !== 0) return;
3849
+ this.line.startPoint = this.snapper.getSnapPoint(event);
3850
+ this.line.render();
3851
+ this.viewer.canvas.setPointerCapture(event.pointerId);
3852
+ this.orbit.enabled = !this.line.startPoint;
3853
+ };
3854
+ this.onPointerMove = event => {
3855
+ if (this.orbit.enabled && this.orbit.state !== -1) return;
3856
+ this.line.endPoint = this.snapper.getSnapPoint(event);
3857
+ this.line.render();
3858
+ if (this.line.startPoint) this.changed = true;
3859
+ };
3860
+ this.onPointerUp = event => {
3861
+ if (this.line.startPoint && this.line.endPoint && this.line.getDistance() >= PRECISION) {
3862
+ this.line = new MeasureLine(this.overlay);
3863
+ this.overlay.addLine(this.line);
3864
+ } else {
3865
+ this.line.startPoint = undefined;
3866
+ this.line.endPoint = undefined;
3867
+ this.line.render();
3868
+ }
3869
+ this.viewer.canvas.releasePointerCapture(event.pointerId);
3870
+ this.orbit.enabled = true;
3871
+ };
3872
+ this.onPointerCancel = event => {
3873
+ this.viewer.canvas.dispatchEvent(new PointerEvent("pointerup", event));
3874
+ };
3875
+ this.onPointerLeave = () => {
3876
+ this.line.endPoint = undefined;
3877
+ this.line.render();
3878
+ };
3879
+ this.renderOverlay = () => {
3880
+ this.overlay.render();
3881
+ };
3882
+ this.updateSnapper = () => {
3883
+ this.snapper.update(this.viewer.scene);
3884
+ };
3885
+ this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
3886
+ this.overlay.attach();
3887
+ this.line = new MeasureLine(this.overlay);
3888
+ this.overlay.addLine(this.line);
3889
+ this.snapper = new MeasureSnapper(viewer.camera, viewer.canvas);
3890
+ this.snapper.update(viewer.scene);
3891
+ this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown);
3892
+ this.viewer.canvas.addEventListener("pointermove", this.onPointerMove);
3893
+ this.viewer.canvas.addEventListener("pointerup", this.onPointerUp);
3894
+ this.viewer.canvas.addEventListener("pointercancel", this.onPointerCancel);
3895
+ this.viewer.canvas.addEventListener("pointerleave", this.onPointerLeave);
3896
+ this.viewer.addEventListener("render", this.renderOverlay);
3897
+ this.viewer.addEventListener("hide", this.updateSnapper);
3898
+ this.viewer.addEventListener("isolate", this.updateSnapper);
3899
+ this.viewer.addEventListener("showall", this.updateSnapper);
3900
+ }
3901
+ dispose() {
3902
+ this.viewer.canvas.removeEventListener("pointerdown", this.onPointerDown);
3903
+ this.viewer.canvas.removeEventListener("pointermove", this.onPointerMove);
3904
+ this.viewer.canvas.removeEventListener("pointerup", this.onPointerUp);
3905
+ this.viewer.canvas.removeEventListener("pointercancel", this.onPointerCancel);
3906
+ this.viewer.canvas.removeEventListener("pointerleave", this.onPointerLeave);
3907
+ this.viewer.removeEventListener("render", this.renderOverlay);
3908
+ this.viewer.removeEventListener("hide", this.updateSnapper);
3909
+ this.viewer.removeEventListener("isolate", this.updateSnapper);
3910
+ this.viewer.removeEventListener("showall", this.updateSnapper);
3911
+ this.overlay.detach();
3912
+ this.overlay.dispose();
3913
+ super.dispose();
3914
+ }
3915
+ }
3916
+
3917
+ class MeasureSnapper {
3918
+ constructor(camera, canvas) {
3919
+ this.objects = [];
3920
+ this.camera = camera;
3921
+ this.canvas = canvas;
3922
+ this.raycaster = new Raycaster;
3923
+ }
3924
+ getSnapPoint(event) {
3925
+ const mouse = new Vector2(event.clientX, event.clientY);
3926
+ const rect = this.canvas.getBoundingClientRect();
3927
+ const x = (mouse.x - rect.left) / rect.width * 2 - 1;
3928
+ const y = -(mouse.y - rect.top) / rect.height * 2 + 1;
3929
+ const coords = new Vector2(x, y);
3930
+ this.raycaster.setFromCamera(coords, this.camera);
3931
+ this.raycaster.params = {
3932
+ Mesh: {},
3933
+ Line: {
3934
+ threshold: .25
3935
+ },
3936
+ Line2: {
3937
+ threshold: .25
3938
+ },
3939
+ LOD: {},
3940
+ Points: {
3941
+ threshold: .1
3942
+ },
3943
+ Sprite: {}
3944
+ };
3945
+ const intersects = this.raycaster.intersectObjects(this.objects, false);
3946
+ if (intersects.length === 0) return undefined;
3947
+ return intersects[0].point;
3948
+ }
3949
+ update(scene) {
3950
+ this.objects = [];
3951
+ scene.traverseVisible((child => this.objects.push(child)));
3952
+ }
3953
+ }
3954
+
3955
+ class MeasureOverlay {
3956
+ constructor(camera, canvas) {
3957
+ this.lines = [];
3958
+ this.camera = camera;
3959
+ this.canvas = canvas;
3960
+ this.projector = new MeasureProjector(camera, canvas);
3961
+ }
3962
+ attach() {
3963
+ this.container = document.createElement("div");
3964
+ this.container.id = "measure-container";
3965
+ this.container.style.background = "rgba(0,0,0,0)";
3966
+ this.container.style.position = "absolute";
3967
+ this.container.style.top = "0px";
3968
+ this.container.style.left = "0px";
3969
+ this.container.style.width = "100%";
3970
+ this.container.style.height = "100%";
3971
+ this.container.style.outline = "none";
3972
+ this.container.style.pointerEvents = "none";
3973
+ this.container.style.overflow = "hidden";
3974
+ this.canvas.parentElement.appendChild(this.container);
3975
+ }
3976
+ dispose() {
3977
+ this.clear();
3978
+ }
3979
+ detach() {
3980
+ this.container.remove();
3981
+ this.container = undefined;
3982
+ }
3983
+ clear() {
3984
+ this.lines.forEach((line => line.dispose()));
3985
+ this.lines = [];
3986
+ }
3987
+ render() {
3988
+ this.projector.updateProjectionMatrix();
3989
+ this.lines.forEach((line => line.render()));
3990
+ }
3991
+ update() {
3992
+ this.lines.forEach((line => line.update()));
3993
+ }
3994
+ addLine(line) {
3995
+ this.lines.push(line);
3996
+ }
3997
+ removeLine(line) {
3998
+ this.lines = this.lines.filter((x => x !== line));
3999
+ }
4000
+ }
4001
+
4002
+ const _middlePoint = new Vector3;
4003
+
4004
+ class MeasureLine {
4005
+ constructor(overlay) {
4006
+ this.id = Date.now();
4007
+ this.unit = "";
4008
+ this.scale = 1;
4009
+ this.size = 10;
4010
+ this.lineWidth = 2;
4011
+ this.style = {
4012
+ border: "2px solid #FFFFFF",
4013
+ background: "#009bff",
4014
+ boxShadow: "0 0 10px rgba(0,0,0,0.5)",
4015
+ color: "white",
4016
+ font: "1rem system-ui"
4017
+ };
4018
+ this.overlay = overlay;
4019
+ this.elementStartPoint = overlay.container.appendChild(document.createElement("div"));
4020
+ this.elementEndPoint = overlay.container.appendChild(document.createElement("div"));
4021
+ this.elementLine = overlay.container.appendChild(document.createElement("div"));
4022
+ this.elementLabel = overlay.container.appendChild(document.createElement("div"));
4023
+ this.update();
4024
+ }
4025
+ dispose() {
4026
+ this.elementStartPoint.remove();
4027
+ this.elementEndPoint.remove();
4028
+ this.elementLine.remove();
4029
+ this.elementLabel.remove();
4030
+ }
4031
+ render() {
4032
+ const projector = this.overlay.projector;
4033
+ if (this.startPoint) {
4034
+ const {point: point, visible: visible} = projector.projectPoint(this.startPoint);
4035
+ this.elementStartPoint.style.display = visible ? "block" : "none";
4036
+ this.elementStartPoint.style.left = `${point.x}px`;
4037
+ this.elementStartPoint.style.top = `${point.y}px`;
4038
+ } else {
4039
+ this.elementStartPoint.style.display = "none";
4040
+ }
4041
+ if (this.endPoint) {
4042
+ const {point: point, visible: visible} = projector.projectPoint(this.endPoint);
4043
+ this.elementEndPoint.style.display = visible ? "block" : "none";
4044
+ this.elementEndPoint.style.left = `${point.x}px`;
4045
+ this.elementEndPoint.style.top = `${point.y}px`;
4046
+ } else {
4047
+ this.elementEndPoint.style.display = "none";
4048
+ }
4049
+ if (this.startPoint && this.endPoint) {
4050
+ const {point1: point1, point2: point2, visible: visible} = projector.projectLine(this.startPoint, this.endPoint);
4051
+ point2.sub(point1);
4052
+ const angle = point2.angle();
4053
+ const width = point2.length();
4054
+ this.elementLine.style.display = visible ? "block" : "none";
4055
+ this.elementLine.style.left = `${point1.x}px`;
4056
+ this.elementLine.style.top = `${point1.y}px`;
4057
+ this.elementLine.style.width = `${width}px`;
4058
+ this.elementLine.style.transform = `translate(0px, ${-this.lineWidth / 2}px) rotate(${angle}rad)`;
4059
+ } else {
4060
+ this.elementLine.style.display = "none";
4061
+ }
4062
+ if (this.startPoint && this.endPoint) {
4063
+ _middlePoint.lerpVectors(this.startPoint, this.endPoint, .5);
4064
+ const {point: point, visible: visible} = projector.projectPoint(_middlePoint);
4065
+ const distance = this.getDistance();
4066
+ this.elementLabel.style.display = visible && distance >= PRECISION ? "block" : "none";
4067
+ this.elementLabel.style.left = `${point.x}px`;
4068
+ this.elementLabel.style.top = `${point.y}px`;
4069
+ this.elementLabel.innerHTML = `${distance.toFixed(2)} ${this.unit}`;
4070
+ } else {
4071
+ this.elementLabel.style.display = "none";
4072
+ }
4073
+ }
4074
+ update() {
4075
+ this.elementStartPoint.id = `markup-dot-start-${this.id}`;
4076
+ this.elementStartPoint.style.position = "absolute";
4077
+ this.elementStartPoint.style.zIndex = "2";
4078
+ this.elementStartPoint.style.width = `${this.size}px`;
4079
+ this.elementStartPoint.style.height = `${this.size}px`;
4080
+ this.elementStartPoint.style.border = this.style.border;
4081
+ this.elementStartPoint.style.borderRadius = `${this.size}px`;
4082
+ this.elementStartPoint.style.background = this.style.background;
4083
+ this.elementStartPoint.style.boxShadow = this.style.boxShadow;
4084
+ this.elementStartPoint.style.transform = "translate(-50%, -50%)";
4085
+ this.elementEndPoint.id = `markup-dot-end-${this.id}`;
4086
+ this.elementEndPoint.style.position = "absolute";
4087
+ this.elementEndPoint.style.zIndex = "2";
4088
+ this.elementEndPoint.style.width = `${this.size}px`;
4089
+ this.elementEndPoint.style.height = `${this.size}px`;
4090
+ this.elementEndPoint.style.border = this.style.border;
4091
+ this.elementEndPoint.style.borderRadius = `${this.size}px`;
4092
+ this.elementEndPoint.style.background = this.style.background;
4093
+ this.elementEndPoint.style.boxShadow = this.style.boxShadow;
4094
+ this.elementEndPoint.style.transform = "translate(-50%, -50%)";
4095
+ this.elementLine.id = `markup-line-${this.id}`;
4096
+ this.elementLine.style.position = "absolute";
4097
+ this.elementLine.style.zIndex = "1";
4098
+ this.elementLine.style.height = `${this.lineWidth}px`;
4099
+ this.elementLine.style.background = this.style.background;
4100
+ this.elementLine.style.boxShadow = this.style.boxShadow;
4101
+ this.elementLine.style.transformOrigin = `0px ${this.lineWidth / 2}px`;
4102
+ this.elementLabel.id = `markup-label-${this.id}`;
4103
+ this.elementLabel.style.position = "absolute";
4104
+ this.elementLabel.style.zIndex = "3";
4105
+ this.elementLabel.style.padding = "2px";
4106
+ this.elementLabel.style.paddingInline = "5px";
4107
+ this.elementLabel.style.borderRadius = "5px";
4108
+ this.elementLabel.style.background = this.style.background;
4109
+ this.elementLabel.style.boxShadow = this.style.boxShadow;
4110
+ this.elementLabel.style.color = this.style.color;
4111
+ this.elementLabel.style.font = this.style.font;
4112
+ this.elementLabel.style.transform = "translate(-50%, -50%)";
4113
+ }
4114
+ getDistance() {
4115
+ return this.startPoint.distanceTo(this.endPoint) / this.scale;
4116
+ }
4117
+ }
4118
+
4119
+ let _widthHalf;
4120
+
4121
+ let _heightHalf;
4122
+
4123
+ const _viewMatrix = new Matrix4;
4124
+
4125
+ const _viewProjectionMatrix = new Matrix4;
4126
+
4127
+ const _vector = new Vector3;
4128
+
4129
+ const _vector1 = new Vector4;
4130
+
4131
+ const _vector2 = new Vector4;
4132
+
4133
+ const point = new Vector2;
4134
+
4135
+ const point1 = new Vector2;
4136
+
4137
+ const point2 = new Vector2;
4138
+
4139
+ class MeasureProjector {
4140
+ constructor(camera, canvas) {
4141
+ this.camera = camera;
4142
+ this.canvas = canvas;
4143
+ }
4144
+ updateProjectionMatrix() {
4145
+ const rect = this.canvas.getBoundingClientRect();
4146
+ _widthHalf = rect.width / 2;
4147
+ _heightHalf = rect.height / 2;
4148
+ _viewMatrix.copy(this.camera.matrixWorldInverse);
4149
+ _viewProjectionMatrix.multiplyMatrices(this.camera.projectionMatrix, _viewMatrix);
4150
+ }
4151
+ projectPoint(p) {
4152
+ _vector.copy(p).applyMatrix4(_viewProjectionMatrix);
4153
+ const visible = _vector.z >= -1 && _vector.z <= 1;
4154
+ point.x = (_vector.x + 1) * _widthHalf;
4155
+ point.y = (-_vector.y + 1) * _heightHalf;
4156
+ return {
4157
+ point: point,
4158
+ visible: visible
4159
+ };
4160
+ }
4161
+ projectLine(p1, p2) {
4162
+ let visible;
4163
+ _vector1.copy(p1).applyMatrix4(_viewProjectionMatrix);
4164
+ _vector2.copy(p2).applyMatrix4(_viewProjectionMatrix);
4165
+ const bc1near = _vector1.z + _vector1.w;
4166
+ const bc2near = _vector2.z + _vector2.w;
4167
+ const bc1far = -_vector1.z + _vector1.w;
4168
+ const bc2far = -_vector2.z + _vector2.w;
4169
+ if (bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0) visible = true; else if (bc1near < 0 && bc2near < 0 || bc1far < 0 && bc2far < 0) visible = false; else {
4170
+ let alpha1 = 0;
4171
+ let alpha2 = 1;
4172
+ if (bc1near < 0) alpha1 = Math.max(alpha1, bc1near / (bc1near - bc2near)); else if (bc2near < 0) alpha2 = Math.min(alpha2, bc1near / (bc1near - bc2near));
4173
+ if (bc1far < 0) alpha1 = Math.max(alpha1, bc1far / (bc1far - bc2far)); else if (bc2far < 0) alpha2 = Math.min(alpha2, bc1far / (bc1far - bc2far));
4174
+ visible = alpha2 >= alpha1;
4175
+ if (visible) {
4176
+ _vector1.lerp(_vector2, alpha1);
4177
+ _vector2.lerp(_vector1, 1 - alpha2);
4178
+ }
4179
+ }
4180
+ _vector1.multiplyScalar(1 / _vector1.w);
4181
+ _vector2.multiplyScalar(1 / _vector2.w);
4182
+ point1.x = (_vector1.x + 1) * _widthHalf;
4183
+ point1.y = (-_vector1.y + 1) * _heightHalf;
4184
+ point2.x = (_vector2.x + 1) * _widthHalf;
4185
+ point2.y = (-_vector2.y + 1) * _heightHalf;
4186
+ return {
4187
+ point1: point1,
4188
+ point2: point2,
4189
+ visible: visible
4190
+ };
4191
+ }
4192
+ }
4193
+
4734
4194
  class ExtentsComponent {
4735
4195
  constructor(viewer) {
4736
4196
  this.syncExtents = () => {
4737
- const extents = this.viewer.models.reduce(((result, gltf) => {
4738
- const modelExtents = (new Box3).setFromObject(gltf.scene);
4739
- return result.isEmpty() ? result.copy(modelExtents) : result.union(modelExtents);
4740
- }), new Box3);
4197
+ const extents = this.viewer.models.reduce(((result, gltf) => result.expandByObject(gltf.scene)), new Box3);
4741
4198
  this.viewer.extents.copy(extents);
4742
4199
  this.viewer.target.copy(extents.getCenter(new Vector3));
4743
4200
  };
@@ -4934,7 +4391,9 @@ class WCSHelper extends Object3D {
4934
4391
  class WCSHelperComponent {
4935
4392
  constructor(viewer) {
4936
4393
  this.viewerRender = () => {
4937
- if (!this.viewer.extents.isEmpty()) this.wcsHelper.render(this.viewer.renderer);
4394
+ if (!this.viewer.options.showWCS) return;
4395
+ if (this.viewer.extents.isEmpty()) return;
4396
+ this.wcsHelper.render(this.viewer.renderer);
4938
4397
  };
4939
4398
  this.wcsHelper = new WCSHelper(viewer.camera);
4940
4399
  this.viewer = viewer;
@@ -4962,7 +4421,8 @@ class Viewer extends EventEmitter2 {
4962
4421
  Walk: WalkDragger,
4963
4422
  CuttingPlaneXAxis: CuttingPlaneXAxisDragger,
4964
4423
  CuttingPlaneYAxis: CuttingPlaneYAxisDragger,
4965
- CuttingPlaneZAxis: CuttingPlaneZAxisDragger
4424
+ CuttingPlaneZAxis: CuttingPlaneZAxisDragger,
4425
+ MeasureLine: MeasureLineDragger
4966
4426
  };
4967
4427
  this._activeDragger = null;
4968
4428
  this.models = [];
@@ -5186,6 +4646,7 @@ class Viewer extends EventEmitter2 {
5186
4646
  this.setActiveDragger();
5187
4647
  this.clearSlices();
5188
4648
  this.clearOverlay();
4649
+ this.clearSelected();
5189
4650
  this.helpers.traverse(disposeObject);
5190
4651
  this.helpers.clear();
5191
4652
  this.models.forEach((gltf => gltf.scene.traverse(disposeObject)));